API Reference
Complete REST API and WebSocket protocol for programmatic control of your agent fleet.
Base URL: http://127.0.0.1:5111 (default). All endpoints return JSON. When auth is enabled, include the session cookie or Authorization: Bearer <token> header.
Agents
List Agents
GET /api/agents
Returns all active agents. Supports optional query filters:
| Parameter | Type | Description |
|---|---|---|
project_id | string | Filter by project ID |
branch | string | Filter by git branch name |
status | string | Filter by status (planning, working, waiting, error, idle) |
# Example
curl http://127.0.0.1:5111/api/agents?status=working
# Response
[
{
"id": "a7f3",
"name": "auth-api",
"role": "backend",
"status": "working",
"task": "Add input validation to the user registration endpoint",
"working_dir": "/Users/dev/Projects/my-app",
"backend": "claude-code",
"project_id": "p1a2",
"git_branch": "feature/auth-validation",
"created_at": "2026-03-08T10:30:00Z",
"summary": "Editing src/auth/validators.py — adding email format checks",
"health_score": 92,
"owner": "admin@example.com"
}
]
Spawn Agent
POST /api/agents
| Field | Type | Required | Description |
|---|---|---|---|
role | string | No | Agent role (default from config). One of: frontend, backend, devops, tester, reviewer, security, architect, docs, general. |
task | string | Yes | The task description to send to the agent. |
working_dir | string | No | Working directory path. Must be under ~/ or /tmp. |
backend | string | No | Backend to use (default from config). |
name | string | No | Agent display name. Auto-generated if omitted. |
plan_mode | boolean | No | Enable plan mode (Claude Code only). |
project_id | string | No | Assign to a project. |
model | string | No | Model name override (Claude Code only). |
tools | string | No | Comma-separated tool restriction list (Claude Code only). |
output_mode | string | No | "tmux" (default) or "stream-json". Stream-json uses subprocess instead of tmux (non-interactive, Claude Code only). |
# Example
curl -X POST http://127.0.0.1:5111/api/agents \
-H "Content-Type: application/json" \
-d '{
"role": "backend",
"task": "Add input validation to user registration",
"working_dir": "~/Projects/my-app",
"backend": "claude-code",
"plan_mode": true
}'
# Response
{
"id": "b2c4",
"name": "backend-b2c4",
"role": "backend",
"status": "starting",
"task": "Add input validation to user registration",
"working_dir": "/Users/dev/Projects/my-app",
"backend": "claude-code",
"plan_mode": true
}
Get Agent Details
GET /api/agents/{id}
Returns full agent details including recent terminal output.
# Response includes output lines
{
"id": "a7f3",
"name": "auth-api",
"role": "backend",
"status": "working",
"output": ["line1", "line2", "..."],
"git_branch": "feature/auth-validation",
"health_score": 92,
"summary": "Editing src/auth/validators.py"
}
Kill Agent
DELETE /api/agents/{id}
Sends /exit to the agent, waits 3 seconds, then kills the tmux session. Only the agent owner or admin can kill an agent.
curl -X DELETE http://127.0.0.1:5111/api/agents/a7f3
Send Message to Agent
POST /api/agents/{id}/send
Sends a message to the agent's stdin via tmux send-keys. Maximum message length: 50,000 characters. Returns 400 for stream-json agents (non-interactive).
curl -X POST http://127.0.0.1:5111/api/agents/a7f3/send \
-H "Content-Type: application/json" \
-d '{"message": "yes, proceed with those changes"}'
Pause / Resume Agent
POST /api/agents/{id}/pause — Sends SIGTSTP to pause the agent process.
POST /api/agents/{id}/resume — Sends SIGCONT to resume a paused agent.
Restart Agent
POST /api/agents/{id}/restart
Kills the current agent and respawns with the same configuration (role, task, working directory, backend).
Bulk Actions
POST /api/agents/bulk
curl -X POST http://127.0.0.1:5111/api/agents/bulk \
-H "Content-Type: application/json" \
-d '{
"action": "pause",
"agent_ids": ["a7f3", "b2c4", "d5e6"]
}'
Supported actions: pause, resume, kill, restart.
Projects
List Projects
GET /api/projects
# Response
[
{
"id": "p1a2",
"name": "my-app",
"path": "/Users/dev/Projects/my-app",
"git_remote_url": "git@github.com:user/my-app.git",
"default_branch": "main",
"default_backend": "claude-code",
"created_at": "2026-03-01T09:00:00Z"
}
]
Create Project
POST /api/projects
curl -X POST http://127.0.0.1:5111/api/projects \
-H "Content-Type: application/json" \
-d '{
"name": "my-app",
"path": "~/Projects/my-app"
}'
The path must be a real directory under ~/ or /tmp. Git metadata (remote URL, default branch) is auto-detected.
Update Project
PUT /api/projects/{id}
curl -X PUT http://127.0.0.1:5111/api/projects/p1a2 \
-H "Content-Type: application/json" \
-d '{
"name": "my-app-v2",
"description": "Main application repository"
}'
Delete Project
DELETE /api/projects/{id}
Project Context
GET /api/projects/{id}/context — Returns project agents, branches, and recent tasks.
Project Scratchpad
GET /api/projects/{id}/scratchpad — Get project-level scratchpad notes.
POST /api/projects/{id}/scratchpad — Update project scratchpad.
Project Events
GET /api/projects/{id}/events — Project event feed (agent spawns, completions, conflicts).
Workflows (Pro)
List Workflows
GET /api/workflows
Create Workflow
POST /api/workflows
Define a DAG of agent tasks with dependency ordering:
curl -X POST http://127.0.0.1:5111/api/workflows \
-H "Content-Type: application/json" \
-d '{
"name": "Full Stack Feature",
"agents": [
{
"name": "backend-api",
"role": "backend",
"task": "Create REST endpoint for user profiles",
"backend": "claude-code"
},
{
"name": "frontend-ui",
"role": "frontend",
"task": "Build profile page component",
"backend": "claude-code",
"depends_on": ["backend-api"]
},
{
"name": "test-suite",
"role": "tester",
"task": "Write integration tests for profile feature",
"backend": "claude-code",
"depends_on": ["backend-api", "frontend-ui"]
}
]
}'
Update Workflow
PUT /api/workflows/{id} — Validates that there are no circular dependencies.
Run Workflow
POST /api/workflows/{id}/run — Executes the workflow. Agents are spawned in dependency order.
Delete Workflow
DELETE /api/workflows/{id}
Intelligence (Pro)
Parse Natural Language Command
POST /api/intelligence/command
curl -X POST http://127.0.0.1:5111/api/intelligence/command \
-H "Content-Type: application/json" \
-d '{"text": "spawn 3 backend agents on my-app to refactor the auth module"}'
# Response
{
"intent": "spawn",
"count": 3,
"role": "backend",
"project": "my-app",
"task": "refactor the auth module"
}
Fleet Insights
GET /api/intelligence/insights
Returns LLM-generated analysis of the current fleet: conflicts, stuck agents, handoff opportunities, optimization suggestions.
Authentication
Session-based authentication with bcrypt password hashing. Auth is optional — single-user setups work without it.
Check Auth Status
GET /api/auth/status
# Response (auth not required)
{"require_auth": false}
# Response (auth required)
{"require_auth": true, "user": {"email": "admin@example.com", "role": "admin"}}
Register
POST /api/auth/register
The first user to register becomes the admin and creates the organization.
curl -X POST http://127.0.0.1:5111/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "admin@example.com",
"password": "securepassword123",
"name": "Admin User"
}'
Login
POST /api/auth/login
Returns a session cookie (HttpOnly, SameSite=Strict, Secure behind HTTPS).
curl -X POST http://127.0.0.1:5111/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "admin@example.com", "password": "securepassword123"}'
Logout
POST /api/auth/logout — Clears the session cookie.
Current User
GET /api/auth/me — Returns the current authenticated user info.
Invite User (Admin, Pro)
POST /api/auth/invite
curl -X POST http://127.0.0.1:5111/api/auth/invite \
-H "Content-Type: application/json" \
-d '{"email": "dev@example.com", "name": "Developer"}'
# Response includes temporary password
{"email": "dev@example.com", "temp_password": "abc123xyz"}
List Team Members (Pro)
GET /api/auth/team — Lists all organization members.
Licensing
License Status
GET /api/license/status
# Response
{
"tier": "community",
"max_agents": 5,
"max_seats": 1,
"features": ["core"],
"expires_at": null,
"effective_max_agents": 5
}
Activate License
POST /api/license/activate — Admin only.
curl -X POST http://127.0.0.1:5111/api/license/activate \
-H "Content-Type: application/json" \
-d '{"key": "eyJhbGciOiJFZERTQSIs..."}'
Deactivate License
DELETE /api/license/deactivate — Admin only. Reverts to Community tier.
System
System Metrics
GET /api/system
# Response
{
"cpu_pct": 34.2,
"memory": {"total": 17179869184, "used": 8589934592, "pct": 50.0},
"agents_active": 3,
"agents_total": 5,
"uptime_seconds": 3600
}
Health Check
GET /api/health
{"status": "ok", "version": "1.6.1"}
Get Config
GET /api/config — Returns current runtime configuration.
Update Config
PUT /api/config — Updates config, saves to YAML, applies at runtime. Admin only when auth is enabled.
List Roles
GET /api/roles — Returns all available agent roles with names, colors, and icons.
List Backends
GET /api/backends — Returns available backends with capabilities.
Cost Estimates
GET /api/costs — Returns cost estimates for active and historical agents (heuristic based on character count).
Fleet Templates
List Templates
GET /api/fleet-templates
Create Template
POST /api/fleet-templates
curl -X POST http://127.0.0.1:5111/api/fleet-templates \
-H "Content-Type: application/json" \
-d '{
"name": "Feature Sprint",
"agents": [
{"role": "backend", "task": "Implement {feature} API endpoints"},
{"role": "frontend", "task": "Build {feature} UI components"},
{"role": "tester", "task": "Write tests for {feature}"}
]
}'
Task strings support parameterized variables: {branch}, {project_name}, {date}, and custom variables.
Update / Delete Template
PUT /api/fleet-templates/{id}
DELETE /api/fleet-templates/{id}
Deploy Template
POST /api/fleet-templates/{id}/deploy
curl -X POST http://127.0.0.1:5111/api/fleet-templates/ft1/deploy \
-H "Content-Type: application/json" \
-d '{
"project_id": "p1a2",
"variables": {"feature": "user-profiles"}
}'
Agent Extras
Trigger LLM Summary
POST /api/agents/{id}/summarize — Triggers an immediate LLM-generated summary for the agent.
Configure Auto-Handoff
POST /api/agents/{id}/configure-handoff
curl -X POST http://127.0.0.1:5111/api/agents/a7f3/configure-handoff \
-H "Content-Type: application/json" \
-d '{
"next_agent_config": {
"role": "tester",
"task": "Write tests for the changes made by {prev_agent}: {prev_summary}",
"backend": "claude-code"
}
}'
When the agent completes, Ashlr automatically spawns the next agent with the configured settings. Variables {prev_summary} and {prev_agent} are interpolated. No recursive chains are allowed.
WebSocket Protocol
Connect to ws://127.0.0.1:5111/ws for real-time updates.
Server-to-Client Messages
| Type | Description | Payload |
|---|---|---|
sync | Initial state on connection | agents, projects, config, license, effective_max_agents |
agent_update | Agent state changed | agent object with all fields |
agent_output | New terminal output lines | agent_id, lines array |
metrics | System metrics update | cpu_pct, memory, agents_active |
event | Agent event (needs input, etc.) | event name, agent_id, message |
license_update | License changed | license object, effective_max_agents |
intelligence_alert | Fleet analysis insight | insight object |
file_conflict | Two agents editing same file | conflict object with agent IDs and file path |
Client-to-Server Messages
| Type | Fields | Description |
|---|---|---|
spawn | role, name, working_dir, task, plan_mode | Spawn a new agent |
send | agent_id, message | Send message to agent |
kill | agent_id | Kill an agent |
pause | agent_id | Pause an agent |
resume | agent_id | Resume a paused agent |
Example WebSocket Client
const ws = new WebSocket('ws://127.0.0.1:5111/ws');
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
switch (msg.type) {
case 'sync':
console.log('Connected, agents:', msg.agents.length);
break;
case 'agent_update':
console.log(`Agent ${msg.agent.id}: ${msg.agent.status}`);
break;
case 'agent_output':
console.log(`Output from ${msg.agent_id}:`, msg.lines);
break;
case 'event':
if (msg.event === 'agent_needs_input') {
console.log(`Agent ${msg.agent_id} needs input: ${msg.message}`);
}
break;
}
};
// Spawn an agent via WebSocket
ws.send(JSON.stringify({
type: 'spawn',
role: 'backend',
name: 'my-agent',
working_dir: '~/Projects/my-app',
task: 'Add input validation'
}));
// Send a response to a waiting agent
ws.send(JSON.stringify({
type: 'send',
agent_id: 'a7f3',
message: 'yes, proceed'
}));
Error Responses
All endpoints return consistent error JSON:
// 400 Bad Request
{"error": "task is required"}
// 403 Forbidden (feature gated)
{"error": "Pro plan required for workflows", "feature": "workflows", "current_plan": "community"}
// 404 Not Found
{"error": "agent not found"}
// 429 Too Many Requests
{"error": "rate limit exceeded"}
Rate Limiting
The server applies rate limiting via middleware. Default limits are generous for local use but can be hit during automated scripting. Rate-limited responses return HTTP 429 with a Retry-After header.