Agents API
Manage and invoke AI agents via the client API. Agents combine a model, system prompt, tools, guardrails, and Knowledge Engine modules into a single deployable unit.
This page covers the agent resource (list, read, create, update, publish, delete) and invoking an agent with the Responses API. What happens around a conversation — sessions, events, approvals, files, background runs, budgets — has its own reference: Agent Sessions API, Webhooks API, and the Agent runtime guide.
Field names of the agent family (Responses, runs, sessions) are snake_case. The agent resource itself keeps its older camelCase shape (createdAt).
List Agents
GET /api/client/v1/agentsQuery Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by status: active, inactive, draft |
Response
{
"agents": [
{
"key": "support-bot",
"name": "Support Bot",
"description": "Customer support agent",
"config": {
"modelKey": "gpt-4o",
"temperature": 0.7,
"topP": 1,
"maxTokens": 4096
},
"status": "active",
"createdAt": "2026-01-15T10:00:00.000Z"
}
]
}Get Agent
GET /api/client/v1/agents/:agentKeyPath Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
agentKey | string | Yes | Unique agent key |
Response
{
"agent": {
"key": "support-bot",
"name": "Support Bot",
"description": "Customer support agent",
"config": {
"modelKey": "gpt-4o",
"temperature": 0.7,
"topP": 1,
"maxTokens": 4096
},
"status": "active",
"createdAt": "2026-01-15T10:00:00.000Z",
"experience": {
"welcome": "Hi {{user.firstName}}!",
"starters": [{ "text": "Where is my order?", "label": "Track an order", "auto_send": true }]
},
"attachments": {
"enabled": true,
"max_files": 10,
"max_file_size_mb": 20,
"allowed_mime_types": ["application/pdf", "image/*"],
"accepts_images": true
}
}
}One block is additive and appears only on this single-agent read:
attachments— what a client needs before it offers an attach button:enabledis true only when files are on, a bucket is chosen and that bucket can take a file right now;accepts_imagessays whether the agent's model reads images. See Session files.
The config shown here is a summary. The full config (with secrets masked) is returned by create, update and publish.
Create Agent
POST /api/client/v1/agents| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name. The agent key is generated from it. |
description | string | No | |
status | string | No | active, inactive, draft. |
config | object | Yes | The agent's configuration — see below. |
curl -X POST "$CONSOLE_URL/api/client/v1/agents" \
-H "Authorization: Bearer $COGNIPEER_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Support Bot",
"config": {
"modelKey": "gpt-4o",
"systemPrompt": "You are a support agent.",
"humanInTheLoop": { "toolApproval": { "enabled": true } },
"attachments": { "enabled": true, "bucketKey": "uploads" },
"execution": { "sessionBudget": { "maxCostUsd": 2, "onReach": "pause" } }
}
}'201: { "agent": { …, "key": "support-bot-a1b2c3", "config": { … } } }. The config is validated before it is stored; nothing is saved if it would not run as configured. Errors: 400 { "error": "Invalid agent config — <field>: <message> (and N more)", "validation": { "errors": [...], "warnings": [...] } }; 403 files_write_required when config.attachments.bucketKey is set without write access to Files.
The configuration sections that belong to the agent runtime:
| Section | Key | Guide |
|---|---|---|
| Execution | config.execution — syncTimeoutSeconds, backgroundEnabled, backgroundMaxDurationMinutes, defaultMode, callbackUrl, callbackSecret, sessionBudget | Background runs, Session budgets |
| Files | config.attachments | Session files |
| Approvals & questions | config.humanInTheLoop | Approvals & questions |
Update Agent
PATCH /api/client/v1/agents/:agentKeyAccepts name, description, status, config and metadata; anything else is ignored. config replaces the stored config wholesale — send it complete, not only the part you changed. A native-shaped config sent to a connected (external) agent is ignored so it cannot overwrite the connection. 200: { "agent": { … } }. Same validation errors as create; 404 { "error": "Agent not found" }.
Publish Agent
POST /api/client/v1/agents/:agentKey/publishPublishes the current draft config as a new immutable version. The draft is validated first. Body: { "changelog": "…" } (optional). 201: { "version": { … } }. POST /agents/responses and portals run the published version, so settings you change in the draft — files, approvals, experience — reach them only after you publish.
Delete Agent
DELETE /api/client/v1/agents/:agentKey200: { "success": true }.
Invoke Agent (Responses API)
Invoke an agent using the OpenAI Responses API format. The agent is identified by the model field.
Two endpoints are available, and they are not equivalent — they differ in which agent version they execute:
POST /api/client/v1/agents/responses # runs the PUBLISHED agent version
POST /api/client/v1/responses # runs the DRAFT agent versionUse /api/client/v1/agents/responses for production traffic against the published version, and /api/client/v1/responses to test the current draft.
The SDK calls the draft endpoint
client.agents.responses.create() in @cognipeer/console-sdk posts to /api/client/v1/responses — the draft. To run the published version from code, call /api/client/v1/agents/responses yourself, or pin a version.
Request
{
"model": "support-bot",
"input": "How do I reset my password?",
"previous_response_id": null,
"version": 1
}Parameters
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Agent key (identifies the agent) |
input | string | array | Yes | User message — plain string or array of message items (with input_text, input_file, input_image parts) |
previous_response_id | string | No | resp_{id} (or run_{id}) from a previous response, for multi-turn conversations |
session_id | string | No | Continue a session created with POST /agents/sessions (or any session id). Names the same thing as previous_response_id |
conversation | string | object | No | OpenAI-style alias of session_id: a session id, or { "id": "…" }. Give one of the three, or several that agree |
version | number | No | Specific published version to use (positive integer) |
runtime_context | object | No | Downstream headers and prompt variables for this turn |
budget | object | null | No | Spend budget for the session this request starts: { "max_cost_usd": 2, "on_reach": "pause" }; null = none. Ignored on a request that continues a session. See Session budgets |
background | boolean | No | Run as a background run. Also: header X-Cognipeer-Background: true |
callback_url, callback_secret | string | No | Background only: where to POST the result, and the secret that signs it |
header Idempotency-Key | string | No | Background only: a retried identical request returns the existing run |
Input Formats
Simple string:
{
"model": "support-bot",
"input": "Hello, I need help"
}Message array:
{
"model": "support-bot",
"input": [
{
"role": "user",
"content": "Hello, I need help"
}
]
}Structured content array:
{
"model": "support-bot",
"input": [
{
"role": "user",
"content": [
{ "type": "input_text", "text": "Hello, I need help" }
]
}
]
}With files (input_file, input_image; see Session files):
{
"model": "support-bot",
"session_id": "6f1c0a2b9d3e4f5a6b7c8d9e",
"input": [
{
"role": "user",
"content": [
{ "type": "input_text", "text": "Compare these" },
{ "type": "input_file", "file_data": "data:application/pdf;base64,JVBERi0x…", "filename": "a.pdf" },
{ "type": "input_image", "image_url": "https://example.com/cat.png" }
]
}
]
}input_file and input_image are used, not ignored: an agent that takes no attachments answers a request that carries one with 403 attachments_disabled.
Response
{
"id": "resp_64a1b2c3d4e5f6",
"object": "response",
"model": "support-bot",
"output": [
{
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "To reset your password, go to Settings > Security..."
}
]
}
],
"status": "completed",
"stop_reason": "completed",
"usage": {
"input_tokens": 12,
"output_tokens": 45,
"total_tokens": 57
},
"created_at": 1709500000,
"previous_response_id": null,
"version": 1
}status is completed, incomplete (a run limit, a cancellation or the session budget ended the run before a final answer; stop_reason and incomplete_details.reason say which) or requires_action. When the agent has structured output, the response also carries output_parsed (the validated object) or output_error.
With background: true the call answers 202 with an agent run instead of a response.
Waiting for an approval or an answer
An agent with approvals & questions can pause. The response then has status: "requires_action", stop_reason: "requires_action" and the requests to answer in required_action:
{
"id": "resp_64a1b2c3d4e5f6",
"object": "response",
"status": "requires_action",
"stop_reason": "requires_action",
"required_action": {
"type": "agent_actions",
"actions": [
{ "id": "act_0123456789abcdef01234567", "kind": "tool_approval", "tool_name": "sandbox_exec", "args": { "command": "ls" }, "status": "pending" }
]
}
}Answer with POST /api/client/v1/agents/sessions/{conversationId}/actions/{actionId} (the conversation id is the one inside resp_{conversationId}). An agent that does not use these features never returns this status.
Sessions
The conversation a response belongs to is a session. Besides the Responses call, it has its own endpoints — documented in full on the Agent Sessions API page:
| Endpoint | |
|---|---|
POST /agents/sessions | Start an empty session (to upload files first, give it a budget, or tag it) |
GET /agents/sessions | List the project's sessions |
GET /agents/sessions/{conversationId} | Runtime state: idle, running, requires_action or budget_paused; the pending requests; budget and spend |
PATCH /agents/sessions/{conversationId} | Set, raise or remove the spend budget; continues a session paused on it |
DELETE /agents/sessions/{conversationId} | Delete the session with its files, events and open requests |
GET /agents/sessions/{conversationId}/events | The event log (poll) |
GET /agents/sessions/{conversationId}/events/stream | The event log as Server-Sent Events, resumable with Last-Event-ID |
POST /agents/sessions/{conversationId}/actions/{actionId} | Answer an approval or question |
PUT, DELETE /agents/sessions/{conversationId}/messages/{messageId}/feedback | Rate an answer (messageId is the id of the response's message item) or withdraw the rating |
POST, GET /agents/sessions/{conversationId}/files, GET …/files/{fileId}/content, DELETE …/files/{fileId} | Session files |
GET /agents/runs/{runId}, POST /agents/runs/{runId}/cancel | Background runs |
Webhooks (/webhooks) notify your service when a session goes idle, needs an answer or reaches its budget. The full request and response shapes are in the OpenAPI spec.
Multi-Turn Conversations
Use previous_response_id — or session_id — to continue a conversation:
{
"model": "support-bot",
"input": "Can you elaborate on the security settings?",
"previous_response_id": "resp_64a1b2c3d4e5f6"
}The response ID follows the format resp_{conversationId}. The control plane automatically tracks conversation history and provides context to the agent.
Agent Features
Agents configured in the dashboard can include:
| Feature | Description |
|---|---|
| System Prompt | Base instructions for the agent |
| Tools | Bound tools from the unified tool system or MCP servers |
| Guardrails | Input/output validation rules |
| Knowledge Engine Modules | Retrieval-augmented generation sources |
| Temperature / Top-P | Model parameter overrides |
| Max Tokens | Output length limit |
| Approvals & questions | Pause a turn for a person: tool approvals, questions, page tools |
| Session files | Documents and images attached to a session, stored in a bucket you choose |
| Session budget | A cap on what a whole session may spend |
| Execution | Synchronous timeout, background runs, default callback |
| Versioning | Publish and pin specific agent configurations |
Errors
| Status | Description |
|---|---|
| 400 | Missing model or input field, agent is not active, or an invalid field (invalid_budget, invalid_callback, session_conflict, …) |
| 401 | Invalid API token |
| 402 | The session has reached its spend budget (budget_reached, with spent_usd and max_cost_usd) |
| 403 | The agent takes no attachments (attachments_disabled), or the agent's session budget forbids the change (budget_override_forbidden) |
| 404 | Agent not found, previous_response_id references an invalid conversation, or session_id names no session of this agent (session_not_found) |
| 409 | Another run is active for the conversation (agent_run_conflict), the session is waiting for an approval or an answer (pending_action, with pending_action_ids), or an Idempotency-Key was reused with a different request |
| 429 | The tenant's spend limit is used up (spend_limit_exceeded), or too many background runs are queued or running (agent_run_concurrency_limit) |
| 500 | Internal error during agent execution |
| 502 | The model provider rejected the credentials stored for it (provider_authentication_error) — fix the provider, not your token |
| 504 | A synchronous call passed its ceiling (timeout, with side_effects_possible: true) — use a background run |
The agent family answers with { "error": { "type", "code", "message" } }; a few older checks (a missing model, an unknown agent) answer { "error": "message" } — branch on the status code.

