# eOpenAgent API eOpenAgent runs AI coding agents in Kubernetes containers. One API call starts a container against a Forgejo git repo; the agent (Aider, driven by a Qwen model) edits code, runs the test command, and opens a pull request. Containers come in two lifecycles: - ephemeral: one-shot. Runs the task to completion, opens a PR, then is reaped. - session: long-lived and callable. Clones once, stays warm, and accepts repeated messages so you can drive it conversationally. ## Base URL https://eopenagent.com/v1 (The same API is also reachable at https://.eopenagent.com/v1 — the API key, not the host, determines which workspace you act on.) ## Authentication Every /v1 request requires your workspace API key as a Bearer token: Authorization: Bearer eoa_live_... Keys are created in your workspace dashboard at https://.eopenagent.com. Requests without a valid key get 401. ## Conventions - POST bodies are JSON; send Content-Type: application/json. - Send an explicit User-Agent (e.g. "eopenagent/1.0"). Default HTTP-library user-agents may be blocked by the edge firewall. - Errors are JSON: {"error":{"type":"...","message":"..."}}. - /logs returns text/plain. stop/cancel return 204 No Content. ## Endpoints GET /health Liveness check (no auth). GET /v1/agents List available agents + lifecycles. POST /v1/agents/runs START a container (ephemeral or session). GET /v1/agents/runs List this workspace's runs (newest 100). GET /v1/agents/runs/{id} Get one run (status, repo, branch, ...). GET /v1/agents/runs/{id}/events Run event timeline (transitions + messages). POST /v1/agents/runs/{id}/messages CALL a session container -> agent output. GET /v1/agents/runs/{id}/logs Read the container's logs (text, tail 1000). POST /v1/agents/runs/{id}/stop STOP a container (reaps the workload). POST /v1/agents/runs/{id}/cancel Alias of /stop. GET /v1/agents/containers LIST active (non-terminal) containers. GET /v1/skills SHOW this workspace's agent skills. POST /v1/skills TEACH/upgrade a skill (append a lesson). GET /v1/git-credentials LIST stored git tokens (no secret). POST /v1/git-credentials ATTACH a git token to an owner/repo. DELETE /v1/git-credentials/{id} REVOKE a stored git token. GET /v1/models LIST registered direct model endpoints. POST /v1/models REGISTER a direct model endpoint. DELETE /v1/models/{id} REMOVE a model endpoint. GET /v1/model-key Whether a workspace model key is set. PUT /v1/model-key Set/replace the stored model key. DELETE /v1/model-key Clear the stored model key. ## Secrets are stored, not sent per call You do NOT pass git tokens or model keys in a run request. Configure them once (dashboard or API) and runs use them automatically: - git token -> POST /v1/git-credentials (or the dashboard "Git Tokens" page) - model -> POST /v1/models (or the dashboard "Models" page) — endpoint + key - model key -> PUT /v1/model-key (key for the platform default model) ## POST /v1/agents/runs — request body agent (required) "aider" | "playwright" lifecycle (required) "ephemeral" | "session" | "persistent" task (required) the work order / instructions for the agent repo Forgejo repo as "Org/repo" base base branch to start from (e.g. "main") branch branch the agent commits to (e.g. "eoa/my-feature") model model name; matches a registered model (/v1/models), else the workspace default, else the platform default. Optional. model_api_key optional per-run model API key. Usually omitted — register the model (with its key, if any) via /v1/models or the dashboard. test_cmd test loop command, e.g. "go test ./..." output "pr" (default) | "branch" | "diff" | "result" | "artifacts" run_timeout optional duration string ttl optional duration string Returns 201 with the run object: {"id":"run_...","status":"queued", ...}. ## The four container operations # 1. START a session container (callable). Use "ephemeral" for one-shot -> PR. curl -sX POST https://eopenagent.com/v1/agents/runs \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." \ -H "Content-Type: application/json" -d '{ "agent":"aider", "lifecycle":"session", "repo":"Org/repo", "base":"main", "branch":"eoa/my-feature", "model":"wozinga/qwen3-coder", "task":"session container", "output":"pr" }' # (No model key here — set it once via /v1/model-key or the dashboard Settings page.) # 2. CALL it — drive the warm container; commits accumulate on the branch. curl -sX POST https://eopenagent.com/v1/agents/runs/run_ID/messages \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." \ -H "Content-Type: application/json" \ -d '{"message":"Add a Greet function to greet.go. Output the full file now."}' # -> {"output":"...aider transcript..."} # Note: /messages is session-only; calling an ephemeral run returns 409. # 3. LIST running containers curl -s https://eopenagent.com/v1/agents/containers \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." # 4. STOP it (the reaper deletes the Pod within ~10-35s) curl -sX POST https://eopenagent.com/v1/agents/runs/run_ID/stop \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." ## Observe a run GET /v1/agents/runs/run_ID -> status GET /v1/agents/runs/run_ID/events -> timeline (transitions + your messages) GET /v1/agents/runs/run_ID/logs -> container logs (text/plain) ## Agent skills (self-improvement) Each agent run is primed with a SKILL.md per stack: a platform base skill plus this workspace's accumulated lessons. Teaching a lesson makes every future run in this workspace better at the task. Lessons are workspace-scoped — one tenant can never affect another's skill. # SHOW the workspace's skills (optionally one stack: ?stack=go) curl -s "https://eopenagent.com/v1/skills?stack=go" \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." # -> {"data":[{"scope":"platform","stack":"go","content":"..."}, # {"scope":"workspace","stack":"go","content":"- lesson one\n- lesson two"}]} # TEACH / upgrade a skill — append a lesson for a stack. curl -sX POST https://eopenagent.com/v1/skills \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." \ -H "Content-Type: application/json" \ -d '{"stack":"go","lesson":"Always run gofmt before committing."}' # -> {"stack":"go","name":"go-agent-skill","appended":"- Always run gofmt before committing."} ## Git credentials (per-workspace repo access) By default agents use a shared platform token. Attach your own Forgejo token so agents push to your repos under your identity. A token is scoped to an owner (org-wide) or narrowed to one repo; a run uses the narrowest match. Tokens are encrypted at rest and never returned. # ATTACH a token (owner-wide; add "repo" to narrow to one repo) curl -sX POST https://eopenagent.com/v1/git-credentials \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." \ -H "Content-Type: application/json" \ -d '{"owner":"Acme","token":"","label":"ci bot"}' # -> {"id":"...","host":"git.gandetl.com","owner":"Acme","repo":"","label":"ci bot"} # LIST stored tokens (scopes only, never the secret) curl -s https://eopenagent.com/v1/git-credentials \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." # REVOKE a token curl -sX DELETE https://eopenagent.com/v1/git-credentials/CRED_ID \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." ## Model key — key for the platform default model (optional) If the platform default model needs an API key, store it once on the workspace so runs never carry it. Most self-hosted endpoints are key-optional, so this is often unused — and a registered model (/v1/models) carries its own key. A per-run model_api_key still overrides. # SET / replace the stored model key curl -sX PUT https://eopenagent.com/v1/model-key \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." \ -H "Content-Type: application/json" -d '{"key":"sk-..."}' # -> {"configured":true} # CHECK whether one is set (never returns the key) curl -s https://eopenagent.com/v1/model-key \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." # -> {"configured":true} # CLEAR it curl -sX DELETE https://eopenagent.com/v1/model-key \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." ## Models — the model endpoint runs call eopenagent calls the model endpoint directly (OpenAI-compatible, e.g. a self-hosted vLLM). The platform has a default; register your own to override it per workspace. A run uses the model whose "name" matches its "model" field, else the workspace default, else the platform default. Set in the dashboard "Models" page or via API: # REGISTER a model as the workspace default curl -sX POST https://eopenagent.com/v1/models \ -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." \ -H "Content-Type: application/json" -d '{ "name":"qwen3-coder", "model":"qwen3-coder", "base_url":"http://192.168.134.11:8000/v1", "default":true }' # Then a run with no special config uses it directly: # POST /v1/agents/runs {"agent":"aider","lifecycle":"ephemeral","repo":"...","task":"..."} # LIST / REMOVE curl -s https://eopenagent.com/v1/models -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." curl -sX DELETE https://eopenagent.com/v1/models/MODEL_ID -A "eopenagent/1.0" -H "Authorization: Bearer eoa_live_..." ## Run lifecycle (status field) queued -> provisioning -> running -> (testing|pushing|awaiting_input) -> succeeded Terminal: succeeded | failed | cancelled | timed_out. A successful ephemeral run ends with a pull request on the target repo.