Skip to main content

Endpoints

Agent Runtimes exposes a comprehensive REST and WebSocket API for managing agents, executing prompts, and monitoring system status.

Base URL​

http://localhost:8765/api/v1

WebSocket Base URL​

For WebSocket endpoints, switch from http:// to ws:// (or wss:// in TLS environments).

ws://localhost:8765/api/v1
URL Convention - Trailing Slashes

Most API endpoints should be called without trailing slashes. However, mounted protocol endpoints require trailing slashes:

Standard endpoints (no trailing slash):

  • ✅ /api/v1/agents
  • ✅ /api/v1/mcp/servers

Protocol endpoints (trailing slash required):

  • ✅ /api/v1/ag-ui/{agent_id}/ - AG-UI protocol (mounted Starlette apps)
  • ✅ /api/v1/a2a/{agent_id}/ - A2A protocol (FastA2A compatibility)
  • ✅ /api/v1/examples/{example_name}/ - AG-UI example agents

Without the trailing slash, mounted apps return a 307 redirect which may break streaming clients.

Agents​

Manage AI agents and their configurations.

List Agents​

GET /api/v1/agents

Returns a list of all registered agents.

Response:

{
"agents": [
{
"id": "pydantic-ai",
"name": "Pydantic AI Agent",
"transport": "streaming",
"model": "gpt-4o"
}
]
}

Get Agent​

GET /api/v1/agents/{agent_id}

Get details for a specific agent.

Response:

{
"id": "pydantic-ai",
"name": "Pydantic AI Agent",
"transport": "streaming",
"model": "gpt-4o",
"mcp_toolsets": ["tavily", "fetch"]
}

Create Agent​

POST /api/v1/agents
Content-Type: application/json

Create a new agent.

Request Body:

{
"id": "my-agent",
"name": "My Custom Agent",
"model": "gpt-4o",
"system_prompt": "You are a helpful assistant."
}

Update Agent​

PUT /api/v1/agents/{agent_id}
Content-Type: application/json

Update an existing agent configuration.

Update Agent MCP Servers (Runtime)​

PATCH /api/v1/agents/{agent_id}/mcp-servers
Content-Type: application/json

Dynamically update an agent's selected MCP servers without recreating the agent. This allows adding or removing MCP tools from a running agent.

Request Body:

{
"selected_mcp_servers": ["tavily", "filesystem"]
}

Response:

{
"agent_id": "my-agent",
"selected_mcp_servers": ["tavily", "filesystem"],
"message": "MCP servers updated successfully"
}

Start Agent MCP Servers​

Start catalog MCP servers defined for running agents. Environment variables can be provided to configure the servers (e.g., API keys). If the agent has Codemode enabled, the Codemode toolset will be rebuilt to include the newly started servers as programmatic tools.

Two-Phase Sandbox Bootstrap (Kubernetes)

In a Kubernetes pod, agent-runtimes starts before the Jupyter container is ready. The code sandbox goes through two phases:

PhaseTriggerSandbox VariantCode Execution
1 — StartupDockerfile CMD (--codemode, no --jupyter-sandbox)evalIn-process eval() (fallback)
2 — Companion callPOST /api/v1/agents/mcp-servers/start with jupyter_sandbox + mcp_proxy_urljupyterJupyter kernel (:2300)

Phase 1: The agent-runtimes container starts with --codemode and --no-catalog-mcp-servers. Because no --jupyter-sandbox flag is provided, the CodeSandboxManager defaults to variant="eval".

Phase 2: Once all containers in the pod are healthy, the runtimes-companion sidecar calls this endpoint with:

  • jupyter_sandbox: http://127.0.0.1:2300?token=<token> — the Jupyter kernel URL
  • mcp_proxy_url: http://127.0.0.1:8765/api/v1/mcp/proxy — the HTTP-to-stdio proxy

