Documentation
Everything you need to instrument an agent, replay an incident, write a policy, and ship with confidence. Covers all editions — Community (free), Starter, Growth, Scale, Pro, and Enterprise.
#Overview
Runback is an observability and governance platform for AI agents. It captures every LLM call, tool call, and agent step — then lets you re-run any decision from the exact captured context, enforce policies, run regression tests, and export a tamper-evident audit record.

The platform has five layers:
Instrument with the Runback SDK or send traces via OpenTelemetry. Every span is stored in a Postgres database you own.
Re-run any step from the exact captured context — tools, retrieval, messages[] held fixed. Root-cause in minutes.
Write policies as JSON rules. They evaluate on every run in real time and can gate your CI pipeline.
Any run exports as a signed, re-executable audit record. Deterministic — no model calls required.
Approvals, incidents, trust chains, and regulatory mappings for teams operating in regulated environments.
#Quick start (5 minutes)
CommunityThe fastest path: the managed hosted tier. You get a live dashboard in under 5 minutes without running any infrastructure.
npm install @runback/sdkimport { withDebugger } from "@runback/sdk";
import { generateText, stepCountIs } from "ai";
const dbg = withDebugger(model, {
runName: "support-agent",
apiKey: process.env.RUNBACK_API_KEY,
redact: "standard",
});
const result = await generateText({
model: dbg.model,
tools: dbg.tools(myTools),
stopWhen: stepCountIs(10),
prompt: userMessage,
});
await dbg.finish({ output: result.text, status: "success" });export RUNBACK_API_KEY=rb_live_your_key_herecurl -fsSL https://runback.dev/api/quickstart | RUNBACK_API_KEY=your_key bash#Your first run
Once a run lands in your dashboard you can:
- Click into it — opens the time-travel debugger. Scrub the slider to any step.
- Switch to Inspect mode — see the raw request/response for any LLM or tool call.
- Download the audit record — a signed, re-executable bundle. Verifiable at runback.dev/verify.

#Runs & spans
A run is one end-to-end execution of an agent — from the initial prompt to the final output. A span is a single step within that run: either an LLM call or a tool call.
| Object | What it is | Key fields |
|---|---|---|
| Run | One agent execution | run_id, name, status, input, output, started_at |
| LLM span | One model call | model, messages, response, tokens, latency_ms |
| Tool span | One tool call | tool_name, input, output, error, policy_block |
| Audit record | Signed bundle of all spans | merkle_root, signature, re-executable |

Span IDs are stable — the same span replays identically every time, from the recording. No model call required.
#Replay
Runback has two kinds of replay:
Rewind any run to any step. The full agent state — every prior tool output, every message in context — is reconstructed from the recording. Deterministic, offline, no model calls.
Community+Re-execute a specific LLM call with a different model or prompt. Runback freezes the recorded inputs and makes a fresh call to the model you choose. Use it to bisect which model change caused a regression.
Pro+
#Policies
A policy is a JSON array of rules evaluated against every run. Rules can assert (flag a violation) or require (block the run if triggered).
[
{
"id": "no-large-disputed-refund",
"kind": "require",
"description": "Disputed refunds over $100 must be escalated, not auto-issued",
"when": {
"on": "tool_call",
"tool": "issue_refund",
"and": [
{ "field": "input.amount", "op": "gt", "value": 100 },
{ "field": "run.tags.disputed", "op": "eq", "value": true }
]
},
"action": "block"
}
]
#Evals & CI gate
CommunityEvals test your agent on a fixed dataset. The CI release gate fails a build if a new model or prompt causes a regression against your golden tests.

# .github/workflows/ci.yml
- name: Runback eval gate
run: npx runback eval run --dataset my-dataset --threshold 0.9
env:
RUNBACK_API_KEY: ${{ secrets.RUNBACK_API_KEY }}#Golden test suite
GrowthThe golden suite automatically mines your production incident runs into regression tests. Every run that triggered a policy violation or was marked as a failure is surfaced for review and approval as a golden test.

