REST API
Base URL: https://therobot.is/api/v1 (self-hosted: your deployment's origin). All bodies are JSON; all single-entity responses are wrapped ({ "agent": … }, { "memory": … }, { "credential": … }).
Authentication
Two bearer schemes, by surface:
- Management (
/api/v1/agents, credentials CRUD): your Guardian JWT from register/login — machine keys never manage agents or credentials. - Memory (
/api/v1/memory/agents/:key/…): either the owner's/admin's JWT, or anAuthorization: Bearer trm_api_…key, which is bound server-side to its one agent and cannot address any other.
Agent registry
| Method / path | Who | Body | Response |
|---|---|---|---|
GET /agents | any active user (own agents); ?all=true admin-only | — | { agents: [agent] } |
POST /agents | any active user | display_name (required), description, agent_key (optional; slug of display_name;^[a-z0-9][a-z0-9_-]{1,63}$, immutable) | 201 { agent } |
GET /agents/:key | owner or admin | — | { agent } |
PATCH /agents/:key | owner or admin | any of display_name, description, status (active|suspended|deleted) — agent_key is ignored if sent | { agent } |
PATCH /agents/:key/owner | admin only | owner_user_id (uuid) | { agent } |
GET /agents/:key/credentials | owner or admin | — | { credentials: [meta] } — revoked rows included; metadata only, no hashes |
POST /agents/:key/credentials | owner or admin | kind (api_key|mcp_token), label, writes_enabled (default false) | 201 { credential, secret } — plaintext shown exactly once |
DELETE /agents/:key/credentials/:id | owner or admin | — | { credential } with revoked_at set |
Memory surface
| Method / path | Notes |
|---|---|
GET /memory/agents | Agents with memory state (bucket, counts); tenancy-scoped, ?all=true for admins. |
GET /memory/agents/:key/graph | Association subgraph. Params: compartment, min_weight (default 0.2), hops,seed, limit (default 500). Only nodes owned by the agent; only edges whose both endpoints are owned. |
POST /memory/agents/:key/recall/preview | Side-effect-free ranked recall with per-source RRF contributions. query and/or mood required; overrides optional. Never reinforces. |
GET /memory/agents/:key/memories | Browse/search list. Filters: q (trigram), content_type, state, compartment, domain, pinned, occurred_after/before; sort occurred_at | salience | last_recalled_at. Keyset-paginated (below). |
POST /memory/agents/:key/memories | Capture (write gate). content required; owner forced to the path agent. 201, or 202 with status: "quarantined" when the Guardian holds the write. |
GET /memory/agents/:key/memories/:id | Full detail: texts, mood/hormones, lifecycle counters, immediate associations. |
PATCH /memory/agents/:key/memories/:id | decay_weight (clamped 0.05–1.0), pinned. |
POST …/memories/:id/reinforce · …/denforce | Standard-step Hebbian strengthen/weaken. |
POST …/memories/:id/archive · …/restore | Lifecycle transitions. |
PATCH /memory/agents/:key/edges/:edge_id | Weight (clamped 0–1) + audit reason; flows to the graph projection, including removal below 0.2. |
GET / PUT /memory/agents/:key/mood | Agent emotional state; read any authenticated, write gated. |
GET /memory/agents/:key/compartments | Compartments for the agent. |
POST /memory/agents/:key/explain-paths | Association paths between owned memories ({ from, to: [...] }). |
Errors
422— validation, as a per-field map:{ "errors": { "agent_key": ["has invalid format"] } }.404—{ "error": "not found" }. At the agent level, unknown and foreign keys are deliberately the same answer — no existence leak.403— authorization. A write against a recall-only credential returns exactly{ "error": "writes are off for this credential" }.401— missing/invalid bearer (or revoked credential).
Pagination
Only GET …/memories is paginated (keyset): limit (default 50, cap 200) and an opaque cursor. The response carries next_cursor — pass it back verbatim; null means the last page. Orderings are total orders (id tiebreaker), so pages neither skip nor repeat rows; an unparseable cursor returns an empty page rather than restarting, so a paging client terminates.