Skip to main content

Application Requests

Application requests use your authenticated API principal as the sender. You supply no email, SMS address, transport URL, or human identity. New admission requires the deployment setting API_APPLICATION_REQUESTS_ENABLED, which defaults false. Service credentials additionally require their installation and Organization gates and current agent grants. Existing email message and Remote MCP contracts remain available.

Routes and authority​

All routes have trailing slashes beneath /api/v1/agents/{id}/requests/.

Method and suffixRequired authority
POST /agents:operate, active agent, current owner/grant, required Idempotency-Key
GET /agents:read; cursor-paged calling-principal requests
GET /{request_id}/Same, plus submission-principal and original-ownership visibility
GET /{request_id}/result/Same; native typed-result envelope, explicitly unavailable/purged when appropriate
GET /{request_id}/responses/Same; explicitly linked reply rows only
POST /{request_id}/wait/agents:read; bounded, read-only revision wait

A member key is its own submission principal. A service's principal is its stable service identity, so rotating an authorized credential retains request visibility and replay continuity. Current revocation, grant/scope removal, account restrictions, archive, and ownership changes are rechecked. These request endpoints do not grant another principal's request bodies or responses just because the agent is visible.

Human administrators may explicitly use inspect=true on the GET collections/detail routes. This requires agents:manage and current Organization-wide agent-management authority, and records an administrative access event. Personal inspection requires the original current owner. Services cannot inspect other principals, and staff status supplies no bypass.

These are resource and routing boundaries. Callers sharing an agent share its model context. Generated content is not confidential between those callers. Use separate agents/workspaces when independent context is required.

Agent-wide REST/MCP timeline, debug-trace and event-wait reads require every retained application request on that agent to belong to the current principal and ownership, with content and artifacts retained. Otherwise REST returns 403 with application_request_scope_required, and MCP returns a structured tool error. Use these principal-scoped request routes instead. agents:manage and staff targeting supply no implicit application-data inspection. Waits recheck this boundary for each snapshot without keeping authority locks while sleeping.

The same restriction covers legacy browser-task collections, detail, results and update representations, persistent-agent web-tasks, and pending-action lists and resolution responses. These projections can contain derived prompts, results, errors, questions, options, or approval content. A collection is denied before counts or pagination if any included agent has inaccessible application history; inspect=true does not widen these legacy routes. Browser tasks retain their source restriction after reassignment or detachment while continuation lineage exists. Missing per-task/action links do not authorize broad shared history, and retained orphan application conversations/inputs remain restricted after request deletion. Ordinary agents without application history and standalone tasks without application lineage retain their workspace-based behavior. Console human decisions retain their existing authority.

The same broad-history boundary covers MCP filespace listing/reads, MCP message attachment reuse and new application admission with attachment references. It prevents an imported working copy from bypassing input visibility, including while import is in progress. An exact application message-attachment resource remains readable by its current submission principal, including a rotated service credential, when every linked source request and its artifacts are retained. Purged older input is not authorized by a newer request in the same conversation. General filespace access and generated model content are shared agent context; use separate agents/workspaces for independent context and files.

Imported copies keep durable request/Organization origin snapshots. Addressing a copy through a peer agent does not change its principal or source-agent grant requirements; removed lineage closes access. Original-Organization file clocks still cover the copy after source/request deletion. Actual message retention closes artifact access immediately, even before request projection cleanup. Migration 0580 backfills retained copied-node links without reclassifying pre-existing shared source files. Drain old import writers before backfill and resuming accepted work; mixed writers are unsupported for this boundary.

Submit and retry​

REQUEST_KEY="$(uuidgen)"
REQUEST_JSON=$(curl --fail-with-body -X POST "$API_BASE/agents/$AGENT_ID/requests/" \
-H "X-Api-Key: $API_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: $REQUEST_KEY" \
-d '{"body":"What is 17 plus 25?","client_reference":"example-7"}')
REQUEST_ID=$(jq -er '.request_id' <<<"$REQUEST_JSON")
CURSOR=$(jq -er '.cursor' <<<"$REQUEST_JSON")

The 202 acceptance includes request_id, message_id, conversation_id, revision, the three state dimensions, resource URLs, and receipt_expires_at. It proves durable local acceptance. It does not prove broker acknowledgement, model execution, external success, or a reply.

