Skip to content

Agents, revisions and skills

An agent is a name and a pointer to its active revision. That is nearly all it is. Everything that decides behaviour — the model, the prompt, the tools, the graph kind, the capability flags — lives on the revision.

The consequence is the thing to remember:

Editing an agent creates revision n+1. It never mutates revision n.

That holds for both verbs. PATCH and PUT on an agent write a new revision and repoint the agent at it. Nothing you have already run is retroactively changed, and a run that happened last month still names the exact revision that produced it.

Rolling back is activating an older revision, not editing your way back to it. The old revision is still there, byte for byte, and activating it is a single call (POST /agents/{agent_id}/revisions/{revision_number}/activate).

The same versioning rule applies to skills, toolkits and review playbooks. Anything the platform calls versioned behaves this way.

A revision declares how the agent is executed. The vocabulary is closed:

graph_kindTopologyToolsWhat it is for
react_loopSTART → agent → (tools → agent)* → ENDyesThe default. Conversation, task execution, anything iterative.
pipelineSTART → n₁ → n₂ → … → ENDnoDeterministic multi-step transformation, one prompt per step.
routerSTART → classifier → one branch → ENDyes, per branchTriage into specialised handlers.
flowAn arbitrary DAG with fan-out and fan-inno per-node loopParallel ensembles, voting, map-reduce over a list.
code_taskNot a graph — a staged executor—Sandboxed code review and editing.

Naming a tool on a pipeline node is a 422 that points you at react_loop; the kinds differ in what they permit, not only in what they draw.

code_task is worth calling out: a code task is not a separate resource. It is a run whose revision has graph_kind = 'code_task'. What you configure separately is everything the delivery resolves against — which repositories are bound, which agent reviews and which edits, the caps, and the review playbook.

A persona is an overlay applied at submission time: the same agent, in a different voice or for a different audience. It is not a copy of the agent and it does not create a revision — you pass persona_id when you submit the run.

A tool is something an agent can do; a toolkit is a named bundle of them.

A fresh deployment seeds sixteen tools, and every one of them is kind: builtin. A builtin may not be named in a revision’s tools[]. If you try, you get a 422 that names the flag instead:

'web_search' is a builtin granted by the 'web' capability flag;
set capabilities.web instead of naming it in tools[]

So there are exactly two routes to an agent that can do something:

  1. Set a capability flag. GET /system/capabilities lists every flag with what it grants and what it requires. A flag whose requires is non-empty is refused with capability_provider_unconfigured until that prerequisite is met. Most are the deployment’s: memory needs an embedder, web needs a search provider, code needs a sandbox. image_generation is the tenant’s: it needs an image or OpenRouter key stored as a workspace or organization secret (PROVIDER_IMAGE_API_KEY or PROVIDER_GATEWAY_API_KEY). self_scheduling requires nothing, which makes it the one flag that works on a stock install.
  2. Register your own tool. POST /tools creates a tool of a non-builtin kind, and that one may be named in tools[].

Reading tools[] alongside the seeded catalogue and assuming they intersect is the most common first 422. On a default install, they do not.

Before you save a tool, testing it invokes it with sample input, resolving secrets and redacting the output — so a misconfigured URL is found at authoring time rather than mid-run. Discovery (probing a remote tool-protocol server for its catalogue) and import (adopting that catalogue) are separate calls on purpose: reading a third party’s catalogue and adopting it are different decisions.

A skill is a named, versioned piece of instruction an agent can be given — how refunds are handled, what tone to use with a regulator. Editing one bumps its version and writes a revision, so what an agent was told last month is still readable, and reverting is a call (POST /skills/{skill_id}/revert/{revision_number}) rather than a paste.

A knowledge base holds items, the edges between them, and the grants that let one agent read another agent’s base.

Every item carries a curation state: pending, reviewed, promoted, superseded, retired. The property that makes agent writes safe is a single absence:

Retrieval cannot see pending.

A model may propose a fact into shared memory and no other run will read it until a human promotes it. Nothing else in the design is load-bearing for that guarantee — the invisibility of pending is.

Importing into a base is asynchronous: the call returns an ingest job, and the job is what you poll. Deleting a base cascades to its items, edges, grants and jobs.

Import and export round-trip the same declarative document, so an agent can be moved between deployments as a file: GET /agents/{agent_id}/export, then POST /agents/import on the other side.