Make a version live for a scope
const url = 'https://example.com/v1/agents/example/promotions';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"version":"example","scope":{"kind":"tenant"},"reason":"example","evalRunId":"example"}'};
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/agents/example/promotions \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "version": "example", "scope": { "kind": "tenant" }, "reason": "example", "evalRunId": "example" }'Pins version live for scope: runs in that scope that don’t name a version use it, from the next run. Open conversations keep their version. The version must be registered and active. Every promotion is recorded, with who asked and why. Needs promote on the agent.
With a gate policy for the scope (GET …/gate-policy), the promotion is checked first against the comparison named by evalRunId: 201 promoted; 202 the gate passed and the policy wants a reviewer’s approval (a HITL approval, subject agent-promotion; the live version moves once it’s approved, if nothing changed meanwhile); 422 gate-failed with details.promotionId, details.policy and every check in details.checks. A refused promotion is recorded too.
A pin in place skips the gate: when the scope has no live version of its own and already serves exactly version (from a scope above, or as the latest), pinning it there changes nothing any run gets, so it is promoted (201) with one passing pinInPlace check, no comparison and no approval, its reason starting pin-in-place. It is re-checked as it is written; if the scope moved meanwhile, 409 promotion-superseded: check again.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”AgentId — dotted namespace (acme.drafting).
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
The agent version to make live (registered, active).
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.
The comparison this promotion was judged on.
Responses
Section titled “Responses”Promoted.
One change of a scope’s live version, kept for good: what was live before, what is after, who asked and why.
object
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.
The scope’s own pin before; null when it had none.
The scope’s own pin after; null after an unpin.
object
The comparison the change was judged on.
A promote row’s state: it changes once, from pending-approval to its final state. Absent on rollback and unpin rows, and on promotions made before gates (promoted).
One of a gate’s checks, as the promotion records it.
object
Stable: comparison.required, comparison.status, comparison.freshness, comparison.suite, sameContents, baselineIsLive, scopeCovered, evidence.<metric>.minCases|minWeight|baselineMinCases|baselineMinWeight, metric.<metric>.k|minCandidate|maxDrop, replay.maxDiverged|maxErrors|maxRefusedWrites|maxStopped, classWeights.restrictedOnly.
A plain sentence: what was found against what the policy asks.
The approval a pending-approval promotion waits on (kept once decided).
When a pending-approval promotion reached its final state.
Example
{ "scope": { "kind": "tenant" }, "action": "promote", "requestedBy": { "kind": "user" }, "status": "promoted"}The gate passed; the promotion waits for an approval (approvalId).
One change of a scope’s live version, kept for good: what was live before, what is after, who asked and why.
object
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.
The scope’s own pin before; null when it had none.
The scope’s own pin after; null after an unpin.
object
The comparison the change was judged on.
A promote row’s state: it changes once, from pending-approval to its final state. Absent on rollback and unpin rows, and on promotions made before gates (promoted).
One of a gate’s checks, as the promotion records it.
object
Stable: comparison.required, comparison.status, comparison.freshness, comparison.suite, sameContents, baselineIsLive, scopeCovered, evidence.<metric>.minCases|minWeight|baselineMinCases|baselineMinWeight, metric.<metric>.k|minCandidate|maxDrop, replay.maxDiverged|maxErrors|maxRefusedWrites|maxStopped, classWeights.restrictedOnly.
A plain sentence: what was found against what the policy asks.
The approval a pending-approval promotion waits on (kept once decided).
When a pending-approval promotion reached its final state.
Example
{ "scope": { "kind": "tenant" }, "action": "promote", "requestedBy": { "kind": "user" }, "status": "promoted"}Malformed request body.
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" }}The version is not registered, or was unregistered; or the eval run is not found.
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" }}promotion-superseded: the scope’s live version changed while the gate ran; check again. gate-policy-descendant-unpinned: the change would also move a narrower scope a gate policy applies to, which has no live version of its own and so follows this scope, without its gate; the message names each one: pin it at its current version first.
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" }}gate-failed: the gate refused it. details.checks has every check; the refusal is recorded (details.promotionId).
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" }}promotion-gate-unsupported: a gate policy applies, and the deployment can’t record a gated promotion.
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" }}