Strict JSON fields are body (nonblank, at most 64 KiB UTF-8), optional client_reference (255 characters), optional owned conversation_id, and optional attachment_file_ids (at most ten distinct existing UUIDs). Unknown fields fail with 400. The reference is descriptive; it does not deduplicate input. Conversations are bound to the principal, agent and original effective owner.

Attachments must be accessible to the target agent and already clean/available through a supported upload path. Admission stages an immutable copy before the database transaction, then rechecks the source generation and scan state. Filespace import retains that admitted snapshot separately from the editable working copy, and post-commit observer failures do not delete accepted snapshot bytes. Invalid references create no input. Inline bytes remain outside request admission. Use REST Files to upload/poll existing file UUIDs and retrieve exact generations or retained immutable attachment copies. Response attachment entries expose authorized references, filenames, sizes and availability.

Retry the identical route/body with the same key after an ambiguous HTTP failure. The default replay lifetime is 24 hours, using the existing deployment retention setting. Changed semantics return 409. Replay returns the original acceptance, with Idempotency-Replayed: true; follow detail for current state. Admission being disabled preserves authorized retained replay and reads. Purged acceptance content returns 404 with original_response_not_retained; existing request metadata remains readable. Expired receipts do not prevent a key from accepting new work, so retain request IDs and do not treat expired keys as deduplication guarantees.

Observe state and replies​

DimensionMeaning
publication_statepending: durable input/intention; queued: acknowledged publication or actual consumer receipt; blocked: publication cannot proceed with its captured authority/generation
execution_statenot_started, processing, awaiting_action, blocked, settled, failed, or unknown; categorical reasons accompany holds and uncertain settlement
response_statenone, responded, or explicitly closed_without_reply; a reply or settled turn does not prove task fulfillment or external success

Execution references distinguish input_disposition=selected from consumed. A prepared/speculative model input can be selected without its result being accepted. Only admitted, accepted input supplies reply lineage. One turn can consume several inputs; one request can span multiple turns. Shared reply rows require one submission principal and conversation. Ordinary reads expose no raw prompt, thinking, unrestricted tool output, or protected audit evidence.

Detail returns at most 100 entries each for execution references, pending-action associations and continuations, with explicit truncation flags. Action IDs reference separately authorized human decisions; they do not expand the service credential's decision permissions. Known browser/MCP follow-ups and human decisions preserve source request and emergency generation. Direct runtime follow-ups also retain a durable safe-retry publication intent and exact source trigger for broker-loss recovery. Missing/crashed settlement stays unknown and is reconciled from retained evidence. An old heartbeat, unrelated schedule, or other principal's reply never proves completion.

Each continuation has a distinct continuation_id. MCP input_required updates produce versioned mcp_input events while the underlying mcp task remains pending; consuming the input event does not resolve that task. A later provider occurrence supersedes an unconsumed older input event. Final prompt references bind consumption to the exact provider occurrence, and terminal results can resume independently. Migration 0580 versions existing ready MCP links and retains already parked input requests for publication recovery.

MCP continuation occurrence versions remain stable across Django signing-key changes. Input-security identities/allowances retain their independent security lifecycle; this continuity does not bypass a current security hold or ownership/generation fence.

curl --fail-with-body -H "X-Api-Key: $API_KEY" \
"$API_BASE/agents/$AGENT_ID/requests/$REQUEST_ID/"
curl --fail-with-body -H "X-Api-Key: $API_KEY" \
"$API_BASE/agents/$AGENT_ID/requests/$REQUEST_ID/responses/"

Request and response lists return results and next_cursor; limit defaults to 40 and must be 1–100. Preserve signed opaque cursors. They expire after 24 hours and bind principal, agent, resource, inspection mode and page size. Start a fresh page when changing those parameters.

Wait without cancelling​

WAIT_BODY=$(jq -n --arg cursor "$CURSOR" '{cursor:$cursor,timeout_seconds:30}')
WAIT_JSON=$(curl --fail-with-body --max-time 40 -X POST \
"$API_BASE/agents/$AGENT_ID/requests/$REQUEST_ID/wait/" \
-H "X-Api-Key: $API_KEY" -H "Content-Type: application/json" -d "$WAIT_BODY")
CURSOR=$(jq -er '.cursor' <<<"$WAIT_JSON")

