Register an guardrail
const url = 'https://example.com/v1/guardrails';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"id":"example","projectId":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","name":"example","description":"example","kind":"zero-llm","check":"example","config":{},"action":{"on-violation":"halt","retry":{"maxAttempts":1},"escalateTo":"example","compensateWith":"example"},"severity":"info","scope":{"when":"always","agents":["example"],"flows":["example"],"tenants":["example"],"tools":["example"]},"at":"before-tool","sees":"turn","budget":{"maxCostUsd":1,"maxLatencyMs":1},"judgeCapabilities":{}}'};
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/guardrails \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "id": "example", "projectId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "name": "example", "description": "example", "kind": "zero-llm", "check": "example", "config": {}, "action": { "on-violation": "halt", "retry": { "maxAttempts": 1 }, "escalateTo": "example", "compensateWith": "example" }, "severity": "info", "scope": { "when": "always", "agents": [ "example" ], "flows": [ "example" ], "tenants": [ "example" ], "tools": [ "example" ] }, "at": "before-tool", "sees": "turn", "budget": { "maxCostUsd": 1, "maxLatencyMs": 1 }, "judgeCapabilities": {} }'Body is a full Guardrail shape. Server validates via @kindgi/guardrails.validateGuardrailSpec. The check id must reference an implementation already available to the runtime; check code is not uploaded through this route.
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). A request whose key store can’t be read before it runs is answered 503 idempotency-store-unavailable with Retry-After: nothing ran, so retry with the same key (from 0.3.0).
Request Bodyrequired
Section titled “Request Bodyrequired”Guardrail spec. Validated server-side via @kindgi/guardrails.validateGuardrailSpec. Metadata-only registration: the check id must reference an implementation already available to the runtime.
object
Project this belongs to (its content scope). Required: missing, or not a project in the caller’s tenant → 400 bad-input.
How the guardrail is checked. Open string: the built-in kinds are listed in examples; adapters register strategies for their own kinds.
Reference to the concrete check implementation registered server-side.
object
object
What a failed check does to the agent turn. Open string: the built-in actions are listed in examples, and any other non-empty name is accepted. The runtime acts on halt: the turn fails with guardrail-violation and its response is not stored. It acts on retry too: the answer goes back to the model with the check’s reason, for a new one, until retry.maxAttempts run out, and then the turn fails the same way, with details.attempts. Any other value is recorded as a violation, as log-only is, and the turn completes: in 0.1 nothing escalates or calls a compensating tool.
Counts the answers this guardrail fails in a turn, the first one included (with maxAttempts: 3 it sends a failed answer back up to twice, and the third answer it fails ends the turn). Left out, 2. The turn’s maxSteps, and the agent loop’s 32 model calls, bound it too.
object
Where an escalate goes. In 0.1 nothing escalates.
The tool id a compensate names. In 0.1 that tool isn’t called.
object
At before-tool and after-tool: the tools whose calls it checks, by id. A trailing * matches every id with that prefix, and a * anywhere else is refused. Absent: every tool.
Where in the agent’s turn the check runs: before a tool call runs, after it runs, on each model reply, or on the final answer. It must be one of the check’s points.
What the check sees: this turn, or the conversation’s earlier turns too.
object
object
Responses
Section titled “Responses”Guardrail registered.
object
Examplegenerated
{ "guardrailId": "example"}Validation failed (see details.issues); or projectId isn’t a project id (a UUID). Or reference-out-of-scope: a pack check it names isn’t registered in its project, its org or the tenant (details.issues); a built-in check is every project’s.
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 body’s projectId names no project of this tenant (project-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" }}Guardrail already registered at that id. Or environment-takes-promotions: the project is a later environment of an environment order, which takes builds only by promotion from the one before it; publish in the order’s first environment instead (details.firstProjectId, when you can read that project; details.position, the project’s place from 0). Nothing is written. Or registry-read-only: this registry takes no writes (under kindgi dev, the pack’s files are the source); the message says what to do instead.
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-config-invalid: the guardrail’s config breaks the configSchema of the check it names (a pack check’s, or a built-in’s), which would refuse it on every call. details.issues lists each problem, { path, message } with path a JSON pointer into the guardrail (/config/maxChars); the message names the guardrail, the check and the setting. Checked when the check’s deployment carries its schema.
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" }}rate-limit-exceeded with details.limit: "schema-compile-time", on a server with a compile budget (Kindgi Cloud): this tenant’s schemas spent details.budgetMs compiling in the last 60 seconds. Nothing was stored; Retry-After says when to send it 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" }}The Idempotency-Key store couldn’t be read before the request ran (idempotency-store-unavailable), so nothing was changed; Retry-After (whole seconds) says when to try again with the same key.
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/guardrails: List guardrails- Operate a self-hosted runtime
- Error code
environment-takes-promotions - Error code
guardrail-config-invalid - Error code
idempotency-store-unavailable - Error code
project-not-found - Error code
rate-limit-exceeded - Error code
reference-out-of-scope - Error code
registry-read-only - Error code
request-too-large - Every error code