The endpoint calls CodeSandboxManager.configure_from_url(), which switches the variant to jupyter and rebuilds the Codemode toolset. All subsequent code execution runs inside the Jupyter kernel instead of local eval.

┌──────────────────────────────────────────────────────────────────────┐
│ Pod │
│ │
│ companion ──POST /mcp-servers/start──▶ agent-runtimes :8765 │
│ (jupyter_sandbox, │ │
│ mcp_proxy_url, ├─ starts MCP servers │
│ env_vars) ├─ switches to jupyter │
│ └─ rebuilds codemode │
│ │
│ agent-runtimes :8765 ──run_code()──▶ jupyter :2300 │
│ jupyter :2300 ──HTTP tool call──▶ agent-runtimes /api/v1/mcp/proxy │
│ │
│ Shared Volume: /mnt/shared-agent/ │
│ ├── generated/ (Python tool bindings written by codemode) │
│ └── skills/ (SKILL.md files for agent skills) │
└──────────────────────────────────────────────────────────────────────┘

Start MCP Servers for All Agents​

POST /api/v1/agents/mcp-servers/start
Content-Type: application/json

Start catalog MCP servers for all running agents.

Request Body:

{
"env_vars": [
{"name": "TAVILY_API_KEY", "value": "tvly-xxx"},
{"name": "GITHUB_TOKEN", "value": "ghp_xxx"}
],
"jupyter_sandbox": "http://localhost:8888?token=my-token",
"mcp_proxy_url": "http://127.0.0.1:8765/api/v1/mcp/proxy"
}
FieldTypeRequiredDescription
env_varsarrayNoList of environment variables to set before starting servers
env_vars[].namestringYesEnvironment variable name
env_vars[].valuestringYesEnvironment variable value
jupyter_sandboxstringNoJupyter server URL with token for code execution. When provided, switches the sandbox from eval to jupyter (Phase 2 of the bootstrap)
mcp_proxy_urlstringNoHTTP proxy URL the Jupyter kernel uses to call MCP tools. Defaults to http://127.0.0.1:8765/api/v1/mcp/proxy when jupyter_sandbox is set

Example Request:

curl -X POST http://localhost:8000/api/v1/agents/mcp-servers/start \
-H "Content-Type: application/json" \
-d '{"env_vars": [{"name": "TAVILY_API_KEY", "value": "tvly-xxx"}]}'

Response: 200 OK

{
"agents_processed": ["agent-1", "agent-2"],
"started_servers": ["tavily", "github"],
"stopped_servers": [],
"already_running": [],
"already_stopped": [],
"failed_servers": [],
"codemode_rebuilt": true,
"sandbox_configured": true,
"sandbox_variant": "jupyter",
"message": "Started 2 server(s) across 2 agent(s), sandbox=jupyter"
}

Start MCP Servers for a Specific Agent​

POST /api/v1/agents/{agent_id}/mcp-servers/start
Content-Type: application/json

Start catalog MCP servers for a specific running agent.

Path Parameters:

ParameterTypeDescription
agent_idstringThe agent identifier

Request Body:

{
"env_vars": [
{"name": "TAVILY_API_KEY", "value": "tvly-xxx"},
{"name": "GITHUB_TOKEN", "value": "ghp_xxx"}
]
}
FieldTypeRequiredDescription
env_varsarrayNoList of environment variables to set before starting servers
env_vars[].namestringYesEnvironment variable name
env_vars[].valuestringYesEnvironment variable value

Example Request:

curl -X POST http://localhost:8000/api/v1/agents/my-agent/mcp-servers/start \
-H "Content-Type: application/json" \
-d '{"env_vars": [{"name": "TAVILY_API_KEY", "value": "tvly-xxx"}]}'

Response: 200 OK

{
"agent_id": "my-agent",
"started_servers": ["tavily"],
"stopped_servers": [],
"already_running": ["github"],
"already_stopped": [],
"failed_servers": [
{"server_id": "filesystem", "error": "Server config not found"}
],
"codemode_rebuilt": true,
"message": "Started 1 server(s), 1 already running, 1 failed"
}

