API ReferenceOverview

API Reference

Interactive REST API documentation auto-generated from the Agor daemon.

📚 Interactive API Docs

The Agor daemon serves live, interactive API documentation via Swagger UI:

Start your daemon:

agor daemon start

Then visit:

→ http://localhost:3030/docs/

Agor REST API interactive documentation with Swagger UI showing endpoints for sessions, worktrees, boards, and real-time collaboration

Features:

  • Always up-to-date - Generated from actual service definitions
  • Try it out - Execute API calls directly from the browser
  • Dark mode - Easy on the eyes
  • Full schema - Request/response models for all endpoints

Quick Reference

Base URL

http://localhost:3030

Authentication

Agor uses JWT-based authentication:

Authorization: Bearer <your-token>

Getting a Bearer Token

Use the CLI to authenticate and retrieve a token:

agor login

You’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>"

Using the token in Swagger UI:

  1. Visit http://localhost:3030/docs/
  2. Click the “Authorize” button (🔒 icon in top-right)
  3. Paste your Bearer token in the input field
  4. Click “Authorize”
  5. Now all generated curl commands and “Try it out” buttons will automatically include your token

Authentication is always required. On first daemon start, an admin user is auto-created with a random password — 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 worktree operations
  • /boards - Spatial organization of sessions with zones and triggers
  • /worktrees - Git worktree 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": "running",
  "streaming": true
}
{
  "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: 'running'. 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);
 
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:

Source Code

For TypeScript type definitions and service implementations:

BSL 1.1 © 2026 Maxime Beauchemin