Gate Agent API Reference
Your runtime owns reasoning and execution. Gate exposes six authenticated endpoints that wrap governed tool execution with contracts, policy, review, decisions, signed approval validation, and audit evidence.
Use your own Gate installation as STACKSONA_GATE_URL and the agent's sg_ key as a Bearer token. JSON requests use Content-Type: application/json.
Gate wraps execution, it does not run the tools
Keep provider keys, service credentials, executable functions, retries, and business logic in your runtime. Resolve contracts earlier if useful, but evaluate the exact final tool arguments immediately before execution.
Endpoint overview
| Method | Path | Purpose |
|---|---|---|
| POST | /api/agent/tools/resolve | Resolve governed tool contracts for the runtime. |
| POST | /api/agent/tasks/{taskID}/events | Append runtime evidence or a guarded revision event. |
| POST | /api/agent/tasks/{taskID}/requests | Evaluate the exact proposed tool call. |
| GET | /api/agent/decisions | Read one current review decision by thread or task. |
| GET | /api/agent/decisions/list | Discover pending or completed review references. |
| POST | /api/agent/approvals/validate | Validate and consume a one-time signed approval token. |
Runtime quick start
# 1. Resolve governed contracts
curl -sS -X POST "$STACKSONA_GATE_URL/api/agent/tools/resolve" \
-H "Authorization: Bearer $STACKSONA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tools":["issue_refund","send_email"]}'
# 2. Gate the exact proposed tool call
curl -sS -X POST "$STACKSONA_GATE_URL/api/agent/tasks/order-1042/requests" \
-H "Authorization: Bearer $STACKSONA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tool_name":"issue_refund","payload":{"amount":389.99,"currency":"usd"}}'
# 3. If pending_review, poll the exact returned thread
curl -sS "$STACKSONA_GATE_URL/api/agent/decisions?thread_id=THR-A1B2C3D4" \
-H "Authorization: Bearer $STACKSONA_API_KEY"1. Resolve tool contracts
/api/agent/tools/resolveResolve registered tool contracts so the runtime can reason over the same names, descriptions, and input schemas configured in Gate.
| Field | Required | Behavior |
|---|---|---|
tools | Yes | Array of 1 to 100 non-empty tool names. Exact duplicates are collapsed. Whitespace-only names are rejected. |
{
"tools": ["issue_refund", "send_email"]
}{
"tools": [
{
"name": "issue_refund",
"description": "Issue a customer refund",
"input_schema": {
"type": "object",
"required": ["amount"],
"properties": {"amount": {"type": "number"}}
}
}
],
"unregistered": ["send_email"]
}Validate model-generated arguments against input_schema in your runtime. Gate returns the schema but does not perform arbitrary JSON Schema validation on /requests.
The request body is limited to 16 KiB, unknown top-level fields are rejected, and the body must contain exactly one JSON object. A body over the current 16 KiB cap surfaces as HTTP 400.
2. Log an event
/api/agent/tasks/{taskID}/eventsAppend evidence to a runtime task. Ordinary event names are open-ended. The revision. prefix is the one namespace that changes request handling.
| Field | Required | Description |
|---|---|---|
event_type | Yes | Any non-empty event name. Use an application-owned namespace for custom evidence. |
event_summary | Yes | Human-readable evidence summary. |
payload | No | Structured event evidence object. |
images | No | Base64 evidence images when attachments are enabled. |
{
"event_type": "tool.execution.completed",
"event_summary": "Refund executed",
"payload": {"provider_id": "rf_123"}
}Success is 201 Created with no JSON body.
Event contract
Processed lifecycle names
| Event | Meaning |
|---|---|
task.started / execution.started | Start timestamp markers used by runtime projection logic. |
task.completed / execution.completed | Terminal completed marker. |
task.failed / execution.failed | Terminal failure marker. |
task.cancelled / execution.cancelled | Terminal cancellation marker. |
task.terminated / execution.terminated | Terminal forced-termination marker. |
Recommended runtime conventions
task.request.loaded, task.input.loaded, task.sop.loaded, task.tools.available, tool.execution.completed, and tool.execution.failed.
Gate-generated names
approval.requested, decision.allow, decision.reject, decision.approved, decision.rejected, task.summary, token_issued, token_consumed, and token_rejected.
Ordinary custom event names are not checked against a fixed enum or reserved-name rejection list. Use your own namespace to avoid confusing application evidence with Gate lifecycle records.
3. Request a decision
/api/agent/tasks/{taskID}/requestsEvaluate the exact tool call the runtime is about to execute. tool_name is the only required field.
| Field | Required | Default / behavior |
|---|---|---|
tool_name | Yes | Exact tool selected by the runtime. |
payload | No | Exact tool arguments. Defaults to {}. |
workflow_name | No | Defaults to agent workflow name, then agent name. |
task_label | No | Defaults to the path taskID. |
subject | No | Defaults to Review {tool_name}. |
preview | No | Short reviewer context. |
risk_level | No | low, medium, high, or critical. Empty or unrecognized values currently normalize to medium. |
summary | No | Review summary items. Defaults to an empty array. |
images | No | Base64 evidence images when attachments are enabled. |
{
"tool_name": "issue_refund",
"payload": {
"amount": 389.99,
"currency": "usd"
}
}An unregistered tool request is still gateable. Gate routes it to human review with an unregistered-tool reason.
Responses
| Status | Meaning |
|---|---|
allow | Automatic policy allow. Execute the proposed call. |
reject | Automatic policy reject. Do not execute. |
pending_review | A human-review thread was created. Persist the returned thread_id. |
{
"status": "pending_review",
"thread_id": "THR-A1B2C3D4",
"task_id": "order-1042",
"message": "Rule matched: amount upper_limit",
"recommended_poll_after_seconds": 15
}4. Get one decision
/api/agent/decisions| Query | Use |
|---|---|
thread_id | Preferred. Identifies the exact review request returned by /requests. |
task_id | Reusable grouping ID. Resolves to the newest review thread for the authenticated agent and task. |
Statuses to handle
pending_review, changes_requested, approved, and rejected.
{
"status": "changes_requested",
"thread_id": "THR-A1B2C3D4",
"task_id": "order-1042",
"message": "Reduce the amount and resubmit",
"modification": {
"requested_changes": "Reduce the amount and resubmit",
"requested_at": "2026-08-09T17:00:00Z"
},
"recommended_poll_after_seconds": 3
}When enabled, the first successful read of an approved decision may additionally include approval_token and token_expires_at. The raw token is delivered once. If signed proof is required by your runtime, a missing token must block execution.
5. List decisions
/api/agent/decisions/list| Parameter | Default | Behavior |
|---|---|---|
status | completed | completed returns approved/rejected. pending returns needs-review/escalated threads as pending_review. |
limit | 25 | Maximum 100. Results are scoped to the authenticated agent and ordered newest first. |
{
"decisions": [
{
"thread_id": "THR-A1B2C3D4",
"task_id": "order-1042",
"status": "approved",
"updated_at": "2026-08-09T17:00:00Z"
}
]
}This endpoint is token-safe discovery. Listing a completed decision does not reveal or consume the one-time signed approval token. Fetch the exact decision by thread_id when the runtime is ready to continue.
6. Validate a signed approval
/api/agent/approvals/validate| Field | Required | Description |
|---|---|---|
task_id | Yes | Task ID associated with the approval. |
signature | Yes | Raw one-time approval token returned by an approved decision. |
{ "valid": true }{
"valid": false,
"reason": "invalid"
}Failure reasons include invalid, expired, and used. Tokens are single-use, expiry-bound, agent/context-bound, and invalidated by agent API-key rotation.
Token validation failures, including invalid, expired, used, malformed, or missing inputs, are currently represented in the JSON body and can return HTTP 200. Always inspect valid.
Requested changes and revisions
When a reviewer requests changes, polling returns changes_requested. Keep the same review thread and POST a guarded revision event.
{
"event_type": "revision.order-1042.THR-A1B2C3D4",
"event_summary": "Revised after reviewer feedback",
"payload": {
"revision": {
"revision_id": "rev-002",
"tool_name": "issue_refund",
"subject": "Review issue_refund",
"request_payload": {"amount": 250}
}
}
}| Revision field | Required | Behavior |
|---|---|---|
revision_id | Yes | Must be unique within the thread. |
tool_name | Yes | Updated proposed tool. |
subject | Yes | Updated reviewer-facing proposal subject. |
request_payload | Yes | Revised tool arguments reevaluated by rules. |
workflow_name, task_label, preview, risk_level, summary | No | May update review context. Existing values are retained when omitted. |
A revision is accepted only for the same agent, task, and thread while the thread is pending, and only after reviewer change-request feedback newer than the latest proposal. Duplicate, stale, or no-longer-pending revisions return 409. A revision that passes policy remains pending for reviewer confirmation; a revision that evaluates to reject may terminate as rejected.
Decision webhooks
When webhook delivery is configured, Gate POSTs completed human decisions to the configured HTTPS endpoint.
{
"thread_id": "THR-A1B2C3D4",
"task_id": "order-1042",
"decision": "approved",
"message": "Approved",
"tenant_id": "tenant-uuid",
"workflow_name": "Customer Support",
"task_label": "Refund review"
}Verify the signature
X-Guard-Signature: sha256=<hex-hmac>
HMAC-SHA256(webhook_secret, exact_raw_request_body)Gate attempts delivery immediately, then retries after 1 second and 3 seconds. Any HTTP status below 300 is treated as success. Webhook destinations must use HTTPS; localhost, loopback, common private ranges, link-local destinations, and unsafe redirect targets are rejected.
Identifiers
| Identifier | Owner | Use |
|---|---|---|
taskID / task_id | Your runtime | Groups events and one or more decision requests. Reuse is supported. Use a stable URL-safe path-segment value. |
thread_id | Gate | Identifies one exact human-review request. Prefer for polling, revisions, and correlation. |
revision_id | Your runtime | Unique identifier for one submitted revision inside a thread. |
There is no live 36-character task-ID contract on this API surface. Avoid path-breaking characters such as /, ?, and #.
Operational limits
| Area | Current behavior |
|---|---|
| Agent rate limit | Enforced per agent from tenant API settings. Exceeded requests return 429. |
| Tool resolve body | 16 KiB maximum. Overflow currently returns 400. |
| Tool resolve count | 1 to 100 tool names. |
| Stored tool input schema | Tool ingestion caps configured input schemas at 64 KiB. |
| Decision listing | Default 25 rows, maximum 100. |
| Images | Limited by installation/tenant attachment configuration and available storage quota. |
| Rule checks / decision threads | Plan entitlements may impose hard caps. Exceeded hard caps can return 402. |
HTTP errors
| Status | Meaning |
|---|---|
400 | Malformed JSON, missing required input, invalid query values, rule-evaluation input errors, malformed revisions, or oversized /tools/resolve body. |
401 | Missing or invalid Bearer agent API key. |
402 | Applicable hard usage or entitlement cap reached. |
403 | Agent API or polling disabled, subscription guard, or unavailable feature. |
404 | Decision or revision target not found for the requested context. |
409 | Revision no longer pending, reviewer feedback stale/missing, or revision ID duplicated. |
413 | Evidence image or attachment/storage limits exceeded. /tools/resolve overflow is the exception and currently reports 400. |
429 | Per-agent API rate limit exceeded. |
500 / 503 | Unexpected server failure or attachment storage unavailable. |
Most Agent API errors are plain HTTP error text rather than a universal JSON envelope. Preserve the response body for diagnostics. The signed approval validation endpoint is the important exception: inspect its JSON valid field even when HTTP is 200.
Fail closed for an unknown decision status. If signed approval proof is required, also fail closed when approved arrives without approval_token. Never execute a governed action merely because an HTTP request succeeded.