eOpenAgent

One billed API call → an AI coding agent in a container → a tested pull request. Multi-tenant, credit-metered, on Kubernetes.

For agents

Point your agent at the machine-readable reference and it has everything it needs:

https://eopenagent.com/llms.txt

Base URL https://eopenagent.com/v1 · auth Authorization: Bearer eoa_live_… · keys from your dashboard at <workspace>.eopenagent.com.

API reference

# 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://<workspace>.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://<workspace>.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":"<forgejo-access-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.