#Approvals
StarterWhen a policy flags a violation (action: flag), team members can review and decide on the incident before the agent is permitted to continue or the run is marked resolved. Approvals are the human-in-the-loop gate for policy violations.
A flagged run creates a pending approval. Approvers (team members with the approve permission) see it in Approvals and can approve or reject with a note. The decision is sealed into the run record.
Every approval decision (who decided, when, with what note) is appended to the run's tamper-evident record. The chain covers both the agent's decision and the human decision.
// Mark a run as requiring approval via the API
POST /api/approvals
{
"run_id": "run_abc123",
"policy_id": "no-large-disputed-refund",
"reason": "Disputed $250 refund — requires senior review"
}
// Get pending approvals
GET /api/approvals?status=pending#Incidents
GrowthAn incident is a structured record of an agent failure or policy breach — separate from the run itself. Incidents track status (open → investigating → resolved), timeline, and linked runs.
| Status | Meaning |
|---|---|
| open | Incident created, not yet assigned or being investigated |
| investigating | A team member is actively looking into the root cause |
| resolved | Root cause identified, fix deployed, golden test added |
// Create an incident from a run
POST /api/incidents
{
"run_id": "run_abc123",
"title": "Refund agent bypassed $100 limit",
"severity": "high"
}
// Update status
PATCH /api/incidents/:id
{ "status": "resolved", "resolution": "Policy updated, golden test enrolled" }From any run detail page, use the Open incident button to create a linked incident in one click. The incident page shows the full run, the policy violation, the approval history, and the timeline.
#Inter-agent trust chain
ProIn multi-agent systems, a subagent receiving instructions from an orchestrator has no cryptographic proof the orchestrator is who it claims to be, or that the scope of the delegation hasn't been widened in transit. Runback's trust fabric seals every delegation edge.
Every orchestrator→subagent call produces an HMAC-SHA256 attestation token. The token carries the calling agent, called agent, depth, permitted scope, and a hash of the parent token.
The full chain from root to leaf exports as a signed artifact. POST it to /api/trust/verify — or re-derive the HMAC yourself. No Runback account needed.
// Issue a delegation token (orchestrator → subagent)
POST /api/trust/chain
{
"parent_run_id": "run_orchestrator_abc",
"child_agent": "kyc-subagent",
"scope": "read:customer",
"depth": 1
}
// Verify the full chain
POST /api/trust/verify
{
"chain": [ /* array of attestation tokens */ ]
}
// Response: { valid: true, depth: 2, root: "loan-orchestrator", ... }AUDIT_SIGNING_KEY in their environment.#Vercel AI SDK
CommunityThe deepest integration — full context capture, in-process PII redaction, step replay, and typed tool wrappers. About 3 lines of change to an existing agent.
import { withDebugger } from "@runback/sdk";
import { generateText, stepCountIs } from "ai";
// 1. Wrap your model and tools
const dbg = withDebugger(model, {
runName: "customer-support",
apiKey: process.env.RUNBACK_API_KEY,
redact: "standard", // "none" | "standard" | "aggressive"
tags: { env: "prod" },
});
// 2. Use dbg.model and dbg.tools — drop-in replacements
const result = await generateText({
model: dbg.model,
tools: dbg.tools(myTools),
stopWhen: stepCountIs(10),
prompt: task,
});
// 3. Finish the run
await dbg.finish({ output: result.text, status: "success" });
// On error:
// await dbg.finish({ status: "error", error: err });Redaction levels:
| Level | What it strips |
|---|---|
| none | Nothing — full fidelity capture |
| standard | Email, phone, SSN, card numbers, API keys, IP addresses |
| aggressive | All of standard + names, addresses, dates, numeric IDs |
#OpenTelemetry (any framework)
CommunityAny framework that emits OpenTelemetry GenAI spans works with Runback. Set three environment variables and your traces flow in automatically.
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://runback.dev/api/otel/v1/traces
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/json
OTEL_EXPORTER_OTLP_TRACES_HEADERS=authorization=Bearer <RUNBACK_API_KEY>RUNBACK_API_KEY with the key from your dashboard. Self-hosted deployments use your own base URL instead of runback.dev.#Python — OpenAI / Anthropic
CommunityUse OpenLLMetry (Traceloop) to auto-instrument the official Python SDKs.
pip install traceloop-sdkfrom traceloop.sdk import Traceloop
Traceloop.init(
api_endpoint="https://runback.dev/api/otel",
headers={"authorization": "Bearer " + os.environ["RUNBACK_API_KEY"]},
)
# All openai.chat.completions.create() and
# anthropic.messages.create() calls are now traced.#LangChain, LangGraph, CrewAI, LlamaIndex
CommunityUse OpenInference or OpenLLMetry instrumentors, then point the OTLP exporter at Runback via the env vars above.
# LangChain / LangGraph
pip install openinference-instrumentation-langchain opentelemetry-exporter-otlp-proto-http
# LangChainInstrumentor().instrument()
# CrewAI
pip install traceloop-sdk
# Traceloop.init(...) — CrewAI spans flow straight in
# LlamaIndex
pip install openinference-instrumentation-llama-index
# LlamaIndexInstrumentor().instrument()OTEL_* environment variables in the same shell before running.#Environment variables
| Variable | Required | Description |
|---|---|---|
| RUNBACK_API_KEY | Yes | Your API key. Prefix rb_live_ for production, rb_test_ for test. |
| RUNBACK_BASE_URL | No | Override the ingest endpoint. Required for self-hosted deployments. |
| RUNBACK_DISABLED | No | Set to 1 to disable all capture (useful in local dev or unit tests). |
| RUNBACK_DEMO_MODE | No | Self-host only. Set to 1 to disable real model calls in replay/evals. |
#Time-travel replay
CommunityOpen any run and drag the timeline slider. Runback reconstructs the exact agent state at every step — the full message history, every prior tool output, what the model knew at that moment — without making a single model call.

