Preview and Replay
Run a change against real data without committing it, then compare it with recorded work before you publish.
Changing an action that agents and callers depend on is safest as a loop: run the change against your real data with nothing committed, compare what it would do with what the current version did, and publish only when the difference is the one you meant. Twisp gives you three tools for that loop, and every one of them is recorded.
- Preview runs work for real, reads real data, and discards its writes, recording each one.
- Replay reruns a recorded agent turn or MCP request with another version or a draft, and commits nothing.
- Version pinning makes sure a change reaches callers only when you update them.
What a preview is
A preview runs everything exactly as a live run would. Tools run their programs, reads see your real data, each call sees the writes of the calls before it, and agents make their real model calls. When the work ends, its business writes are discarded. Each call is recorded with preview: true and lists in its writeSet every record version it would have written.
The record of the preview itself commits: the execution, its calls, an agent's transcript, and its session history. That is what makes a preview useful: you can read exactly what it would have done after the fact. A write set lists only the records you may read, and counts the rest in writeSetUnreadable, so a preview never shows you a record your policies hide.
A preview can read other tenants, but it cannot write to them, and it cannot run an operation that acts outside the ledger, such as a warehouse export. A call to a built-in model is the exception: a preview sends it to the provider like a live call, so it uses tokens and can get a different answer than a live run would. Work that would follow a commit does not happen: a definition created inside a preview is never published. See Preview calls.
Filter on preview to separate what committed from what did not:
query Previews($id: UUID!) {
actions {
executions(where: { actionId: $id, preview: true }, first: 20) {
nodes {
executionId
created
status
writeSet {
recordType
recordId
data
}
writeSetUnreadable
}
}
}
}
Ways to preview
| Preview | How | What runs |
|---|---|---|
| A program | program with commit: false on an MCP server | One Starlark program over the server's tools, in one transaction. The result lists the rows it would write. |
| A tool or agent | invoke with commit: false, the default, on an MCP server | A stored version, a disabled one, or an unpublished draft, on an input the caller chooses. |
| An MCP server | mcp.mode: PREVIEW, the default for every new server | Every call every external agent makes through the server. |
| An agent | config.mode: preview | Every turn the agent runs on real events. Agents default to live. |
Draft previews
A draft is an unpublished definition. invoke with a definition and commit: false runs one without storing it, validated as createAction would validate it. So an agent, or a person through an agent, can build a tool and run it before anything depends on it:
- Create the tool with
enabled: false. It is never triggered or called, but it can be previewed. - Preview drafts of it with
invokeuntil the output, calls, and writes are right. - Publish the draft that worked with
updateActionandenabled: true. - Where a real run is safe,
invokeit withcommit: true.
For a change to a live action, preview the change as a draft before updateAction publishes it to every caller. A draft's execution records the definition it ran in draft. A draft's preview is never rerun or replayed; preview the draft again. See Invoking an action.
Preview mode on MCP servers
Every new MCP server starts in preview mode. External agents get real outputs from your data, and none of their calls commit. Each result carries a preview marker in _meta, so a host can tell its user. The request's execution, its session history, and its uses still commit, and so does a task's cancellation. Point a new agent at a preview server, review what it would have written, then promote the server to LIVE. See MCP servers.
Preview mode on agents
An agent with config.mode: preview runs on real events and changes nothing. Its turns do everything a live turn would, and their writes are discarded when each turn ends. The agent's execution, transcript, and session still commit, so a preview session evolves as a live one would.
A call to a tool that requires approval does not wait in preview mode: it runs at once, as if approved, and the execution lists the request a live turn would have made with grantedInPreview: true, so the record shows that no person approved it. To let the agent act, update config.mode to live.
What preview turns remember
The memory and session history a preview turn writes are kept for audit, marked preview. Later preview turns read them, but a live turn never does: once the agent goes live, it does not act on what it learned about effects that never happened.
A preview turn never changes a memory record a live turn wrote. To correct or delete one, it writes a preview record of its own whose replaces names it. Preview turns stop recalling the original; live turns still recall it, unchanged. Action.memories lists these records with preview: true, so you see exactly what the preview would have changed. See Agent memory.
Replaying against another version
A replay reruns recorded work with another version of an action, or with an unpublished definition of it, and records the result as a new execution beside the original. replayExecution accepts two kinds of source:
- An agent turn. A finished execution of an agent: a triggered turn, a session turn, or a run a client called or started directly. The replay receives what the original turn received: its event, or for a session turn the same inputs and the session checkpoint the turn started from.
- An MCP request. A request's execution of an MCP server. The replay reruns the request, such as a tool call with its recorded arguments, against a later version of the server or a draft.
A replay commits no business writes. Every call runs as it would live, and its writes are discarded and recorded in its write set, as for a preview. It is never part of the live session: it admits no inputs and leaves the session and the agent's memory unchanged. It starts nothing and cancels nothing: a replayed request that would start a task records the start as not started.
mutation Replay($sourceId: UUID!, $replayId: UUID!, $version: Int!) {
actions {
replayExecution(
id: $sourceId
input: { executionId: $replayId, actionVersion: $version, model: RECORDED }
) {
executionId
status
replayOfId
}
}
}
What a replay holds fixed
| In a replay | |
|---|---|
| Input | The original's: its event, its session inputs and starting checkpoint, or its request. |
| Tool and skill versions | A reference without a version resolves to the version the original used, and to the latest only for a tool or skill the original did not use. A pinned reference uses its pin, so a draft that pins a new tool version tests exactly that change. |
| Data | Current. A replay's tools read the data as it is when the replay runs, not as the original saw it; replay.data is CURRENT to say so. |
| Model | For an agent turn, LIVE calls the model the replayed version configures; RECORDED answers with the model outputs the original recorded, so a change of tools or skills is compared without the model's variability. A request to an MCP server involves no model, so RECORDED is rejected for one. |
| Built-in model calls | Made again, as every tool call is, even with RECORDED: each sends its input to the provider, uses tokens, and can answer differently. A call to a model version retired since the original fails with action_not_callable. |
Comparing outputs and write sets
A replay has its own output, calls, transcript, and uses, which you compare with the original's. replayOf reads the original from the replay, so one query reads both:
query Compare($id: UUID!) {
actions {
execution(id: $id) {
invocation {
output
}
children(first: 50) {
nodes {
actionId
invocation {
output
}
writeSet {
recordType
recordId
data
}
}
}
replayOf {
invocation {
output
}
}
}
}
}
For a session turn, replay.session shows the status, reason, and state the turn would have given the session, to compare with what the original committed. Before publishing a change to an MCP server or a tool it uses, replay the server's recent requests against a draft that pins the new version, and compare request by request. Building actions with a coding agent shows that loop driven by an agent.
A replay of work that had a caller, such as a client's call or an MCP request, runs under both you and that caller, so it can do nothing either of you could not; a replay of a triggered or session turn runs under the agent's own policies, as the turn did. See Authority and audit and Replays.
Reruns, replays, and previews
A rerun runs work again for real. A replay reruns recorded work with another version and commits nothing. A preview runs work once without committing it.
| Rerun | Replay | Preview | |
|---|---|---|---|
| Operation | rerunExecution | replayExecution | program or invoke with commit: false, or preview mode on a server or agent |
| Source | A finished execution: triggered, called, or started | A finished agent turn or MCP request | New work |
| Version | The source's pinned version, or one you choose | The source's version by default, another stored version, or an unpublished definition | The current or a chosen version, or a draft through invoke |
| Business writes | Committed, unless the original was a preview | Discarded, and recorded in write sets | Discarded, and recorded in write sets |
| Session and memory | A session turn is not rerun | Unchanged | Preview mode keeps a preview session and preview memory |
| Authority | The action's own policies for a triggered execution; yours for a call or a start | You and the original principal, then the action's policies | The same as a live run of the same work |
| Not available for | Session turns, MCP requests, replays, and drafts' previews | Calls made by another execution, other replays, intake records, and drafts' previews | Operations that act outside the ledger or write to other tenants |
Use a rerun to finish work that failed for a reason you have since fixed, such as a policy an update now grants: it runs under the update's policies at once. See Manual reruns.
Pin what others depend on
A tool reference with a version always calls that version: its program, schemas, and policies. One without a version calls the latest version, resolved when each execution starts. Pin the tool versions your MCP servers and agents depend on, so a new tool version reaches them only when you update them, after a replay has shown what changes. Every invocation records the exact version each reference resolved to, so a replay and an audit always know what ran. See Versions.
Where to go next
Authority and audit
Who each action runs as, and what Twisp records about everything it does.
Executions reference
Preview calls, reruns, replays, and their fields.
Building actions with a coding agent
Let a coding agent validate and replay changes before a person publishes them.