API Reference
SDK version 0.9. All endpoints require an API key passed as X-Relai-Key in the request header. Search for a method or endpoint below.
/v1/capture
relai.capture()
Captures the execution context of an agent run for later replay. Call this inside your exception handler or after any agent turn that produced an unexpected result. Returns a bundle_id you can pass to relai verify.
Request body
{
"agent_id": "order-processing-v2",
"run_id": "run_8f2a1c9e",
"inputs": {
"user_message": "Cancel my last order and issue a refund.",
"conversation_history": [
{ "role": "user", "content": "I need help with order #8821" },
{ "role": "assistant", "content": "I found order #8821. What would you like to do?" }
]
},
"tool_state": {
"orders_api_version": "2024-01",
"user_id": "usr_49f3c",
"cart_id": null
},
"model": "gpt-4o-2024-08-06",
"temperature": 0.2,
"failure_signal": "tool_call_error",
"error_message": "orders.cancel: permission denied for user role=viewer",
"metadata": {
"environment": "production",
"region": "us-east-1"
}
}
Response
{
"bundle_id": "bndl_4a7f29cd83e1",
"status": "captured",
"replay_url": "https://app.getrelai.org/replay/bndl_4a7f29cd83e1",
"expires_at": "2026-07-25T00:00:00Z",
"sha256": "e3b0c44298fc1c149afbf4c8996fb924"
}
/v1/bundles/{bundle_id}
listReplays()
Retrieves a single capture bundle by its ID. The response includes the full execution context: inputs, tool state, model version, and the original failure signal. Use this to inspect what was recorded before running replay.
Path parameters
{
"bundle_id": "bndl_4a7f29cd83e1",
"agent_id": "order-processing-v2",
"captured_at": "2026-06-13T14:22:10Z",
"failure_signal": "tool_call_error",
"model": "gpt-4o-2024-08-06",
"inputs": { "...": "see /v1/capture schema" },
"tool_state": { "...": "snapshotted at capture time" },
"replay_count": 3,
"last_replayed_at": "2026-06-14T09:15:44Z"
}
/v1/fixes/propose
proposefix()
Attaches a proposed code diff to a bundle. When the fix is submitted, Relai automatically replays the original failure context against the patched agent and returns a structured pass/fail verdict. The diff must be in unified diff format.
Request body
{
"bundle_id": "bndl_4a7f29cd83e1",
"diff": "--- a/tools/orders.py\n+++ b/tools/orders.py\n@@ -44,7 +44,7 @@\n- if user.role == 'viewer':\n+ if user.role in ('viewer', 'support'):\n raise PermissionError('permission denied')",
"commit_sha": "3f1e7a8",
"pr_url": "https://github.com/yourorg/agent/pull/82",
"notes": "Extend cancel permission to support role per product spec"
}
Response
{
"fix_id": "fix_7b3c90da",
"bundle_id": "bndl_4a7f29cd83e1",
"replay_status": "running",
"estimated_completion_ms": 4200,
"webhook_url": "https://app.getrelai.org/hooks/fix_7b3c90da"
}
/v1/fixes/{fix_id}/status
getStatus()
Polls the replay status of a submitted fix. Once status transitions to complete, the verdict field contains the full structured diff result indicating whether the fix resolved the original failure.
Response
{
"fix_id": "fix_7b3c90da",
"bundle_id": "bndl_4a7f29cd83e1",
"status": "complete",
"verdict": "pass",
"replay_duration_ms": 3840,
"assertion_results": [
{
"assertion": "no_tool_call_error",
"result": "pass",
"detail": "orders.cancel completed with status 200"
},
{
"assertion": "output_contains_confirmation",
"result": "pass",
"detail": "Response includes 'refund initiated'"
}
],
"completed_at": "2026-06-14T09:20:22Z"
}
CI integration
Run Relai replay checks as part of your existing CI pipeline. The relai verify CLI command exits 0 on pass and non-zero on failure, so it integrates with any CI system that reads exit codes.
GitHub Actions example
name: Relai Replay Gate
on:
pull_request:
branches: [main]
jobs:
replay-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Relai CLI
run: pip install relai-sdk
- name: Run replay suite
env:
RELAI_API_KEY: ${{ secrets.RELAI_API_KEY }}
run: relai verify --suite production-failures --fail-on-regression
CLI options
relai verify [options]
--suite <name> Named bundle suite to replay (default: all)
--bundle <bundle_id> Replay a single bundle
--fix <fix_id> Verify a specific fix proposal
--timeout <ms> Per-replay timeout in milliseconds (default: 30000)
--fail-on-regression Exit 1 if any previously-passing bundle now fails
--json Output results as JSON to stdout
Response codes
| Code | Meaning | Common cause |
|---|---|---|
200 |
OK | Request succeeded. |
400 |
Bad request | Missing required field or malformed JSON body. |
401 |
Unauthorized | API key absent or expired. |
404 |
Not found | The requested bundle_id or fix_id does not exist. |
409 |
Conflict | A replay is already running for this bundle. |
429 |
Rate limited | See rate limits below. |
500 |
Internal error | Retry with exponential backoff; contact support if persistent. |
Error response shape
{
"error": {
"code": "bundle_not_found",
"message": "No bundle with ID bndl_00000000 found in this workspace.",
"request_id": "req_9c1d4ef7"
}
}
Rate limits
Rate limits apply per API key. Exceeding a limit returns HTTP 429 with a Retry-After header (seconds until the window resets).
| Endpoint | Rate (free) | Rate (pro) |
|---|---|---|
POST /v1/capture |
60 / min | 600 / min |
GET /v1/bundles/* |
120 / min | 1200 / min |
POST /v1/fixes/propose |
10 / min | 100 / min |
GET /v1/fixes/*/status |
120 / min | 1200 / min |