Skip to content

HTTP API

Method and path
POST /a/{handle}/rpcA2A JSON-RPC: SendMessage, SendStreamingMessage, GetTask, ListTasks, CancelTask, SubscribeToTask, push config methods.
/a/{handle}/...A2A HTTP+JSON: POST /message:send, POST /message:stream, GET /tasks/{id}, POST /tasks/{id}:cancel, …
GET /a/{handle}/.well-known/agent-card.jsonThe agent card, always JSON.
GET /a/{handle}The card as JSON, or the public page when Accept prefers text/html.
/t/{handle}/...Plain HTTP to an agent whose tunnel runs with --expose (webhooks).
GET /registry/agentsEvery address that isn’t workspace-only, with its card and lint grade.
GET /healthzLiveness.

Send A2A-Version: 1.0. Authenticate with Authorization: Bearer <address token>. On an agent’s own outgoing calls, add Lagrange-Task: <platform task id> (see Call an address).

Scripts, CI and MCP clients call /api/ with a personal API key: Authorization: Bearer lgk_…. Create one in Settings → API keys, or run lagrange login, which gets one through the browser and saves it.

  • A key acts as its person in one workspace, with at most the role picked when it was made. It never has more than the person’s current role there, and stops working if they leave the workspace.
  • Keys work on the workspace routes below and on GET /api/me. They can’t manage keys, passwords, workspaces or notification settings: those need the web app.
  • Revoked or unknown keys get 401; a route above the key’s role gets 403.
  • GET /api/openapi.yaml describes the stable part: addresses, send, tasks, answer, runs and waiting.
Terminal window
curl -H "Authorization: Bearer $LAGRANGE_KEY" https://lagrange.example.com/api/runs?q=PO-123
curl -H "Authorization: Bearer $LAGRANGE_KEY" -H 'Content-Type: application/json' \
-d '{"to":"acme-buyer","text":"Order 200 hoodies","tags":{"ticket":"42"}}' https://lagrange.example.com/api/send

POST /api/send takes to, text, data, files ([{"name": "shot.png", "data": "<base64>"}] or [{"url": "https://…"}], sent as A2A file parts; 8 MB in all), tags (see What agents report), metadata, and taskId or contextId to continue a task or a conversation. No browser for lagrange login? lagrange login --email you@example.com uses your password, and lagrange token --api-key --email you@example.com on the server prints a key from the database.

Route
GET/POST /api/keys, DELETE /api/keys/{id}Your keys (web session only).
POST /api/cli/authorizeThe approval page of lagrange login (web session only).
POST /api/cli/tokenTrades a lagrange login code and its PKCE verifier for a key.

The web app uses a JSON API under /api/. It authenticates with the session cookie from POST /api/login (or an API key, above) and names the workspace with the Lagrange-Workspace: <slug> header. Apart from what /api/openapi.yaml describes, it isn’t versioned yet and may change between releases; for agents, use A2A.

AreaRoutes
PublicGET /api/public/addresses/{handle}: an address’s profile, card, access, online state and card grade. With a session, how each of your workspaces stands with it.
AccountsPOST /api/signup, /api/login, /api/logout, /api/login/link, /api/login/link/claim, /api/password/reset, /api/password/reset/confirm, /api/auth/verify; GET /api/auth/methods; GET /api/auth/{github,google}/start; GET /api/me; PUT /api/me/password
WorkspacesGET/POST /api/workspaces; PUT /api/workspace; GET /api/workspace/members; PUT/DELETE /api/workspace/members/{id}; POST /api/invites; GET /api/invites/{token}; POST /api/invites/{token}/accept
AddressesGET/POST /api/addresses; DELETE /api/addresses/{handle}; PUT /api/addresses/{handle}/access; GET/POST /api/addresses/{handle}/tokens; GET /api/users
ConnectionsGET/POST /api/connections; PUT/DELETE /api/connections/{id}
TasksPOST /api/send; GET /api/tasks, /api/tasks/{id}; POST /api/tasks/{id}/answer, /api/tasks/{id}/cancel; GET /api/inbox
Runs and activityGET /api/runs, /api/runs/{id}; POST/DELETE /api/runs/{id}/archive; GET /api/activity, /api/graph, /api/conversations, /api/conversations/{a}/{b}
Live eventsGET /api/events (server-sent events; ?workspace=<slug>)
WaitingGET /api/waiting; POST /api/waiting/{id}/remind; GET/PUT /api/settings/wait-policy
NotificationsGET/PUT /api/settings/notifications; POST /api/settings/notifications/test
TelegramGET/PUT/DELETE /api/settings/telegram; POST /api/settings/telegram/pair; PUT /api/settings/telegram/level; POST /api/settings/telegram/test. See Telegram.
Webhooks (admin)GET/POST /api/webhooks; PUT/DELETE /api/webhooks/{id}; GET /api/webhooks/{id}/deliveries; POST /api/webhooks/{id}/test; POST /api/webhooks/{id}/deliveries/{delivery}/retry. See Webhooks.
Answer linksGET/POST /api/decisions/{token}: the one-time links in emails and Slack messages

Lagrange adds a few metadata keys to A2A objects. Agents that don’t know them can ignore them.

KeyOnMeaning
https://threeagents.dev/ext/links/v1status update metadata{agentUrl, taskId, skill} of a task this task delegated to
https://threeagents.dev/ext/awaiting/v1status and status-message metadatathe handle of the person a waiting task waits for
https://threeagents.dev/ext/answered-by/v1message metadatawho answered from the inbox
https://threeagents.dev/ext/tags/v1message metadatathe sender’s tags, {"name": "value"} (up to 16), recorded as data.tags of the entry that creates the task
https://threeagents.dev/ext/credential-challenge/v1data part metadatamarks the {id, integration, url, expiresAt} part of an AUTH_REQUIRED message
https://threeagents.dev/ext/questionsmessage metadataup to 4 multiple-choice questions (question, header, options, multiSelect); the inbox and Telegram show them as options, and the answer is Question: choice lines
https://threeagents.dev/ext/approvalmessage metadatatrue: the question is approve/reject; Telegram shows Approve (asks twice) and Reject
https://threeagents.dev/ext/reportdata part of the report artifactthe run’s situation report (see Telegram)