Run Endpoint
Invoke an agent through the unified run endpoint, with streaming or JSON responses.
Endpoint Overview
The Run Endpoint is the single entry point for invoking an agent over HTTP. It replaces the deprecated Chat and Execute endpoints.
The stream field in the request body selects the response mode:
stream: true— real-time streaming response (AI SDK UI Message Stream over SSE), equivalent to the old Chat Endpoint.stream: false(default) — a single JSON response withtext,usage, andfinishReason, equivalent to the old Execute Endpoint.
| Property | Value |
|---|---|
| Method | POST |
| Endpoint | /api/agents/{agentId}/run |
| Response Type | JSON (default) or Streaming SSE (stream: true) |
| Authentication | Authorization (user JWT) or cf-api-key |
Both modes invoke the same agent configuration, including its model, system prompt, tools, and knowledge sources.
Authentication
You can authenticate using a user session token or a scoped API key.
Bearer Token
Authorization: Bearer <supabase_jwt>Use for platform users with an active Supabase session.
Optional Headers
Pass x-agent-payload additional metadata to downstream MCP integrations.
x-agent-payload: {"x-user-id":"123","x-tenant-id":"acme"}- Must contain valid JSON.
- Only string, number, and boolean values are preserved.
- Unsafe headers such as
authorization,host, andcontent-lengthare automatically removed before forwarding.
Request Body
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
stream | boolean | No | true for a streaming SSE response, false (default) for a single JSON response |
message | string or UIMessage | No | Latest user message. Plain strings are wrapped into a user message automatically |
messages | UIMessage[] | No | Complete conversation history (client-managed mode) |
id | string | No | Conversation ID or client session ID |
vars | Record<string, any> | No | Runtime variables injected into the agent prompt |
customTools | Array | No | Runtime-defined tools for advanced scenarios |
In non-streaming mode, both message and messages may be omitted — the agent runs from its rendered system prompt and the supplied vars (template-driven execution). In streaming mode, provide either message or messages.
Message Object
Structured messages use the AI SDK UI Message format.
{
"id": "msg-1",
"role": "user",
"parts": [
{
"type": "text",
"text": "Hello"
}
]
}Runtime Variables
Use the optional vars field to provide runtime values that can be referenced by agent prompts, workflows, or tools.
{
"vars": {
"customerName": "My Customer",
"bookingId": "BK-12345",
"locale": "en-SG"
}
}Non-Streaming Mode (default)
With stream omitted or set to false, the endpoint executes the agent synchronously and returns a single JSON payload.
Use non-streaming mode when:
- You want a simple request/response integration.
- You are generating content from prompt templates and variables.
- You are calling agents from forms, backend services, scheduled jobs, or workflows.
Request Example
{
"message": "Write a product announcement email",
"vars": {
"productName": "Chocolate Factory AI",
"audience": "existing customers"
}
}Template-Driven Execution
If your agent already contains a prompt template that expects variables, you can run the agent using only vars — no message required.
{
"vars": {
"title": "AI in logistics",
"tone": "professional",
"keywords": "automation, supply chain, forecasting"
}
}Response Fields
| Field | Type | Description |
|---|---|---|
text | string | Generated output from the agent |
usage | object | Token usage information |
finishReason | string | Reason generation stopped |
conversationId | string | null | Conversation ID when server-managed history is used |
Response Example
{
"text": "Generated output from the agent",
"usage": {
"inputTokens": 123,
"outputTokens": 456,
"totalTokens": 579
},
"finishReason": "stop",
"conversationId": null
}Streaming Mode
With stream: true, the endpoint returns a streaming response using the AI SDK UI Message Stream protocol over SSE.
Use streaming mode when:
- You are building chat widgets, copilots, or multi-turn conversational UIs.
- You want live responses including tool execution, reasoning, and incremental message updates.
Conversation Management Modes
Streaming requests support two history modes:
- Server-Managed History — send only the latest
messageplus an optional conversationid; the platform loads and persists history automatically. The first response returns anX-Conversation-Idheader. - Client-Managed History — send the complete
messagesarray with each request; nothing is stored server-side.
Recommended Integration: AI SDK
The streaming mode natively returns the AI SDK UI Message Stream format, making the AI SDK the recommended integration approach.
"use client";
import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai";
const agentId = "YOUR_AGENT_ID";
export function ChatWidget() {
const transport = new DefaultChatTransport({
api: `${process.env.NEXT_PUBLIC_APP_URL}/api/agents/${agentId}/run`,
headers: {
"cf-api-key": "YOUR_API_KEY",
},
body: {
stream: true,
},
});
const { messages, sendMessage, status } = useChat({
transport,
id: `chat-${agentId}`,
});
return (
<div>
<button
onClick={() =>
sendMessage({
text: "Hello",
metadata: { agentId },
})
}
disabled={status !== "ready"}
>
Send
</button>
<pre>{JSON.stringify(messages, null, 2)}</pre>
</div>
);
}In streaming mode, do not use response.json(). The endpoint returns a stream that must be consumed incrementally.
Integration Examples
Non-Streaming (fetch)
The most common request/response integration pattern.
const agentId = "YOUR_AGENT_ID";
const response = await fetch(`/api/agents/${agentId}/run`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"cf-api-key": "YOUR_API_KEY",
},
body: JSON.stringify({
message: "Write a product announcement email",
vars: {
productName: "Chocolate Factory AI",
audience: "existing customers",
tone: "friendly",
},
}),
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`Run request failed: ${response.status} ${errorBody}`);
}
const data = await response.json();
console.log(data.text);
console.log(data.usage);
console.log(data.finishReason);Error Responses
| Status | Response |
|---|---|
400 | { "error": "Agent is not active" } |
400 | { "error": "Agent must belong to an organization" } |
400 | { "error": "No valid messages to process" } |
401 | { "error": "Unauthorized" } |
403 | { "error": "Forbidden" } |
404 | { "error": "Agent not found" } |
500 | { "error": "Internal server error" } |
Migrating from /chat and /execute
The deprecated endpoints remain available as thin wrappers around /run and respond with a Deprecation: true header.
| Old endpoint | Replacement |
|---|---|
POST /api/agents/{agentId}/chat | POST /api/agents/{agentId}/run with "stream": true |
POST /api/agents/{agentId}/execute | POST /api/agents/{agentId}/run (default "stream": false) |
Request and response formats are unchanged — only the URL and the stream field differ.
Best Practices
- Use streaming mode for conversational UIs; use non-streaming mode for forms, content generation, workflows, and backend jobs.
- Use Server-Managed History when conversation persistence should be handled by Chocolate Factory.
- Use vars to inject runtime context into prompts, workflows, or business-specific information.
- Use x-agent-payload when MCP tools require additional contextual metadata.
- Reuse conversation IDs to maintain context across multiple user interactions.
- Inspect the
usageobject to monitor token consumption.