/v0. Bodies are JSON. Errors use a {code, message, details} envelope.
Authentication
- Client and admin routes use a bearer token:
Authorization: Bearer <token>. Set it with--bearer-token/REBUNO_BEARER_TOKEN(required in server mode). The dev kernel disables auth. - Agent routes use HMAC. The agent sends
Rebuno-Agent-IdandRebuno-Signature: sha256=<HMAC-SHA256(secret, body)>, computed over the raw request body with the agent’s registered secret. - Agent routes that write also send
Rebuno-Dispatch-IdandRebuno-Dispatch-Attempt, copied from the webhook that delivered the run. A call from an attempt the kernel has already re-delivered gets409 lease_superseded. - A few routes (fetching execution input and steps) take either one: bearer for clients, HMAC for the agent.
/v0/health,/v0/ready, and/metricsare unauthenticated.
Client API
Create an execution
POST /v0/executions · bearer
201 with the created execution. The kernel records execution.created
and enqueues a dispatch.
Get an execution
GET /v0/executions/{id} · bearer or HMAC
List executions
GET /v0/executions?agent_id=&status=&cursor=&limit= · bearer
Newest first. Keyset paging: pass the returned next_cursor back as cursor.
Get the event log
GET /v0/executions/{id}/events?after_seq=&limit= · bearer
Returns an ordered array of events. limit defaults to 100, max
1000. Poll with after_seq set to the last event_seq you saw.
Stream live output
GET /v0/executions/{id}/stream · bearer
Server-Sent Events carrying the deltas an agent publishes while a step is still
running. Best-effort, never persisted, and separate from the event log. See
Live streaming.
Cancel an execution
POST /v0/executions/{id}/cancel · bearer → 204
Records execution.cancelled, moves the execution to a terminal state, and stops
further dispatch.
Agent API
The kernel dispatches a webhook carrying{execution_id, dispatch_id, dispatch_attempt, lease_timeout_seconds}. The agent acks 200 OK, then pulls
what it needs and drives its effects. These routes are HMAC-verified, except the
reads, which also take a bearer token.
Read execution input and steps
GET /v0/executions/{id} returns the original input and the current status.
GET /v0/executions/{id}/steps?status=terminal returns the execution’s steps in
one read, for inspection and auditing. status=terminal trims the list to
succeeded, failed, and denied.
GET /v0/executions/{id}/steps/{step_id} looks up one step, and returns 404 if
it is not there.
Submit a step
POST /v0/executions/{id}/steps · HMAC · dispatch headers
kind is tool_call, llm_call, or local. The dispatch headers are
required, and the kernel rejects the request if either is missing, or if they
name a dispatch that is not this execution’s or an attempt that no longer owns
it. The dispatch scopes the kernel’s occurrence counter. The kernel derives the
step ID, runs the replay short-circuit and policy, and
returns a decision. The step_id that comes back is what addresses the step’s
complete and fail routes:
Report a step outcome
POST /v0/executions/{id}/steps/{step_id}/complete takes { "result": {...} }
and records step.succeeded.
POST /v0/executions/{id}/steps/{step_id}/fail takes { "error": {...} } and
records step.failed.
Publish a stream delta
POST /v0/executions/{id}/steps/{step_id}/stream · HMAC → 204
Body { "seq": <int64>, "data": "<chunk>" }. Live output while a step runs,
delivered best-effort. data is opaque to the kernel and capped per batch. See
Live streaming.
Send a heartbeat
POST /v0/executions/{id}/heartbeat · HMAC → 204
Touches the dispatch lease so a long-running dispatch is not reclaimed as
stalled.
Report execution outcome
POST /v0/executions/{id}/complete takes { "output": {...} } → 204. Records
execution.completed.
POST /v0/executions/{id}/fail takes { "error": "..." } → 204. Records
execution.failed.
Admin API
Agents
POST /v0/agents · bearer registers or upserts an agent. Body
{ "id", "webhook_url", "secret", "lease_timeout_seconds?" }. Returns 201 and
the stored agent.
GET /v0/agents · bearer lists agents.
GET /v0/agents/{id} · bearer fetches one.
DELETE /v0/agents/{id} · bearer → 204.
An agent reads { "id", "webhook_url", "policy_bundle?", "registered_at", "lease_timeout_seconds?" }. The secret is never returned.
Policy
POST /v0/policies/{agent_id} · bearer loads or replaces the agent’s bundle.
Body { "bundle": "<raw YAML>" } → 204. See Policy.
POST /v0/policies/{agent_id}/test · bearer evaluates a bundle without storing
it. Body { "bundle?", "cases?", "execution_id?" }. Omit bundle to test the
agent’s stored one; give cases to evaluate inputs, or execution_id to replay
a past execution’s steps. Returns each case’s decision and a count of those that
did not match. See Testing a bundle.
Approvals
GET /v0/approvals · bearer lists pending approvals.
GET /v0/approvals/{id} · bearer fetches one.
POST /v0/approvals/{id}/grant · bearer takes { "decided_by", "rationale?" }
→ 204. Resumes the execution, and the gated step proceeds.
POST /v0/approvals/{id}/deny · bearer takes { "decided_by", "rationale?" }
→ 204. The resumed loop sees a policy error at that step.
Both return 403 forbidden when the approval lists approvers and decided_by
is not one of them. The kernel takes decided_by at face value, because the
bearer token carries no identity. The check stops someone off the list from
deciding. It cannot stop someone who types another person’s name into the field.
See Approvals.
Operational endpoints
GET /v0/health is a liveness check, returning {"status":"ok"}.
GET /v0/ready is a readiness check, returning 503 if a dependency check
fails.
GET /metrics serves Prometheus metrics.