Skip to content

Assistant Config API

Version-control instructions and Agent Graphs, and push them from CI.

Authentication is a project API key (Dashboard → Assistant → API Keys) sent as a bearer token. Two scopes govern access:

Scope Grants
assistant:read GET the configuration
assistant:write PATCH the configuration

These are deliberately separate from ingest, so a content-ingestion credential can never rewrite the prompt that governs the assistant’s behaviour. See API Keys for issuing and scoping keys.

GET /api/v1/projects/{projectId}/assistant

Section titled “GET /api/v1/projects/{projectId}/assistant”
Terminal window
curl https://your-ragtime-instance.com/api/v1/projects/{projectId}/assistant \
-H "Authorization: Bearer rt_live_..."
{
"assistant": {
"customInstructions": "You are a calm, precise guide…",
"openingInstructions": "Greet the user and ask what they are working on.",
"openingInstructionsLiteral": false,
"agentGraph": { "entryNodeId": "intake", "nodes": [] },
"persona": "",
"updatedAt": "2026-07-30T09:12:44.000Z"
}
}

persona is read-only here; switch personas in the dashboard.

PATCH /api/v1/projects/{projectId}/assistant

Section titled “PATCH /api/v1/projects/{projectId}/assistant”

Partial by design — only the fields you send are written, so a pipeline that owns the prompt does not have to round-trip settings it does not manage.

Terminal window
curl -X PATCH https://your-ragtime-instance.com/api/v1/projects/{projectId}/assistant \
-H "Authorization: Bearer rt_live_..." \
-H "Content-Type: application/json" \
-d '{
"customInstructions": "You are a calm, precise guide…",
"agentGraph": {
"entryNodeId": "intake",
"nodes": [
{
"id": "intake",
"name": "Intake",
"instructions": "Establish what the user is trying to achieve…",
"toolIds": [],
"edges": [{ "id": "e1", "toNodeId": "capabilities", "label": "They are ready to scope capabilities" }]
},
{
"id": "capabilities",
"name": "Capabilities",
"instructions": "One relevance threshold applies to the whole list…",
"toolIds": [],
"edges": []
}
]
}
}'

Accepted fields: customInstructions, openingInstructions, openingInstructionsLiteral, agentGraph. Anything else is rejected rather than ignored, so a typo’d field in a deploy script fails loudly instead of silently doing nothing.

Validation:

  • customInstructions ≤ 7,500 characters; openingInstructions ≤ 2,000.
  • agentGraph node instructions are uncapped.
  • Structural problems are errors, not warnings: a missing entry node or an edge pointing at a node that does not exist is a 400. (The dashboard can show these next to the canvas; an API caller has no canvas to look at.)
  • agentGraph: null, or a graph with no nodes, clears the graph and returns the assistant to single-prompt behaviour.

The cached system prompt is recompiled before the response returns, so the next chat turn cannot be served from instructions the request just replaced.

Status Meaning
401 Missing or invalid API key, or the key lacks assistant:read / assistant:write.
403 The key belongs to a different project than the one in the path.
400 Malformed JSON, an unknown field, or a value that fails validation.
500 The configuration was saved but the system prompt could not be recompiled.

A 500 here means the stored configuration is current but the compiled prompt is stale — the previous prompt is served until the next successful save, so retry the PATCH rather than treating it as a no-op.

Putting instructions in code is worth doing mainly because it lets you assert on them. Two tests worth writing for any assistant that describes a UI:

  1. Content tests — the instructions you serve for each step name the controls that exist and do not name ones that do not. These catch a regression at edit time.
  2. A transcript test — ask a question late in a step, not on the first turn, and assert the answer still names the real controls. This is the one that catches context decay; a first-turn test passes even when the material is no longer reaching the model on turn five.
  • Dynamic Instructions — what belongs in these fields, and when to send instructions per request instead.
  • API Keys — issuing keys and choosing scopes.