Skip to main content

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.

get/api/action-agents

List 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_KEY

Every 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 organizationId may 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-agents must include an authorized organizationId.
  • An authenticated application session may omit organizationId when activeOrganizationId is 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:

FieldTypeRequiredMeaning
modelstringYesThe Action Agent id. Unknown or foreign ids return 404 with code model_not_found.
messagesarrayYesOpenAI message array. Only the last user message drives the turn; the agent owns its transcript per session.
streambooleanNotrue returns OpenAI SSE chunks.
userstringNoStored 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" } }
StatusMeaning
400Invalid body or user message (invalid_request_error).
401Missing or invalid authentication (authentication_error).
402The organization has no credits (insufficient_quota).
403The caller cannot access the organization (permission_error).
404Unknown model (model_not_found) or session (session_not_found).
409The turn is pending Lead review (LEAD_REVIEW_PENDING). A gated non-streaming turn also returns workItemId and revision in error.
429Rate limit exceeded (rate_limit_error).
500The 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.

See also

On this page