Response Fields​

FieldTypeDescription
agent_idstringThe agent identifier (only for single-agent endpoint)
agents_processedarrayList of agent IDs that were processed (only for all-agents endpoint)
started_serversarrayList of server IDs that were successfully started
already_runningarrayList of server IDs that were already running
failed_serversarrayList of servers that failed to start with error details
codemode_rebuiltbooleanWhether the Codemode toolset was rebuilt
sandbox_configuredbooleanWhether the code sandbox was (re)configured
sandbox_variantstringThe sandbox variant after configuration (eval or jupyter)
messagestringSummary message

Error Responses:

CodeDescription
404Agent not found (single-agent endpoint only)
500Failed to start MCP servers

Stop Agent MCP Servers​

Stop catalog MCP servers for running agents.

Stop MCP Servers for All Agents​

POST /api/v1/agents/mcp-servers/stop

Stop catalog MCP servers for all running agents.

Example Request:

curl -X POST http://localhost:8000/api/v1/agents/mcp-servers/stop

Response: 200 OK

{
"agents_processed": ["agent-1", "agent-2"],
"started_servers": [],
"stopped_servers": ["tavily", "github"],
"already_running": [],
"already_stopped": [],
"failed_servers": [],
"codemode_rebuilt": false,
"message": "Stopped 2 server(s) across 2 agent(s)"
}

Stop MCP Servers for a Specific Agent​

POST /api/v1/agents/{agent_id}/mcp-servers/stop

Stop catalog MCP servers for a specific running agent.

Path Parameters:

ParameterTypeDescription
agent_idstringThe agent identifier

Example Request:

curl -X POST http://localhost:8000/api/v1/agents/my-agent/mcp-servers/stop

Response: 200 OK

{
"agent_id": "my-agent",
"started_servers": [],
"stopped_servers": ["tavily", "github"],
"already_running": [],
"already_stopped": ["filesystem"],
"failed_servers": [],
"codemode_rebuilt": false,
"message": "Stopped 2 server(s), 1 already stopped"
}

Response Fields​

FieldTypeDescription
agent_idstringThe agent identifier (only for single-agent endpoint)
agents_processedarrayList of agent IDs that were processed (only for all-agents endpoint)
stopped_serversarrayList of server IDs that were successfully stopped
already_stoppedarrayList of server IDs that were already stopped
failed_serversarrayList of servers that failed to stop with error details
messagestringSummary message

Error Responses:

CodeDescription
404Agent not found (single-agent endpoint only)
500Failed to stop MCP servers

Code Sandbox Configuration​

The Code Sandbox Manager controls how code is executed when using Code Mode or Skills. It supports two variants:

  • eval: Uses Python exec() for simple code execution (default)
  • jupyter: Connects to an external Jupyter server for persistent kernel state

Get Sandbox Status​

GET /api/v1/agents/sandbox/status

Get the current status of the code sandbox manager.

Example Request:

curl http://localhost:8000/api/v1/agents/sandbox/status

Response: 200 OK

{
"variant": "eval",
"jupyter_url": null,
"jupyter_token_set": false,
"sandbox_running": true
}
FieldTypeDescription
variantstringCurrent sandbox variant (eval or jupyter)
jupyter_urlstringJupyter server URL if configured
jupyter_token_setbooleanWhether a Jupyter token is configured
sandbox_runningbooleanWhether a sandbox instance is currently active

Sandbox Status WebSocket​

GET /api/v1/configure/sandbox/ws?agent_id={agent_id}

Streams sandbox execution state and accepts interrupt requests.

Server -> Client status message:

{
"variant": "eval",
"sandbox_running": true,
"is_executing": false,
"jupyter_url": null
}
FieldTypeDescription
variantstringeval, jupyter, unavailable, or error
sandbox_runningbooleanWhether sandbox exists and is ready
is_executingbooleanWhether sandbox is currently executing code
jupyter_urlstring/nullEffective Jupyter URL when applicable

