On this page

1Endpoints

GroupDescriptionOperations
HealthLiveness. The only route that needs no bearer token.1
DaemonThe daemon process itself: this OpenAPI document and graceful shutdown.2
EventsLive umbilical event stream (Server-Sent Events) and per-agent replay windows.2
AgentsLoad, start, stop and inspect agents: status, config, tools, metadata, local tables, logs and usage.28
LoopsCognition loops: main plus an agent's inner loops, their persisted history, context usage and compaction.8
ChatChat turns, event triggers and the agent's message inbox / outbox.7
FilesThe agent's virtual file system, including its primary document and mind.12
Identity (agent)An agent's own identity store: DID, keys, password and stored values (metadata only, never values).16
Owner identityThe owner identity on this machine (seed phrase, keychain or passphrase file). State-changing routes are loopback only.6
CredentialsPer-agent provider, MCP and channel credentials. Writes take a value; reads return metadata only.6
ChannelsChannel adapters (Telegram, email, …) attached to an agent and their live state.5
MCPMCP servers attached to an agent, their live state, and the daemon-wide registrations.6
Providers & sign-inApp-level LLM providers, model lists, agent provider configs and subscription sign-in (ChatGPT, Grok).14
Tasks & approvalsHuman-in-the-loop: tool approvals, ask requests and suspend prompts.8
TimersAn agent's scheduled wake-ups.4
TemplatesAgent templates new agents are created from. Every route needs a ready owner identity (409 identity_not_ready).12
Tracked foldersFolders whose agents the daemon autostarts (settings.trackedDirectories).5
RuntimeRuntime diagnostics, token usage and token counting, daemon-wide and per agent.11
NetworkMesh registration, the mesh HTTP server and WebSocket diagnostics.12
ComputeThe Podman compute environment and its containers.11
AdminPackage installs for MCP servers, channel adapters and the code sandbox.12
SettingsThe daemon settings file. Secret and identity keys are never read or written here.4
Total22 groups192

2Base URL

The daemon listens on http://127.0.0.1:7385 by default and speaks plain HTTP. Set the address withADF_DAEMON_HOST and ADF_DAEMON_PORT. Requests and responses are JSON. SendContent-Type: application/json only with a body.

Agents are addressed by id, handle or name ({id}). Loop-aware routes take loop; absent means main.

First requests
export TOKEN=$(adf daemon token)
curl http://127.0.0.1:7385/health
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:7385/agents

3Authentication

Every route except GET /health needs a bearer token:

Authorization: Bearer <token>

Per-install token from <settings dir>/daemon-token (printed by adf daemon token), or ADF_DAEMON_TOKEN. Local adf clients send it automatically.

ADF_DAEMON_TOKEN overrides the file, on the daemon and in clients. A missing or wrong token gets401 with code unauthorized.

4Request guard

Three header checks run on every route, before authentication. The daemon sends no CORS headers, so web pages cannot call it.

CheckRefused with
Host must name this daemon: 127.0.0.1, localhost or [::1] on any port, or the bind address. Extra names go in ADF_DAEMON_ALLOWED_HOSTS.403 host_not_allowed
An Origin header that is not one of those hosts403 cross_origin
Sec-Fetch-Site: cross-site or same-site403 cross_origin

These routes answer local callers only (403 loopback_only): a loopback connection with no proxy header (Forwarded, X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Proto,X-Real-IP, Via).

Behind a reverse proxy on the same host, start the daemon with ADF_DAEMON_BEHIND_PROXY=1. These routes then also need X-ADF-Local-Proof, a secret the daemon writes at every start to<settings dir>/daemon-local-proof. The adf CLI and terminal app on that host send it; a caller through the proxy cannot.

5Turns and events

POST /agents/{id}/chat and POST /agents/{id}/trigger answer 202 with aturnId. Every event of that turn carries it as turn_id, ending with turn.completedor agent.error. Messages sent while the loop is busy queue in arrival order and are not dropped; the first interrupts the running turn.

GET /events is a server-sent event stream. Each frame has a daemon-wide cursor, also the SSEid. Resume with ?since=<cursor> or Last-Event-ID, plus?epoch=. Every connection opens with a stream.hello frame that names the daemon run (epoch). A stream.gap frame reports that frames were lost or the daemon restarted; re-read agent state when you get one. Replay comes from an in-memory buffer of the last 1000 frames.

6Errors

Errors are JSON with a human-readable error and a stable machine code. Every error has acode: a specific one where the route defines it, otherwise the status default (bad_request,forbidden, not_found, not_supported, conflict,internal_error, upstream_error, unavailable). Show error; branch oncode.

ErrorResponse
{ "error": "Unknown agent \"agent-1\"", "code": "not_found" }
FieldTypeDescription
errorrequiredstring

Human-readable message

codestring

Stable machine-readable code. Every error body has one: route-specific where listed, else the status default (400 bad_request, 403 forbidden, 404 not_found, 405 not_supported, 409 conflict, 500 internal_error, 502 upstream_error, 503 unavailable)

A body the HTTP framework cannot parse (malformed JSON, or an empty body sent withContent-Type: application/json) is refused with 400 in Fastify's shape:{ statusCode, code, error, message }. Send no Content-Type on bodiless POSTs.

StatusMeaningCodes
400Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_request FST_ERR_CTP_EMPTY_JSON_BODY
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowed cross_origin loopback_only
404Unknown agent (or the named resource: loop, task, file, …)ask_not_found not_found
405Not available on this daemon (the subsystem is read-only or lacks this operation)
409The resource is in a state that does not allow this nowidentity_not_ready name_taken
422The template was refused (template_missing, template_unreviewed, template_invalid) or the new file could not load (load_failed)
500Unexpected runtime failure
502An upstream call failed (e.g. the summarization request of a compaction); nothing was changed
503The subsystem is not configured on this daemon

7Versioning

The API is not versioned by URL. This reference documents API version 0.2.0. A running daemon serves its own contract at GET /openapi.json, and GET /runtime returns its package version as daemon.version.

  • Ignore fields you do not know. New fields are added without notice.
  • Treat a 404 on a route you need as an older daemon: fall back, or ask the user to update.
  • There are no ETags. The last write wins; re-read before you replace a whole config.

8Mesh server

Agent websites, agent cards and ALF message delivery are served by a separate HTTP server on the mesh port (default7295), not by this API. It does not use the daemon token. It is on by default and starts once a reachable agent loads; /network/server/* and meshServerEnabled control it.

MethodPathDescription
GET/healthMesh server health check
GET/pingRuntime identity probe
GET/agentsAgent directory, filtered by visibility
GET/agents/:handle/cardOne agent's card
GET/agents/:handle/healthOne agent's health
POST/agents/:handle/inboxALF message delivery

POST /agents/:handle/inbox is the only way to deliver a real inbound message: it takes a full, signedALF message. POST /agents/{id}/trigger on the Daemon API does not substitute for it. Everything else under /agents/:handle/* is served by the agent itself: see HTTP serving.

9Specification file

This reference is generated from docs/daemon/openapi.json in the ADF repository, atv0.7.4 (commit 56f129b). Download it to generate a client or load it into an OpenAPI tool.

Download openapi.json · OpenAPI 3.1.0 · 192 operations

For concepts and flows (chat turns, the event stream, approvals, identity), read the API guide. To install and run the daemon, see ADF daemon.