Agents API
Discover Action Agents over REST and chat through the OpenAI-compatible /v1/chat/completions endpoint.
Agents API
The Action Agents API provides discovery and chat for agents configured in Action Agent Studio. It does not configure agents.
Call this API from your backend with an organization API key. Never expose the API key, model-provider keys, organization connection secrets, or internal chat-runtime credentials to a browser or end user.
New public sessions require an active agent. Action Agent Studio chat can still start a session for a passive agent. The current runtime does not re-check active when an existing public session sends another message. See Action Agent lifecycle.
Try it
Live requests run from your browser. Open the API Explorer to try every operation from one screen.
/api/action-agentsList agents
Requests go to the live API from your browser. The docs server never sees this key.
curl -X GET 'https://api.actionflows.ai/api/action-agents' \ -H 'Authorization: Bearer YOUR_API_KEY' \ -H 'Accept: application/json'
Response
Send a request to see the response.
Authentication and organization scope
Send the API key as a bearer token:
Authorization: Bearer YOUR_API_KEYEvery operation is organization-scoped. The resolver uses the authenticated context's organization; an organization-scoped API key supplies its key organization.
- An organization-scoped API key supplies its key organization, so
organizationIdmay be omitted on discovery routes; if supplied, it must match. - A user-scoped API key has no active organization in this context, so
GET /api/action-agentsmust include an authorizedorganizationId. - An authenticated application session may omit
organizationIdwhenactiveOrganizationIdis present, or provide another authorized organization. If neither source supplies one, the request is forbidden.
GET /api/action-agents/{actionAgentId} may omit organizationId because the gateway loads the agent and authorizes its owning organization. If supplied, the value must match that organization.
List and get agents
GET /api/action-agents?organizationId={organizationId}
GET /api/action-agents/{actionAgentId}?organizationId={organizationId}The response contains discovery metadata only: id, name, description, slug, active, organizationId, selected service and model names, tags, and timestamps. It does not contain the system prompt, Action Agent Studio layout, tool configuration, MCP configuration, provider credential mode, or configVersion.
Chat completions (OpenAI-compatible)
Chat runs on the OpenAI-compatible endpoint. Pass the Action Agent id as model:
POST /v1/chat/completions
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"model": "{actionAgentId}",
"messages": [
{ "role": "user", "content": "Where is my invoice?" }
]
}Request fields the endpoint reads:
| Field | Type | Required | Meaning |
|---|---|---|---|
model | string | Yes | The Action Agent id. Unknown or foreign ids return 404 with code model_not_found. |
messages | array | Yes | OpenAI message array. Only the last user message drives the turn; the agent owns its transcript per session. |
stream | boolean | No | true returns OpenAI SSE chunks. |
user | string | No | Stored as the session endUserId correlation label. |
Other OpenAI fields (temperature, max_tokens, tools, n, ...) are ignored: the agent configuration owns sampling and tools. The last user message is trimmed, empty text is rejected, and the maximum length is 100,000 characters.
Sessions and the response header
The OpenAI protocol has no session concept. Every request without X-ActionFlows-Session-Id starts a new durable session; the response always carries the id:
X-ActionFlows-Session-Id: {sessionId}Send that header back to continue the same conversation, memory, and transcript. A wrong, closed, deleted, or foreign session id returns 404 with code session_not_found; it never creates a replacement session.
Non-streaming response
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1730000000,
"model": "agent_123",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "Your latest invoice is paid." },
"finish_reason": "stop",
"logprobs": null
}
]
}Streaming
With "stream": true the endpoint returns OpenAI SSE chunks and terminates with data: [DONE]:
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1730000000,"model":"agent_123","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1730000000,"model":"agent_123","choices":[{"index":0,"delta":{"content":"Your latest invoice"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1730000000,"model":"agent_123","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]A runtime failure mid-stream emits one data: {"error": {...}} frame instead of [DONE]. When a Lead Agent gates the turn, the stream ends with finish_reason: "stop" and no further content; the approved submission is delivered later and recorded on the Lead Review work item.
OpenAI-compatible errors
Errors use the OpenAI envelope:
{ "error": { "message": "...", "type": "invalid_request_error", "code": "model_not_found", "param": "model" } }| Status | Meaning |
|---|---|
400 | Invalid body or user message (invalid_request_error). |
401 | Missing or invalid authentication (authentication_error). |
402 | The organization has no credits (insufficient_quota). |
403 | The caller cannot access the organization (permission_error). |
404 | Unknown model (model_not_found) or session (session_not_found). |
409 | The turn is pending Lead review (LEAD_REVIEW_PENDING). A gated non-streaming turn also returns workItemId and revision in error. |
429 | Rate limit exceeded (rate_limit_error). |
500 | The runtime could not complete the operation (server_error). |
cURL examples
List agents
curl -X GET "https://api.actionflows.ai/api/action-agents?organizationId=org_123" \
-H "Authorization: Bearer YOUR_API_KEY"Chat (non-streaming)
curl -X POST "https://api.actionflows.ai/v1/chat/completions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"agent_123","messages":[{"role":"user","content":"Where is my invoice?"}]}'Chat (streaming)
curl -N -X POST "https://api.actionflows.ai/v1/chat/completions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"agent_123","messages":[{"role":"user","content":"Explain the refund policy briefly."}],"stream":true}'Continue a session
Send the X-ActionFlows-Session-Id value from the previous response:
curl -X POST "https://api.actionflows.ai/v1/chat/completions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "X-ActionFlows-Session-Id: sess_123" \
-d '{"model":"agent_123","messages":[{"role":"user","content":"And the second one?"}]}'OpenAI SDK example
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.ACTIONFLOWS_API_KEY,
baseURL: "https://api.actionflows.ai/v1",
});
const completion = await client.chat.completions.create({
model: "agent_123",
messages: [{ role: "user", content: "Where is my invoice?" }],
});
console.log(completion.choices[0]?.message.content);The Agent API has no endpoint to close, delete, list, or fetch the full transcript of a session. The separate public Explore visitor endpoint can return a bounded recent transcript; see Sessions & chat.