Quickstart

Run the local stack, capture a tool-backed execution, replay a branch, and inspect bounded evidence.

Use this as the smallest complete local loop. It uses recorded/transform replay: isplay patches recorded evidence and substitutes fixtures. It does not re-run your model or tools unless you wire an explicit executor.

Start Local

This page assumes jq is installed for shell JSON extraction. Run npx isplay start in one terminal and leave it running.

npx isplay init
npx isplay start

In another terminal:

export ISPLAY_API_URL=http://127.0.0.1:7373
export ISPLAY_PROJECT_ID="$(npx isplay projects create --name 'Claims Lab' | jq -r .id)"

Capture A Run

Create capture-demo.mjs:

import { init } from "@isplay/sdk";

const client = init({
  projectId: process.env.ISPLAY_PROJECT_ID,
  baseUrl: process.env.ISPLAY_API_URL,
  serviceName: "claims-agent",
});

await client.withRun({ name: "claim-review" }, async () => {
  await client.annotateContext({
    kind: "system_message",
    path: "prompt.system",
    value: "Prefer policy-grounded answers.",
  });

  const model = await client.startModelCall({
    provider: "example",
    model: "recorded-demo",
    operation: "generate",
    params: { claimId: "C-104" },
  });

  const proposal = await client.recordToolProposal({
    modelCallId: model.id,
    toolName: "policy_search",
    args: { claimId: "C-104", query: "eligibility" },
  });

  const execution = await client.startToolExecution({
    proposalId: proposal.id,
    toolCallId: proposal.toolCallId,
    toolName: "policy_search",
    args: { claimId: "C-104", query: "eligibility" },
    sideEffectClass: "read",
  });

  await client.finishToolExecution(execution, {
    output: { eligible: false, reason: "missing receipt" },
  });
  await client.finishModelCall(model, { output: { decision: "deny" } });

  await client.checkpoint("before-decision", { claimId: "C-104", stage: "ready" });
});

Then run it:

node capture-demo.mjs

Branch And Replay

RUN_ID="$(npx isplay runs list --project "$ISPLAY_PROJECT_ID" | jq -r '.[0].id')"
CHECKPOINT_ID="$(npx isplay runs checkpoints "$RUN_ID" | jq -r '.[0].id')"
BRANCH_ID="$(npx isplay branch create --project "$ISPLAY_PROJECT_ID" --from "$RUN_ID" --checkpoint "$CHECKPOINT_ID" --name receipt-found | jq -r .id)"

cat > patch.json <<'JSON'
{ "args": { "claimId": "C-104", "query": "eligibility with receipt" } }
JSON

npx isplay branch intervene "$BRANCH_ID" \
  --project "$ISPLAY_PROJECT_ID" \
  --kind tool_args_patch \
  --target-tool policy_search \
  --patch patch.json

REPLAY_ID="$(npx isplay replay "$RUN_ID" --project "$ISPLAY_PROJECT_ID" --branch "$BRANCH_ID" | jq -r .id)"
npx isplay replay events "$REPLAY_ID"
npx isplay replay diff "$REPLAY_ID"

If replay pauses for a fixture, add a fixture with explicit provenance, then resume:

npx isplay fixtures add "$REPLAY_ID" \
  --project "$ISPLAY_PROJECT_ID" \
  --tool policy_search \
  --matcher '{"argsHash":"<args-hash-from-requirement>"}' \
  --output '{"eligible":true,"reason":"receipt found"}' \
  --provenance analyst_fixture

npx isplay replay resume "$REPLAY_ID"

Background Jobs

REPLAY_ID="$(npx isplay replay "$RUN_ID" --project "$ISPLAY_PROJECT_ID" --branch "$BRANCH_ID" --no-wait | jq -r .id)"
JOB_ID="$(npx isplay replay get "$REPLAY_ID" | jq -r .metadata.jobId)"
npx isplay jobs events "$JOB_ID"

The job feed is durable SSE over stored job events. isplay start runs the API and local Graphile worker.

On this page