agent-fleet/docs/agent-api-reference.md
Zer4tul d1a746a8cb docs: add agent API reference, onboarding guide, and universal skill
- docs/agent-api-reference.md (473 lines): complete HTTP API reference for all 12 endpoints
- docs/agent-onboarding-guide.md (272 lines): ssh_cli and http_pull workflows, Forgejo integration
- skill/SKILL.md (281 lines): universal agent skill, platform-agnostic, curl-based examples

All content in English. No code changes.
2026-05-12 14:57:05 +08:00

10 KiB

Agent Fleet — HTTP API Reference

Base URL: http://<host>:9090 Content-Type: application/json for all request/response bodies unless noted. All timestamps are ISO 8601 (RFC 3339).


Authentication

http_pull Bearer Token

Endpoints that are specific to http_pull agents require a Bearer token in the Authorization header. The token is configured in config.toml as orchestrator.http_pull_token. If no token is configured in the config, authentication is skipped (open mode).

Authorization: Bearer <http_pull_token>

Affected endpoints: POST /api/v1/tasks/dequeue, POST /api/v1/tasks/{task_id}/status.

Webhook HMAC-SHA256

The POST /api/v1/webhooks/forgejo endpoint requires an X-Hub-Signature-256 (or X-Gitea-Signature / X-Forgejo-Signature) header containing sha256=<hex_hmac> of the request body using the configured webhook_secret.

X-Hub-Signature-256: sha256=abcdef...

Error Responses

All errors return JSON:

{ "error": "<human-readable message>" }
Status Meaning Trigger
400 Bad Request Invalid state transition, wrong execution_mode, malformed input
401 Unauthorized Missing or invalid Bearer token for http_pull endpoints
404 Not Found Task or agent does not exist
500 Internal Server Error Database failure, lock poisoning, unexpected errors

Endpoints

Health Check

GET /healthz

Response: 200 OK — body: ok

curl http://localhost:9090/healthz

Register Agent

POST /api/v1/agents/register

Register a new agent or update an existing one (upsert by agent_id).

Request:

Field Type Required Description
agent_id string yes Unique identifier
agent_type string yes openclaw, claude-code, codex-cli, hermes, acp, shell, or custom
hostname string yes Machine hostname
capabilities string[] yes e.g. ["code:rust", "review"]
max_concurrency u32 yes Max parallel tasks
metadata object no Arbitrary key-value pairs

Response: 200 OK

{
  "agent_id": "worker-01",
  "registry_token": "registry_a1b2c3d4..."
}
curl -X POST http://localhost:9090/api/v1/agents/register \
  -H 'Content-Type: application/json' \
  -d '{
    "agent_id": "worker-01",
    "agent_type": "codex-cli",
    "hostname": "host-worker-01",
    "capabilities": ["code:rust"],
    "max_concurrency": 2
  }'

Heartbeat

POST /api/v1/agents/heartbeat

Request:

Field Type Required Description
agent_id string yes Agent to update

Response: 200 OK

{
  "agent_id": "worker-01",
  "status": "online",
  "last_heartbeat_at": "2025-01-15T10:30:00Z"
}

Errors: 404 if agent not found.

curl -X POST http://localhost:9090/api/v1/agents/heartbeat \
  -H 'Content-Type: application/json' \
  -d '{"agent_id": "worker-01"}'

Deregister Agent

POST /api/v1/agents/deregister

Sets agent offline and requeues all its active tasks back to created.

Request:

Field Type Required
agent_id string yes

Response: 200 OK

{
  "agent_id": "worker-01",
  "status": "offline",
  "requeued_tasks": 3
}
curl -X POST http://localhost:9090/api/v1/agents/deregister \
  -H 'Content-Type: application/json' \
  -d '{"agent_id": "worker-01"}'

List Agents

GET /api/v1/agents

Query Parameters:

Param Type Description
capability string Filter by capability (e.g. code:rust)
status string Filter: online, offline, draining

Response: 200 OK — JSON array of Agent objects.

curl 'http://localhost:9090/api/v1/agents?status=online'

List Tasks

GET /api/v1/tasks

Query Parameters:

Param Type Description
status string Filter by status (e.g. created, running, failed)
agent_id string Filter by assigned agent

Response: 200 OK — JSON array of Task objects. Ordered by created_at descending.

curl 'http://localhost:9090/api/v1/tasks?status=running'

Get Task

GET /api/v1/tasks/{task_id}

Response: 200 OK — single Task object.

Errors: 404 if task not found.

curl http://localhost:9090/api/v1/tasks/org%2Frepo%2342

Dequeue Task (http_pull only)

POST /api/v1/tasks/dequeue

Requires Bearer token if http_pull_token is configured. Only returns tasks with execution_mode = http_pull.

Request:

Field Type Required Description
agent_id string yes Agent claiming the task
capabilities string[] no Capabilities to match against task labels

Response: 200 OK with Task object, or 204 No Content if no matching task.

