Session replay fixtures

Session replay stands in for the model with recorded traffic: it rebuilds each model call from a recorded session log, so the real Oda agent runs its loops with no provider key and the same output every run. Use it for automated scenarios that need real loop behaviour with fixed model output; to choose between the test tiers, see Testing tiers.

Set up a replay scenario

Replay mounts in place of a real model route:

The settings a scenario passes:

SettingWhat it setsDefault
fileThe primary fixture: session.jsonl for a v0 log, or session.vN.jsonl for a numbered generation.The path the snapshot suite supplies for the scenario.
overrideFileAn optional sidecar for the primary session (see below).The path the suite supplies when a scenario has one.
childFilesRecorded subagent logs for a nested scenario, one per child session.None; the suite supplies them for nested scenarios.
providersAn optional replay-only provider and model catalogue for scenarios that exercise model discovery.None; every model call is intercepted.
paceMsA delay before each replayed chunk, for genuinely incremental delivery.None; chunks yield at once.

A run with no fixture path at all is refused: a fixture path is required.

What the fixture is

How live sessions bind to recorded scripts

Overrides for what a log cannot record

Two failure shapes cannot be rebuilt from a session log alone: a call that threw before producing any chunk, and a call that hung or was cancelled. A scenario that needs them points overrideFile at a replay.override.json sidecar in the scenario folder.

json
{ "patches": [{ "at": 0, "entry": { "kind": "throw", "chunks": [], "message": "<error text>", "code": "<code>" } }] }

Placeholders in scripted entries

When replay stops or refuses

Limits

The tier that records the fixtures replay runs on, with its record, replay and refresh modes, is Recorded-session snapshots.

Questions, answered

Why does my scenario need a replay.override.json sidecar?

Because two failure shapes cannot be rebuilt from a session log: a call that threw before producing any chunk, and a call that hung or was cancelled. The sidecar supplies them, and the message for a stream that ended without a finish chunk points at it.

How does replay decide which live session gets which recorded script?

By first-call order. The first live session to make a model call takes the parent script, and the next new session takes the next child script, each advancing its own cursor. More live sessions than recorded scripts fails loud rather than guessing.

What happens if my scenario makes more model calls than the fixture recorded?

script exhausted, naming the call the session wanted and the calls the script has. Re-record the scenario so the script covers the run.

What happens if a session appears that the recording does not have?

The call fails with the unrecorded-session message: more distinct live sessions made calls than the scenario recorded. Re-record the scenario.

How do I slow a replayed stream down?

Set paceMs to delay each chunk. It exists for genuinely incremental delivery; never let correctness depend on it.

Does replay send anything to a model provider?

No. Every call is answered from the fixture, and the provider catalogue replay can expose is replay-only, so a keyless run is also a harmless one.

How do I check the scenario used the whole fixture?

Run the consumption check at teardown. It fails unless every recorded script bound to a live session and every bound session consumed its whole script, so an underrun cannot pass silently.

Why did a {{fromRequest:...}} placeholder fail?

The resolution names its reason: an invalid pattern, a pattern that matched nothing in the request, or an unterminated placeholder. Remember that the last match wins and its first capture group substitutes.

Can two subagents that ran at the same time be replayed?

Not deterministically. Binding follows first-call order and assumes delegation ran one session at a time, so a recording whose sibling sessions interleave cannot be bound reliably.

Where does the fixture path come from?

From the scenario's own settings, or from the snapshot suite, which supplies the selected fixture per scenario. With neither, replay refuses to run: a fixture path is required.

Does replay change the fixture file?

No. Replay never rewrites or renames a fixture, and a historical fixture is migrated in memory as it reads it. Recording is the snapshot suite's job.