Controls:
- Drag the slider to scrub to any step
- ← / → step backward and forward one span at a time
- Click any span in the transcript to jump directly to that step
- Switch to Inspect mode to see the raw request/response JSON for any step
#Step replay
ProRe-run a specific LLM call from a run with a different model. Runback freezes the recorded inputs (system prompt, message history, tool definitions) and makes a fresh call to the model you choose. The result is compared side-by-side with the original.
Use this to:
- Verify that switching to a cheaper model doesn't change behaviour on historical incidents
- Bisect which model or prompt change caused a regression
- Build a counterfactual — “what would the agent have done if I'd used GPT-4o mini here?”
#Fleet benchmarks
ProThe Benchmarks page compares your fleet's error rate, latency, and token spend against anonymised aggregate data from peer organisations in the same vertical. Percentile bands (p25, p50, p75, p95) let you see where your fleet stands relative to comparable deployments.
| Metric | What it shows |
|---|---|
| Error rate | % of runs ending in error vs. peer p50/p75 |
| Latency (p95) | Your 95th-percentile run duration vs. peer distribution |
| Token spend / run | Average tokens consumed per run vs. vertical peers |
| Policy block rate | % of runs blocked by governance rules vs. peer fleet |
#Fleet topology
ScaleThe Topology view renders your entire agent fleet as a live DAG — orchestrators at the top, subagents and tools at the leaves. Each node shows its call volume, error rate, and token spend. Click a node to drill into its runs.
Use topology to:
- Identify which subagent is the source of a systemic failure
- Spot unexpected delegation chains (orchestrator calling an agent it shouldn't)
- See token spend distribution across the fleet at a glance
#Writing policies
CommunityPolicies live in your dashboard under Policies. Each policy has a name, a version, and an array of rules.

Rule fields:
| Field | Values | Description |
|---|---|---|
| kind | require / assert | require = block the run if triggered. assert = flag a violation but let the run continue. |
| on | tool_call / llm_call / run_end | Which event type triggers evaluation. |
| when | JSON condition object | Field path, operator, and value. Supports and / or / not nesting. |
| action | block / flag / alert | block stops execution. flag records a violation. alert also fires your alert rules. |
Operators: eq ne gt gte lt lte contains starts_with exists
#Policy causes
ScaleThe Policy causes page shows a heat map of which policy × agent pairs produce the most blocks. It answers: “which agent is firing this rule most, and is it getting better or worse?”
| Column | What it shows |
|---|---|
| Block rate | Fraction of runs blocked by this policy/agent pair |
| Trend | ↑ worse / ↓ better vs. prior 30-day window |
| Total blocks | Absolute count over the selected window |
The heat map intensifies as block rate increases — zero is transparent, >20% is rose. Use it to identify policies that need rule refinement or agents that need prompt changes.
#PII redaction
CommunityPII redaction runs in-process — inside your application, before any data leaves to Runback. The raw values are never stored anywhere outside your process.
Standard redaction strips: email addresses, phone numbers, SSNs, credit card numbers, API keys, bearer tokens, IP addresses, and common secret patterns.
Redacted values are replaced with a deterministic placeholder like [redacted:email] so the structure of the trace is preserved for replay.
aggressive redaction or implement a custom redactor via the SDK.#Cost attribution
ScaleThe Cost page breaks down your AI spend by model and agent over any time window. The Cost → Teams view shows spend per team with budget tracking and alert thresholds.

Cost data is derived from captured token counts in every LLM span. No billing integration required.
#Signed audit records
CommunityEvery run can be exported as a signed audit record — a JSON bundle containing all spans, a Merkle root over the span tree, and a cryptographic signature. Verifiable independently at runback.dev/verify without trusting Runback.
# Download via API
curl -H "Authorization: Bearer $RUNBACK_API_KEY" \
https://runback.dev/api/runs/{run_id}/audit > audit.json
# Verify locally
npx runback verify audit.json#Regulatory dashboard
EnterpriseThe Regulatory page maps your live run data to framework controls — EU AI Act Annex III, APRA CPS 230, and NIST AI RMF. Each control shows whether it's satisfied, partially covered, or missing evidence, based on your actual captures.
| Framework | Controls mapped |
|---|---|
| EU AI Act Art. 12 | Logging and traceability — tamper-evident decision record |
| APRA CPS 230 | Operational risk, continuous monitoring, incident management |
| NIST AI RMF | Govern, Map, Measure, Manage — live status per function |
| ISO/IEC 42001 | AI management system — evidence export for auditors |
#Team chargeback
EnterpriseThe Chargeback page breaks AI spend down to the team level, with monthly budget caps and automated alerts when a team approaches or exceeds its cap.
| Feature | Description |
|---|---|
| Per-team spend | Token cost attributed to each team over a rolling 30-day window |
| Budget caps | Set a monthly spend limit per team; alerts fire at 80% and 100% |
| Overage enforcement | Optional: block ingest for a team that exceeds its cap until the next month |
| CSV export | Export the period report for internal billing or departmental chargebacks |
Configure team budgets under Settings → Teams → Budget. Spend is derived from captured token counts — no billing integration required.
#Compliance export
EnterpriseThe Compliance export generates a structured evidence package for auditor and regulator submissions. The package contains a signed, time-stamped summary of your governance posture — not a self-assessment, but a machine-generated artifact backed by your actual run data.
What the export includes:
- Policy inventory: all active rules, their versions, and block/flag counts over the audit period
- Incident log: every opened incident, its resolution, and the run record it links to
- Model change history: every model upgrade event and the CI gate result that preceded it
- Merkle-rooted ledger checkpoint: proof that the audit period record is complete and unaltered
#CI release gate
CommunityAdd the release gate to your CI pipeline. It runs your eval suite and fails the build if any golden test regresses beyond your threshold.
# GitHub Actions
- name: Runback release gate
uses: letsRunback/runback-action@v1
with:
api-key: ${{ secrets.RUNBACK_API_KEY }}
dataset: golden
threshold: 0.95
model: gpt-4o-mini# Or via CLI
- run: npx runback eval run --dataset golden --threshold 0.95
env:
RUNBACK_API_KEY: ${{ secrets.RUNBACK_API_KEY }}#Golden test suite
GrowthThe golden suite automatically promotes production failures into regression tests.

#Requirements
CommunityRunback is a standard Next.js app backed by a Postgres database. No exotic infrastructure.
| Component | Minimum | Recommended |
|---|---|---|
| Node.js | 20 LTS | 22 LTS |
| Postgres | 14 | 16 (Supabase, RDS, Cloud SQL) |
| RAM | 512 MB | 2 GB |
| CPU | 1 vCPU | 2 vCPU |
| Disk | 10 GB | 50 GB (depends on run volume) |
#Docker Compose
CommunityThe fastest self-host path. Spins up the app and a local Postgres in two commands.
# 1. Clone the repo
git clone https://github.com/letsRunback/runback.git
cd runback
# 2. Copy and fill in the env file (set AUDIT_SIGNING_KEY and JWT_SECRET at minimum)
cp .env.example .env && $EDITOR .env
# 3. Start
docker compose up -d
# App is now at http://localhost:3000Postgres is bundled — no external database required. For production, override POSTGRES_PASSWORD in .env and point NEXT_PUBLIC_APP_URL at your domain.
#Environment variables (self-hosted)
Community| Variable | Required | Description |
|---|---|---|
| AUDIT_SIGNING_KEY | Yes | HMAC key for tamper-evident audit records. Generate: openssl rand -hex 32 |
| JWT_SECRET | Yes | Signs PostgREST session tokens. Generate: openssl rand -hex 32 |
| POSTGRES_PASSWORD | Yes | Postgres password. No default — must be set in .env before docker compose up. |
| NEXT_PUBLIC_APP_URL | Production | Your public base URL. e.g. https://runback.yourco.com |
| RUNBACK_LICENSE | Enterprise | License key for Enterprise features (SSO, fleet dashboard, etc.). |
| RUNBACK_DEMO_MODE | No | Set to 1 to disable real model calls in replay/evals. |
| RESEND_API_KEY | No | Resend API key for magic-link email auth. |
| OPENAI_API_KEY | No | Only needed for live step-replay & LLM eval judges. |
#Upgrading
CommunitySQL migrations run automatically on startup — no manual steps required.
# Docker Compose
docker compose pull
docker compose up -d
# Migrations run automatically on boot.
# Downtime: typically under 5 seconds for minor releases.#Authentication
All API requests require a Bearer token in the Authorization header.
curl -H "Authorization: Bearer rb_live_your_key" \
https://runback.dev/api/runsAPI keys are created in your dashboard under Settings → API Key (SDK). Keys are prefixed rb_live_ for production and rb_test_ for test.
#Runs API
| Method | Path | Description |
|---|---|---|
| GET | /api/runs | List runs. Query params: limit, offset, status, agent_name, from, to. |
| GET | /api/runs/:id | Get a single run with all spans. |
| POST | /api/runs/:id/replay | Trigger a step replay. Body: { span_id, model }. |
| GET | /api/runs/:id/audit | Download the signed audit record as JSON. |
| GET | /api/runs/:id/cassette | Download the re-executable cassette bundle. |
# List the last 10 failed runs
curl -H "Authorization: Bearer $KEY" \
"https://runback.dev/api/runs?status=error&limit=10"
# Download audit record
curl -H "Authorization: Bearer $KEY" \
"https://runback.dev/api/runs/run_abc123/audit" > audit.json#Approvals & Incidents API
Starter| Method | Path | Description |
|---|---|---|
| GET | /api/approvals | List approvals. Query: status=pending|approved|rejected |
| POST | /api/approvals | Create an approval request for a run. |
| PATCH | /api/approvals/:id | Approve or reject. Body: { decision, note } |
| GET | /api/incidents | List incidents. Query: status=open|investigating|resolved |
| POST | /api/incidents | Create an incident linked to a run. |
| PATCH | /api/incidents/:id | Update incident status or resolution. |
#Audit API
Audit records are self-contained signed JSON bundles. To verify a record without trusting Runback:
# Verify with the CLI
npx runback verify ./audit.json
# Output: OK root=abc123... signature=valid spans=14The CLI recomputes the Merkle tree from the raw span data and checks it against the root in the record. The signature is an HMAC-SHA256 signature verifiable with your own key.
#Trust chain API
Pro| Method | Path | Description |
|---|---|---|
| POST | /api/trust/chain | Issue a delegation token from orchestrator to subagent. |
| POST | /api/trust/verify | Verify a trust chain. Returns: valid, depth, root, chain. |
#Webhooks
StarterRunback can POST a JSON payload to any URL when a run ends or a policy is triggered.
| Event | When it fires |
|---|---|
| run.completed | Any run finishes (success or error) |
| run.error | A run ends with status = error |
| policy.block | A policy rule fires with action = block |
| policy.flag | A policy rule fires with action = flag |
| approval.created | An approval request is created |
| incident.opened | A new incident is opened |
// Example payload — policy.block
{
"event": "policy.block",
"run_id": "run_abc123",
"policy_id": "no-large-disputed-refund",
"tool": "issue_refund",
"blocked_at": "2026-07-01T14:22:01Z"
}Configure webhooks in your dashboard under Alerts → Webhooks. HMAC-SHA256 request signing is enabled by default.
#Rate limits
| Limit | Community | Starter | Growth | Scale | Pro | Enterprise |
|---|---|---|---|---|---|---|
| Ingest — spans/sec | 50 | 200 | 500 | 1,000 | 2,000 | Custom |
| API reads — req/min | 60 | 300 | 600 | 900 | 1,200 | Custom |
| Replay — per hour | 10 | 50 | 100 | 200 | 500 | Custom |
| Eval runs — per day | 5 | 20 | 100 | 200 | 500 | Custom |
| Audit exports — per day | 10 | 50 | 200 | 500 | 1,000 | Custom |
X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset. Requests over the limit return 429 Too Many Requests.