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 an Authorization: Bearer trm_api_… key, which is bound server-side to its one agent and cannot address any other.

Agent registry

Method / pathWhoBodyResponse
GET /agentsany active user (own agents); ?all=true admin-only—{ agents: [agent] }
POST /agentsany active userdisplay_name (required), description, agent_key (optional; slug of display_name;^[a-z0-9][a-z0-9_-]{1,63}$, immutable)201 { agent }
GET /agents/:keyowner or admin—{ agent }
PATCH /agents/:keyowner or adminany of display_name, description, status (active|suspended|deleted) — agent_key is ignored if sent{ agent }
PATCH /agents/:key/owneradmin onlyowner_user_id (uuid){ agent }
GET /agents/:key/credentialsowner or admin—{ credentials: [meta] } — revoked rows included; metadata only, no hashes
POST /agents/:key/credentialsowner or adminkind (api_key|mcp_token), label, writes_enabled (default false)201 { credential, secret } — plaintext shown exactly once
DELETE /agents/:key/credentials/:idowner or admin—{ credential } with revoked_at set

Memory surface

Method / pathNotes
GET /memory/agentsAgents with memory state (bucket, counts); tenancy-scoped, ?all=true for admins.
GET /memory/agents/:key/graphAssociation 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/previewSide-effect-free ranked recall with per-source RRF contributions. query and/or mood required; overrides optional. Never reinforces.
GET /memory/agents/:key/memoriesBrowse/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/memoriesCapture (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/:idFull detail: texts, mood/hormones, lifecycle counters, immediate associations.
PATCH /memory/agents/:key/memories/:iddecay_weight (clamped 0.05–1.0), pinned.
POST …/memories/:id/reinforce · …/denforceStandard-step Hebbian strengthen/weaken.
POST …/memories/:id/archive · …/restoreLifecycle transitions.
PATCH /memory/agents/:key/edges/:edge_idWeight (clamped 0–1) + audit reason; flows to the graph projection, including removal below 0.2.
GET / PUT /memory/agents/:key/moodAgent emotional state; read any authenticated, write gated.
GET /memory/agents/:key/compartmentsCompartments for the agent.
POST /memory/agents/:key/explain-pathsAssociation 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.