Open a verbose capture window on an Agent
POST /v1/agents/{agent_id}/capture-windows
| Property | Value |
|---|---|
| Operation | create_capture_window |
| Group | Capture windows and reveal grants |
| Scope | agents:write |
| Route class | control |
| Idempotency | Idempotency-Key required: a retry with the same key replays the first answer |
| Audit | Audited capture_window.create (mutation) |
| Released in | 1.57.0 |
| Phase 0 host | Served (the hosted api pins 1.65.0) |
Opens a window during which dispatch makes each admitted Call of the Agent (one version of it, when named) in the window's environment verbose, inbound Calls included, until the window ends or has captured max_calls Calls (1.57.0). Refused with 403 capture_not_allowed when the Compliance profile's verbose_capture is off, or test_only for a live window, and with 404 not_found for an Agent of another Organization or an agent_version the Agent has not published. The Audit event capture_window.create records the window, never its reason.
Request
Set VOCAL_API to the base URL of your API and VOCAL_API_KEY to an API key with the agents:write scope (Authentication and keys). Replace each placeholder, such as agt_... or <name>, with your own value.
curl -X POST "$VOCAL_API/v1/agents/agt_.../capture-windows" \
-H "Authorization: Bearer $VOCAL_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "environment": "live", "reason": "<reason>" }'const response = await fetch(`${process.env.VOCAL_API}/v1/agents/agt_.../capture-windows`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VOCAL_API_KEY}`,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
"environment": "live",
"reason": "<reason>"
}),
});
console.log(response.status, await response.text());import os
import uuid
import requests
response = requests.post(
f"{os.environ['VOCAL_API']}/v1/agents/agt_.../capture-windows",
headers={
"Authorization": f"Bearer {os.environ['VOCAL_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"environment": "live",
"reason": "<reason>",
},
)
print(response.status_code, response.text)Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
agent_id | path | AgentId | yes | The id of an Agent: agt_ and the row's UUIDv7 in 26 Crockford base32 characters. Opaque and safe to log. |
idempotency-key | header | string | yes | A client-chosen key, kept 24 hours per Organization, environment and route. A replay returns the stored response. |
Request body
Content type application/json, required: CaptureWindowCreateRequest.
| Field | Type | Required | Description |
|---|---|---|---|
agent_version | integer | no | Only Calls pinned to this published version; every version of the Agent when absent. |
duration_minutes | integer | no | How long the window stays open: 1 to 1,440 minutes (24 hours, a target), 60 when absent. |
environment | Environment | yes | The environment whose Calls the window captures. A developer opens test windows only (forbidden, detail owner_or_admin_required); from 1.58.0 the contracts state that an API key opens one in its own environment only (forbidden, detail environment_not_grantable), as it starts Calls there. |
max_calls | integer | no | The most Calls the window captures: 1 to 200 (a target), 200 when absent. |
reason | string | yes | Why the window is opened, for the access review: free text, stored as a content pair and scrubbed at retention_days. |
starts_at | RequestTimestamp | no | When the window starts; now when absent. An instant in the past is now. |
Responses
| Status | Content type | Shape | Error codes |
|---|---|---|---|
201 | application/json | CaptureWindow | |
400 | application/json | ErrorEnvelope | invalid_request |
401 | application/json | ErrorEnvelope | unauthenticated |
403 | application/json | ErrorEnvelope | forbidden, org_suspended, capture_not_allowed |
404 | application/json | ErrorEnvelope | not_found |
409 | application/json | ErrorEnvelope | idempotency_in_progress, idempotency_key_reused |
422 | application/json | ErrorEnvelope | validation_failed |
429 | application/json | ErrorEnvelope | rate_limited |
500 | application/json | ErrorEnvelope | internal_error |
Fields of the 201 answer
The shape is CaptureWindow.
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | AgentId | yes | |
agent_version | integer or null | yes | The one version the window captures; null for every version. |
calls_captured | integer | yes | The Calls the window made verbose so far. |
closed_at | Timestamp or null | yes | When a Member closed the window early. |
closed_by | ActorRef or null | yes | |
created_at | Timestamp | yes | |
created_by | ActorRef | yes | |
ends_at | Timestamp | yes | starts_at plus the duration; at most 24 hours later. |
environment | Environment | yes | |
id | CaptureWindowId | yes | |
max_calls | integer | yes | |
object | "capture_window" | yes | |
reason | string or null | no | Why the window is opened, for the access review: free text, stored as a content pair and scrubbed at retention_days. Answered only by GET /v1/agents/{agent_id}/capture-windows/{capture_window_id}, an audited content read; null once scrubbed. |
starts_at | Timestamp | yes | |
status | CaptureWindowStatus | yes |