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/docsroute now brings you back to this maintained reference instead of installing a separate documentation application on every machine.
Quick Reference
Base URL
http://localhost:3030Authentication
Agor uses JWT-based authentication:
Authorization: Bearer <your-token>Getting a Bearer Token
Use the CLI to authenticate and retrieve a token:
agor loginYou’ll be prompted for your email and password. Your token is automatically saved to ~/.agor/cli-token and is valid for 7 days.
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 itemPOST /service- Create new itemPATCH /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:
stringContentBlock[]
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);
await client.authenticate({
strategy: 'jwt',
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);WebSocket Events
Real-time updates via Socket.IO:
- WebSocket Events - Real-time event documentation
Source Code
For TypeScript type definitions and service implementations:
- TypeScript types:
packages/core/src/types - Service implementations:
apps/agor-daemon/src/services