Client -> Server interrupt request:

{
"action": "interrupt"
}

Server -> Client interrupt response:

{
"action": "interrupt",
"success": true
}

On error:

{
"action": "interrupt",
"success": false,
"error": "<reason>"
}

Configure Sandbox​

POST /api/v1/agents/sandbox/configure
Content-Type: application/json

Configure the code sandbox manager at runtime. If a sandbox is running with a different configuration, it will be stopped and recreated on next use.

When variant is jupyter:

  • If jupyter_url is provided, agent-runtimes connects to that existing Jupyter server.
  • If jupyter_url is omitted, agent-runtimes uses a managed local Jupyter sandbox.

Request Body:

{
"variant": "jupyter",
"jupyter_url": "http://localhost:8888?token=my-token"
}
FieldTypeRequiredDescription
variantstringNoSandbox variant: eval (default) or jupyter
jupyter_urlstringNoOptional Jupyter server URL (can include token as query param). If omitted with variant=jupyter, a managed local Jupyter sandbox is used.
jupyter_tokenstringNoJupyter token (overrides token in URL if provided)

Example Requests:

# Configure for managed local Jupyter sandbox
curl -X POST http://localhost:8000/api/v1/agents/sandbox/configure \
-H "Content-Type: application/json" \
-d '{"variant": "jupyter"}'

# Configure for external Jupyter server
curl -X POST http://localhost:8000/api/v1/agents/sandbox/configure \
-H "Content-Type: application/json" \
-d '{"variant": "jupyter", "jupyter_url": "http://localhost:8888?token=my-token"}'

# Reset to eval sandbox
curl -X POST http://localhost:8000/api/v1/agents/sandbox/configure \
-H "Content-Type: application/json" \
-d '{"variant": "eval"}'

Response: 200 OK

{
"variant": "jupyter",
"jupyter_url": null,
"jupyter_token_set": false,
"sandbox_running": false
}

Error Responses:

CodeDescription
500Failed to configure sandbox

Restart Sandbox​

POST /api/v1/agents/sandbox/restart

Restart the code sandbox with current configuration. This stops any running sandbox and creates a new instance.

Example Request:

curl -X POST http://localhost:8000/api/v1/agents/sandbox/restart

Response: 200 OK

{
"variant": "jupyter",
"jupyter_url": "http://localhost:8888",
"jupyter_token_set": true,
"sandbox_running": true
}

Error Responses:

CodeDescription
500Failed to restart sandbox

Delete Agent​

DELETE /api/v1/agents/{agent_id}

Remove an agent from the system.

Prompts​

Execute prompts against agents and manage conversations.

Send Prompt (Streaming)​

POST /api/v1/agents/{agent_id}/prompt
Content-Type: application/json

Send a prompt to an agent and receive a streaming response.

Request Body:

{
"message": "What is the weather in Paris?",
"conversation_id": "optional-conversation-id"
}

Response: Server-Sent Events (SSE) stream

data: {"type": "text", "content": "Based on "}
data: {"type": "text", "content": "the current weather..."}
data: {"type": "tool_call", "name": "get_weather", "args": {...}}
data: {"type": "tool_result", "result": {...}}
data: {"type": "done"}

Send Prompt (Non-Streaming)​

POST /api/v1/agents/{agent_id}/prompt/sync
Content-Type: application/json

Send a prompt and wait for the complete response.

Response:

{
"response": "Based on the current weather data...",
"tool_calls": [...],
"usage": {
"prompt_tokens": 150,
"completion_tokens": 200
}
}

Configuration​

System configuration and status endpoints.

Get Configuration​

GET /api/v1/configure

Get the current system configuration including available models and MCP servers.

Response:

{
"models": [...],
"mcp_servers": [...],
"tools": [...]
}

