Skip to Content
API ReferenceUsing the API

Using the API

The interactive API Reference is generated from the OpenAPI document exposed by the Agor daemon.

Need the exact schema for your installed version? Start Agor and fetch http://localhost:3030/docs.json. The /docs route now brings you back to this maintained reference instead of installing a separate documentation application on every machine.

Quick Reference

Base URL

http://localhost:3030

Authentication

Every request carries a bearer credential — either a short-lived access token from password login, or a personal API key (agor_sk_…):

Authorization: Bearer <your-token-or-api-key>

Personal API keys

Create a key in the web UI under your user settings → API tokens. It is shown once. Keys act as you, never expire on their own, and stop working as soon as you delete them. They also work as X-API-Key: agor_sk_…, including on the /mcp endpoint.

Signing in to the CLI

On deployments that sign in with Google or another SSO provider instead of passwords, such as Agor Cloud, agor login uses your browser:

agor login --url https://your-workspace.example.com

The CLI prints (and opens) a page in your workspace. Sign in if asked, click Create CLI key, and paste the key into the terminal. The key is tagged CLI under API tokens and named after the machine (agor-cli-<hostname>-<id>); logging in again on the same machine replaces it, so each machine has one. agor logout deletes that machine’s key on the server (--keep-key only removes the local login). Use --web to pick the browser flow on a deployment that also has password login.

To use a key you created yourself instead:

agor login --url https://your-workspace.example.com --api-key # paste the key at the prompt, or pipe it in: pbpaste | agor login --url https://your-workspace.example.com --api-key

Either way the CLI checks the key against the deployment, saves it to ~/.agor/cli-token (mode 0600), and sends it on every later command. Keys are never accepted on the command line and never sent to a plain http:// URL other than localhost. agor logout does not delete keys you created yourself, since they may be used elsewhere. For CI, AGOR_API_KEY with DAEMON_URL and AGOR_DEPLOYMENT_ID still works without a saved login.

Keys are bound to the workspace they were created in. On a multi-tenant deployment the daemon uses the workspace URL you connect to to decide which workspace to check the key against, and the key must belong to that workspace. A key presented at another workspace’s URL is rejected, as is any request to a workspace URL the daemon has not yet seen a browser sign-in for. Use the same URL you open in your browser.

Password login

On deployments with email/password sign-in:

agor login

You’ll be prompted for your email and password. The access token is saved to ~/.agor/cli-token; it is short-lived (15 minutes), so run agor login again when commands report that your session expired, or use an API key for longer work.

Using the token with cURL:

# 1. Get your token (already saved locally) cat ~/.agor/cli-token # 2. Use it in curl commands curl -X GET http://localhost:3030/sessions \ -H "Authorization: Bearer <your-token>"

The public API reference is intentionally read-only. Browsers cannot call your local daemon from agor.live unless you deliberately add that origin to the daemon’s CORS policy. Use cURL or another local API client for requests; this avoids broadening the daemon’s default browser trust boundary.

Authentication is always required. On first daemon start, an admin user is auto-created with a random password. The credentials are written to ~/.agor/admin-credentials (mode 0600) and printed once to the daemon log. Use those to log in and obtain a JWT.

Core Services

  • /sessions - AI agent session management with genealogy (fork/spawn)
  • /tasks - Work units within sessions tracking prompts and execution
  • /messages - Conversation messages with streaming support
  • /repos - Git repository management and branch operations
  • /boards - Spatial organization of sessions with zones and triggers
  • /branches - Git branch isolation for sessions
  • /users - User account management and authentication
  • /mcp-servers - Model Context Protocol server configurations

Response Format

All FeathersJS endpoints return data in this format:

// Single resource { data: { id: '...', ... } } // List of resources (paginated) { data: [{ id: '...', ... }], total: 100, limit: 50, skip: 0 }

RESTful Conventions

All services follow standard REST patterns:

  • GET /service - List items (paginated)
  • GET /service/:id - Get single item
  • POST /service - Create new item
  • PATCH /service/:id - Update item (partial)
  • DELETE /service/:id - Delete item

Session Prompt Endpoint

Use POST /sessions/:id/prompt to send a prompt to an existing session.

curl -X POST http://localhost:3030/sessions/<session-id>/prompt \ -H "Content-Type: application/json" \ -H "Authorization: Bearer <your-token>" \ -d '{ "prompt": "Review the latest auth changes for security issues", "permissionMode": "auto", "stream": true }'

Possible response shapes:

{ "success": true, "taskId": "0195d3c0-82df-7a75-b9b3-83f58de12345", "status": "dispatching", "streaming": true }

The immediate response is dispatching; the authenticated executor changes the task to running after it connects.

{ "success": true, "queued": true, "message": { "message_id": "0195d3c0-82df-7a75-b9b3-83f58de67890", "status": "queued" }, "queue_position": 2 }

Task Run Endpoint

POST /sessions/:id/prompt is the simplest way to drive a session. It creates the underlying task and starts execution in one round-trip. If you’d rather create the task as a separate step (e.g. so you have its task_id before triggering execution), POST /tasks followed by POST /tasks/:id/run does the same thing in two calls. This is the path pure-REST harnesses use to skip the MCP transport entirely.

# 1. Create a task (status will be 'created') curl -X POST http://localhost:3030/tasks \ -H "Content-Type: application/json" \ -H "Authorization: Bearer <your-token>" \ -d '{ "session_id": "<session-id>", "full_prompt": "Run the test suite and summarize failures", "status": "created" }' # 2. Trigger executor pickup curl -X POST http://localhost:3030/tasks/<task-id>/run \ -H "Content-Type: application/json" \ -H "Authorization: Bearer <your-token>" \ -d '{ "stream": true }'

The response is the patched Task row with status: 'dispatching'; the authenticated executor changes it to running after connecting. The endpoint only accepts tasks in created state on an idle session — queued tasks drain automatically in queue-position order, and busy sessions should be prompted via POST /sessions/:id/prompt (which creates and queues the task atomically).

Message Content Shape

Message content supports both plain text and structured blocks:

  • string
  • ContentBlock[]

String content example:

{ "role": "assistant", "content": "Implemented the fix and added tests." }

Structured content example:

{ "role": "assistant", "content": [ { "type": "text", "text": "Implemented the fix." }, { "type": "thinking", "thinking": "Checking edge cases before final response." } ] }

Browser Client Quick Start

import { createClient } from '@agor/core/api'; const client = createClient('http://localhost:3030', true, { socketAuthentication: { accessToken: '<your-token>' }, }); const sessions = await client.service('sessions').findAll({ query: { $limit: 20 }, }); const promptResult = await client.sessions.prompt( sessions[0].session_id, 'Summarize current progress and next steps', { stream: true } ); console.log(promptResult); // Or create the task explicitly first, then trigger execution: const task = await client.service('tasks').create({ session_id: sessions[0].session_id, full_prompt: 'Run the test suite and summarize failures', status: 'created', }); const runningTask = await client.tasks.run(task.task_id, { stream: true }); console.log(runningTask);

The WebSocket bearer is verified during every Socket.IO handshake. A socket never starts anonymous and cannot change user or tenant through a later client.authenticate() call. To rotate a browser access token while retaining the client object and its listeners, supply an accessToken getter and update its value. A healthy connection keeps its immutable authenticated authority; the next automatic or explicit transport reconnect invokes the getter and verifies the fresh token.

WebSocket Events

Real-time updates via Socket.IO:

Source Code

For TypeScript type definitions and service implementations:

Last updated on