Dynamic Instructions
Keep an assistant’s instructions in your own codebase instead of only in the Ragtime dashboard — sending the detail that changes with each screen or step at request time, and carrying reference material fetched by an action across turns.
Why System Instructions are capped at 7,500 characters
Section titled “Why System Instructions are capped at 7,500 characters”The cap is a design signal, not a technical ceiling. A prompt that outgrows it has almost always stopped being a description of behaviour and started carrying content — the specifics of six different screens, a policy document, a product catalogue.
That is a problem before it is a size problem. Everything in System Instructions is sent on every request, whether or not it is relevant to what the user just asked, and when the available space is divided across many topics each one gets a couple of lines. The model does not report a thin section; it fills the gap with whatever is plausible for that kind of screen. The result is an assistant that confidently describes a checkbox or a slider that does not exist.
So when you hit the cap, the fix is not a bigger box. It is to decide which of your text is behaviour and which is content:
| Kind of text | Where it belongs |
|---|---|
| Tone, pacing, prohibitions, escalation rules | System Instructions (dashboard) |
| Detail that changes with the screen or step | instructionOverrides per request, or a conversation stage |
| Reference material the user may ask about | A knowledge source (RAG) |
| Data fetched live during the conversation | An action, with persistResult when it must persist |
None of the last three are bound by the 7,500-character limit.
Per-request instructions (instructionOverrides)
Section titled “Per-request instructions (instructionOverrides)”Send instructions with each chat request. The dashboard keeps the durable behaviour; your application appends whatever depends on where the user currently is. Your text lands in the system prompt with full authority — it is not tool output the model may weigh as ordinary data.
Enabling it
Section titled “Enabling it”- Deployment → Embedding → Additional Permissions → Injection must be on.
- Request signing must be on (Deployment → Embedding → Security), and every
request carrying
instructionOverridesmust be signed with your Signing Secret. Unsigned overrides are ignored. - Injected instructions pass the same safety check as published ones; a
flagged payload is refused with a
422.
Sending it
Section titled “Sending it”From your backend, sign each request: add a timestamp query parameter and
send X-Ragtime-Signature, an HMAC-SHA256 of the sorted query string followed by
the raw JSON body (see Embedding).
A request without a snapshotId is served the published version of the
assistant; only signed-in members of your organisation (the dashboard preview)
are ever served the unpublished draft.
POST /api/chat/stream?timestamp=1760000000000X-Ragtime-Signature: <hex HMAC-SHA256>{ "projectId": "…", "message": "How do I take this capability out of scope?", "messages": [...], "instructionOverrides": { "customInstructions": { "value": "STAGE: Capabilities.\nControls on this screen: a single relevance threshold that applies to the whole list. There is no per-capability slider and no per-capability checkbox.", "mode": "append" } }}mode: "append"adds your text after the stored instructions — the usual choice, since the dashboard keeps owning tone and prohibitions.mode: "replace"substitutes them entirely.openingInstructionsmay be overridden the same way (cap: 2,000 characters).
The 7,500-character limit applies per request, not in aggregate. One stage’s detail gets the whole budget, so splitting six stages across six requests gives you roughly six times the room — and each request carries only what is relevant.
To pass the same overrides from an embedded chat rather than from your own backend, see Chat Injection.
Both transports honour it
Section titled “Both transports honour it”Text chat and realtime/voice sessions apply the same overrides with the same gating. For an embedded chat, deliver them through the embed (Chat Injection): Ragtime verifies them when the page loads and the voice session picks them up from there. They are validated before a voice session connects, so a rejected payload never opens a billable session.
Before 2026-07, only the text pipeline honoured instructionOverrides —
realtime silently ignored them. If you built around that, you can remove the
workaround.
Per-step instructions (conversation stages)
Section titled “Per-step instructions (conversation stages)”When the conversation moves through a fixed set of steps, conversation stages
are usually a better fit than injection. Each stage carries its own
instructions (up to 2,000 characters) and its own subset of actions, and the
model moves between them via generated transfer_to_<stage> handoffs.
See Conversation Stages for the conceptual model and guidance on when to use it instead of an Action or Operational Workflow.
When your host application owns the step (for example, users move through your own screen flow), the host can switch the active stage directly in an embedded chat:
const frame = document.getElementById('ragtime-chat');frame.contentWindow.postMessage( { type: 'ragtime-host', action: 'set-stage', stageId: 'stage-3' }, 'https://<host>');- Text path: the stage is applied on the next chat request.
- Realtime path: the stage is applied on the open session at a safe boundary, without restarting the connection.
- Unknown stage ids are rejected; the conversation stays in the current stage.
To confirm which stage was actually applied, listen for the
ragtime-event event named stage_changed on your host page. Its stageId
names the stage.
- Only one stage is active at a time, so stages are how a long prompt is meant to be split up. Each stage’s instructions are capped at 2,000 characters.
- The active stage’s instructions are layered on top of the assistant’s base instruction, so identity and prohibitions are never discarded.
- Works in text and realtime alike — a handoff pushes a
session.updatecarrying the new stage’s instructions.
Manage stages from the dashboard, or from code via the Assistant Config API.
Retained action results (persistResult)
Section titled “Retained action results (persistResult)”By default an action’s result is available only for the reply it was fetched for. The chat transport carries user and assistant turns between requests; the tool message is not among them, so the material is gone on the next turn. For a one-off lookup that is correct. For an action that serves reference material it is a trap: the assistant answers correctly once and then, several turns later, goes back to guessing — with nothing in the UI to indicate anything changed.
Enable Keep result for later turns on the action (persistResult: true) and
the result is carried forward:
- The server signs the retained results into an opaque token; the client echoes it back with each request and the server re-injects the verified entries as a system section.
- The token is HMAC-signed and bound to the project. A tampered or foreign token yields nothing.
- Re-running an action replaces its retained entry, so retention always holds the current answer, never a pile of stale ones.
- A failed call is never retained — carrying an error forward would suppress the retry that would have fixed it.
- Budget: up to 8 entries and ~12,000 characters combined, expiring after 24 hours. Oldest entries are shed first.
- Retained material is presented as authoritative, and the model is told not to re-call those actions unless it needs something the data does not cover.
Realtime sessions already keep tool results in the session, so this flag changes nothing there.
Choosing between injection and a retained action
Section titled “Choosing between injection and a retained action”Prefer instructionOverrides when your application already knows what the user
is looking at — it is deterministic, costs no extra round trip, and cannot be
skipped by a model that decides not to call a tool. Reach for a retained action
when only the model knows what is needed, or when the data is genuinely fetched
mid-conversation.
Managing instructions from code
Section titled “Managing instructions from code”Both the stored instructions and the conversation stages can be read and written over the API, so a prompt can live in your repository and be pushed from CI rather than edited in the dashboard — which also makes it something your tests can assert on. See the Assistant Config API.
Related
Section titled “Related”- Assistant Config API — reading and writing instructions and conversation stages.
- Chat Injection — delivering
instructionOverridesfrom an embed. - How Ragtime Works — where instructions sit relative to retrieval.