Errors: 401 if token required and missing/invalid.

curl -X POST http://localhost:9090/api/v1/tasks/dequeue \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer my-token' \
  -d '{"agent_id": "worker-03", "capabilities": ["code:rust"]}'

Update Task Status (http_pull only)

POST /api/v1/tasks/{task_id}/status

Requires Bearer token. Only works for tasks with execution_mode = http_pull.

Request:

Field Type Required Description
status string yes Target status: running, review_pending, etc.

Response: 200 OK — updated Task.

Errors: 400 if task is not http_pull mode or transition is invalid. 404 if task not found.

curl -X POST http://localhost:9090/api/v1/tasks/org%2Frepo%2342/status \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer my-token' \
  -d '{"status": "running"}'

Complete Task

POST /api/v1/tasks/{task_id}/complete

Works for both ssh_cli and http_pull tasks. Submit a receipt to mark the task done.

Request: A Receipt object.

Response: 200 OK

{
  "task_id": "org/repo#42",
  "status": "completed"
}

Errors: 404 if task not found. 400 if task is not in a completable state.

curl -X POST http://localhost:9090/api/v1/tasks/org%2Frepo%2342/complete \
  -H 'Content-Type: application/json' \
  -d '{
    "task_id": "org/repo#42",
    "agent_id": "worker-01",
    "status": "completed",
    "duration_seconds": 120,
    "summary": "Implemented feature X",
    "artifacts": [
      {"artifact_type": "pr", "url": "https://git.example/org/repo/pulls/7"}
    ],
    "error": null
  }'

Retry Task

POST /api/v1/tasks/{task_id}/retry

Retry a failed or agent_lost task. Transitions it back to assigned.

Response: 200 OK — updated Task.

Errors: 400 if task status is not failed or agent_lost. 404 if task not found.

curl -X POST http://localhost:9090/api/v1/tasks/org%2Frepo%2342/retry

Submit Receipt

POST /api/v1/receipts

Submit a receipt for a task. Validates artifacts (e.g. checks PR exists via Forgejo API).

Request: A Receipt object.

Response: 200 OK

Errors: 404 if task not found. 400 if validation fails.

curl -X POST http://localhost:9090/api/v1/receipts \
  -H 'Content-Type: application/json' \
  -d '{
    "task_id": "org/repo#42",
    "agent_id": "worker-01",
    "status": "completed",
    "duration_seconds": 95,
    "summary": "Fixed the bug",
    "artifacts": [],
    "error": null
  }'

Forgejo Webhook

POST /api/v1/webhooks/forgejo

Receives Forgejo webhook events. Requires HMAC-SHA256 signature header.

Headers: X-Forgejo-Event or X-Gitea-Event determines the event type.

Supported events:

Event Action
issues (opened) Creates a task from the Issue (requires agent:* label)
pull_request (opened) Sets task to review_pending (branch name → task_id)
pull_request (merged/closed with merged: true) Sets task to completed, auto-generates receipt
push (to task/* branch) Updates last_activity_at on the task

Response: 200 OK

{
  "accepted": true,
  "task_id": "org/repo#42"
}

Errors: 401 if signature invalid. 400 if payload unparseable.


Object Schemas

Agent Object

{
  "agent_id": "worker-01",
  "agent_type": "codex-cli",
  "hostname": "host-worker-01",
  "capabilities": ["code:rust"],
  "max_concurrency": 2,
  "current_tasks": 1,
  "status": "online",
  "last_heartbeat_at": "2025-01-15T10:30:00Z",
  "registered_at": "2025-01-15T09:00:00Z",
  "metadata": {}
}

Task Object

{
  "task_id": "org/repo#42",
  "source": "forgejo:org/repo#42",
  "task_type": "code",
  "priority": "normal",
  "status": "created",
  "execution_mode": "ssh_cli",
  "assigned_agent_id": null,
  "assigned_host": null,
  "requirements": "Implement the feature described in the issue body",
  "labels": ["agent:code", "code:rust"],
  "branch_name": "task/org%2Frepo%2342",
  "pr_title": "feat: Implement feature (#42)",
  "created_at": "2025-01-15T10:00:00Z",
  "assigned_at": null,
  "started_at": null,
  "completed_at": null,
  "last_activity_at": null,
  "retry_count": 0,
  "max_retries": 2,
  "review_count": 0,
  "timeout_seconds": 1800
}

Status values: created, assigned, running, review_pending, completed, failed, agent_lost, cancelled

Priority values: low, normal, high, urgent

Execution mode values: ssh_cli, http_pull

Receipt Object

{
  "task_id": "org/repo#42",
  "agent_id": "worker-01",
  "status": "completed",
  "duration_seconds": 120,
  "summary": "Implemented the feature",
  "artifacts": [
    {"artifact_type": "pr", "url": "https://git.example/org/repo/pulls/7", "path": null, "description": null}
  ],
  "error": null
}

Receipt status values: completed, failed, partial

Artifact type values: pr, commit, file, comment, url