MCP Toolsets Status​

GET /api/v1/configure/mcp-toolsets-status

Get the status of MCP toolsets initialization.

Response:

{
"initialized": true,
"ready_count": 3,
"failed_count": 0,
"ready_servers": ["tavily", "linkedin", "kaggle"],
"failed_servers": {}
}

MCP Toolsets Info​

GET /api/v1/configure/mcp-toolsets-info

Get detailed information about running MCP toolsets.

Response:

[
{
"type": "MCPToolset",
"id": "tavily",
"command": "npx",
"args": ["-y", "tavily-mcp@0.1.3"]
}
]

Tool Approvals / Monitoring Stream (WebSocket)​

GET /api/v1/tool-approvals/ws?agent_id={agent_id}

Compatibility aliases are also available:

  • /api/ai-agents/v1/tool-approvals/ws
  • /api/ai-agents/v1/ws

This stream sends a versioned envelope. The first message is always an agent.snapshot, followed by incremental events and refreshed snapshots.

Server -> Client envelope:

{
"version": "1.0",
"type": "agent.snapshot",
"agentId": "my-agent",
"timestamp": "2026-04-19T19:00:00Z",
"payload": {
"agentId": "my-agent",
"approvals": [],
"pendingApprovalCount": 0,
"contextSnapshot": null,
"costUsage": null,
"mcpStatus": null,
"codemodeStatus": null,
"fullContext": null
},
"event": "agent.snapshot",
"data": {
"agentId": "my-agent"
}
}

Client -> Server control messages:

{ "type": "request_snapshot" }
{ "type": "request_otel_flush" }
{
"type": "tool_approval_decision",
"approvalId": "approval-123",
"approved": true,
"note": "Looks safe"
}
{ "type": "skill_enable", "skillId": "github" }
{ "type": "skill_disable", "skillId": "github" }

ACP Protocol WebSocket​

GET /api/v1/acp/ws/{agent_id}

Bidirectional ACP transport over WebSocket. This endpoint expects ACP message objects (for example initialize, session/new, session/prompt, etc.) and returns ACP-compliant responses/events.

If {agent_id} is unknown, the server sends an ACP error payload and closes the socket.

MCP Servers​

Manage MCP (Model Context Protocol) servers for tool integration. There are two types of MCP servers:

  • MCP Config: User-defined servers from ~/.datalayer/mcp.json that start automatically
  • MCP Catalog: Predefined servers that can be enabled on-demand
Separate Storage

Config and catalog servers are stored separately, allowing the same server ID to exist in both without conflict. For example, you can have a custom tavily server in your mcp.json while also having access to the predefined tavily in the catalog.

Starting Without Config MCP Servers

When you start the server with the --no-config-mcp-servers CLI flag, config MCP servers from ~/.datalayer/mcp.json are not started automatically. You can then use the endpoints below to dynamically enable MCP servers from the catalog at runtime:

# Start server without config MCP servers
python -m agent_runtimes --no-config-mcp-servers

# Then enable MCP servers via API
curl -X POST http://localhost:8000/api/v1/mcp/servers/catalog/tavily/enable
curl -X POST http://localhost:8000/api/v1/mcp/servers/catalog/github/enable

This is useful for scenarios where you want fine-grained control over which MCP servers are running, or when you need to manage resources carefully.

List MCP Config Servers​

GET /api/v1/mcp/servers/config

Get all running MCP Config servers from ~/.datalayer/mcp.json. These servers start automatically when the agent runtime starts.

Response:

[
{
"id": "tavily",
"name": "Tavily Search",
"description": "Web search and research capabilities",
"enabled": true,
"tools": [
{
"name": "tavily-search",
"description": "Search the web using Tavily",
"enabled": true
}
],
"isAvailable": true,
"isRunning": true,
"isConfig": true,
"transport": "stdio"
}
]

List Catalog Servers​

