Agent Session Endpoints
Agent sessions represent an agent acting on behalf of a user or autonomously. Sessions scope credentials, attach a Biscuit capability token, and enforce policy on every credential vend.
All endpoints below are under
/api/v1/agent/sessions(note theagent/segment). Earlier drafts of these docs used/api/v1/sessions/*; that prefix does not exist.
Authentication
| Header | Description |
|--------|-------------|
| Authorization | Bearer <agent-api-key> — Required on every endpoint. The agent's API key authenticates the request and identifies the acting agent. |
| X-Bulwark-Tenant | Tenant UUID. |
| X-Bulwark-Token | Biscuit token from the create-session response. Required on credential / proxy endpoints; the token carries the session's capability rights. |
Create Session
POST /api/v1/agent/sessions
Creates a new agent session and returns a Biscuit capability token. The Biscuit token must be sent on subsequent credential / proxy requests.
Body
{
"task_description": "Reconcile invoices for Q2",
"ttl_seconds": 900,
"max_uses": 50,
"rights": [
{ "service": "stripe", "operation": "charges:list" }
],
"device": {
"device_id": "macbook-air-m2-001",
"hostname": "ron.local",
"platform": "darwin",
"arch": "arm64",
"labels": { "team": "engineering" }
}
}
| Field | Required | Description |
|-------|----------|-------------|
| task_description | No | Human-readable purpose. Surfaced in audit and CIBA approval prompts. |
| ttl_seconds | No | Session lifetime. Defaults to 900 (15 min). |
| max_uses | No | Credential vend cap for this session. Defaults to a service-level setting. |
| rights | No | Biscuit capability rights to attenuate the session with. Empty = full agent capabilities. |
| device | No | Device attestation context. If supplied and the device is suspended, the session is rejected with 403. |
Response 201
{
"session": {
"id": "01j...",
"agent_id": "01j...",
"tenant_id": "01j...",
"status": "active",
"task_description": "Reconcile invoices for Q2",
"expires_at": "2026-05-07T00:15:00Z",
"max_uses": 50,
"current_uses": 0,
"created_at": "2026-05-07T00:00:00Z"
},
"biscuit_token": "<base64-biscuit>"
}
The biscuit_token is shown ONCE. Store it client-side and send it as X-Bulwark-Token on subsequent calls within this session.
Request Credentials (Vending)
POST /api/v1/agent/sessions/{id}/credentials
Vend specific credential fields from a registered vault service. Bulwark evaluates the credential vending policy. If denied, returns 403. If approval is required, returns 202 with an approval reference (CIBA flow); the agent should then poll the CIBA endpoint and retry once approved.
Headers
X-Bulwark-Token is required (the Biscuit from create-session).
Body
{
"service_name": "stripe",
"fields": ["api_key"],
"approval_id": "01j..."
}
| Field | Required | Description |
|-------|----------|-------------|
| service_name | Yes | Service registered in the vault. |
| fields | Yes | Specific credential fields to return (e.g. ["api_key"], ["username", "password"], ["totp_code"]). Only the requested fields are returned. |
| approval_id | No | If a previous request returned 202 with an approval ID, pass it here on retry after the user approved. |
Response 200 (vended)
{
"fields": {
"api_key": "sk_live_..."
},
"grant_id": "01j...",
"use_count": 1,
"max_uses": 50
}
Response 202 (approval required)
{
"approval_required": true,
"approval_id": "01j...",
"poll_url": "/api/v1/ciba/requests/01j.../poll"
}
Errors
| Status | Cause |
|--------|-------|
| 403 | Session not active, session not owned by this agent, policy denied access, or biscuit denied operation. |
| 404 | Service not found in vault, or connector not registered. |
| 429 | Session's max_uses exhausted. |
Proxy Service Call
POST /api/v1/agent/sessions/{id}/proxy
Make an outbound HTTP call to a registered service through Bulwark, which injects the credential at the gateway layer. Useful when you don't want plaintext credentials touching the agent at all.
Headers
X-Bulwark-Token is required.
Body
{
"service_name": "stripe",
"method": "GET",
"path": "/v1/charges?limit=10",
"body": null,
"operations": ["charges:list"]
}
| Field | Required | Description |
|-------|----------|-------------|
| service_name | Yes | Service registered in the vault. |
| method | Yes | HTTP method to use against the service. |
| path | Yes | Path on the service (Bulwark prepends the service's base_url). |
| body | No | Request body for POST/PUT/PATCH. |
| operations | Yes | Operation labels for policy decisions (e.g. ["charges:list"]). Must be a subset of the service's available_operations AND the session's biscuit rights. |
Response
The provider's response is forwarded as-is. Bulwark adds X-Bulwark-Vended-Grant: <grant_id> to the response headers for audit correlation.
Attenuate Session
POST /api/v1/agent/sessions/{id}/attenuate
Tighten the session's biscuit token by appending additional restrictions (TTL shorten, scope narrow, single-operation lock). Returns a new biscuit token that the agent must use going forward; the old token still works until it expires, but any restriction added is permanent on the new token.
Body
{
"rights": [
{ "service": "stripe", "operation": "charges:list" }
],
"ttl_seconds": 300
}
Response 200
{
"biscuit_token": "<new-base64-biscuit>"
}
Complete Session
POST /api/v1/agent/sessions/{id}/complete
Marks the session completed. Future credential vends and proxy calls return 403. Use when the agent's task is done and you want to release any remaining capacity.
Response 200
{ "status": "completed" }
Typical flow
- Agent (with API key) calls
POST /agent/sessionswith task description and optional rights/device. Receives session + Biscuit token. - Agent calls
POST /agent/sessions/{id}/credentials(withX-Bulwark-Token) to fetch credential fields, OR callsPOST /agent/sessions/{id}/proxyto call the service through Bulwark. - If
202 approval_required, agent pollsGET /api/v1/ciba/requests/{approval_id}/polluntil status changes, then retries the credential request withapproval_id. - When the task is done, agent calls
POST /agent/sessions/{id}/complete.