Start a run
const url = 'https://example.com/v1/runs';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"agent":"example","agentVersion":"example","projectId":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","segments":[{"key":"example","value":"example"}],"input":"example","options":{"dryRun":true,"wait":true}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/v1/runs \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "agent": "example", "agentVersion": "example", "projectId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "segments": [ { "key": "example", "value": "example" } ], "input": "example", "options": { "dryRun": true, "wait": true } }'One primitive, discriminated subject (agent XOR flow). When the deployment issues public run tokens, the response carries publicAccessToken: a read-only token for this run (15 minutes by default) to hand to a browser, which follows the run with it on GET /v1/runs/{runId}/progress and its stream.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”Caller-supplied idempotency key, scoped to the caller: the same key from someone else in the tenant is their own request (from 0.1.5). Retries with the same key return the original response byte-identical (per docs/API-ROUTE-CONVENTIONS.md §3.1). A retry sent while the first request still runs is answered 409 idempotency-key-in-flight with Retry-After, on a runtime whose store holds keys (from 0.1.5); retry after it, and you get the first request’s answer. An answer that carries a secret (a new API key or public run token, a session token, a generated signing secret) isn’t kept: a retry gets 409 idempotency-key-replay-withheld, with the first request’s status and when it succeeded (from 0.1.5).
Request Bodyrequired
Section titled “Request Bodyrequired”object
AgentId.
Semver. Omit → the conversation’s own version for a follow-up turn, else the version live for the run’s scope, else the latest.
Project to run under; omit → the tenant’s Default project.
The run’s segment path below its project, coarse to fine (an app-defined finer scope, e.g. company then role). A version live on a prefix of it serves the run.
object
Lowercase, like an identifier: company, contact-role.
Opaque payload forwarded to the agent binding.
object
When true, the run executes with side-effects mocked; the row is marked dryRun: true.
When false, respond 202 as soon as the run exists and finish it in the background; poll GET /v1/runs/{runId} for its status and output. Default true: respond 201 once the run completes, fails or suspends.
object
FlowId.
Semver; omit → latest.
Project to run under; omit → the tenant’s Default project.
The run’s segment path below its project, coarse to fine (an app-defined finer scope, e.g. company then role). A version live on a prefix of it serves the run.
object
Lowercase, like an identifier: company, contact-role.
Opaque payload forwarded to the flow runtime.
object
When true, the run executes with side-effects mocked; the row is marked dryRun: true.
When false, respond 202 as soon as the run exists and finish it in the background; poll GET /v1/runs/{runId} for its status and output. Default true: respond 201 once the run completes, fails or suspends.
Examplegenerated
{ "agent": "example", "agentVersion": "example", "projectId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "segments": [ { "key": "example", "value": "example" } ], "input": "example", "options": { "dryRun": true, "wait": true }}Responses
Section titled “Responses”Run finished, failed or suspended.
object
RunId.
Semver.
The failure as the runtime recorded it. Read failure instead: an agent turn records its typed error here in an internal form.
Why a failed run failed; present only on a failed run. An agent turn’s failure carries its own code (budget-exceeded, capability-routing-failed, model-invocation-failed, …; rate-limit-exceeded when a budget kept per tenant refused work the turn needed, with details naming the budget); any other failure is run-failed, with the run’s failure message.
object
What the error came from, when it says: e.g. for capability-routing-failed, the router’s capability-unsatisfiable with its reasons, by provider.
The error’s own reason, when it gives one: for a turn that ended at its approval (hitl-cancelled), timeout when nobody decided in time. Absent from an older runtime and from errors without one; read code then.
The error’s own facts, for a code that has them: for rate-limit-exceeded, limit (the budget that refused: schema-compile-time or template-render-time) and budgetMs, the names the API’s 429 uses. Never the wait: read back later, it’s stale. Absent for any other code, and from an older runtime.
object
The run’s output once it completed. Present on single-run responses; on lists only with ?include=output.
When an erasure cleared the run’s content (its input, output, failure message and journal payloads): a person’s words were erased. Structure (status, times, ids) stays.
Set on a child run (a sub-flow run, or the agent turn an agent step started): the run that started it.
Set on a child run: the node in the parent run that started it.
Set on an agent’s turn (an agent run, or the turn a flow’s agent step started): the agent, the version that ran and the conversation. Absent on other runs, and on turns that ran before Kindgi 0.1.3.
object
The agent id.
The agent version that ran (semver).
Why this version ran: named by the caller (explicit); held by the flow version a flow’s agent step runs in (flow-pin: the node’s config.version, else the version the flow version pinned when it was published); the conversation’s own (conversation); the version live for the run’s scope (live); or the latest, nothing being live (latest). Absent on runs from before Kindgi 0.1.4.
The agent’s default for the whole tenant.
object
An org’s projects.
object
One project.
object
A segment path within a project: it covers every run whose path starts with it.
object
object
Lowercase, like an identifier: company, contact-role.
Set on a suspended run by GET /v1/runs/{runId} (not the list): what it waits for, its journal’s open waits. approvals: those still to be decided, linked to the waits. other: the rest. Absent from a runtime before Kindgi 0.1.6, or when the journal can’t be read; kindgi runs resume then works it out itself.
object
An approval the run waits for, as a run reader sees it: its identity and state. Its subject’s details, description, context and decision stay on GET /v1/approvals/{approvalId}, behind the reviewer gate.
object
Still to be decided: pending, assigned, in_review or escalated.
The reviewer role that may decide it, or above.
What waits: e.g. tool-call:pending (a tool call held for review).
For a tool call held for review: which tool and which call. Never the call’s arguments.
object
The tool id.
The model’s id for the call.
child-run (childRunId, childStatus, timesOutAt): a child run must finish. decided-approval (approvalId, approvalStatus): decided, the runtime continues. unattributed (tokenId, timesOutAt): a wait no approval is linked to. no-open-wait: the journal shows none; the runtime picks the run up again.
object
Set on a run a trigger started: the trigger and the fire that started it. Absent on other runs. The runtime fires schedules only; event and webhook are kept for event triggers and inbound webhooks, which aren’t served yet.
object
The fire that started the run: one entry of the trigger’s fire history.
A schedule’s fire: the occurrence the run is for.
How the run started, recorded when it was created and never changed: person (a person, signed in or with their own API key), key (a service account’s key), or the kind of trigger that fired it. A child run has its parent’s. Only person counts as attended: in any other run, or one without this field (runs from before runs recorded it), a tool that declares needsApprovalWhenUnattended waits for a person’s yes.
Set on a replay run (an eval run re-running a past run): the run it replays.
Set on a replay run: the eval run that started it.
Agents and tools a flow runs at other exact versions than the flow version’s pins (“this flow, with acme.scorer at 0.4.0”), without publishing a new flow version: a comparison’s flow candidate (versions on the start body and the run’s comparison), and the flow runs that replay it (a run’s versions). Each id must be an agent or tool the flow uses.
object
Tool id → exact version.
object
Agent id → exact version, for agent nodes with or without a version of their own.
object
The segment path the run was started with (coarse to fine), which picks live agent versions. A child run has its parent’s. Absent when there was none.
object
Lowercase, like an identifier: company, contact-role.
The W3C trace id of the request that started the run: the caller’s (from its traceparent) or one the API minted. The runtime’s records about the run carry it; GET responses answer traceresponse with each request’s own. Absent for a run no request started, and on runs from before runs recorded it.
Only in the response to POST /v1/runs, when the deployment issues public run tokens: a read-only token for this run (and its descendants) to hand to a browser, for GET /v1/runs/{runId}/progress and its stream.
When publicAccessToken stops working.
Example
{ "status": "pending", "agent": { "via": "explicit", "liveScope": { "kind": "tenant" } }, "waitingFor": { "other": [ { "what": "child-run" } ] }, "trigger": { "kind": "schedule" }, "startedBy": "person"}Run started (options.wait: false); poll GET /v1/runs/{runId}.
object
RunId.
Semver.
The failure as the runtime recorded it. Read failure instead: an agent turn records its typed error here in an internal form.
Why a failed run failed; present only on a failed run. An agent turn’s failure carries its own code (budget-exceeded, capability-routing-failed, model-invocation-failed, …; rate-limit-exceeded when a budget kept per tenant refused work the turn needed, with details naming the budget); any other failure is run-failed, with the run’s failure message.
object
What the error came from, when it says: e.g. for capability-routing-failed, the router’s capability-unsatisfiable with its reasons, by provider.
The error’s own reason, when it gives one: for a turn that ended at its approval (hitl-cancelled), timeout when nobody decided in time. Absent from an older runtime and from errors without one; read code then.
The error’s own facts, for a code that has them: for rate-limit-exceeded, limit (the budget that refused: schema-compile-time or template-render-time) and budgetMs, the names the API’s 429 uses. Never the wait: read back later, it’s stale. Absent for any other code, and from an older runtime.
object
The run’s output once it completed. Present on single-run responses; on lists only with ?include=output.
When an erasure cleared the run’s content (its input, output, failure message and journal payloads): a person’s words were erased. Structure (status, times, ids) stays.
Set on a child run (a sub-flow run, or the agent turn an agent step started): the run that started it.
Set on a child run: the node in the parent run that started it.
Set on an agent’s turn (an agent run, or the turn a flow’s agent step started): the agent, the version that ran and the conversation. Absent on other runs, and on turns that ran before Kindgi 0.1.3.
object
The agent id.
The agent version that ran (semver).
Why this version ran: named by the caller (explicit); held by the flow version a flow’s agent step runs in (flow-pin: the node’s config.version, else the version the flow version pinned when it was published); the conversation’s own (conversation); the version live for the run’s scope (live); or the latest, nothing being live (latest). Absent on runs from before Kindgi 0.1.4.
The agent’s default for the whole tenant.
object
An org’s projects.
object
One project.
object
A segment path within a project: it covers every run whose path starts with it.
object
object
Lowercase, like an identifier: company, contact-role.
Set on a suspended run by GET /v1/runs/{runId} (not the list): what it waits for, its journal’s open waits. approvals: those still to be decided, linked to the waits. other: the rest. Absent from a runtime before Kindgi 0.1.6, or when the journal can’t be read; kindgi runs resume then works it out itself.
object
An approval the run waits for, as a run reader sees it: its identity and state. Its subject’s details, description, context and decision stay on GET /v1/approvals/{approvalId}, behind the reviewer gate.
object
Still to be decided: pending, assigned, in_review or escalated.
The reviewer role that may decide it, or above.
What waits: e.g. tool-call:pending (a tool call held for review).
For a tool call held for review: which tool and which call. Never the call’s arguments.
object
The tool id.
The model’s id for the call.
child-run (childRunId, childStatus, timesOutAt): a child run must finish. decided-approval (approvalId, approvalStatus): decided, the runtime continues. unattributed (tokenId, timesOutAt): a wait no approval is linked to. no-open-wait: the journal shows none; the runtime picks the run up again.
object
Set on a run a trigger started: the trigger and the fire that started it. Absent on other runs. The runtime fires schedules only; event and webhook are kept for event triggers and inbound webhooks, which aren’t served yet.
object
The fire that started the run: one entry of the trigger’s fire history.
A schedule’s fire: the occurrence the run is for.
How the run started, recorded when it was created and never changed: person (a person, signed in or with their own API key), key (a service account’s key), or the kind of trigger that fired it. A child run has its parent’s. Only person counts as attended: in any other run, or one without this field (runs from before runs recorded it), a tool that declares needsApprovalWhenUnattended waits for a person’s yes.
Set on a replay run (an eval run re-running a past run): the run it replays.
Set on a replay run: the eval run that started it.
Agents and tools a flow runs at other exact versions than the flow version’s pins (“this flow, with acme.scorer at 0.4.0”), without publishing a new flow version: a comparison’s flow candidate (versions on the start body and the run’s comparison), and the flow runs that replay it (a run’s versions). Each id must be an agent or tool the flow uses.
object
Tool id → exact version.
object
Agent id → exact version, for agent nodes with or without a version of their own.
object
The segment path the run was started with (coarse to fine), which picks live agent versions. A child run has its parent’s. Absent when there was none.
object
Lowercase, like an identifier: company, contact-role.
The W3C trace id of the request that started the run: the caller’s (from its traceparent) or one the API minted. The runtime’s records about the run carry it; GET responses answer traceresponse with each request’s own. Absent for a run no request started, and on runs from before runs recorded it.
Only in the response to POST /v1/runs, when the deployment issues public run tokens: a read-only token for this run (and its descendants) to hand to a browser, for GET /v1/runs/{runId}/progress and its stream.
When publicAccessToken stops working.
Example
{ "status": "pending", "agent": { "via": "explicit", "liveScope": { "kind": "tenant" } }, "waitingFor": { "other": [ { "what": "child-run" } ] }, "trigger": { "kind": "schedule" }, "startedBy": "person"}Malformed request body, or the body’s projectId isn’t a project id (a UUID). Or reference-out-of-scope: the agent or flow isn’t registered in the named projectId’s project, its org or the tenant (details.issues).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Missing / malformed / expired / revoked bearer token.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}No execute on the agent or flow; or, for one more than one project serves run in one of its projects (the one named, else the conversation’s, else a project-scoped key’s when it is one of them, else its first), no call there for an agent (caller or editor) or execute there for a flow (executor or editor), asked in place of its own execute and of write on a named project; otherwise, naming a projectId without write on it; or a turn run as a participant whose memory the caller may not read (participant-not-allowed). A turn runs with its participant’s memory (the conversation’s stored participant, else input.participantId), so running as one takes being them (a person, by their user id) or write on the turn’s project, as reading their memory does. A turn into a conversation with no participant takes having opened it (the caller ?openedBy=me names) or write on its project (on its agent, for a conversation from before projects): permission-denied, with details.resource the conversation.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Agent or flow not found; or projectId names no project of this tenant (project-not-found); or input.conversationId names no conversation of this tenant (conversation-not-found), answered before any turn starts, with options.wait: false too. A caller who can’t read the conversation gets the same answer, byte for byte, in place of the 409 for a turn naming another project, or of the 403 for a conversation with no participant.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Idempotency-Key was reused with a different body; or projectId names a project other than input.conversationId’s (conversation-project-mismatch, with details.projectId and details.conversationProjectId): a conversation belongs to one project, so name its own or omit projectId; or an erasure of the turn’s person (its conversation or its participantId) is in progress (erasure-in-progress): no new turn starts for them until it completes; or the run’s project is suspended (project-suspended): no run starts in it until it’s restored.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The request body is over the API’s limit (request-too-large; details.maxBytes says how much).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Guardrail violation or budget exceeded.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}A limit of the tenant’s (set by the runtime’s operator): past its limit on runs waiting to start, rate-limit-exceeded with details.limit: 'runs-pending', with the limit in details.runsPending; a turn whose gate asked for an approval past its limit on approvals waiting for a decision, approvals-pending-limit (details.approvalsPending), when the call waits for the run (with options.wait: false, the call answers 202 and the run fails with that code). On a server with budgets kept per tenant (Kindgi Cloud), also rate-limit-exceeded when work the agent’s turn needed was refused, because this tenant’s work of that kind took details.budgetMs in the last 60 seconds: details.limit names the budget, template-render-time (rendering instructions templates) or schema-compile-time (compiling schemas). The turn’s run failed with this error (details.runId); Retry-After says when to start the turn again.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Server error (unmapped domain code or framework crash).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}See also
GET /v1/runs: List runs- Security
- Operate a self-hosted runtime
- Organize work by org and project
- Error code
approvals-pending-limit - Error code
conversation-not-found - Error code
conversation-project-mismatch - Error code
erasure-in-progress - Error code
participant-not-allowed - Error code
permission-denied - Error code
project-not-found - Error code
project-suspended - Error code
rate-limit-exceeded - Error code
reference-out-of-scope - Error code
request-too-large - Every error code