GET /api/v1/mcp/servers/catalog

Get all predefined MCP servers from the catalog. These are NOT started automatically.

Response:

[
{
"id": "tavily",
"name": "Tavily Search",
"description": "Web search and research capabilities via Tavily API",
"enabled": true,
"tools": [],
"command": "npx",
"args": ["-y", "tavily-mcp"],
"requiredEnvVars": ["TAVILY_API_KEY"],
"isAvailable": false,
"isConfig": false,
"transport": "stdio"
}
]

List All Available Servers​

GET /api/v1/mcp/servers/available

Get all available MCP servers - combines catalog servers with running config servers. Since config and catalog servers are stored separately, the same ID can appear in both (as separate entries).

Response:

[
{
"id": "tavily",
"name": "Tavily Search",
"isAvailable": true,
"isRunning": true,
"isConfig": true,
"transport": "stdio"
},
{
"id": "tavily",
"name": "Tavily Search",
"description": "Web search via Tavily API",
"isAvailable": false,
"isRunning": false,
"isConfig": false,
"transport": "stdio"
}
]

Note: The same ID (tavily) can appear twice - once from config (user's mcp.json) and once from catalog (predefined).

List Running Servers​

GET /api/v1/mcp/servers

Get all currently running MCP servers (both config and catalog).

Response:

[
{
"id": "tavily",
"name": "Tavily Search",
"enabled": true,
"tools": [
{
"name": "tavily-search",
"description": "A powerful web search tool...",
"enabled": true,
"inputSchema": {...}
}
],
"isAvailable": true
}
]

Get Server​

GET /api/v1/mcp/servers/{server_id}

Get details for a specific MCP server.

Enable Catalog Server​

POST /api/v1/mcp/servers/catalog/{server_name}/enable

Start an MCP server from the catalog for the current session. Only works for catalog servers (not config servers which start automatically).

This is particularly useful when:

  • You started the server with --no-config-mcp-servers
  • You want to dynamically add tools to an agent at runtime
  • You need fine-grained control over which MCP servers are running

Path Parameters:

ParameterTypeDescription
server_namestringThe name/ID of the MCP server from the catalog (e.g., tavily, github, filesystem)

Example Request:

curl -X POST http://localhost:8000/api/v1/mcp/servers/catalog/tavily/enable

Response: 201 Created

{
"id": "tavily",
"name": "Tavily Search",
"enabled": true,
"tools": [
{
"name": "tavily-search",
"description": "Search the web using Tavily"
}
],
"isRunning": true,
"isConfig": false
}

Error Responses:

CodeDescription
404Server not found in catalog
500Failed to start the MCP server

Disable Catalog Server​

DELETE /api/v1/mcp/servers/catalog/{server_name}/disable

Stop an MCP server and remove it from the current session. This stops the MCP server process and frees up resources.

Path Parameters:

ParameterTypeDescription
server_namestringThe name/ID of the MCP server to disable

Example Request:

curl -X DELETE http://localhost:8000/api/v1/mcp/servers/catalog/tavily/disable

Response: 204 No Content

Error Responses:

CodeDescription
404Server is not currently enabled
500Failed to stop the MCP server

Create Server​

POST /api/v1/mcp/servers
Content-Type: application/json

Add a new MCP server configuration.

Request Body:

{
"id": "my-server",
"name": "My Custom Server",
"command": "npx",
"args": ["-y", "my-mcp-server"],
"enabled": true
}

Update Server​

PUT /api/v1/mcp/servers/{server_id}
Content-Type: application/json

Update an existing MCP server configuration.

Delete Server​

DELETE /api/v1/mcp/servers/{server_id}

Remove an MCP server configuration.

Response: 204 No Content

AG-UI Protocol​

The AG-UI (Agent-User Interface) protocol provides streaming agent communication using Server-Sent Events (SSE). Each agent is mounted as a Starlette application.

Trailing Slash Required

AG-UI endpoints are mounted Starlette apps and require a trailing slash. Without it, you'll get a 307 redirect that breaks streaming.

List AG-UI Agents​

GET /api/v1/ag-ui/agents

List all agents available via AG-UI protocol.

Response:

{
"protocol": "ag-ui",
"version": "0.1.0",
"agents": [
{
"agent_id": "pydantic-ai",
"endpoint": "/api/v1/ag-ui/pydantic-ai/"
}
],
"agents_endpoint": "/api/v1/ag-ui/agents",
"terminate_endpoint": "/api/v1/ag-ui/terminate",
"note": "Each agent is mounted at /api/v1/ag-ui/{agent_id}/ (trailing slash required)"
}

AG-UI Protocol Info​

GET /api/v1/ag-ui/

Get AG-UI protocol information and list of available agents.

Send Message (Streaming)​

POST /api/v1/ag-ui/{agent_id}/
Content-Type: application/json

Send a message to an AG-UI agent and receive streaming SSE response.

Request Body:

{
"thread_id": "thread-123",
"run_id": "run-456",
"messages": [
{
"id": "msg-1",
"role": "user",
"content": "Hello, how are you?"
}
],
"state": {},
"tools": [],
"context": [],
"forwardedProps": {}
}

Response: Server-Sent Events (SSE) stream with AG-UI events:

event: RUN_STARTED
data: {"type": "RUN_STARTED", "thread_id": "thread-123", "run_id": "run-456"}

event: TEXT_MESSAGE_START
data: {"type": "TEXT_MESSAGE_START", "message_id": "msg-2", "role": "assistant"}

event: TEXT_MESSAGE_CONTENT
data: {"type": "TEXT_MESSAGE_CONTENT", "message_id": "msg-2", "delta": "Hello! "}

event: TEXT_MESSAGE_CONTENT
data: {"type": "TEXT_MESSAGE_CONTENT", "message_id": "msg-2", "delta": "I'm doing well."}

event: TEXT_MESSAGE_END
data: {"type": "TEXT_MESSAGE_END", "message_id": "msg-2"}

event: RUN_FINISHED
data: {"type": "RUN_FINISHED", "thread_id": "thread-123", "run_id": "run-456"}

Terminate Run​

POST /api/v1/ag-ui/terminate
Content-Type: application/json

Terminate an active AG-UI run.

Request Body:

{
"thread_id": "thread-123",
"run_id": "run-456"
}

AG-UI Event Types​

EventDescription
RUN_STARTEDRun has started processing
RUN_FINISHEDRun completed successfully
RUN_ERRORRun encountered an error
TEXT_MESSAGE_STARTBeginning of a text message
TEXT_MESSAGE_CONTENTIncremental text content (streaming)
TEXT_MESSAGE_ENDEnd of a text message
TOOL_CALL_STARTTool invocation started
TOOL_CALL_ARGSTool call arguments (streaming)
TOOL_CALL_ENDTool invocation completed
TOOL_CALL_RESULTResult from tool execution
STATE_SNAPSHOTCurrent state snapshot
STATE_DELTAIncremental state update
CUSTOMCustom event type

Example: Using curl​

curl -X POST "http://localhost:8765/api/v1/ag-ui/pydantic-ai/" \
-H "Content-Type: application/json" \
-d '{
"thread_id": "test-thread",
"run_id": "test-run",
"messages": [{"id": "1", "role": "user", "content": "Hello!"}],
"state": {},
"tools": [],
"context": [],
"forwardedProps": {}
}'

