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

PreviewHowWhat runs
A programprogram with commit: false on an MCP serverOne Starlark program over the server's tools, in one transaction. The result lists the rows it would write.
A tool or agentinvoke with commit: false, the default, on an MCP serverA stored version, a disabled one, or an unpublished draft, on an input the caller chooses.
An MCP servermcp.mode: PREVIEW, the default for every new serverEvery call every external agent makes through the server.
An agentconfig.mode: previewEvery 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:

  1. Create the tool with enabled: false. It is never triggered or called, but it can be previewed.
  2. Preview drafts of it with invoke until the output, calls, and writes are right.
  3. Publish the draft that worked with updateAction and enabled: true.
  4. Where a real run is safe, invoke it with commit: 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
InputThe original's: its event, its session inputs and starting checkpoint, or its request.
Tool and skill versionsA 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.
DataCurrent. 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.
ModelFor 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 callsMade 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.

RerunReplayPreview
OperationrerunExecutionreplayExecutionprogram or invoke with commit: false, or preview mode on a server or agent
SourceA finished execution: triggered, called, or startedA finished agent turn or MCP requestNew work
VersionThe source's pinned version, or one you chooseThe source's version by default, another stored version, or an unpublished definitionThe current or a chosen version, or a draft through invoke
Business writesCommitted, unless the original was a previewDiscarded, and recorded in write setsDiscarded, and recorded in write sets
Session and memoryA session turn is not rerunUnchangedPreview mode keeps a preview session and preview memory
AuthorityThe action's own policies for a triggered execution; yours for a call or a startYou and the original principal, then the action's policiesThe same as a live run of the same work
Not available forSession turns, MCP requests, replays, and drafts' previewsCalls made by another execution, other replays, intake records, and drafts' previewsOperations 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.

Previous
MCP Servers