Skip to main content
pikopod scenario check drives its own requests against a throwaway engine, so your application is never in the loop. A mode is the other half: it arms the scenario’s standing conditions on the sandbox pikopod up is serving, and then your own tests, your own app, Postman, or plain curl meet the failure.
Now run your integration’s test suite against http://127.0.0.1:4600/examplepay. Every GET /charges is delayed, and your timeout handling is what gets exercised.

What a mode arms

The scenario’s standing conditions: the faults it injects and the state it seeds. Its request steps are not run; those are yours to make. A scenario whose first step is a request has no standing state and is refused with the reason.
Packs work as well as archetypes, so a reproduced production incident can be the standing state your whole suite runs against.

Scoped, or global

A mode is set on the sandbox and stays until cleared. What each test sees is partitioned by one request header, X-Pikopod-Scope. Three things are partitioned: fault times and per windows, the request journal, and the recordings cursor. Two workers that each send their own scope get their own 503, 503, 201 under the same idempotency key, and mode verify --scope judges one partition:
Requests without the header share the unscoped partition, and an unscoped mode verify judges only that partition. A scoped client never consumes an unscoped window, and the reverse. The Jest and pytest helpers send the header per test with scoped(). The header is stripped before the request is journaled, so a scope token never appears in pikopod requests output or in a recording. A sandbox keeps at most 256 live scopes; when a 257th arrives, the scope idle longest is forgotten, with its journal and windows, and the control plane counts the eviction. A scope longer than 128 characters is refused with 400.
clear leaves the standing state and clears every fault on the sandbox, in every scope.

Verify what your tests sent

A mode arms the failure. verify asks whether your client did what the scenario expects once it met that failure. It reads the sandbox’s request journal and judges it against the scenario’s verification steps: request order and spacing, webhook counts, stored state. It never arms, seeds, or resets anything.
Run your tests. retry_storm refuses the first two creates under one idempotency key with 503 and answers the third, so a client that retries correctly sends three. Then:
A client that gave up after the second 503 fails, and the summary says which expectation the journal never met and which journaled request came closest:
When a request did reach the sandbox but the matcher still missed, the closest line says what differed, so a wrong path, a missing header or a changed query key is named rather than guessed at. This client retried against the charge instead of the collection:
Paths are shown as templates and header and query values are never printed, only their names, so the summary is safe to paste into a ticket. --format junit or --format githubactions turns the verdict into a build artifact, one testsuite for the mode and one testcase per verification step, the same shapes scenario check writes:
Exit 0 when every step passed, 1 when the client fell short, 2 when no mode is set or the mode’s scenario has no verification step. Spacing between requests is judged on wall-clock time, because your client made them in real time. Clear the mode between suites, or give each suite its own scope; otherwise the next suite is judged against the last one’s requests too.

From a test

The Go package pkg/sandboxtest does the same inside a test, with no pikopod up: New, Mode, run your code, Verify. See Use it from a test.

From a coding agent

The same operations are MCP tools: set_mode, mode_verify, clear_mode, and get_requests to read the journal itself. See MCP tools.

When you want one fault, not a story

See Faults.

When the failure depends on the request

A mode and a fault answer every matching request the same way. For “answer 422 when this reference already exists”, write a rule.