Api / Agents

POST/v1/agents

Auth: tenant — Status: stable

Create a stored agent for this tenant. The id is caller-chosen — typically a UUID owned by the sibling service. Two tenants may independently use the same id without collision.

Stored agents are visible from the agents catalog, addressable from /agent and /parallel slash commands inside other agents' turns, and snapshotted onto conversations created against them.

Request

Body

Either a bare constitution or wrapped under agent_def:

{
  "id": "researcher",
  "name": "Researcher",
  "role": "researcher",
  "model": "claude-sonnet-4-6",
  "goal": "answer one factual question in one short paragraph",
  "brevity": "bullets",
  "max_tokens": 256,
  "temperature": 0.2,
  "rules": [],
  "capabilities": ["research"]
}
FieldTypeRequiredConstraint
idstringyes[A-Za-z0-9_-]{1,64}, unique per tenant, id != "index". Becomes a path component for the file scratchpad and a token in slash-command syntax.
namestringyesFree-form display name.
rolestringyesShort role descriptor (e.g. "code reviewer").
modelstringyesRouted by arbiter's provider prefix table — see GET/v1/models.
goalstringyesWhat this agent is trying to accomplish. Goes into its system prompt.
brevitystringno"lite" | "full" | "ultra". Default "full".
max_tokensintnoResponse cap per turn. Default 1024.
temperaturenumberno0.0–2.0. Default 0.3.
rulesarray<string>noBehavioural constraints appended to the system prompt.
capabilitiesarray<string>noTools this agent uses. Used by master for routing.
modestringno"" / "standard" (default) or "writer".
advisorobject | stringnoAdvisor configuration. Object form: {model, prompt?, mode?, max_redirects?, malformed_halts?}. String form is treated as {model: <s>, mode: "consult"} (back-compat). See advisor concept.
advisor_modelstringnoLegacy. Higher-capability model for /advise consults. New configurations should use advisor.model instead. If both advisor and advisor_model are present, the structured advisor block wins.
memoryobjectnoPer-agent memory enrichment toggles for /mem search and /mem add entry. See schema below and Memory enrichment in the structured-memory concept.
personalitystringnoFree-form personality overlay.

advisor object schema

Sub-fieldTypeDefaultNotes
modelstring(required when mode != "off")Higher-capability model used for consults and gate decisions.
modestring"consult""off" disables both consult and gate; "consult" makes /advise available to the executor; "gate" additionally gates the executor's terminating turn — the runtime calls the advisor with the executor's output and a tool summary, and only returns to the caller on a CONTINUE signal. See advisor concept.
promptstringbuilt-inOverride the gate's system prompt. Only consulted in mode: "gate".
max_redirectsint2Cap on how many REDIRECT signals the gate can issue per top-level turn before the runtime synthesises a HALT.
malformed_haltsbooltrueWhether an unparseable advisor reply should be treated as HALT (true — fail-closed) or CONTINUE (false — fail-open).

memory object schema

Controls advisor-driven enrichment on this agent's /mem operations. Every field is optional; absent fields fall through to the documented default. The advisor-driven toggles (search_expand, auto_tag, auto_supersede) need an advisor.model configured — without one they silently no-op.

Sub-fieldTypeDefaultNotes
search_expandboolfalseOn /mem search: call the advisor once to generate 2 paraphrases of the query, run all 3 variants through FTS, RRF-fuse the rankings. No-embedding alternative to dense retrieval. ~150 ms + ~$0.0001 per search at Haiku speeds.
auto_tagboolfalseOn /mem add entry: advisor extracts 2-4 lowercase hyphenated tags from title + content before storage. Tags get an 8× weight in the BM25 ranking, so this is one of the strongest no-cost ways to lift retrieval signal on agent ingest paths.
auto_supersedeboolfalseOn /mem add entry: after the new entry is created, advisor inspects the top-5 same-type FTS hits on the new title for direct contradictions and stamps valid_to=now() on flagged ids. Bias is conservative — false positives erase legitimate prior memory.
intent_routingbooltrueOn /mem search: heuristic regex-based question-intent classifier maps cue words ("favorite", "when", "how to", …) to memory-entry type boosts via the existing 1.3× BM25 multiplier. Caller-supplied type= always wins. Zero LLM cost; defaults on because the worst case is "no boost applied" (monotonic vs. off).
curl -X POST \
  -H "Authorization: Bearer atr_…" \
  -H "Content-Type: application/json" \
  -d '{"id":"researcher","name":"Researcher","role":"researcher","model":"claude-sonnet-4-6","goal":"answer factual questions"}' \
  http://arbiter.example.com/v1/agents

Response

201 Created

The stored agent with created_at / updated_at. The full blob is persisted; the response is rendered by re-parsing it through Constitution::from_json, so what comes back is exactly what's stored.

{
  "id": "researcher",
  "name": "Researcher",
  "role": "researcher",
  "model": "claude-sonnet-4-6",
  "goal": "answer factual questions",
  "brevity": "full",
  "max_tokens": 1024,
  "temperature": 0.3,
  "rules": [],
  "capabilities": [],
  "created_at": 1777060001,
  "updated_at": 1777060001
}

Failure modes

StatusWhenBody
400Body isn't a valid constitution (Constitution::from_json failed); id missing / malformed; id == "index".{"error": "..."}
401Missing / invalid bearer; tenant disabled.{"error": "..."}
409Duplicate id for this tenant.{"error": "agent '<id>' already exists for this tenant", "existing": { ...AgentRecord... }}

To replace an existing stored agent, use PATCH/v1/agents/:id.

See also