Developer Reference
M3SHD Docs
Multi-Agent AI Mesh — API & Setup Reference
Authorization: Bearer <token> unless noted. Tokens are issued by POST /api/admin/tokens (master token only). The master token is set via the M3SHDUP_TOKEN environment variable. All request and response bodies are JSON.
01 Quick Start
Three steps: deploy the Commander, register a N0D3, submit a task.
Deploy the Commander
Clone the repo and create a .env file alongside docker-compose.yml.
Verify the Commander is up:
Issue a Worker Token
Start a Worker
Submit a Task
Poll for completion or subscribe to GET /api/stream for real-time status events.
02 Agents
Agents self-register and send periodic heartbeats. The Commander tracks status (online / busy / offline) and uses capabilities for task routing.
| Method | Path | Permission | Description |
|---|---|---|---|
| POST | /api/agents/{agent_id}/register |
any valid token | Register or re-register an agent with capabilities |
| POST | /api/agents/{agent_id}/heartbeat |
any valid token | Keep agent alive; transitions offline → online |
| GET | /api/agents |
agents:read |
List all registered agents and their status |
| DELETE | /api/agents/{agent_id} |
agents:delete |
Remove an agent from the registry |
| POST | /api/agents/{agent_id}/fcm-token |
agent's own token | Update Firebase push token (mobile workers only) |
| GET | /api/agents/{agent_id}/reputation |
any valid token | UCB reputation score per capability |
| GET | /api/admin/reputation/leaderboard |
master token | Ranked leaderboard across all agents |
Register Body
Note
An agent token may only register/heartbeat for its own agent_id. The master token can act on behalf of any agent.
03 Tasks
Tasks are the unit of work. The Commander dispatches each task to the best available agent based on capabilities and reputation score. Task prompts and outputs are encrypted at rest.
| Method | Path | Permission | Description |
|---|---|---|---|
| POST | /api/tasks |
tasks:create |
Create and dispatch a task |
| GET | /api/tasks |
tasks:read |
List tasks (agents see only their own) |
| GET | /api/tasks/{id} |
tasks:read |
Get a single task with dependencies |
| PUT | /api/tasks/{id} |
tasks:update |
Update status or output (agents call this to report) |
| GET | /api/tasks/{id}/deps |
tasks:read |
List dependency tasks for a task |
| POST | /api/tasks/{id}/stream |
agent's own token | Append a live output chunk to the task stream log |
| POST | /api/tasks/{id}/handoff |
tasks:update |
Re-assign a task to another agent |
| POST | /api/tasks/{id}/verify |
master token | Manually mark a task as verified |
| GET | /api/tasks/{id}/provenance |
master token | HMAC-SHA256 provenance chain for this task |
Create Task Body
Update Task Body
N0D3S call PUT /api/tasks/{id} to report progress. The Commander auto-extracts [REMEMBER] blocks from the output when status reaches done or failed.
List Tasks — Query Params
| Param | Type | Description |
|---|---|---|
status | string | Filter by status (e.g. assigned) |
assigned_to | string | Filter by agent name |
limit | int | Max results, capped at 100 (default 20) |
compact | bool | Truncate prompt/output to 200 chars |
Access Control
Non-master agent tokens only see tasks they are assigned to or created. The Commander returns 404 (not 403) for tasks the caller doesn't own to avoid leaking task existence.
04 Pipelines
A pipeline is a list of tasks submitted atomically, where each task can declare a dependency on a previous task by its 0-based index in the tasks array. Tasks with no unmet dependencies are dispatched immediately; blocked tasks become queued until their dependency completes.
| Method | Path | Permission | Description |
|---|---|---|---|
| POST | /api/pipelines |
pipelines:create |
Create a dependency-chained pipeline of tasks |
Pipeline Body
Returns {"tasks": [...], "count": N} — the full list of created task objects. Max 50 tasks per pipeline.
Task Templates
Templates allow one-tap dispatch of recurring workflows without writing prompts each time.
| Method | Path | Description |
|---|---|---|
| POST | /api/templates | Create a template |
| GET | /api/templates | List templates |
| GET | /api/templates/{id} | Get a template |
| DELETE | /api/templates/{id} | Delete a template |
| POST | /api/templates/{id}/dispatch | Dispatch a task from template |
05 Memory
Each agent has a persistent key-value memory store backed by SQLite FTS5. Memory entries are encrypted at rest. The Commander auto-injects relevant memories into task prompts before dispatch, and auto-extracts [REMEMBER] key: value [/REMEMBER] blocks from task output.
| Method | Path | Permission | Description |
|---|---|---|---|
| POST | /api/agents/{id}/memory |
memory:write |
Store or overwrite a memory entry |
| GET | /api/agents/{id}/memory |
memory:read |
List memories; add ?q= for FTS search |
| GET | /api/agents/{id}/memory/{key} |
memory:read |
Get a specific memory entry by key |
| DELETE | /api/agents/{id}/memory/{key} |
memory:write |
Delete a memory entry |
Store Memory
Auto-Extraction via [REMEMBER]
Include a [REMEMBER] block anywhere in task output. The Commander parses it when the task reaches done or failed:
Limits
Max 20 [REMEMBER] blocks per task output. Key max 120 chars, value max 4000 chars. Keys matching security-sensitive patterns (token, password, api_key, etc.) are blocked to prevent prompt injection attacks writing to the memory store.
06 Messages
The messages API is a simple channel-based chat bus. N0D3S post status updates; the Commander app reads them. All participants subscribe to the SSE stream for real-time delivery.
| Method | Path | Permission | Description |
|---|---|---|---|
| POST | /api/messages |
messages:write |
Send a message to a channel |
| GET | /api/messages |
messages:read |
Retrieve message history |
Send Message
07 Webhooks
Webhooks let external systems trigger tasks without holding a long-lived bearer token. Each webhook has a generated secret and an optional template binding. Inbound webhooks are rate-limited per name.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/admin/webhooks |
master token | Create a webhook |
| GET | /api/admin/webhooks |
master token | List webhooks |
| DELETE | /api/admin/webhooks/{name} |
master token | Delete a webhook |
| POST | /api/webhooks/{name} |
X-Webhook-Secret header | Trigger webhook (custom or Uptime Kuma) |
| POST | /api/webhooks/{name}/github |
X-Hub-Signature-256 | Trigger from GitHub event (HMAC-validated) |
Create Webhook
08 Admin
Admin endpoints manage users, tokens, audit logs, peer federation, and system analytics. Most require the master token or admin:* permissions.
Users
| Method | Path | Description |
|---|---|---|
| POST | /api/admin/users | Create a user account |
| GET | /api/admin/users | List users |
| PUT | /api/admin/users/{id} | Update user (role, password, enabled) |
| DELETE | /api/admin/users/{id} | Delete a user |
Tokens
| Method | Path | Description |
|---|---|---|
| POST | /api/admin/tokens | Issue an agent token (master only) |
| GET | /api/admin/tokens | List tokens (hashes redacted) |
| PUT | /api/admin/tokens/{hash}/permissions | Update token permissions |
| DELETE | /api/admin/tokens/{hash} | Revoke a token |
| GET | /api/admin/roles | List role presets and their permissions |
Audit Log
| Method | Path | Description |
|---|---|---|
| GET | /api/admin/audit | Query audit log (?limit=, ?actor=, ?action=) |
Analytics
| Path | Description |
|---|---|
/api/admin/analytics/tasks | Task volume and completion rates over time |
/api/admin/analytics/costs | Daily Claude API cost breakdown |
/api/admin/analytics/agents | Per-agent task counts and success rates |
/api/admin/analytics/metacognition | Confidence score distribution |
/api/admin/analytics/summary | High-level system summary |
Federation Peers
| Method | Path | Description |
|---|---|---|
| POST | /api/admin/peers | Register a peer hub |
| GET | /api/admin/peers | List peer hubs |
| DELETE | /api/admin/peers/{name} | Remove a peer |
| POST | /api/admin/peers/{name}/ping | Test peer connectivity |
| POST | /api/federation/tasks | Accept a task relayed from a peer |
| GET | /api/federation/status | Federation health and peer list |
09 Health & SSE
Health Check
SSE Stream
Subscribe to GET /api/stream to receive all Commander events in real-time. The connection is long-lived; the Commander sends a keepalive event every 30 seconds and caps the per-subscriber queue at 500 events.
Live task stream
POST /api/tasks/{id}/stream lets a worker push incremental output chunks. Clients subscribed to /api/stream receive each chunk as a task_stream event, enabling a live console view of long-running Claude tasks.
10 Worker Setup
mesh-worker.py is a zero-dependency Python script (stdlib only) that polls the Commander for assigned tasks and executes them via the Claude CLI. It self-registers on startup and sends a heartbeat every 30 seconds.
Requirements
- Python 3.9+ (no third-party packages — stdlib only)
- Claude CLI installed and authenticated (
claude --versionmust work) - A valid worker or agent token from
POST /api/admin/tokens - Network access to the Commander URL
CLI Reference
Capabilities
Capabilities are free-form strings. The Commander routes tasks to N0D3S whose capability list contains the task's required_capability. The N0D3 also has per-capability timeout overrides:
| Capability | Default Timeout | Description |
|---|---|---|
research | 30 min | General research, analysis, writing |
web_search | 30 min | Internet search tasks |
code_write | 30 min | Code generation and refactoring |
file_ops | 15 min | File system operations |
git | 15 min | Git commits, PRs, rebases |
docker | 15 min | Container builds and restarts |
deploy | 15 min | VPS deploys and config changes |
Agent Mode vs. Print Mode
Without --agent-mode, the N0D3 runs claude --print <prompt> — Claude responds with text only. With --agent-mode, it runs claude -p <prompt> --dangerously-skip-permissions — Claude has full tool access (file reads, bash, etc.) and streams output chunks back to the Commander in real time.
Agent mode security
--dangerously-skip-permissions means Claude can run arbitrary shell commands on the worker machine. Only use agent mode on machines you trust and where the Claude CLI is the primary operator. Never run agent mode as root.
Failure & Escalation
When a task fails, the N0D3 retries up to 3 times. On the third failure it calls POST /api/escalations to notify the Commander and posts a message to the general channel. The Commander operator can then investigate via the audit log or reassign the task.
Running as a Service
11 Pi Deployment
A Raspberry Pi 5 makes an effective edge N0D3 — low power, always-on, Tailscale-connected. The setup below produces a headless N0D3 that starts automatically on boot.
1 — Flash Pi OS Lite
Use Raspberry Pi Imager to flash Pi OS Lite 64-bit (no desktop). In the advanced settings, configure your SSH key, hostname, and Wi-Fi credentials before writing. This avoids needing a monitor at any point.
2 — Install Tailscale
3 — Install Claude CLI
4 — Deploy the Worker
5 — Create systemd Service
Verify
Once the N0D3 starts, hit GET /api/agents on the Commander — the Pi node should appear as online within a few seconds of the service starting.
12 Security
Authentication
All API endpoints require Authorization: Bearer <token>. Three token types exist:
| Type | How Created | Scope |
|---|---|---|
| Master token | M3SHDUP_TOKEN env var |
Full access — all endpoints, all agents |
| Agent token | POST /api/admin/tokens |
RBAC-scoped — only what the role allows |
| Session cookie | POST /api/login (browser) |
User-scoped, for the web dashboard |
Agent tokens are stored as SHA-256 hashes in the database — the raw token is shown only once at creation time. Tokens are prefixed m3shd_ag_ and are 32 hex chars of entropy (128 bits).
RBAC Roles
Named roles are permission bundles. The master token can also issue tokens with a custom explicit permission list.
| Role | Permissions |
|---|---|
| worker | tasks:read, tasks:execute, tasks:update, messages:read, messages:write, agents:read, agents:register, memory:read, memory:write, escalations:create |
| mobile | Same as worker minus escalations:create |
| commander | tasks:read, tasks:create, messages:read, messages:write, agents:read, escalations:read, admin:templates, pipelines:create |
| admin | All permissions |
Empty permissions = no access
A token with an empty permission list has zero access beyond basic auth. This is intentional — there is no implicit "read-all" grant. Every capability must be explicitly listed in the token's permission set.
Encryption at Rest
Task prompts, task outputs, and agent memory values are encrypted at rest using Fernet symmetric encryption (AES-128-CBC + HMAC-SHA256). The encryption key is derived from M3SHDUP_ENCRYPT_KEY. If that variable is not set, the system falls back to M3SHDUP_TOKEN — set a dedicated key in production.
The system supports key rotation via M3SHDUP_LEGACY_ENCRYPT_KEY. Rows encrypted under the old key are re-encrypted on next read using a MultiFernet approach.
Token Budgets
The Commander enforces a per-day Claude API cost cap configurable via M3SHDUP_DAILY_COST_CAP (default $5.00). Task creation and webhook dispatch return HTTP 429 when the cap is reached. N0D3S also track per-agent daily token usage, capped at 500k tokens/day per agent.
Audit Log
Every write operation — token creation, task creation, memory writes, agent registration, user changes — is appended to an immutable audit log. Query it via GET /api/admin/audit with optional ?actor= and ?action= filters.
Kill Switch
The kill switch halts all new task creation instantly without taking the Commander offline. Activate via the admin dashboard or directly via the kill switch API. Existing running tasks complete; no new tasks are accepted until the switch is cleared.
13 Configuration
The Commander is configured entirely via environment variables. Set them in a .env file at the project root — Docker Compose picks it up automatically.
| Variable | Required | Default | Description |
|---|---|---|---|
M3SHDUP_TOKEN |
yes | — | Master API token. All Commander management operations require this. |
M3SHDUP_ENCRYPT_KEY |
recommended | falls back to TOKEN | Fernet encryption key for prompts, outputs, and memory. Use a random 32-char string. |
M3SHDUP_LEGACY_ENCRYPT_KEY |
no | — | Old key for transparent re-encryption during key rotation. |
M3SHDUP_DAILY_COST_CAP |
no | 5.00 |
USD daily Claude API spend ceiling. Task creation fails with 429 when hit. |
M3SHDUP_NTFY_URL |
no | https://ntfy.gritwerk.com |
ntfy server URL for push alerts (agent down, cost budget, escalations). |
M3SHDUP_NTFY_TOPIC |
no | mediaserver-b0c64542 |
ntfy topic name. |
M3SHDUP_ALERTS_ENABLED |
no | true |
Set to false to disable all ntfy notifications. |
M3SHDUP_DEMO_ENABLED |
no | false |
Enable the read-only demo endpoints (/api/demo/*) with synthetic data. |
Worker Environment Variables
| Variable | Default | Description |
|---|---|---|
M3SHDUP_HUB | http://localhost:8333 | Hub base URL |
M3SHDUP_AGENT_TOKEN | — | Agent bearer token (preferred over M3SHDUP_TOKEN) |
M3SHDUP_AGENT_NAME | worker | Agent name used for registration |
M3SHDUP_MACHINE | system hostname | Machine identifier label |
M3SHDUP_MAX_CONCURRENT | 1 | Max parallel Claude invocations |
M3SHDUP_CAPABILITIES | research | Comma-separated capability list |
M3SHDUP_EXCLUDED | — | Comma-separated capabilities to refuse |
M3SHDUP_CLAUDE_TIMEOUT | 1800 | Per-task Claude timeout in seconds |
M3SHDUP_AGENT_MODE | false | Set to true to use claude -p with tool access |
Database
SQLite WAL database at data/m3shdup.db relative to the project root. Mount ./data as a Docker volume to persist across container rebuilds. WAL mode is enabled on startup for concurrent read performance.
14 Webhook Integration
Custom Webhooks
Create a webhook via the admin API, then send a POST to /api/webhooks/{name} with the webhook secret in the X-Webhook-Secret header (or ?secret= query param).
GitHub Integration
Point a GitHub webhook at /api/webhooks/{name}/github. The Commander validates the X-Hub-Signature-256 HMAC header using the webhook secret. Supported events: pull_request, issues, push.
Uptime Kuma Integration
Uptime Kuma payloads are auto-detected on /api/webhooks/{name}. Point a Kuma monitor notification at the webhook URL with the secret in the header. The Commander parses the heartbeat and monitor fields and dispatches an alert task automatically.
Federation
Two M3SHD Commander instances can exchange tasks via federation. Each Commander registers the other as a peer with a shared token. The sending Commander calls POST /api/federation/tasks on the receiving Commander; the receiving Commander validates the federation token (constant-time compare), enforces the daily cost cap, and dispatches the task locally. Relay chains are capped at 3 hops to prevent loops.