Example: Using TypeScript​

import { AGUIAdapter } from '@datalayer/agent-runtimes';

const adapter = new AGUIAdapter({
baseUrl: 'http://localhost:8765/api/v1/ag-ui/pydantic-ai/',
// Note: The adapter automatically ensures trailing slash
});

await adapter.sendMessage('Hello!', {
onToken: (token) => console.log(token),
onComplete: (message) => console.log('Done:', message),
});

Example: Using Python​

from agent_runtimes.transports.clients import AGUIClient

async with AGUIClient("http://localhost:8765/api/v1/ag-ui/pydantic-ai/") as client:
async for event in client.run("Hello!"):
print(event)

Extensions​

A2UI Endpoints​

GET  /api/v1/a2ui/           # A2UI protocol
GET /api/v1/a2ui/agents # List A2UI agents

MCP-UI Endpoints​

GET  /api/v1/mcp-ui/         # MCP-UI protocol
GET /api/v1/mcp-ui/agents # List MCP-UI agents

Agent Nodes​

Agent Node operations are split between:

  • Local node runtime endpoints on agent-runtimes (/api/v1/...)
  • Central control-plane endpoints on datalayer-runtimes (/api/runtimes/v1/...)

Local Agent Node Configuration (agent-runtimes)​

GET  /api/v1/agent-node/configuration
POST /api/v1/agent-node/configuration

