Send an action through the Gate
const url = 'http://127.0.0.1:8080/v1/actions';const options = { method: 'POST', headers: { 'Deedglass-Version': '2026-10-01', Authorization: 'Bearer <token>', 'Content-Type': 'application/json' }, body: '{"tool":"fake.echo","args":{"message":"hello"},"mode":"gateway","wait":10,"context":{"client":{"name":"deedglass-cli","version":"0.1.0"},"transport":"rest"}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url http://127.0.0.1:8080/v1/actions \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --header 'Deedglass-Version: 2026-10-01' \ --data '{ "tool": "fake.echo", "args": { "message": "hello" }, "mode": "gateway", "wait": 10, "context": { "client": { "name": "deedglass-cli", "version": "0.1.0" }, "transport": "rest" } }'Every tool call an agent makes passes through here (docs/GATE.md). The Gate checks the signed intent (when the agent’s intent mode asks for one), reads the agent’s Stop state, asks the active policy, and then refuses the action, waits for a person, runs the tool (gateway mode) or authorizes the edge to run it (proxy mode). Every action it records ends as a sealed deed. status is the one field an agent needs: executed (200: the tool ran and the action is sealed, whatever the verdict), failed (200: the tool certainly didn’t apply the call), authorized (200, proxy mode: run the tool at the edge now, then report it to next_action.report_url), processing (202: still running when wait ended; poll GET /v1/actions/{id}?wait=25) and pending_approval (202: waiting for a person; next_action.poll_url waits for the decision). A refusal is an error envelope that carries the sealed action in error.action: policy_denied and policy_unavailable (403 policy_error), agent_stopped, agent_suspended and org_stopped (403 permission_error), budget_exceeded (429 rate_limit_error, with Retry-After) and tool_unknown (404). The message is the decision’s own sentence, verbatim. Malformed requests (400 validation_failed) and identity failures (intent_required, intent_invalid, intent_replay) are not recorded. A gateway action keeps running when the HTTP request ends: it is recorded and sealed either way. The Gate owns idempotency on this route, not S03’s middleware: a key names one action per agent for 24 hours, the same key with the same request answers with the original action (and Deedglass-Idempotent-Replayed: true), a duplicate that arrives while the original runs waits for it, and the same key with a different request is 422 idempotency_conflict. An agent key with actions:execute; a stopped or suspended agent’s attempt is recorded and sealed, then refused.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”The API version (YYYY-MM-DD). Leave it out to use your org’s pinned version (public routes use the latest). An unknown version is 400 api_version_invalid.
Recommended (the SDKs always send one). 1 to 255 printable ASCII characters. It names one action of this agent for 24 hours. The comparison is the request digest plus Deedglass-On-Behalf-Of and Deedglass-Session; a signed intent isn’t part of it, so a retry signed again still replays.
A signed intent: base64url of the intent’s JCS bytes, ., and base64url of the 64-byte Ed25519 signature. The intent follows the schema deedglass.intent/1; the signature input is "deedglass/intent/v1\n" followed by the intent_hash. Clocks may differ by up to 60 s either way, and an intent lives at most 5 minutes. See docs/INTENTS.md.
The end user the agent acts for, in your own ids. At most once; a malformed or repeated header is 422 validation_failed.
The conversation or session the call belongs to, in your own ids. At most once; a malformed or repeated header is 422 validation_failed.
Request Bodyrequired
Section titled “Request Bodyrequired”The body of POST /v1/actions.
object
<connector>.<tool>, split at the first dot. The connector is ^[a-z][a-z0-9-]{1,31}$. The tool part is ^[a-z][a-z0-9_]{0,63}$ for native connectors, and the MCP charset ^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$ in proxy mode. Empty, over 200 bytes or not UTF-8 is 400 validation_failed; any other name that isn’t a tool, or that no connector serves in gateway mode, is recorded, sealed and refused with 404 tool_unknown.
The tool’s arguments, a JSON object ({} for none): at most gate.max_args_bytes (256 KiB), nested at most 32 levels, and no integer beyond ±9007199254740991, which RFC 8785 would round (send it as a string). Floats are fine.
object
gateway: Deedglass runs the tool through a connector. proxy: the edge runs it and reports the result.
Seconds to wait for a gateway action to finish before answering 202 processing. The default is gate.wait_timeout (10 s). 0 answers at once.
Who sent the action, as the client says. Never part of any digest; at most 4 KiB.
object
object
rest, sdk, mcp_stdio or mcp_http. A call through mcp_stdio or mcp_http for an agent whose intent mode is required is refused with intent_required.
The agent framework’s own id for this tool call (a LangChain tool_call_id, a Claude tool_use_id, an OpenAI call_id), stored with the context for correlation. Never part of a digest or a deed. Added 2026-10-05 (S32), additive.
Proxy mode only: the edge’s connector type (default mcp). postgres turns on the SQL facts for a string args.sql. In gateway mode it is 400 validation_failed.
The digest of the tool’s definition, sent by MCP edges. Part of request_digest.
S40, additive. Gateway mode only (proxy: 400 validation_failed, param: schedule). With require_approval, the approved action runs inside the window: the countersign schedules the run at not_before, and past not_after it is cancelled and sealed with schedule_missed. With allow, it runs now when not_before is at most 60 seconds away and is denied (schedule_needs_approval) otherwise. At least 5 minutes long, not_after within 72 hours and still ahead. Bound into the approval’s context_digest.
object
Examples
Deedglass runs the tool
{ "tool": "fake.echo", "args": { "message": "hello" }, "mode": "gateway", "wait": 10, "context": { "client": { "name": "deedglass-cli", "version": "0.1.0" }, "transport": "rest" }}The edge runs the tool and reports back
{ "tool": "filesystem.write_file", "args": { "path": "/tmp/deedglass-demo/allowed/notes.txt", "content": "hello" }, "mode": "proxy", "connector_type": "mcp", "tool_digest": "sha256:7c675408077d30b6ef05421be9370eb9c75c661f7cd6966c1b73454db1cc8018", "context": { "client": { "name": "deedglass-mcp", "version": "0.1.0" }, "transport": "mcp_stdio" }}Responses
Section titled “Responses”executed or failed (sealed), or authorized (proxy mode). execution.result holds the tool’s result on this response only.
One agent action. Its sections mirror the deed’s. status is the one field an agent needs; state is the exact lifecycle state (docs/GATE.md). The Gate’s own responses (POST /v1/actions and its result report) add execution.result and witness.reasons; lists leave both out.
object
true for a dg_live_ key, false for a dg_test_ key. Recorded, not enforced: connectors have no test mode in v1.
object
executed: the tool ran and the action is sealed, whatever the verdict. failed: the tool certainly didn’t apply the call. authorized: proxy mode, run the tool at the edge now. processing: still executing or witnessing. pending_approval: waiting for a person. denied: a policy, a budget or Stop refused it, and nothing ran. expired and cancelled: it waited for approval and never ran. A sealed action keeps the status of the state it was sealed from.
The action’s undo object (S23). undoes names the action an undo puts back; undone_by names the undo that put this one back; pending an undo waiting for approval or running. eligible is cheap (L2 evidence from a bound transaction, gateway mode, sealed, not undone, within undo.max_age, the row images kept): it only decides whether the Console shows Preview undo. The full answer is always the preview.
object
S40, additive: the window an approved action runs in, stored once at creation and never changed. Absent when the request carried no schedule.
object
The policy decision as an agent reads it: S11’s decision, its source, its message verbatim, the policy version that made it (pinned: a later activation doesn’t change it), and the shadow decision next to it. null until the action is evaluated.
object
The refusal code (policy_denied, budget_exceeded, agent_stopped, tool_unknown, …), approval_required, or null for an allow.
builtin is the Gate’s own decision, such as tool_unknown.
The sentence the agent sees
The policy id (pol_…).
The policy version id (pv_…).
S27, additive: the decision trace’s line about the anomaly facts the policy saw, like anomaly facts: volume_spike, or anomaly facts: detector_stale (…) when detection was behind and the policy treated the agent as anomalous. Absent when no anomaly fact was active.
What the shadow policy would have decided. Recorded, never enforced.
object
object
The approval the action waits for, or waited for. null when no rule asked for one.
object
The approval id (apr_…).
S22, additive: the reason a person gave when they denied it. Absent otherwise.
object
A short, redacted message from the tool or the Gate (at most 1 KiB).
The tool’s result. Only on the Gate’s own responses (POST /v1/actions and POST /v1/actions/{id}/result); never on lists. GET /v1/actions/{id} has it as the top-level result.
The Witness’s verdict about the action (S19): one level, one verdict and the method of that level. A verdict is never stronger than its evidence: VERIFIED needs a clean level at or above required_level; any contradicting evidence is MISMATCH; missing evidence is UNVERIFIABLE. Lists carry the claim only. The Gate’s own responses and GET /v1/actions/{id} add summary, reasons (violations and gaps; passes and notes are in the detail) and witnessed_at; ?expand[]=witness.detail adds detail. An executed action answers 200 whatever the verdict: the tool ran, and the verdict says what that means.
object
The claimed level’s method: reported, edge_reported or response.schema (L0); readback.<connector type>.<read tool>, readback.postgres.row or postcondition.<connector type> (L1); postgres.pgoutput (L2).
The level the policy’s verify: asks for (null on actions recorded before S19).
One sentence a support engineer can read aloud.
One piece of evidence, or one missing piece. The class and the message come from the reason catalog (docs/witness/REASONS.md). The full WitnessReason schema is in openapi.yaml.
object
sha256: of JCS(witness_detail): the deed’s witness.detail_digest.
Witness_detail v1 (S19): what actions.witness_detail holds and what the deed’s witness.detail_digest is the digest of. Changes are additive only; S21 fills levels.L2. The full WitnessDetail schema is in openapi.yaml.
object
GET /v1/actions/{id} only (S21): every witness section sealed about the action, oldest first: the action deed, then any amendment deeds (a later verdict never edits a deed; at most three amendments). An entry a later amendment replaced names the reason it stopped where it did (l2_timeout, …).
object
object
“sha256:” + lowercase hex of SHA-256.
What the caller does next. await_approval: wait for a person (poll_url long-polls the action). execute_at_edge: proxy mode, run the tool at the edge and report the result to report_url before deadline. scheduled (S40): approved, it runs between not_before and not_after. null otherwise.
object
await_approval only: the approval id.
scheduled only (S40): an approved action runs from this time.
scheduled only (S40): past it the action is cancelled and sealed with schedule_missed; nothing runs.
await_approval only.
await_approval only: /v1/actions/{id}?wait=25.
execute_at_edge only: /v1/actions/{id}/result.
execute_at_edge only: after it, the action is sealed UNVERIFIABLE (edge_lost).
Examples
Gateway mode, executed and sealed
{ "object": "action", "id": "act_01k6w3p8r2t4v6x8z0b2d4f6h8", "created_at": "2026-10-05T04:12:09.114Z", "livemode": false, "agent": { "id": "agt_01k633rrmh3bcz2p39gg4vp46q", "name": "support-bot" }, "tool": "fake.echo", "connector": null, "mode": "gateway", "state": "sealed", "status": "executed", "on_behalf_of": null, "session": null, "decision": { "outcome": "allow", "code": null, "source": "rule", "rule_id": "allow-fake", "reason": "Fake tools are safe to run.", "message": null, "policy": "pol_01k6r2m8q0s2v4x6z8b0d2f4h6", "policy_version": "pv_01k6r2m9a1c3e5g7j9m1q3s5v7", "shadow": null }, "policy": { "id": "pol_01k6r2m8q0s2v4x6z8b0d2f4h6", "version_id": "pv_01k6r2m9a1c3e5g7j9m1q3s5v7", "mode": "enforce", "decision": "allow", "rule_id": "allow-fake" }, "approval": null, "execution": { "status": "succeeded", "started_at": "2026-10-05T04:12:09.116Z", "finished_at": "2026-10-05T04:12:09.117Z", "latency_ms": 1, "error_code": null, "error_message": null, "result": { "echo": { "message": "hello" } } }, "witness": { "object": "witness", "level": "L0", "verdict": "VERIFIED", "method": "reported", "required_level": "L0", "summary": "The tool reported success.", "reasons": [], "witnessed_at": "2026-10-05T04:12:09.130Z", "detail_digest": "sha256:0b5f2e9a7c4d1e8f3a6b9c2d5e8f1a4b7c0d3e6f9a2b5c8d1e4f7a0b3c6d9e2f" }, "cost": { "amount": 0, "currency": "usd" }, "request_digest": "sha256:c2cb9a8c51c029f97049fed02f985cc49cee22836423d2c9a8e1b74e333a3c4c", "result_digest": "sha256:fca08626754877b4929151a6f5a278d4189da0bdff4e71b4f523d6f97bb8f0d0", "payload_pruned_at": null, "deed": "deed_01k6w3p9a1c3e5g7j9m1q3s5v7", "next_action": null}Proxy mode, the edge may run the tool now
{ "object": "action", "id": "act_01k6w5b3d5f7h9k1n3q5s7w9y1", "created_at": "2026-10-05T04:20:10.902Z", "livemode": false, "agent": { "id": "agt_01k633rrmh3bcz2p39gg4vp46q", "name": "support-bot" }, "tool": "filesystem.write_file", "connector": null, "mode": "proxy", "state": "executing", "status": "authorized", "on_behalf_of": null, "session": null, "decision": { "outcome": "allow", "code": null, "source": "rule", "rule_id": "allow-demo-dir", "reason": "Writes inside the demo folder are fine.", "message": null, "policy": "pol_01k6r2m8q0s2v4x6z8b0d2f4h6", "policy_version": "pv_01k6r2m9a1c3e5g7j9m1q3s5v7", "shadow": null }, "policy": { "id": "pol_01k6r2m8q0s2v4x6z8b0d2f4h6", "version_id": "pv_01k6r2m9a1c3e5g7j9m1q3s5v7", "mode": "enforce", "decision": "allow", "rule_id": "allow-demo-dir" }, "approval": null, "execution": null, "witness": null, "cost": null, "request_digest": "sha256:30f3b488ca53be83e50a9adf9c649ec4d2c1ec5087de8ebfc473bc1b834c01de", "result_digest": null, "payload_pruned_at": null, "deed": null, "next_action": { "type": "execute_at_edge", "report_url": "/v1/actions/act_01k6w5b3d5f7h9k1n3q5s7w9y1/result", "deadline": "2026-10-05T04:30:10.903Z" }}Headers
Section titled “Headers”This request’s id. Quote it to support; it matches error.request_id.
The API version this response follows.
Present, and true, when the response is a stored one replayed for an Idempotency-Key.
processing (still executing or witnessing when wait ended) or pending_approval (waiting for a person). Poll GET /v1/actions/{id}?wait=25.
One agent action. Its sections mirror the deed’s. status is the one field an agent needs; state is the exact lifecycle state (docs/GATE.md). The Gate’s own responses (POST /v1/actions and its result report) add execution.result and witness.reasons; lists leave both out.
object
true for a dg_live_ key, false for a dg_test_ key. Recorded, not enforced: connectors have no test mode in v1.
object
executed: the tool ran and the action is sealed, whatever the verdict. failed: the tool certainly didn’t apply the call. authorized: proxy mode, run the tool at the edge now. processing: still executing or witnessing. pending_approval: waiting for a person. denied: a policy, a budget or Stop refused it, and nothing ran. expired and cancelled: it waited for approval and never ran. A sealed action keeps the status of the state it was sealed from.
The action’s undo object (S23). undoes names the action an undo puts back; undone_by names the undo that put this one back; pending an undo waiting for approval or running. eligible is cheap (L2 evidence from a bound transaction, gateway mode, sealed, not undone, within undo.max_age, the row images kept): it only decides whether the Console shows Preview undo. The full answer is always the preview.
object
S40, additive: the window an approved action runs in, stored once at creation and never changed. Absent when the request carried no schedule.
object
The policy decision as an agent reads it: S11’s decision, its source, its message verbatim, the policy version that made it (pinned: a later activation doesn’t change it), and the shadow decision next to it. null until the action is evaluated.
object
The refusal code (policy_denied, budget_exceeded, agent_stopped, tool_unknown, …), approval_required, or null for an allow.
builtin is the Gate’s own decision, such as tool_unknown.
The sentence the agent sees
The policy id (pol_…).
The policy version id (pv_…).
S27, additive: the decision trace’s line about the anomaly facts the policy saw, like anomaly facts: volume_spike, or anomaly facts: detector_stale (…) when detection was behind and the policy treated the agent as anomalous. Absent when no anomaly fact was active.
What the shadow policy would have decided. Recorded, never enforced.
object
object
The approval the action waits for, or waited for. null when no rule asked for one.
object
The approval id (apr_…).
S22, additive: the reason a person gave when they denied it. Absent otherwise.
object
A short, redacted message from the tool or the Gate (at most 1 KiB).
The tool’s result. Only on the Gate’s own responses (POST /v1/actions and POST /v1/actions/{id}/result); never on lists. GET /v1/actions/{id} has it as the top-level result.
The Witness’s verdict about the action (S19): one level, one verdict and the method of that level. A verdict is never stronger than its evidence: VERIFIED needs a clean level at or above required_level; any contradicting evidence is MISMATCH; missing evidence is UNVERIFIABLE. Lists carry the claim only. The Gate’s own responses and GET /v1/actions/{id} add summary, reasons (violations and gaps; passes and notes are in the detail) and witnessed_at; ?expand[]=witness.detail adds detail. An executed action answers 200 whatever the verdict: the tool ran, and the verdict says what that means.
object
The claimed level’s method: reported, edge_reported or response.schema (L0); readback.<connector type>.<read tool>, readback.postgres.row or postcondition.<connector type> (L1); postgres.pgoutput (L2).
The level the policy’s verify: asks for (null on actions recorded before S19).
One sentence a support engineer can read aloud.
One piece of evidence, or one missing piece. The class and the message come from the reason catalog (docs/witness/REASONS.md). The full WitnessReason schema is in openapi.yaml.
object
sha256: of JCS(witness_detail): the deed’s witness.detail_digest.
Witness_detail v1 (S19): what actions.witness_detail holds and what the deed’s witness.detail_digest is the digest of. Changes are additive only; S21 fills levels.L2. The full WitnessDetail schema is in openapi.yaml.
object
GET /v1/actions/{id} only (S21): every witness section sealed about the action, oldest first: the action deed, then any amendment deeds (a later verdict never edits a deed; at most three amendments). An entry a later amendment replaced names the reason it stopped where it did (l2_timeout, …).
object
object
“sha256:” + lowercase hex of SHA-256.
What the caller does next. await_approval: wait for a person (poll_url long-polls the action). execute_at_edge: proxy mode, run the tool at the edge and report the result to report_url before deadline. scheduled (S40): approved, it runs between not_before and not_after. null otherwise.
object
await_approval only: the approval id.
scheduled only (S40): an approved action runs from this time.
scheduled only (S40): past it the action is cancelled and sealed with schedule_missed; nothing runs.
await_approval only.
await_approval only: /v1/actions/{id}?wait=25.
execute_at_edge only: /v1/actions/{id}/result.
execute_at_edge only: after it, the action is sealed UNVERIFIABLE (edge_lost).
Example
{ "object": "action", "id": "act_01k6w6c4e6g8j0m2p4r6t8w0y2", "created_at": "2026-10-05T04:25:31.208Z", "livemode": false, "agent": { "id": "agt_01k633rrmh3bcz2p39gg4vp46q", "name": "support-bot" }, "tool": "fake.write", "connector": null, "mode": "gateway", "state": "pending_approval", "status": "pending_approval", "on_behalf_of": "u_4821", "session": null, "decision": { "outcome": "require_approval", "code": "approval_required", "source": "rule", "rule_id": "writes-need-approval", "reason": "Writes wait for a human.", "message": "Waiting for approval under policy \"writes-need-approval\": Writes wait for a human.", "policy": "pol_01k6r2m8q0s2v4x6z8b0d2f4h6", "policy_version": "pv_01k6r2m9a1c3e5g7j9m1q3s5v7", "shadow": null }, "policy": { "id": "pol_01k6r2m8q0s2v4x6z8b0d2f4h6", "version_id": "pv_01k6r2m9a1c3e5g7j9m1q3s5v7", "mode": "enforce", "decision": "require_approval", "rule_id": "writes-need-approval" }, "approval": { "id": "apr_01k6w6c5f7h9k1n3q5s7v9x1z3", "status": "pending", "expires_at": "2026-10-05T04:40:31.210Z" }, "execution": null, "witness": null, "cost": null, "request_digest": "sha256:f7ee87ae04b701c55919513f07a30d1c1d738b0373f17df44ed99607f3580749", "result_digest": null, "payload_pruned_at": null, "deed": null, "next_action": { "type": "await_approval", "approval": "apr_01k6w6c5f7h9k1n3q5s7v9x1z3", "expires_at": "2026-10-05T04:40:31.210Z", "poll_url": "/v1/actions/act_01k6w6c4e6g8j0m2p4r6t8w0y2?wait=25" }}Headers
Section titled “Headers”This request’s id. Quote it to support; it matches error.request_id.
The API version this response follows.
Present, and true, when the response is a stored one replayed for an Idempotency-Key.
validation_failed: a malformed request, not recorded. param names the field (tool, args, mode, wait, connector_type, tool_digest, context.transport, context.client).
object
object
One or more calm sentences with the next step.
The request field, query parameter or header the error is about.
On policy_invalid only. Each problem with its line, code and hint.
One finding about a policy file, with its position and the next step. Codes are stable and listed in docs/POLICY_ERRORS.md. In the policy_invalid error envelope each diagnostic also carries object: policy_diagnostic. The full PolicyDiagnostic schema is in openapi.yaml.
object
One agent action. Its sections mirror the deed’s. status is the one field an agent needs; state is the exact lifecycle state (docs/GATE.md). The Gate’s own responses (POST /v1/actions and its result report) add execution.result and witness.reasons; lists leave both out. The full Action schema is in openapi.yaml.
object
On undo_unavailable only. Every check of the undo, each with its fix. Additive (S23).
One of the twelve safety checks (S23 §3.3). Available means no check failed. The full UndoCheck schema is in openapi.yaml.
object
Example
{ "error": { "type": "invalid_request_error", "code": "validation_failed", "message": "args is 312 KiB; the limit is 256 KiB. Send a reference to the data instead of the data itself.", "param": "args", "request_id": "req_01k6w4a3d5f7h9k1n3q5s7v9x1", "doc_url": "https://docs.deedglass.com/errors/validation_failed" }}Headers
Section titled “Headers”This request’s id. Quote it to support; it matches error.request_id.
The API key is missing, not valid, revoked or expired. Nothing is recorded.
object
object
One or more calm sentences with the next step.
The request field, query parameter or header the error is about.
On policy_invalid only. Each problem with its line, code and hint.
One finding about a policy file, with its position and the next step. Codes are stable and listed in docs/POLICY_ERRORS.md. In the policy_invalid error envelope each diagnostic also carries object: policy_diagnostic. The full PolicyDiagnostic schema is in openapi.yaml.
object
One agent action. Its sections mirror the deed’s. status is the one field an agent needs; state is the exact lifecycle state (docs/GATE.md). The Gate’s own responses (POST /v1/actions and its result report) add execution.result and witness.reasons; lists leave both out. The full Action schema is in openapi.yaml.
object
On undo_unavailable only. Every check of the undo, each with its fix. Additive (S23).
One of the twelve safety checks (S23 §3.3). Available means no check failed. The full UndoCheck schema is in openapi.yaml.
object
Example
{ "error": { "type": "invalid_request_error", "code": "not_found", "message": "There's no endpoint at GET /v1/helth. Did you mean /v1/health?", "param": null, "request_id": "req_01j9zr3m5k8q2w7x4t6v0b1c9d", "doc_url": "https://docs.deedglass.com/errors/not_found" }}Headers
Section titled “Headers”This request’s id. Quote it to support; it matches error.request_id.
Refused. policy_denied and policy_unavailable (policy_error), and agent_stopped, agent_suspended and org_stopped (permission_error) are recorded and sealed, and carry the action in error.action. intent_required, intent_invalid and intent_replay (permission_error) and insufficient_scope are identity failures: nothing is recorded and there is no error.action.
object
object
One or more calm sentences with the next step.
The request field, query parameter or header the error is about.
On policy_invalid only. Each problem with its line, code and hint.
One finding about a policy file, with its position and the next step. Codes are stable and listed in docs/POLICY_ERRORS.md. In the policy_invalid error envelope each diagnostic also carries object: policy_diagnostic. The full PolicyDiagnostic schema is in openapi.yaml.
object
One agent action. Its sections mirror the deed’s. status is the one field an agent needs; state is the exact lifecycle state (docs/GATE.md). The Gate’s own responses (POST /v1/actions and its result report) add execution.result and witness.reasons; lists leave both out. The full Action schema is in openapi.yaml.
object
On undo_unavailable only. Every check of the undo, each with its fix. Additive (S23).
One of the twelve safety checks (S23 §3.3). Available means no check failed. The full UndoCheck schema is in openapi.yaml.
object
Examples
A rule denied it; the refusal is sealed
{ "error": { "type": "policy_error", "code": "policy_denied", "message": "Blocked by policy \"no-bulk-writes\": writes over 100 rows need a person, not an agent.", "param": null, "request_id": "req_01k6w4a3d5f7h9k1n3q5s7v9x1", "doc_url": "https://docs.deedglass.com/errors/policy_denied", "action": { "object": "action", "id": "act_01k6w4a2c4e6g8j0m2p4r6t8v0", "created_at": "2026-10-05T04:14:52.630Z", "livemode": false, "agent": { "id": "agt_01k633rrmh3bcz2p39gg4vp46q", "name": "support-bot" }, "tool": "fake.write", "connector": null, "mode": "gateway", "state": "sealed", "status": "denied", "on_behalf_of": null, "session": null, "decision": { "outcome": "deny", "code": "policy_denied", "source": "rule", "rule_id": "no-bulk-writes", "reason": "writes over 100 rows need a person, not an agent.", "message": "Blocked by policy \"no-bulk-writes\": writes over 100 rows need a person, not an agent.", "policy": "pol_01k6r2m8q0s2v4x6z8b0d2f4h6", "policy_version": "pv_01k6r2m9a1c3e5g7j9m1q3s5v7", "shadow": null }, "policy": { "id": "pol_01k6r2m8q0s2v4x6z8b0d2f4h6", "version_id": "pv_01k6r2m9a1c3e5g7j9m1q3s5v7", "mode": "enforce", "decision": "deny", "rule_id": "no-bulk-writes" }, "approval": null, "execution": null, "witness": null, "cost": null, "request_digest": "sha256:be1b8c0dafafa9da4de5a1acf33834b5d7306ea41eec46ea1f8befb7985332dc", "result_digest": null, "payload_pruned_at": null, "deed": "deed_01k6w4a4e6g8j0m2p4r6t8w0y2", "next_action": null } }}The agent is stopped; its attempt is sealed
{ "error": { "type": "permission_error", "code": "agent_stopped", "message": "Agent \"support-bot\" is stopped. Deedglass refuses its calls until an admin starts it in Console › Agents.", "param": null, "request_id": "req_01k6w4a3d5f7h9k1n3q5s7v9x1", "doc_url": "https://docs.deedglass.com/errors/agent_stopped", "action": { "object": "action", "id": "act_01k6w4a2c4e6g8j0m2p4r6t8v0", "state": "sealed", "status": "denied", "deed": "deed_01k6w4a4e6g8j0m2p4r6t8w0y2" } }}An MCP call for an agent that must sign; nothing is recorded
{ "error": { "type": "permission_error", "code": "intent_required", "message": "Agent \"support-bot\" requires a signed intent for every call, and MCP clients can't sign intents yet. Call it through the SDK or the REST API, or an admin can set its intent mode to optional in Console › Agents.", "param": "Deedglass-Intent", "request_id": "req_01k6w4a3d5f7h9k1n3q5s7v9x1", "doc_url": "https://docs.deedglass.com/errors/intent_required" }}Headers
Section titled “Headers”This request’s id. Quote it to support; it matches error.request_id.
tool_unknown: no connector serves the tool (gateway mode), or the name isn’t a tool name (a look-alike, say). The attempt is recorded and sealed (decision.source: builtin), and error.action carries it.
object
object
One or more calm sentences with the next step.
The request field, query parameter or header the error is about.
On policy_invalid only. Each problem with its line, code and hint.
One finding about a policy file, with its position and the next step. Codes are stable and listed in docs/POLICY_ERRORS.md. In the policy_invalid error envelope each diagnostic also carries object: policy_diagnostic. The full PolicyDiagnostic schema is in openapi.yaml.
object
One agent action. Its sections mirror the deed’s. status is the one field an agent needs; state is the exact lifecycle state (docs/GATE.md). The Gate’s own responses (POST /v1/actions and its result report) add execution.result and witness.reasons; lists leave both out. The full Action schema is in openapi.yaml.
object
On undo_unavailable only. Every check of the undo, each with its fix. Additive (S23).
One of the twelve safety checks (S23 §3.3). Available means no check failed. The full UndoCheck schema is in openapi.yaml.
object
Example
{ "error": { "type": "invalid_request_error", "code": "tool_unknown", "message": "No tool named \"fake.ecko\". Tools look like \"connector.tool\", for example \"fake.echo\".", "param": null, "request_id": "req_01k6w4a3d5f7h9k1n3q5s7v9x1", "doc_url": "https://docs.deedglass.com/errors/tool_unknown", "action": { "object": "action", "id": "act_01k6w4a2c4e6g8j0m2p4r6t8v0", "tool": "fake.ecko", "state": "sealed", "status": "denied", "deed": "deed_01k6w4a4e6g8j0m2p4r6t8w0y2" } }}Headers
Section titled “Headers”This request’s id. Quote it to support; it matches error.request_id.
idempotency_key_in_use, rarely: two requests with the same key raced, and the other one’s action can’t be read yet. Retry in a moment with the same key.
object
object
One or more calm sentences with the next step.
The request field, query parameter or header the error is about.
On policy_invalid only. Each problem with its line, code and hint.
One finding about a policy file, with its position and the next step. Codes are stable and listed in docs/POLICY_ERRORS.md. In the policy_invalid error envelope each diagnostic also carries object: policy_diagnostic. The full PolicyDiagnostic schema is in openapi.yaml.
object
One agent action. Its sections mirror the deed’s. status is the one field an agent needs; state is the exact lifecycle state (docs/GATE.md). The Gate’s own responses (POST /v1/actions and its result report) add execution.result and witness.reasons; lists leave both out. The full Action schema is in openapi.yaml.
object
On undo_unavailable only. Every check of the undo, each with its fix. Additive (S23).
One of the twelve safety checks (S23 §3.3). Available means no check failed. The full UndoCheck schema is in openapi.yaml.
object
Example
{ "error": { "type": "invalid_request_error", "code": "not_found", "message": "There's no endpoint at GET /v1/helth. Did you mean /v1/health?", "param": null, "request_id": "req_01j9zr3m5k8q2w7x4t6v0b1c9d", "doc_url": "https://docs.deedglass.com/errors/not_found" }}Headers
Section titled “Headers”This request’s id. Quote it to support; it matches error.request_id.
idempotency_conflict: this agent used the Idempotency-Key in the last 24 hours with a different request (another tool, other arguments, another on-behalf-of or session). Also validation_failed for a malformed Deedglass-On-Behalf-Of or Deedglass-Session header.
object
object
One or more calm sentences with the next step.
The request field, query parameter or header the error is about.
On policy_invalid only. Each problem with its line, code and hint.
One finding about a policy file, with its position and the next step. Codes are stable and listed in docs/POLICY_ERRORS.md. In the policy_invalid error envelope each diagnostic also carries object: policy_diagnostic. The full PolicyDiagnostic schema is in openapi.yaml.
object
One agent action. Its sections mirror the deed’s. status is the one field an agent needs; state is the exact lifecycle state (docs/GATE.md). The Gate’s own responses (POST /v1/actions and its result report) add execution.result and witness.reasons; lists leave both out. The full Action schema is in openapi.yaml.
object
On undo_unavailable only. Every check of the undo, each with its fix. Additive (S23).
One of the twelve safety checks (S23 §3.3). Available means no check failed. The full UndoCheck schema is in openapi.yaml.
object
Example
{ "error": { "type": "invalid_request_error", "code": "idempotency_conflict", "message": "This Idempotency-Key was used with a different request in the last 24 hours. Use a new key for a new request.", "param": "Idempotency-Key", "request_id": "req_01k6w4a3d5f7h9k1n3q5s7v9x1", "doc_url": "https://docs.deedglass.com/errors/idempotency_conflict" }}Headers
Section titled “Headers”This request’s id. Quote it to support; it matches error.request_id.
budget_exceeded: a budget refused it. The refusal is recorded and sealed, and error.action carries it. Retry-After says when the budget’s window resets.
object
object
One or more calm sentences with the next step.
The request field, query parameter or header the error is about.
On policy_invalid only. Each problem with its line, code and hint.
One finding about a policy file, with its position and the next step. Codes are stable and listed in docs/POLICY_ERRORS.md. In the policy_invalid error envelope each diagnostic also carries object: policy_diagnostic. The full PolicyDiagnostic schema is in openapi.yaml.
object
One agent action. Its sections mirror the deed’s. status is the one field an agent needs; state is the exact lifecycle state (docs/GATE.md). The Gate’s own responses (POST /v1/actions and its result report) add execution.result and witness.reasons; lists leave both out. The full Action schema is in openapi.yaml.
object
On undo_unavailable only. Every check of the undo, each with its fix. Additive (S23).
One of the twelve safety checks (S23 §3.3). Available means no check failed. The full UndoCheck schema is in openapi.yaml.
object
Example
{ "error": { "type": "rate_limit_error", "code": "budget_exceeded", "message": "Budget \"agent-rate\" reached: 60 of 60 calls this minute. Try again in 14 s.", "param": null, "request_id": "req_01k6w4a3d5f7h9k1n3q5s7v9x1", "doc_url": "https://docs.deedglass.com/errors/budget_exceeded", "action": { "object": "action", "id": "act_01k6w4a2c4e6g8j0m2p4r6t8v0", "state": "sealed", "status": "denied", "deed": "deed_01k6w4a4e6g8j0m2p4r6t8w0y2" } }}Headers
Section titled “Headers”This request’s id. Quote it to support; it matches error.request_id.
Seconds until the budget’s window resets, at least 1.
default
Section titled “default”An error. Every error has this envelope; doc_url explains the code.
object
object
One or more calm sentences with the next step.
The request field, query parameter or header the error is about.
On policy_invalid only. Each problem with its line, code and hint.
One finding about a policy file, with its position and the next step. Codes are stable and listed in docs/POLICY_ERRORS.md. In the policy_invalid error envelope each diagnostic also carries object: policy_diagnostic. The full PolicyDiagnostic schema is in openapi.yaml.
object
One agent action. Its sections mirror the deed’s. status is the one field an agent needs; state is the exact lifecycle state (docs/GATE.md). The Gate’s own responses (POST /v1/actions and its result report) add execution.result and witness.reasons; lists leave both out. The full Action schema is in openapi.yaml.
object
On undo_unavailable only. Every check of the undo, each with its fix. Additive (S23).
One of the twelve safety checks (S23 §3.3). Available means no check failed. The full UndoCheck schema is in openapi.yaml.
object
Example
{ "error": { "type": "invalid_request_error", "code": "not_found", "message": "There's no endpoint at GET /v1/helth. Did you mean /v1/health?", "param": null, "request_id": "req_01j9zr3m5k8q2w7x4t6v0b1c9d", "doc_url": "https://docs.deedglass.com/errors/not_found" }}Headers
Section titled “Headers”This request’s id. Quote it to support; it matches error.request_id.
The API version this response follows.