The response contains changed, cursor, and the request snapshot. An empty wait preserves the supplied cursor. timeout_seconds is an integer 0–30, default 30. Wait expiry and client disconnect do not cancel work or close a request.

Defaults are four concurrent waits per principal and 32 per effective owner, configured through API_APPLICATION_REQUEST_WAIT_PRINCIPAL_LIMIT and API_APPLICATION_REQUEST_WAIT_OWNER_LIMIT. Capacity excess returns 429 with Retry-After: 1. Capacity is held by a database lease, released in cleanup and recoverable after its 35-second expiry if the web process dies. Disconnect cleanup can take the remaining bounded wait. No authority transaction is held while sleeping. PostgreSQL wait snapshots have one-second lock and two-second statement budgets; unavailable snapshots return 503/wait_state_unavailable, with a one-second retry hint. HTTP deadlines should allow normal request/snapshot overhead.

Holds, retention and deployment​

An inactive agent rejects new input. An active halted agent can retain a blocked request in the halt generation. Reset does not restamp or revive that input. Input-security holds remain explicit, and authorized review follows the existing policy/generation fences.

Original Organization conversation/file clocks scrub application content and artifact references even after transfer; content_purged reports unavailable content while permitted request/outcome structure remains. Linked replies may have been observed even when their retained bodies are now purged. Historical snapshots do not transfer request access to a new Organization.

Apply migrations 0579_application_requests and 0580_application_request_reconciliation after the service-credential and safe-retry migrations, upgrade and drain web, runtime, pending-work, reply, action, browser/MCP continuation, retention, recovery and Beat writers together, then validate the exact release in a non-production environment before enabling admission. Keep new admission off on rollback; preserve instrumented readers/replay/settlement/reconciliation until accepted work settles. Older workers must not consume application requests. Automatic request/reply webhook delivery, SSE, SDKs and per-request cancellation are separate work.

A missing eligible model configuration is explicitly blocked with model_configuration_unavailable, with no consumed execution/reply claim. After configuration repair, bounded reconciliation checks the retained token/profile context and republishes this proven pre-model blocked input through safe-retry publication with its original generation and a new owned source trigger. It does not retry unknown provider/external outcomes. Configuration repair alone is not proof that a worker resumed the request; verify a newer observation. Validate real-provider and worker behavior in your environment.

Recovery publication groups retain principal, conversation, original ownership and emergency generation even when a provider source is shared. Consumed original or decision deliveries require an unconsumed owned continuation trigger or the exact current security-hold receipt to resume. Periodic request reconciliation processes at most 100 due rows, schedules checked rows 60 seconds ahead without changing public revisions for unchanged holds, and batches terminal-execution observations. This yields progress past old blocked rows; it is not a worker or throughput guarantee.

Automatic events and recovery​

Deployments with event delivery enabled can subscribe to body-free agent.request.updated, agent.request.responded and request-scoped agent.message.created. Capture defaults off. Events use committed revisions and explicit original-principal reply lineage; shared replies produce separate request-scoped events and responded never means successful external work. Use authorized current request/response reads to reconcile notification gaps. See webhook operations and deployment limits.

General admission limits​

Deployments may enable shared request quotas, concurrent-wait capacity and queued-input backpressure. Accepted replays do not reserve new work capacity; ordinary HTTP quotas still apply. Honor Retry-After on 429/503 and keep the original protected-write key/body. Pending publication remains accepted input and is recovered independently of the caller. Enforced legacy task submission requires omission of wait; shared application/timeline waits remain bounded to 30 seconds. Validate throughput in your own environment.

Request attachments add input_attachments to acceptance/detail/list/wait projections: at most ten retained immutable input-copy IDs, filenames, content types, sizes and known scan availability. These IDs work with the immutable attachment download route, independently of later working-file replacement. Purged input/artifact content returns an empty array. Old replay bodies may omit the additive field; retrieve current detail to discover copies.

Operational reconciliation​

The independently gated usage and audit reads expose only known consumed execution links for the calling principal. Run/dispatch accounting can cover several requests and is not per-request cost allocation. Reporting scopes do not reveal another principal's request identifiers or protected request content; retained metadata can outlive content.

Optional typed result​

result_schema selects the separately default-off structured application result contract. Request detail adds body-free result metadata and urls.result. Retrieve native content separately; result.state and availability never replace execution/response state. Normal text requests and chat behavior remain supported. Accepted schema/profile/hash participate in retry identity.