Read or update local node configuration.

Configuration fields:

  • mode: private, shared, or sleep.
  • billing_entity_uid
  • billing_entity_type
  • billing_entity_handle
  • sharing (JSON object)

Central Agent Node Registry (datalayer-runtimes)​

POST /api/runtimes/v1/agent-nodes/register
POST /api/runtimes/v1/agent-nodes/heartbeat
POST /api/runtimes/v1/agent-nodes/configuration
POST /api/runtimes/v1/agent-nodes/aws/discover
GET /api/runtimes/v1/agent-nodes
GET /api/runtimes/v1/agent-nodes/{node_id}

These endpoints maintain fleet state and enforce visibility:

  • own nodes are always visible,
  • other users' nodes are visible only when mode=shared.

POST /agent-nodes/aws/discover accepts { "aws_account_id": "123456789012" }, allowlists that account id for the caller in memory, and returns currently available nodes registered with the same AWS account id.

Agent Node Tunnel (datalayer-runtimes)​

GET  /api/runtimes/v1/agent-nodes/tunnel/ws
POST /api/runtimes/v1/agent-nodes/{node_id}/tunnel/messages
GET /api/runtimes/v1/agent-nodes/{node_id}/tunnel/events
GET /api/runtimes/v1/agent-nodes/{node_id}/tunnel/status

The tunnel provides bidirectional routing for central chat:

  • UI -> runtimes -> selected node (chat.request)
  • node -> runtimes -> UI (chat.response / chat.error)

The websocket endpoint requires authenticated query parameters (node_id and token) and keeps a persistent node session.

Conversations​

Manage conversation history and context.

Get Conversation​

GET /api/v1/conversations/{conversation_id}

Retrieve a conversation by ID.

List Conversations​

GET /api/v1/conversations

List all conversations, optionally filtered by agent.

Delete Conversation​

DELETE /api/v1/conversations/{conversation_id}

Delete a conversation and its history.

Health & Status​

Health Check​

GET /api/v1/health

Response:

{
"status": "healthy",
"version": "0.4.5"
}

Readiness Check​

GET /api/v1/ready

Returns 200 when the service is ready to accept requests.

Error Responses​

All endpoints return standard error responses:

{
"detail": "Agent not found",
"status_code": 404
}

Common Status Codes​

CodeDescription
200Success
201Created
400Bad Request
404Not Found
422Validation Error
500Internal Server Error

Authentication​

info

Authentication is optional and configurable. When enabled, include the API key in the request header:

Authorization: Bearer your-api-key

Rate Limiting​

Rate limiting can be configured per endpoint. When rate limited, you'll receive:

HTTP/1.1 429 Too Many Requests
Retry-After: 60

OpenAPI Documentation​

Interactive API documentation is available at:

  • Swagger UI: http://localhost:8765/docs
  • ReDoc: http://localhost:8765/redoc
  • OpenAPI JSON: http://localhost:8765/openapi.json