API Reference¶
Base URL: http://localhost:8000
All request and response bodies are JSON unless noted. Streaming endpoints return text/event-stream.
Contents¶
- Health & Readiness
- Sessions
POST /sessionsGET /sessionsGET /sessions/{session_id}PATCH /sessions/{session_id}DELETE /sessions/{session_id}POST /sessions/{session_id}/abort- Messages
POST /sessions/{session_id}/messagesGET /sessions/{session_id}/messagesGET /sessions/{session_id}/messages/{message_id}- SSE Event Types
tokentool_calltool_resultplanning(reserved)step_complete(reserved)delegationstatususageerrordone- Agents
GET /agentsGET /agents/{name}POST /agentsPUT /agents/{name}PATCH /agents/{name}DELETE /agents/{name}- Skills
GET /skillsGET /skills/{name}POST /skillsPUT /skills/{name}PATCH /skills/{name}DELETE /skills/{name}- Tools
GET /toolsGET /tools/{name}GET /tools/errorsPOST /toolsDELETE /tools/{name}POST /tools/reload- Models
GET /modelsGET /models/providersGET /models/providers/{provider_id}/modelsPOST /models/providersPATCH /models/providers/{provider_id}DELETE /models/providers/{provider_id}POST /models/providers/{provider_id}/test- Configuration
GET /configPATCH /configPOST /config/rollback- MCP Servers
GET /mcp-serversPOST /mcp-serversGET /mcp-servers/{name}PATCH /mcp-servers/{name}DELETE /mcp-servers/{name}- Artifacts
GET /artifactsPOST /artifactsGET /artifacts/{artifact_id}PUT /artifacts/{artifact_id}DELETE /artifacts/{artifact_id}GET /artifacts/{artifact_id}/versions- Capabilities
GET /capabilities- A2A Protocol
GET /.well-known/agent-card.jsonPOST /a2a/{agent_name}- Multi-Tenant Scoping
- Rate Limiting
- Error Format
Health & Readiness¶
GET /health¶
Returns server health status.
Response 200 OK:
{
"status": "healthy",
"version": "0.10.0",
"active_sessions": 3,
"circuit_breakers": [],
"timestamp": "2026-03-19T12:00:00Z"
}
GET /ready¶
Readiness probe. Returns 200 when the server has completed startup.
Response 200 OK:
Sessions¶
POST /sessions¶
Create a new session.
Request body:
{
"title": "My session",
"agent_name": "default",
"metadata": {
"repository": "myorg/myrepo",
"pr_number": "42"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
title |
string (max 200) | No | Human-readable label |
agent_name |
string | No | Agent to bind; must be a known primary or all agent. Defaults to "default". Returns 422 if name is unknown. |
metadata |
object | No | Arbitrary builder-defined flat key-value metadata attached to the session |
Headers (when scoping enabled):
Response 201 Created:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "My session",
"thread_id": "7f3e4a12-...",
"status": "active",
"agent_name": "default",
"metadata": {"repository": "myorg/myrepo", "pr_number": "42"},
"created_at": "2026-03-02T12:00:00Z",
"updated_at": "2026-03-02T12:00:00Z",
"message_count": 0
}
Response 422 Unprocessable Entity: agent_name is not a known primary agent.
GET /sessions¶
List sessions for the current workspace. Filtered by scope when scoping is enabled.
Metadata filtering is supported with query parameters of the form metadata.<key>=<value>.
Examples:
curl "http://localhost:8000/sessions?metadata.repository=myorg/myrepo"
curl "http://localhost:8000/sessions?metadata.repository=myorg/myrepo&metadata.pr_number=42"
Response 200 OK:
GET /sessions/{session_id}¶
Get session details.
Response 200 OK: Session object (same schema as create response)
Response 404 Not Found: Session does not exist or is out of scope.
PATCH /sessions/{session_id}¶
Update session metadata or LLM configuration.
Request body (all fields optional):
{
"title": "Updated title",
"agent_name": "readonly",
"metadata": {
"repository": "myorg/myrepo",
"pr_number": "43"
},
"config": {
"provider_id": "my-openai-config",
"model": "gpt-4o-mini",
"temperature": 0.3,
"provider": "openai",
"max_tokens": 2048,
"recursion_limit": 500
}
}
SessionConfig fields:
| Field | Type | Description |
|---|---|---|
provider_id |
string | Reference a specific ProviderConfig by ID from ConfigRegistry. Takes priority over provider/model. |
provider |
string | Provider type override: openai, anthropic, bedrock, openai_compatible, google_genai, google_vertexai |
model |
string | Model ID override |
temperature |
float | Temperature (0.0–2.0) |
max_tokens |
int | Max output tokens |
recursion_limit |
int | Max agent ReAct loop depth |
Provider resolution priority (highest to lowest): provider_id → provider+model → AgentDefinition.config → first enabled ProviderConfig from ConfigRegistry.
Validation rules:
config.provider_idselects an exact configured provider row.config.providerrequiresconfig.model.config.modelwithoutconfig.providerorconfig.provider_idis only accepted when exactly one enabled provider type matches that model.- If no enabled provider matches the model, Cognition returns
422. - If multiple enabled provider types match the model, Cognition returns
422and asks the caller to specifyproviderorprovider_id.
Response 200 OK: Updated session object
Response 404 Not Found
DELETE /sessions/{session_id}¶
Delete a session and all its messages.
Response 204 No Content
Response 404 Not Found
POST /sessions/{session_id}/abort¶
Cancel any in-progress agent operation for this session.
Response 200 OK:
Response 404 Not Found
POST /sessions/{session_id}/resume¶
Resume an interrupted HITL session after an interrupt SSE event.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
decision |
approve | edit | reject |
Yes | Human decision for the interrupted tool call |
tool_call_id |
string | Yes | Interrupted tool call identifier |
tool_name |
string | Yes | Interrupted tool name |
args |
object | No | Replacement tool args when decision="edit"; may include a rejection message for reject |
If Accept: text/event-stream is sent, Cognition streams the resumed continuation. Otherwise it returns a simple success response.
Response 200 OK (JSON):
Response 409 Conflict: Session is not in waiting_for_approval state.
Messages¶
POST /sessions/{session_id}/messages¶
Send a user message and receive the agent's streaming response via Server-Sent Events.
Request body:
{
"content": "List the files in the workspace.",
"model": "gpt-4o-mini",
"callback_url": "https://example.com/cognition-callback"
}
| Field | Type | Required | Description |
|---|---|---|---|
content |
string (min 1) | Yes | The user's message |
model |
string | No | Override model for this message only |
parent_id |
string | No | Parent message ID for threaded context |
callback_url |
URL | No | Best-effort completion callback URL for a final POST after the run finishes |
Headers:
Content-Type: application/json
Last-Event-ID: 42 # Optional; triggers reconnection replay from this event ID
Response 200 OK:
Content-Type: text/event-stream
The response is a stream of SSE events. See SSE Event Types below.
Errors:
- 429 Too Many Requests — Rate limit exceeded
- 404 Not Found — Session not found
- 403 Forbidden — Scope mismatch
GET /sessions/{session_id}/messages¶
List messages in a session with pagination.
Query parameters:
| Parameter | Default | Description |
|---|---|---|
limit |
50 |
Number of messages to return |
offset |
0 |
Number of messages to skip |
Response 200 OK:
{
"messages": [
{
"id": "msg-uuid",
"session_id": "session-uuid",
"role": "user",
"content": "List files.",
"created_at": "2026-03-02T12:00:00Z",
"tool_calls": [],
"token_count": null,
"model_used": null
},
{
"id": "msg-uuid-2",
"role": "assistant",
"content": "Here are the files...",
"tool_calls": [
{"name": "bash", "args": {"command": "ls -la"}, "id": "call_xyz"}
],
"token_count": 142,
"model_used": "gpt-4o"
}
],
"total": 2,
"has_more": false
}
role values: user, assistant, system, tool.
GET /sessions/{session_id}/messages/{message_id}¶
Get a specific message by ID.
Response 200 OK: Message object
Response 404 Not Found
SSE Event Types¶
Every event in the POST /sessions/{id}/messages stream has the structure:
token¶
A single LLM output token. Stream these into a buffer to accumulate the full response.
tool_call¶
The agent is invoking a tool. id correlates with the tool_call_id in the subsequent tool_result.
tool_result¶
Result of a tool invocation. tool_call_id matches the id in the preceding tool_call.
exit_code is 0 for success, non-zero for failure.
planning¶
The agent has created a task plan.
{
"todos": [
"Read the main configuration file",
"Identify all API endpoints",
"Generate the summary"
]
}
step_complete¶
A step in the agent's task plan has been completed.
delegation¶
The primary agent is delegating a subtask to a subagent.
status¶
The agent's status has changed.
Values: thinking, idle, waiting_for_approval, resuming, cancelled.
interrupt¶
The agent is paused waiting for human approval before executing a protected tool.
{
"tool_call_id": "call_abc123",
"tool_name": "write_file",
"args": {"file_path": "notes.txt", "content": "hello"},
"session_id": "session-uuid",
"action_requests": [
{
"name": "write_file",
"args": {"file_path": "notes.txt", "content": "hello"},
"review_config": {"action_name": "write_file", "allowed_decisions": ["approve", "edit", "reject"]}
}
]
}
Use this payload with POST /sessions/{session_id}/resume.
usage¶
Token usage and estimated cost for this response.
{
"input_tokens": 245,
"output_tokens": 380,
"estimated_cost": 0.0038,
"provider": "openai",
"model": "gpt-4o"
}
error¶
A recoverable error occurred. The stream terminates after an error event.
done¶
The stream is complete. Contains the full assistant message.
{
"assistant_data": {
"id": "msg-uuid",
"session_id": "session-uuid",
"role": "assistant",
"content": "Here are the files in your workspace...",
"tool_calls": [...],
"token_count": 380,
"model_used": "gpt-4o",
"created_at": "2026-03-02T12:00:01Z"
}
}
Agents¶
GET /agents¶
List all non-hidden agents available in the registry.
Response 200 OK:
{
"agents": [
{
"name": "default",
"description": "Full-access coding agent with all tools enabled",
"mode": "primary",
"hidden": false,
"native": true,
"model": null,
"temperature": null,
"response_format": null,
"interrupt_on": {},
"tools": [],
"skills": [],
"system_prompt": "You are a coding agent..."
}
]
}
mode values: primary, subagent, all.
system_prompt is truncated to 500 characters in the response.
Response 503 Service Unavailable: Registry not yet initialized.
GET /agents/{name}¶
Get a specific agent by name.
Response 200 OK: Agent object
Response 404 Not Found: Agent not found or hidden
Response 503 Service Unavailable: Registry not yet initialized
POST /agents¶
Create or replace an agent definition in the ConfigRegistry.
Request body:
{
"name": "security-auditor",
"system_prompt": "You are a security expert. Audit code for vulnerabilities.",
"description": "Audits code for security issues",
"mode": "subagent",
"tools": ["run_semgrep"],
"skills": ["python-review"],
"memory": ["AGENTS.md"],
"interrupt_on": {},
"model": "gpt-4o",
"temperature": 0.1,
"scope": {}
}
| Field | Type | Description |
|---|---|---|
name |
string | Agent identifier (1–100 chars) |
system_prompt |
string | Agent's system prompt |
description |
string | Human-readable description |
mode |
"primary" | "subagent" | "all" |
Whether agent can own sessions, be delegated to, or both |
tools |
list[string] | Registry tool names to attach to this agent |
skills |
list[string] | Registry skill names to attach to this agent |
memory |
list[string] | Paths to instruction files (e.g. AGENTS.md) |
interrupt_on |
dict | Tool names mapped to true for HITL confirmation |
model |
string | Model override (overrides global default for this agent's sessions) |
temperature |
float | Temperature override |
scope |
dict | Scope restriction; empty {} = global |
Response 201 Created: Agent object
Response 422 Unprocessable Entity: Validation error
PUT /agents/{name}¶
Replace an agent definition entirely.
Request body: Same as POST /agents
Response 200 OK: Updated agent object
Response 404 Not Found
PATCH /agents/{name}¶
Partially update an agent definition. Only provided fields are changed.
Request body (all fields optional):
Response 200 OK: Updated agent object
Response 404 Not Found
DELETE /agents/{name}¶
Delete an agent definition from the ConfigRegistry.
Response 204 No Content
Response 404 Not Found: Agent not found
Response 400 Bad Request: Attempt to delete a built-in (native) agent
Skills¶
Skills are SKILL.md files stored in the ConfigRegistry. When an agent loads, its configured skills are injected progressively as the context window fills.
File-managed skills (seeded from skill_sources directories at startup) have source: "file" and cannot be modified or deleted via the API (returns 409 Conflict). API-created skills have source: "api".
GET /skills¶
List all registered skills.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
scope |
dict (via headers) | Filtered by scope when scoping is enabled |
Response 200 OK:
{
"skills": [
{
"name": "python-testing",
"path": "/skills/api/python-testing",
"enabled": true,
"description": "pytest patterns and fixtures",
"content": "# Python Testing\n\n...",
"scope": {},
"source": "api"
}
],
"count": 1
}
GET /skills/{name}¶
Get a specific skill by name, including full content.
Response 200 OK: Skill object
Response 404 Not Found
POST /skills¶
Create or replace a skill in the ConfigRegistry.
Request body:
{
"name": "python-testing",
"content": "# Python Testing\n\nUse pytest. Write tests in tests/. Run with `pytest`.",
"description": "pytest patterns for this project",
"enabled": true,
"scope": {}
}
| Field | Type | Description |
|---|---|---|
name |
string | Skill identifier (1–100 chars) |
content |
string | Full SKILL.md content (YAML frontmatter + Markdown body) |
path |
string | Filesystem path alternative to inline content |
description |
string | Short description |
enabled |
bool | Whether this skill is active (default true) |
scope |
dict | Scope restriction; empty {} = global |
Response 201 Created: Skill object
Response 422 Unprocessable Entity: Validation error
PUT /skills/{name}¶
Replace a skill entirely.
Request body: Same as POST /skills
Response 200 OK: Updated skill object
Response 404 Not Found
PATCH /skills/{name}¶
Partially update a skill. Only provided fields are changed.
Request body (all fields optional):
Response 200 OK: Updated skill object
Response 404 Not Found
DELETE /skills/{name}¶
Delete a skill from the ConfigRegistry.
Response 204 No Content
Response 404 Not Found
Tools¶
GET /tools¶
List all registered tools from both file discovery (AgentRegistry) and API registration (ConfigRegistry).
Response 200 OK:
{
"tools": [
{
"name": "bash",
"source_type": "file",
"source": "file",
"module": "server.app.agent.tools",
"description": null,
"enabled": true,
"interrupt_on": false
},
{
"name": "search-jira",
"source_type": "api_code",
"source": "api_code",
"module": null,
"description": "Search Jira issues",
"enabled": true,
"interrupt_on": true
},
{
"name": "run_analysis",
"source_type": "api_path",
"source": "api_path",
"module": "myapp.tools.analysis",
"description": null,
"enabled": true
}
],
"count": 3
}
source_type values:
- "file" — auto-discovered from .cognition/tools/ or built-in
- "api_code" — registered via POST /tools with code field (Python source stored in DB)
- "api_path" — registered via POST /tools with path field (module path)
File-managed tools (seeded from tool_sources directories at startup) have source: "file" and cannot be modified or deleted via the API (returns 409 Conflict).
GET /tools/{name}¶
Get a specific tool by name. Checks file-discovered tools first, then ConfigRegistry.
Response 200 OK: Tool object
Response 404 Not Found
GET /tools/errors¶
Get any errors that occurred during tool discovery or reload.
Response 200 OK:
[
{
"file": ".cognition/tools/broken_tool.py",
"error_type": "ImportError",
"error": "No module named 'missing_dep'",
"timestamp": 1711972800.0
}
]
POST /tools¶
Register a tool in the ConfigRegistry. Exactly one of code or path must be provided.
Request body — inline source code:
{
"name": "search-jira",
"code": "from langchain_core.tools import tool\n\n@tool\ndef search_jira(query: str) -> str:\n \"\"\"Search Jira issues by query string.\"\"\"\n ...",
"enabled": true,
"description": "Search Jira issues",
"scope": {}
}
Request body — module path:
| Field | Type | Description |
|---|---|---|
name |
string | Tool identifier (1–100 chars) |
code |
string | Full Python source containing @tool-decorated functions or BaseTool subclasses |
path |
string | Dotted module path importable by the server process |
enabled |
bool | Whether this tool is active (default true) |
description |
string | Optional description |
interrupt_on |
bool | Whether this tool should require approval by default in builders that consume tool metadata |
scope |
dict | Scope restriction; empty {} = global |
Response 201 Created: Tool object with source_type
Response 422 Unprocessable Entity: Neither code nor path provided; or both provided
Security: Tool code executes with full Python privileges inside the sandbox backend. Restrict this endpoint to authorized administrators at the Gateway/proxy layer.
DELETE /tools/{name}¶
Remove an API-registered tool from the ConfigRegistry.
Response 204 No Content
Response 404 Not Found: Tool not in ConfigRegistry
POST /tools/reload¶
Trigger a manual reload of file-discovered tools from .cognition/tools/.
Response 200 OK:
Models¶
Provider configs are the canonical model selection surface in Cognition. Cognition validates the provider config, resolves credentials and transport settings, builds a concrete LangChain chat model, and passes that model into Deep Agents.
Provider Types And Validation¶
| Provider type | Required fields | Notes |
|---|---|---|
openai |
id, provider, model |
Uses OPENAI_API_KEY unless api_key_env overrides it |
anthropic |
id, provider, model |
Uses ANTHROPIC_API_KEY unless api_key_env overrides it |
bedrock |
id, provider, model, region |
role_arn is allowed only for bedrock |
openai_compatible |
id, provider, model, base_url |
Covers OpenRouter, Ollama, vLLM, LiteLLM, LM Studio, and similar endpoints |
google_genai |
id, provider, model |
Uses GOOGLE_API_KEY unless api_key_env overrides it |
google_vertexai |
id, provider, model |
Vertex runtime details come from ADC and project config |
mock |
id, provider, model |
Test-only provider |
Validation rules enforced by Cognition:
base_urlis required foropenai_compatiblebase_urlis rejected for non-openai_compatibleprovidersregionis required forbedrockregionis rejected for non-bedrockprovidersrole_arnis rejected for non-bedrockproviders
GET /models¶
List models from the models.dev catalog with optional filtering.
This endpoint returns catalog metadata only for provider types that have at least one enabled provider config visible in the current scope. It does not expose the full global models.dev catalog.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
provider |
string | Filter by Cognition provider type (e.g. openai, anthropic) |
tool_call |
bool | Filter by tool call support |
q |
string | Search by model name or ID |
Notes:
- if no enabled providers are configured in scope, the response is empty
- if
provideris requested but no matching enabled provider config exists in scope, the response is empty openai_compatibleproviders do not contribute catalog entries unless Cognition has an explicit catalog mapping for the upstream service
Response 200 OK:
{
"models": [
{
"id": "gpt-4o",
"provider": "openai",
"display_name": "GPT-4o",
"context_window": 128000,
"output_limit": 16384,
"capabilities": ["tool_call", "vision", "structured_output"],
"input_cost": 2.5,
"output_cost": 10.0,
"modalities": {"input": ["text", "image"], "output": ["text"]},
"family": "gpt",
"status": null
}
]
}
status values: null (active), "deprecated", "beta".
GET /models/providers¶
List all provider configs from the ConfigRegistry.
Use this endpoint to inspect the effective provider registry before binding sessions by provider_id.
Response 200 OK:
{
"providers": [
{
"id": "default",
"provider": "openai_compatible",
"model": "google/gemini-3-flash-preview",
"display_name": null,
"enabled": true,
"priority": 1,
"max_retries": 2,
"api_key_env": "COGNITION_OPENAI_COMPATIBLE_API_KEY",
"base_url": "https://openrouter.ai/api/v1",
"region": null,
"role_arn": null,
"extra": {},
"scope": {},
"source": "api"
}
],
"count": 1
}
GET /models/providers/{provider_id}/models¶
List catalog models available for a specific provider config.
For openai_compatible providers, the catalog may be incomplete because available models depend on the upstream service.
Response 200 OK: Same schema as GET /models
POST /models/providers¶
Create a provider config in the ConfigRegistry. Takes effect immediately — no restart required.
Request body:
{
"id": "my-openai",
"provider": "openai",
"model": "gpt-4o",
"api_key_env": "OPENAI_API_KEY",
"enabled": true,
"priority": 0,
"max_retries": 2,
"base_url": null,
"region": null,
"role_arn": null,
"scope": {}
}
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique identifier for this config |
provider |
string | Yes | openai, anthropic, bedrock, openai_compatible, google_genai, google_vertexai |
model |
string | Yes | Model ID |
api_key_env |
string | No | Name of the env var holding the API key (not the key itself) |
enabled |
bool | No | Default true |
priority |
int | No | Lower = higher priority in resolution chain. Default 0 |
max_retries |
int | No | Stored but not yet enforced — field is accepted and persisted but not passed to the LLM client. Default 2 |
base_url |
string | No | Required for openai_compatible |
region |
string | No | AWS region for bedrock |
role_arn |
string | No | IAM role ARN for Bedrock cross-account access |
scope |
dict | No | Scope restriction; empty {} = global |
Response 201 Created: Provider config object
Response 422 Unprocessable Entity: Validation error
Preferred usage:
- use the returned
idasSessionConfig.provider_id - prefer
provider_idover model-only session selection
Common invalid configs:
openai_compatiblewithoutbase_urlbedrockwithoutregionregionorrole_arnon non-bedrockprovidersbase_urlon non-openai_compatibleproviders
PATCH /models/providers/{provider_id}¶
Partially update a provider config.
Updates are fully revalidated, so an invalid partial update is rejected instead of leaving the provider in a broken state.
Request body (all fields optional):
Response 200 OK: Updated provider config
Response 404 Not Found
DELETE /models/providers/{provider_id}¶
Delete a provider config.
Response 204 No Content
Response 404 Not Found
POST /models/providers/{provider_id}/test¶
Validate that the configured provider can be resolved and instantiated successfully.
Use this endpoint during onboarding before binding sessions to a new provider_id.
Test provider connectivity and credentials.
Response 200 OK:
{
"success": true,
"provider": "openai",
"model": "gpt-4o",
"message": "Connection successful",
"response_preview": "Hello!"
}
Response 200 OK (failure):
{
"success": false,
"provider": "openai",
"model": "gpt-4o",
"message": "AuthenticationError: Invalid API key",
"response_preview": null
}
Configuration¶
GET /config¶
Get the current server configuration (infrastructure only). Secrets are redacted.
Response 200 OK:
{
"server": {
"host": "127.0.0.1",
"port": 8000,
"log_level": "info",
"scoping_enabled": false
},
"llm": {
"available_providers": [
{"id": "openai", "name": "Openai", "models": ["gpt-4o", "gpt-4o-mini", "..."]}
]
},
"rate_limit": {
"per_minute": 60,
"burst": 10
}
}
PATCH /config¶
Note: LLM and agent configuration is managed via the ConfigRegistry API (
POST /models/providers,PATCH /agents/{name}, etc.), notPATCH /config.
Update infrastructure configuration at runtime. Changes are persisted to .cognition/config.yaml.
Allowed paths: rate_limit.per_minute, rate_limit.burst, observability.otel_enabled, observability.metrics_port, observability.otel_endpoint, mlflow.enabled, mlflow.experiment_name.
Request body:
Response 200 OK:
{
"updated": true,
"changes": {"rate_limit.per_minute": 120},
"backup_created": true,
"timestamp": "2026-03-02T12:00:00Z"
}
Response 422 Unprocessable Entity: Disallowed field or empty change set.
POST /config/rollback¶
Roll back to the previous configuration backup.
Response 200 OK:
Response 404 Not Found: No backup exists.
MCP Servers¶
Manage remote MCP (Model Context Protocol) tool servers at runtime. File-managed servers (from .cognition/config.yaml) have source: "file" and cannot be modified via the API (returns 409 Conflict).
GET /mcp-servers¶
List all registered MCP servers visible in the current scope.
Response 200 OK:
{
"servers": [
{
"name": "github-tools",
"url": "https://mcp.github.example.com/sse",
"headers": {},
"enabled": true,
"transport": "sse",
"scope": {},
"source": "api"
}
],
"count": 1
}
Note:
headersis always returned as an empty{}to prevent credential leakage.
POST /mcp-servers¶
Register a new MCP server.
Request body:
{
"name": "my-tools",
"url": "https://tools.example.com/sse",
"transport": "sse",
"enabled": true,
"headers": {"Authorization": "Bearer ..."},
"scope": {}
}
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string (1–100) | Yes | — | Unique server identifier |
url |
string | Yes | — | HTTP/HTTPS URL (stdio not supported) |
transport |
"sse" | "streamable_http" |
No | "sse" |
Transport protocol |
enabled |
bool | No | true |
Whether to connect |
headers |
dict | No | {} |
HTTP headers sent with requests |
scope |
dict | No | {} |
Scope restriction |
Response 201 Created: MCP server object
Response 422 Unprocessable Entity: Validation error
GET /mcp-servers/{name}¶
Get a specific MCP server by name.
Response 200 OK: MCP server object
Response 404 Not Found
PATCH /mcp-servers/{name}¶
Partially update an MCP server.
Request body (all fields optional):
Response 200 OK: Updated MCP server object
Response 404 Not Found
Response 409 Conflict: Server is file-managed
DELETE /mcp-servers/{name}¶
Delete an MCP server.
Response 204 No Content
Response 404 Not Found
Response 409 Conflict: Server is file-managed
Artifacts¶
Artifacts are durable, scope-aware files that agents and builders can read, write, list, and diff. They provide explicit state outside the model context window for long-running agent handoffs.
Artifact types: scratch (thread-scoped), artifact (user-visible), contract (done criteria), eval (evaluator results), memory (scoped memory), policy (read-only org policy).
Visibilities: private (session-scoped), run (run-scoped), public (scope-visible).
GET /artifacts¶
List all artifacts visible in the current scope.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
artifact_type |
string | Filter by type (scratch, artifact, etc.) |
run_id |
string | Filter by run ID |
Response 200 OK:
{
"artifacts": [
{
"id": "art-abc123",
"name": "deployment-plan",
"artifact_type": "artifact",
"path": "/plans/deployment.md",
"content": "# Deployment Plan\n...",
"content_type": "text/markdown",
"version": 3,
"parent_version": 2,
"run_id": null,
"checkpoint_id": null,
"visibility": "public",
"scope": {"user": "alice"},
"source": "api",
"created_at": "2026-05-21T10:00:00Z",
"updated_at": "2026-05-21T12:00:00Z"
}
],
"count": 1
}
POST /artifacts¶
Create a new artifact.
Request body:
{
"id": "deployment-plan",
"name": "Deployment Plan",
"artifact_type": "artifact",
"content": "# Deployment Plan\n...",
"content_type": "text/markdown",
"visibility": "public",
"scope": {}
}
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique identifier |
name |
string | Yes | Human-readable name |
artifact_type |
string | Yes | scratch, artifact, contract, eval, memory, policy |
content |
string | Yes | Artifact content |
content_type |
string | No | MIME type (e.g. text/markdown, application/json) |
path |
string | No | Logical path |
run_id |
string | No | Associated run ID |
checkpoint_id |
string | No | Associated checkpoint ID |
visibility |
string | No | private, run, or public (default: private) |
scope |
dict | No | Scope restriction |
Response 201 Created: Artifact object
Response 422 Unprocessable Entity: Invalid type or visibility
GET /artifacts/{artifact_id}¶
Get the latest version of an artifact.
Response 200 OK: Artifact object
Response 404 Not Found
PUT /artifacts/{artifact_id}¶
Update an artifact. Content changes automatically create a new version (version number increments, parent_version set to previous version).
Request body (all fields optional):
Response 200 OK: Updated artifact object
Response 404 Not Found
Response 409 Conflict: Artifact is file-managed
DELETE /artifacts/{artifact_id}¶
Delete an artifact and all its versions.
Response 204 No Content
Response 404 Not Found
GET /artifacts/{artifact_id}/versions¶
List all versions of an artifact, ordered by version descending.
Response 200 OK:
{
"artifact_id": "deployment-plan",
"versions": [
{
"version": 3,
"parent_version": 2,
"content": "# Deployment Plan v3\n...",
"content_type": "text/markdown",
"created_at": "2026-05-21T12:00:00Z"
},
{
"version": 2,
"parent_version": 1,
"content": "# Deployment Plan v2\n...",
"content_type": "text/markdown",
"created_at": "2026-05-21T11:00:00Z"
}
],
"count": 2
}
GET /artifacts/{artifact_id}/versions/{version}¶
Get a specific version of an artifact.
Response 200 OK: Artifact object at that version
Response 404 Not Found
Capabilities¶
GET /capabilities¶
Returns the deployment's runtime feature set, package versions, and configuration. Use this to discover available features without parsing error messages.
Response 200 OK:
{
"versions": {
"cognition": "0.10.0",
"deepagents": "0.6.3",
"langgraph": "1.2.0",
"langchain": "1.3.1",
"langchain_core": "1.4.0"
},
"stream_protocols": ["sse"],
"sandbox_backends": ["local", "docker", "kubernetes"],
"features": {
"async_subagents": true,
"mcp": true,
"mcp_tool_name_prefix": true,
"hitl": true,
"permissions": true,
"artifacts": true,
"context_policy": true,
"context_controls": true,
"tool_safety": true,
"tool_argument_validation": true,
"trusted_runtime_context": true,
"checkpoint_apis": true,
"scope_propagation": true,
"provider_config_crud": true,
"agent_config_crud": true,
"model_catalog": true,
"a2a": true,
"a2a_jsonrpc": true,
"a2a_streaming": true,
"a2a_per_agent_cards": true,
"a2a_push_notifications": false,
"a2a_grpc": false
},
"middleware": [
"ToolSecurityMiddleware",
"ToolArgumentValidationMiddleware",
"TrustedRuntimeContextMiddleware",
"CognitionObservabilityMiddleware",
"CognitionStreamingMiddleware",
"HumanInTheLoopMiddleware",
"FilesystemMiddleware",
"MemoryMiddleware",
"SummarizationToolMiddleware"
],
"scope_keys": ["user"],
"deployment": {
"sandbox_backend": "local"
}
}
A2A Protocol¶
Cognition exposes agents via the Agent-to-Agent (A2A) protocol. Only agents with a2a_exposed: true on their definition are visible. The adapter is implemented in server/app/protocols/a2a/ and uses the a2a-sdk for protocol compliance.
The A2A protocol surface can be disabled entirely by setting COGNITION_A2A_ENABLED=false. When disabled, the /.well-known/agent-card.json and /a2a/{agent_name} endpoints are not mounted, and GET /capabilities reports a2a: false.
GET /.well-known/agent-card.json¶
Discover available agents. Returns A2A AgentCard objects filtered by the request's scope.
Headers:
Response 200 OK:
{
"cards": [
{
"name": "deploy-agent",
"description": "Handles deployment workflows",
"url": "http://localhost:8000/a2a/deploy-agent",
"version": "1.0",
"capabilities": {
"streaming": true,
"pushNotifications": false
},
"skills": [
{
"name": "deploy",
"description": "Deploy applications to production"
}
]
}
]
}
Only agents visible in the caller's scope with a2a_exposed=True are returned. Built-in agents are not exposed by default.
POST /a2a/{agent_name}¶
Send a JSON-RPC request to a specific agent. The {agent_name} is resolved at request time — agents created after the server starts are immediately available without restart.
Headers:
Request body (JSON-RPC 2.0):
{
"jsonrpc": "2.0",
"id": "1",
"method": "SendMessage",
"params": {
"message": {
"role": "user",
"parts": [
{"type": "text", "text": "Deploy the staging environment"}
]
}
}
}
Supported methods:
| Method | Description |
|---|---|
SendMessage |
Send a message and get the complete response |
SendStreamingMessage |
Send a message and stream the response (SSE) |
Response 200 OK (SendMessage):
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"taskId": "task-abc123",
"status": {
"state": "completed",
"message": {
"role": "agent",
"parts": [
{"type": "text", "text": "Staging environment deployed successfully."}
]
}
}
}
}
Response 200 OK (SendStreamingMessage):
Content-Type: text/event-stream — streams A2A task state events as SSE.
A2A task state mapping:
| Cognition Event | A2A TaskState |
|---|---|
StatusEvent("thinking") |
working |
TokenEvent |
working (with content part) |
DoneEvent |
completed |
ErrorEvent |
failed |
Errors:
- 404 Not Found — Agent not found or not A2A-exposed
- 422 Unprocessable Entity — Invalid JSON-RPC request
- 400 Bad Request — Unsupported A2A method
For full A2A protocol details, see the A2A SDK documentation.
Multi-Tenant Scoping¶
When COGNITION_SCOPING_ENABLED=true, all session endpoints require scope headers. The required headers are determined by COGNITION_SCOPE_KEYS — these are builder-defined key names. Cognition does not hardcode a vocabulary.
For scope_keys: ["user", "project"]:
For scope_keys: ["tenant", "env"]:
Missing required headers return 403 Forbidden:
Sessions are automatically filtered to match the request's scope values. One tenant cannot read or write another tenant's sessions. The effective_scope dict propagates through the full runtime stack — ConfigRegistry CRUD, session persistence, CognitionContext, middleware, and tools.
Rate Limiting¶
Requests are throttled using a token bucket algorithm. When the limit is exceeded:
Response 429 Too Many Requests:
The Retry-After header indicates when the next request will be accepted.
Configure limits: COGNITION_RATE_LIMIT_PER_MINUTE (default: 60) and COGNITION_RATE_LIMIT_BURST (default: 10).
Error Format¶
All error responses follow a consistent structure:
Error codes:
| Code | HTTP Status | Description |
|---|---|---|
NOT_FOUND |
404 | Resource not found |
PERMISSION_DENIED |
403 | Scope header missing or mismatch |
RATE_LIMITED |
429 | Rate limit exceeded |
VALIDATION_ERROR |
422 | Request body validation failed |
SESSION_NOT_FOUND |
404 | Session ID does not exist |
LLM_UNAVAILABLE |
503 | LLM provider configuration error or provider unreachable |
TOOL_EXECUTION_ERROR |
500 | Tool raised an exception |
STREAMING_ERROR |
500 | Error during agent streaming |
ABORTED |
— | Stream aborted via POST /sessions/{id}/abort (delivered as SSE error event) |
INTERNAL_ERROR |
500 | Unexpected server error |