Coding Agent API
Run OpenCode-backed coding agents over HTTP — prompt in, sandbox execution, patch and optional draft PR out.
The Coding Agent API exposes the same OpenCode + E2B runtime as Builder for automation: CI bots, internal tools, and agents that already use Critique crt_ keys.
Marketing overview and copy-paste examples also live at /coding-agent-api.
Need token-in/token-out chat only (no sandbox)? See the sibling Inference API — POST /api/v1/chat/completions on the same crt_ keys and credit pool.
Authentication
| Item | Value |
|---|---|
| Auth | Authorization: Bearer crt_… |
| Create keys | Settings → Connections → Critique API keys |
| Scopes | read:builder, write:builder (included on new keys by default) |
Keys act as your Critique user. The repository must already be on a GitHub App installation you control.
Endpoints
| Method | Path | Scope | Purpose |
|---|---|---|---|
POST | /api/v1/coding-agent/runs | write:builder | Start a run |
GET | /api/v1/coding-agent/models | read:builder | List allowed models, credit floors, and capabilities |
GET | /api/v1/coding-agent/runs?limit=20&cursor=RUN_ID | read:builder | List recent runs with cursor pagination |
GET | /api/v1/coding-agent/runs/{id} | read:builder | Status, summary, optional events |
GET | /api/v1/coding-agent/runs/{id}/status | read:builder | Lightweight polling status |
GET | /api/v1/coding-agent/runs/{id}?patch=1 | read:builder | Include patch text when ready |
GET | /api/v1/coding-agent/runs/{id}?events=1 | read:builder | Include OpenCode activity timeline |
POST | /api/v1/coding-agent/runs/{id}/messages | write:builder | Send a follow-up on the same run (live session when status is idle) |
GET | /api/v1/coding-agent/runs/{id}/stream | read:builder | Server-Sent Events stream of run activity |
POST / PATCH | /api/v1/coding-agent/runs/{id}/cancel | write:builder | Cancel a run and tear down its sandbox when possible |
Create run body
| Field | Required | Notes |
|---|---|---|
repository or repositoryFullName | One of repo id/name | owner/repo form |
repositoryId | Alternative | Critique repository id |
title | No | Operator-facing run title, max 120 chars |
tags | No | Up to 20 normalized labels for CI jobs, owners, incidents, or queues |
metadata | No | Client metadata echoed on the run; max 16KB serialized |
prompt | Yes | Task instruction (max 120k chars) |
modelId | No | OpenRouter id from Remedy/Builder catalog |
taskKind | No | code or plan |
baseRef / gitCheckoutRef | No | Branch or ref to check out |
validationMode | No | basic, tests, or minimal |
publish.mode | No | draft_pr or none |
publish.branch | No | Branch name when publishing |
billing.mode | No | managed (Critique credits) or openrouter |
billing.openRouterApiKey | When openrouter | Encrypted and saved as your OpenRouter BYOK key for future API runs |
idempotencyKey | No | Alternative to the Idempotency-Key header; max 160 chars |
webhook.url | No | Public HTTPS endpoint for signed run status callbacks |
webhook.secret | With webhook.url | At least 32 chars; encrypted at rest and used for HMAC-SHA256 signing |
webhook.events | No | Any of run.idle, run.completed, run.failed, run.cancelled; defaults to all |
safety.network.mode | No | default, restricted, or disabled; injected into sandbox instructions |
safety.network.allowlist | No | Hostnames/URLs the agent should treat as allowed when network is restricted |
safety.tools.permissionMode | No | default, suggest, or readonly; injected into sandbox instructions |
safety.tools.allowedWritePaths | No | Path/glob hints limiting where the agent should edit |
safety.tools.blockedCommands | No | Commands the agent is instructed not to run |
safety.resources.maxTurns | No | Server-enforced cap on follow-up turns for the run |
safety.resources.maxRuntimeMs | No | Used as sandbox timeout when sandboxTimeoutMs is omitted |
safety.resources.maxCredits | No | Managed-billing preflight fails if the selected model floor exceeds this cap |
Idempotent create
Use an idempotency key when creating runs from CI, job queues, or webhook handlers. Retries with the same key and same payload return the original run instead of creating another sandbox or branch. Reusing the same key with a different payload returns 409.
curl https://critique.sh/api/v1/coding-agent/runs \
-H "Authorization: Bearer crt_YOUR_KEY" \
-H "Idempotency-Key: stripe-webhook-fix-2026-06-05" \
-H "Content-Type: application/json" \
-d '{
"repository": "acme/web",
"prompt": "Add Stripe webhook signature verification and tests.",
"publish": { "mode": "draft_pr" }
}'Example — managed billing
curl https://critique.sh/api/v1/coding-agent/runs \
-H "Authorization: Bearer crt_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"repository": "acme/web",
"prompt": "Add Stripe webhook signature verification and tests.",
"modelId": "anthropic/claude-sonnet-4.6",
"billing": { "mode": "managed" },
"publish": { "mode": "draft_pr" },
"validationMode": "tests",
"safety": {
"network": { "mode": "restricted", "allowlist": ["api.stripe.com"] },
"tools": { "permissionMode": "suggest" },
"resources": { "maxTurns": 3, "maxCredits": 12 }
},
"webhook": {
"url": "https://example.com/webhooks/critique-agent",
"secret": "replace-with-at-least-32-random-characters"
}
}'Example — OpenRouter billing
Pass your OpenRouter key in the body; Critique runs the sandbox and OpenRouter bills tokens on your account.
curl https://critique.sh/api/v1/coding-agent/runs \
-H "Authorization: Bearer crt_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"repository": "acme/web",
"prompt": "Migrate the settings page to server actions.",
"modelId": "openai/gpt-5.4",
"billing": {
"mode": "openrouter",
"openRouterApiKey": "sk-or-v1-..."
},
"publish": {
"mode": "draft_pr",
"branch": "critique-agent/settings-server-actions"
}
}'Follow-up messages (persistent session)
When a run finishes its first turn, status becomes idle and the E2B sandbox + OpenCode session stay warm until sessionExpiresAt. Send another prompt on the same run id — no new sandbox, no chained summary prompt.
curl https://critique.sh/api/v1/coding-agent/runs/RUN_ID/messages \
-H "Authorization: Bearer crt_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Add a regression test for expired signatures.",
"publish": { "mode": "draft_pr" }
}'Close the session explicitly (kills the sandbox) with { "endSession": true }.
If the session expired or the run predates persistent sessions, the API falls back to a chained new run (prior context in the prompt, new sandbox) when the parent run is idle, completed, or failed.
Status responses include convenience fields for automation:
| Field | Meaning |
|---|---|
lifecycle | Stable lifecycle enum: queued, running, idle, completed, failed, cancelled, or unknown |
terminal | True for completed, failed, or cancelled runs |
awaitingFollowUp | True when the run is idle and the live sandbox session is still active |
canFollowUp | True when the run can accept either a live follow-up or a chained follow-up |
nextActions | Suggested client actions such as stream, poll, send_message, end_session, open_builder, open_pull_request, or inspect_error |
intent | Deterministic category derived from the prompt for filtering and reporting |
Cancel a run
curl -X POST https://critique.sh/api/v1/coding-agent/runs/RUN_ID/cancel \
-H "Authorization: Bearer crt_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "Superseded by a newer CI job." }'Live event stream (SSE)
curl -N "https://critique.sh/api/v1/coding-agent/runs/RUN_ID/stream?after=EVENT_ID" \
-H "Authorization: Bearer crt_YOUR_KEY"Events: builder.event (OpenCode activity rows), run.status when the turn reaches idle, completed, failed, or cancelled.
The after cursor is the last received event id. Reconnects resume from the durable event ledger order. run.status events include the same lifecycle fields as the compact status endpoint.
Signed webhooks
When webhook is set on create, Critique sends HTTPS POST callbacks to a public endpoint for selected run events. Each delivery includes:
| Header | Value |
|---|---|
User-Agent | Critique-Coding-Agent-Webhook/1.0 |
X-Critique-Webhook-ID | Unique delivery id |
X-Critique-Webhook-Event | run.idle, run.completed, run.failed, or run.cancelled |
X-Critique-Webhook-Signature | sha256=<hex HMAC> over the raw JSON body using webhook.secret |
Verify the signature with a constant-time comparison before trusting the payload.
import crypto from 'node:crypto'
export function verifyCritiqueWebhook(secret: string, rawBody: string, signature: string) {
const expected = `sha256=${crypto.createHmac('sha256', secret).update(rawBody).digest('hex')}`
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
}Response shape
Completed runs return (among other fields):
status—queued,running,idle(session warm),completed,failedlifecycle,terminal,awaitingFollowUp,canFollowUp,nextActions— stable automation statesessionActive—truewhenidleand insidesessionExpiresAtturnCount— number of user turns on this runtags,metadata,intent— client attribution and deterministic task classificationrepository— full name and idsmodelId— selected modelsummary— assistant-facing completion textchangedPaths,diffStats— when a patch existspatch— when requested with?patch=1events— OpenCode activity when requested with?events=1pullRequest— GitHub metadata whenpublish.modewasdraft_pr
Poll GET /api/v1/coding-agent/runs/{id}?patch=1 until status is terminal.
GET /api/v1/openapi is the canonical machine contract for generated clients. The examples on this page are intentionally shorter than the schema.
Billing modes
| Mode | Who pays models | Who pays sandbox |
|---|---|---|
| managed | Critique credits (plan gates apply) | Critique |
| openrouter | Your OpenRouter account | Critique credits for orchestration only |
Managed mode uses the same catalog as Builder and Remedy. See Billing & credits.
Runtime
- Engine: OpenCode headless server inside an ephemeral E2B sandbox
- Isolation: Repo clone at the requested ref; sandbox stays alive between turns while
idle, then until expiry orendSession - Output: No automatic push unless
publish.modeisdraft_prand GitHub permissions allow it
This API is not the same as BYOA review-run queueing (Cursor / Claude / Codex on a completed PR review). Use BYOA when you want Critique to hand off a fix blueprint from a review; use the Coding Agent API when you want a general coding task on a repo.
For judging whether an agent’s PR should merge (verdict + structured findings), use the Merge Gate API instead.
Related
- Coding Agent API product page — comparison table, FAQ, pricing for “best/cheapest cloud coding agent API”, cookbooks, and signed-in
crt_key generation - Merge Gate API — PR review gate for orchestrators and agent supervisors
- Chat & workspace — Builder UI at
/builderand/workspace?mode=build - Inference API — OpenAI-compatible chat on Critique credits
- Connections & Platform API — MCP, passports,
crt_scopes - BYOK — OpenRouter for review/chat, optional per-run key here
Agent stack integrations
Pair Critique’s merge gate with RWX, Swytchcode, and Identity Machines — upstream signals, cookbooks, and where each layer sits in the agent loop.
Inference API
OpenAI-compatible chat completions on Critique credits — Western-hosted models, usage dashboards, and per-user limits.