Key Features

Agent API Endpoint Guide

Agent API Endpoint Guide

Agent API Endpoint Guide

Using the Agent API Endpoint

If you've deployed an agent you built in Agentria as an API, external services can call its API endpoint to chat with the agent. The Agent API is a REST API that supports creating, listing, and deleting chat rooms, async chat, and SSE (Server-Sent Events) streaming chat.

This guide walks through how to call each endpoint and how to safely retrieve execution results while keeping conversation context.

Before You Begin


  • The agent must already be deployed as an API. If you haven't deployed it yet, complete the 🔗API Release guide first.

  • You'll need the endpoint code (api_endpoint) and API key issued during deployment.


The base URL and authentication method apply to every endpoint below.

Base URL

Every request requires an X-API-KEY header.

If the API key is invalid or lacks permission, the API returns 403 Forbidden. Specific error codes can vary by endpoint, so check the Error Responses table in each step below.

Step 1: Manage Chat Rooms

Conversations with an agent are organized by chat room. To maintain conversation history, create a chat room first, then keep reusing the same chat room ID in subsequent requests.

Create a Chat Room

Parameter

Type

Description

api_endpoint

string

Agent code (unique identifier of the released agent)

Header

Type

Required

Description

X-API-KEY

string

Yes

API access token

{
  "user_ids": [1, 2]
}
{
  "user_ids": [1, 2]
}
{
  "user_ids": [1, 2]
}

Field

Type

Required

Description

user_ids

list[int]

Yes

List of user IDs to add to the chat room (the first ID becomes the creator)

On success, returns 200 OK with the created chat room's UUID.

"e36644fa-0b2e-11f0-b130-143627ec67e9"
"e36644fa-0b2e-11f0-b130-143627ec67e9"
"e36644fa-0b2e-11f0-b130-143627ec67e9"

Status

Description

400 Bad Request

user_ids is missing or not a list

403 Forbidden

API key is invalid, or you don't have access to the agent

curl -X POST "{host}/api/agent/my-agent/rooms" \
  -H "X-API-KEY: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"user_ids": [1]}'
curl -X POST "{host}/api/agent/my-agent/rooms" \
  -H "X-API-KEY: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"user_ids": [1]}'
curl -X POST "{host}/api/agent/my-agent/rooms" \
  -H "X-API-KEY: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"user_ids": [1]}'

List Chat Rooms

Lists the chat rooms created via this agent API, in a paginated format.

Parameter

Type

Required

Default

Description

page_index

int

No

0

Page number (0-indexed)

page_size

int

No

10

Items per page (max 100; values above 100 are capped)

order_by

list[string]

No

created_time,desc

Sort order (e.g. created_time,desc)

On success, returns 200 OK with the result below.

{
  "data": [
    {
      "id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
      "creator_id": 1,
      "properties_json": {},
      "created_time": "2026-01-15T10:30:00",
      "updated_time": "2026-01-15T10:30:00"
    }
  ],
  "page": {
    "page_size": 10,
    "page_number": 0,
    "total_elements": 1,
    "total_pages": 1
  }
}
{
  "data": [
    {
      "id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
      "creator_id": 1,
      "properties_json": {},
      "created_time": "2026-01-15T10:30:00",
      "updated_time": "2026-01-15T10:30:00"
    }
  ],
  "page": {
    "page_size": 10,
    "page_number": 0,
    "total_elements": 1,
    "total_pages": 1
  }
}
{
  "data": [
    {
      "id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
      "creator_id": 1,
      "properties_json": {},
      "created_time": "2026-01-15T10:30:00",
      "updated_time": "2026-01-15T10:30:00"
    }
  ],
  "page": {
    "page_size": 10,
    "page_number": 0,
    "total_elements": 1,
    "total_pages": 1
  }
}

Status

Description

403 Forbidden

API key is invalid, or you don't have access to the agent

curl -X GET "{host}/api/agent/my-agent/rooms?page_index=0&page_size=10" \
  -H "X-API-KEY: your-api-key"
curl -X GET "{host}/api/agent/my-agent/rooms?page_index=0&page_size=10" \
  -H "X-API-KEY: your-api-key"
curl -X GET "{host}/api/agent/my-agent/rooms?page_index=0&page_size=10" \
  -H "X-API-KEY: your-api-key"

Get Chat Room Details

Retrieves details for a specific chat room.

Parameter

Type

Description

api_endpoint

string

Agent code

chat_room_id

UUID

Chat room ID

On success, returns 200 OK with the result below. participants_json shows the users and agents that belong to the chat room.

{
  "id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "participants_json": {
    "users": {
      "1": {
        "id": 1,
        "type": "USER",
        "joined_time": "2026-01-15T10:30:00",
        "name": null
      }
    },
    "agents": {
      "42": {
        "id": 42,
        "type": "AGENT",
        "joined_time": "2026-01-15T10:30:00",
        "name": "My Agent"
      }
    }
  },
  "creator_id": 1,
  "properties_json": {},
  "created_time": "2026-01-15T10:30:00",
  "updated_time": "2026-01-15T10:30:00"
}
{
  "id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "participants_json": {
    "users": {
      "1": {
        "id": 1,
        "type": "USER",
        "joined_time": "2026-01-15T10:30:00",
        "name": null
      }
    },
    "agents": {
      "42": {
        "id": 42,
        "type": "AGENT",
        "joined_time": "2026-01-15T10:30:00",
        "name": "My Agent"
      }
    }
  },
  "creator_id": 1,
  "properties_json": {},
  "created_time": "2026-01-15T10:30:00",
  "updated_time": "2026-01-15T10:30:00"
}
{
  "id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "participants_json": {
    "users": {
      "1": {
        "id": 1,
        "type": "USER",
        "joined_time": "2026-01-15T10:30:00",
        "name": null
      }
    },
    "agents": {
      "42": {
        "id": 42,
        "type": "AGENT",
        "joined_time": "2026-01-15T10:30:00",
        "name": "My Agent"
      }
    }
  },
  "creator_id": 1,
  "properties_json": {},
  "created_time": "2026-01-15T10:30:00",
  "updated_time": "2026-01-15T10:30:00"
}

Status

Description

403 Forbidden

API key is invalid, or the chat room doesn't exist

curl -X GET "{host}/api/agent/my-agent/rooms/e36644fa-0b2e-11f0-b130-143627ec67e9" \
  -H "X-API-KEY: your-api-key"
curl -X GET "{host}/api/agent/my-agent/rooms/e36644fa-0b2e-11f0-b130-143627ec67e9" \
  -H "X-API-KEY: your-api-key"
curl -X GET "{host}/api/agent/my-agent/rooms/e36644fa-0b2e-11f0-b130-143627ec67e9" \
  -H "X-API-KEY: your-api-key"

Delete a Chat Room

On success, returns 200 OK with true (succeeded) or false (failed).

Status

Description

403 Forbidden

API key is invalid, or you don't have access to the agent

curl -X DELETE "{host}/api/agent/my-agent/rooms/e36644fa-0b2e-11f0-b130-143627ec67e9" \
  -H "X-API-KEY: your-api-key"
curl -X DELETE "{host}/api/agent/my-agent/rooms/e36644fa-0b2e-11f0-b130-143627ec67e9" \
  -H "X-API-KEY: your-api-key"
curl -X DELETE "{host}/api/agent/my-agent/rooms/e36644fa-0b2e-11f0-b130-143627ec67e9" \
  -H "X-API-KEY: your-api-key"

Step 2: Send a Chat Message Asynchronously

Sends a message to the agent and immediately returns a request_id. You can retrieve the result via the status query API (Step 3) or a callback URL.

Path Parameters

Parameter

Type

Description

api_endpoint

string

Agent code

Headers

Header

Type

Required

Description

X-API-KEY

string

Yes

API access token

Request Body (multipart/form-data)

Field

Type

Required

Description

params_json

string (JSON)

Yes

Request parameters (see structure below)

callback_url

string

No

Callback URL that receives the result via POST

debug

boolean

No

Debug mode (default: false)

external_request_id

string

No

Client-issued external request identifier (up to 128 characters, ^[A-Za-z0-9_\-\.:]+$). Must be unique within the same agent.

files

file[]

No

Files to upload

{
  "input_message": "Hello",
  "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "input_files": [
    "<https: example.com="" image1.jpg="">",
    "s3://bucket-name/image2.jpg"
  ]
}<

{
  "input_message": "Hello",
  "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "input_files": [
    "<https: example.com="" image1.jpg="">",
    "s3://bucket-name/image2.jpg"
  ]
}<

{
  "input_message": "Hello",
  "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "input_files": [
    "<https: example.com="" image1.jpg="">",
    "s3://bucket-name/image2.jpg"
  ]
}<

Field

Type

Required

Description

input_message

string

No

Text message

chat_room_id

string (UUID)

No

Existing chat room ID (a new one is created if omitted)

input_files

list[string]

No

List of file URLs (HTTP URL or S3 URI)

If you don't specify chat_room_id, a new chat room may be created automatically for each request. To continue a conversation, keep passing the same chat room ID — the one you created in Step 1, or one you got back from a previous response.

external_request_id is an identifier the client issues before sending the request, and it serves two purposes. First, if the same external_request_id is submitted again, the server treats it as the same request and rejects it with 409 Conflict, which prevents duplicate execution (idempotency) from things like network retries. Second, because the client already holds this identifier before making the call, you can track and query the request by this value even before the server returns its own request_id in the response.

Response

On success, returns 200 OK with the request ID (string).

"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"

Error Responses

Status

Description

400 Bad Request

external_request_id is malformed

401 Unauthorized

Authentication failed

404 Not Found

Agent not found

409 Conflict

The same external_request_id is already registered

500 Internal Server Error

Internal server error

Example Request

# Text only
curl -X POST "{host}/api/agent/my-agent/async" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message": "Hello", "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9"}' \
  -F 'debug=false'

# With an external request ID
curl -X POST "{host}/api/agent/my-agent/async" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message": "Please process this order", "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9"}' \
  -F 'callback_url=https://my-service.com/webhook' \
  -F 'external_request_id=order-12345'

# With a file attached
curl -X POST "{host}/api/agent/my-agent/async" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message": "Please analyze this image"}' \
  -F 'callback_url=https://my-service.com/webhook' \
  -F 'files=@/path/to/image.png'
# Text only
curl -X POST "{host}/api/agent/my-agent/async" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message": "Hello", "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9"}' \
  -F 'debug=false'

# With an external request ID
curl -X POST "{host}/api/agent/my-agent/async" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message": "Please process this order", "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9"}' \
  -F 'callback_url=https://my-service.com/webhook' \
  -F 'external_request_id=order-12345'

# With a file attached
curl -X POST "{host}/api/agent/my-agent/async" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message": "Please analyze this image"}' \
  -F 'callback_url=https://my-service.com/webhook' \
  -F 'files=@/path/to/image.png'
# Text only
curl -X POST "{host}/api/agent/my-agent/async" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message": "Hello", "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9"}' \
  -F 'debug=false'

# With an external request ID
curl -X POST "{host}/api/agent/my-agent/async" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message": "Please process this order", "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9"}' \
  -F 'callback_url=https://my-service.com/webhook' \
  -F 'external_request_id=order-12345'

# With a file attached
curl -X POST "{host}/api/agent/my-agent/async" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message": "Please analyze this image"}' \
  -F 'callback_url=https://my-service.com/webhook' \
  -F 'files=@/path/to/image.png'

Step 3: Check Request Status and Results

Queries the processing status and result of an async chat request.




Both endpoints return the same response.

Path Parameters

Parameter

Type

Description

api_endpoint

string

Agent code

request_id

string

Async request ID (returned by /async)

Response

On success, returns 200 OK with the result below.

{
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "external_request_id": null,
  "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "status": "COMPLETED",
  "failure_reason": null,
  "results": {
    "output": "Agent response content"
  },
  "artifact_metadata_json": null,
  "request_params_json": "{\"method\":\"POST\",\"client\":\"127.0.0.1\",\"params\":[{\"type\":\"text\",\"text\":\"Hello\"}]}",
  "result_metadata_json": null,
  "requested_time": "2026-01-15T10:30:00",
  "updated_time": "2026-01-15T10:31:00"
}
{
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "external_request_id": null,
  "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "status": "COMPLETED",
  "failure_reason": null,
  "results": {
    "output": "Agent response content"
  },
  "artifact_metadata_json": null,
  "request_params_json": "{\"method\":\"POST\",\"client\":\"127.0.0.1\",\"params\":[{\"type\":\"text\",\"text\":\"Hello\"}]}",
  "result_metadata_json": null,
  "requested_time": "2026-01-15T10:30:00",
  "updated_time": "2026-01-15T10:31:00"
}
{
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "external_request_id": null,
  "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "status": "COMPLETED",
  "failure_reason": null,
  "results": {
    "output": "Agent response content"
  },
  "artifact_metadata_json": null,
  "request_params_json": "{\"method\":\"POST\",\"client\":\"127.0.0.1\",\"params\":[{\"type\":\"text\",\"text\":\"Hello\"}]}",
  "result_metadata_json": null,
  "requested_time": "2026-01-15T10:30:00",
  "updated_time": "2026-01-15T10:31:00"
}

external_request_id is populated only if an external ID was assigned at request time; otherwise it's null.

status Values

Value

Description

NONE

Initial state (awaiting processing)

PROCESSING

Processing

COMPLETED

Completed

FAILURE

Failed (see the failure_reason field for details)

CANCELED

Canceled

Example Request

curl -X GET "{host}/api/agent/my-agent/a1b2c3d4-e5f6-7890-abcd-ef1234567890/status" \
  -H "X-API-KEY: your-api-key"
curl -X GET "{host}/api/agent/my-agent/a1b2c3d4-e5f6-7890-abcd-ef1234567890/status" \
  -H "X-API-KEY: your-api-key"
curl -X GET "{host}/api/agent/my-agent/a1b2c3d4-e5f6-7890-abcd-ef1234567890/status" \
  -H "X-API-KEY: your-api-key"

Querying by External Request ID

If you assigned an external_request_id at request time, you can query the same response using that value instead.




Status

Description

400 Bad Request

external_request_id is malformed

404 Not Found

No request is registered under that external ID

curl -X GET "{host}/api/agent/my-agent/external/order-12345/status" \
  -H "X-API-KEY: your-api-key"
curl -X GET "{host}/api/agent/my-agent/external/order-12345/status" \
  -H "X-API-KEY: your-api-key"
curl -X GET "{host}/api/agent/my-agent/external/order-12345/status" \
  -H "X-API-KEY: your-api-key"

Step 4: Receive Real-Time Chat Responses via SSE

Runs a real-time streaming chat with the agent, receiving its responses over SSE.

Path Parameters / Headers

Same as Steps 1 and 2 — requires the api_endpoint path parameter and the X-API-KEY header.

Request Body (multipart/form-data)

Field

Type

Required

Description

params_json

string (JSON)

Yes

Request parameters (same structure as Step 2)

debug

boolean

No

Debug mode (default: false)

external_request_id

string

No

Client-issued external request identifier. Same format rules as Step 2. Once the SSE stream ends, you can also query status/results by this value.

{
  "input_message": "Hello",
  "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "input_files": [
    "<https: example.com="" image1.jpg="">"
  ]
}<

{
  "input_message": "Hello",
  "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "input_files": [
    "<https: example.com="" image1.jpg="">"
  ]
}<

{
  "input_message": "Hello",
  "chat_room_id": "e36644fa-0b2e-11f0-b130-143627ec67e9",
  "input_files": [
    "<https: example.com="" image1.jpg="">"
  ]
}<

Response

The response Content-Type is text/event-stream.

The X-Agent-Request-Id response header carries the request ID. Even if the connection drops before the first event arrives, you can use this value to re-query — it matches the first request_id event.

Note: The X-Request-Id header is a separate value used for HTTP tracing. Don't confuse it with X-Agent-Request-Id.

Each event is delivered in a self-defined SSE line format that is not compatible with the standard EventSource format. A blank line separates events.




event_type Values and Body Shapes

In Agent API's SSE, every event except the initial request_id meta event is serialized wrapped once more in {"ability_node_id", "ability_node_name", "results"}. This differs from the Ability API's SSE, where the response/error event body arrives as the result schema itself — keep this in mind if you integrate both APIs together.

event_type

When it fires

Body shape

request_id

Right after the stream starts (first, once)

Plain string (UUID), delivered with no wrapping. The request ID to use for re-querying results if the stream is lost

node

Each time a node finishes executing (intermediate, repeats per node)

{"ability_node_id":, "ability_node_name":, "results":}

response

Agent completes successfully (final, once)

{"ability_node_id":0, "ability_node_name":"final_output", "results":}

error

Agent fails or a processing error occurs (final, once)

{"ability_node_id":0, "ability_node_name":"final_output", "results":}

What matters here is that the final event has the full APIResponseSchema nested once more inside the results field (the same shape as the status query response in Step 3). So to check the final status, look at chunk.results.status rather than chunk.status.

Distinguishing Intermediate vs. Final Events


  • event_type == "request_id" → meta event (once, right after the stream starts, carries the request ID)

  • chunk.ability_node_id === 0 → final event

  • Or if chunk.results.status is COMPLETED or FAILURE → final event

  • Otherwise (none of the above) → intermediate node event


Re-Querying Results After a Lost Stream

If a network drop causes you to miss the final event, don't resend the same request — that would re-run the agent and duplicate the conversation history. Instead, re-query, since the server completes execution and records the result regardless of the stream connection.


  • Poll GET /{api_endpoint}/{request_id}/result using the request ID from the request_id event (or the X-Agent-Request-Id header) — see Step 3.

  • If you assigned an external_request_id, you can also query GET /{api_endpoint}/external/{external_request_id}/result — see Step 3.


Poll until status becomes COMPLETED, FAILURE, or CANCELED. Resending with the same external_request_id is rejected with 409 Conflict, so using an external ID also protects you against accidental duplicate runs.

Example Request

curl -N -X POST "{host}/api/agent/my-agent/sse" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message":"Hello","chat_room_id":"e36644fa-0b2e-11f0-b130-143627ec67e9"}' \
  -F 'debug=false'
curl -N -X POST "{host}/api/agent/my-agent/sse" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message":"Hello","chat_room_id":"e36644fa-0b2e-11f0-b130-143627ec67e9"}' \
  -F 'debug=false'
curl -N -X POST "{host}/api/agent/my-agent/sse" \
  -H "X-API-KEY: your-api-key" \
  -F 'params_json={"input_message":"Hello","chat_room_id":"e36644fa-0b2e-11f0-b130-143627ec67e9"}' \
  -F 'debug=false'

The -N (--no-buffer) option is required — without it, chunks arrive in bursts.

Example Response (Wire Format)




JavaScript Client Example

const formData = new FormData();
formData.append('params_json', JSON.stringify({
  input_message: 'Hello',
  chat_room_id: 'e36644fa-0b2e-11f0-b130-143627ec67e9'
}));
formData.append('debug', 'false');

const response = await fetch(`${host}/api/agent/my-agent/sse`, {
  method: 'POST',
  headers: { 'X-API-KEY': 'your-api-key' },
  body: formData
});

// For re-querying via GET .../{requestId}/result if the stream is lost. Also updated by the first request_id event.
let requestId = response.headers.get('X-Agent-Request-Id');

// A single read() can return multiple events merged together, so line-buffered parsing is required.
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buf = '';
let currentEvent = null;

const chunks = []; // Accumulates every chunk
let finalChunk = null;

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buf += decoder.decode(value, { stream: true });

  let nl;
  while ((nl = buf.indexOf('\n')) !== -1) {
    const line = buf.slice(0, nl);
    buf = buf.slice(nl + 1);

    if (line === '') { currentEvent = null; continue; } // event boundary
    if (line.endsWith(':')) { currentEvent = line.slice(0, -1); continue; }

    // The request_id event's body is a plain, unwrapped UUID string — handle it before JSON.parse
    if (currentEvent === 'request_id') { requestId = line; continue; }

    let body;
    try { body = JSON.parse(line); } catch { continue; }

    chunks.push(body);

    // Intermediate vs. final
    const status = body.results?.status;
    if (body.ability_node_id === 0 || status === 'COMPLETED' || status === 'FAILURE') {
      finalChunk = body; // The full APIResponseSchema lives inside results
      console.log('[final]', status, finalChunk.results.results);
    } else {
      console.log('[node]', body.ability_node_id, body.ability_node_name, body.results);
    }
  }
}

if (finalChunk?.results?.status === 'FAILURE') {
  console.error('Failed:', finalChunk.results.failure_reason);
}

// Stream ended without a final chunk — re-query instead of resending (re-running)
if (!finalChunk && requestId) {
  const res = await fetch(`${host}/api/agent/my-agent/${requestId}/result`, {
    headers: { 'X-API-KEY': 'your-api-key' }
  });
  const result = await res.json(); // Poll until status is COMPLETED or FAILURE
}
const formData = new FormData();
formData.append('params_json', JSON.stringify({
  input_message: 'Hello',
  chat_room_id: 'e36644fa-0b2e-11f0-b130-143627ec67e9'
}));
formData.append('debug', 'false');

const response = await fetch(`${host}/api/agent/my-agent/sse`, {
  method: 'POST',
  headers: { 'X-API-KEY': 'your-api-key' },
  body: formData
});

// For re-querying via GET .../{requestId}/result if the stream is lost. Also updated by the first request_id event.
let requestId = response.headers.get('X-Agent-Request-Id');

// A single read() can return multiple events merged together, so line-buffered parsing is required.
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buf = '';
let currentEvent = null;

const chunks = []; // Accumulates every chunk
let finalChunk = null;

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buf += decoder.decode(value, { stream: true });

  let nl;
  while ((nl = buf.indexOf('\n')) !== -1) {
    const line = buf.slice(0, nl);
    buf = buf.slice(nl + 1);

    if (line === '') { currentEvent = null; continue; } // event boundary
    if (line.endsWith(':')) { currentEvent = line.slice(0, -1); continue; }

    // The request_id event's body is a plain, unwrapped UUID string — handle it before JSON.parse
    if (currentEvent === 'request_id') { requestId = line; continue; }

    let body;
    try { body = JSON.parse(line); } catch { continue; }

    chunks.push(body);

    // Intermediate vs. final
    const status = body.results?.status;
    if (body.ability_node_id === 0 || status === 'COMPLETED' || status === 'FAILURE') {
      finalChunk = body; // The full APIResponseSchema lives inside results
      console.log('[final]', status, finalChunk.results.results);
    } else {
      console.log('[node]', body.ability_node_id, body.ability_node_name, body.results);
    }
  }
}

if (finalChunk?.results?.status === 'FAILURE') {
  console.error('Failed:', finalChunk.results.failure_reason);
}

// Stream ended without a final chunk — re-query instead of resending (re-running)
if (!finalChunk && requestId) {
  const res = await fetch(`${host}/api/agent/my-agent/${requestId}/result`, {
    headers: { 'X-API-KEY': 'your-api-key' }
  });
  const result = await res.json(); // Poll until status is COMPLETED or FAILURE
}
const formData = new FormData();
formData.append('params_json', JSON.stringify({
  input_message: 'Hello',
  chat_room_id: 'e36644fa-0b2e-11f0-b130-143627ec67e9'
}));
formData.append('debug', 'false');

const response = await fetch(`${host}/api/agent/my-agent/sse`, {
  method: 'POST',
  headers: { 'X-API-KEY': 'your-api-key' },
  body: formData
});

// For re-querying via GET .../{requestId}/result if the stream is lost. Also updated by the first request_id event.
let requestId = response.headers.get('X-Agent-Request-Id');

// A single read() can return multiple events merged together, so line-buffered parsing is required.
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buf = '';
let currentEvent = null;

const chunks = []; // Accumulates every chunk
let finalChunk = null;

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buf += decoder.decode(value, { stream: true });

  let nl;
  while ((nl = buf.indexOf('\n')) !== -1) {
    const line = buf.slice(0, nl);
    buf = buf.slice(nl + 1);

    if (line === '') { currentEvent = null; continue; } // event boundary
    if (line.endsWith(':')) { currentEvent = line.slice(0, -1); continue; }

    // The request_id event's body is a plain, unwrapped UUID string — handle it before JSON.parse
    if (currentEvent === 'request_id') { requestId = line; continue; }

    let body;
    try { body = JSON.parse(line); } catch { continue; }

    chunks.push(body);

    // Intermediate vs. final
    const status = body.results?.status;
    if (body.ability_node_id === 0 || status === 'COMPLETED' || status === 'FAILURE') {
      finalChunk = body; // The full APIResponseSchema lives inside results
      console.log('[final]', status, finalChunk.results.results);
    } else {
      console.log('[node]', body.ability_node_id, body.ability_node_name, body.results);
    }
  }
}

if (finalChunk?.results?.status === 'FAILURE') {
  console.error('Failed:', finalChunk.results.failure_reason);
}

// Stream ended without a final chunk — re-query instead of resending (re-running)
if (!finalChunk && requestId) {
  const res = await fetch(`${host}/api/agent/my-agent/${requestId}/result`, {
    headers: { 'X-API-KEY': 'your-api-key' }
  });
  const result = await res.json(); // Poll until status is COMPLETED or FAILURE
}

Note (Python client): Parse line by line using httpx.AsyncClient.stream()'s aiter_lines() and JSON parsing, skipping node: / response: / error: prefix lines with a JSON parse error. The request_id event's body (a plain UUID) isn't JSON either, so it's skipped the same way — meaning an existing client's check like chunks[-1].get("results", {}).get("status") == "FAILURE" keeps working as-is. If you need the ID for re-querying, either track whether the previous line was request_id: or use the X-Agent-Request-Id response header.

Usage Flows at a Glance

Pick one of the three flows below depending on your use case.

Flow 1: Async + Polling




Flow 2: Async + Callback




Example callback payloads:

// Callback for a request with an external_request_id — key included
{
  "request_id": "a1b2c3d4-...",
  "external_request_id": "order-12345",
  "chat_room_id": "e36644fa-...",
  "status": "COMPLETED",
  "results": { ... },
  "failure_reason": null
}

// Callback for a request without an external_request_id — key is omitted entirely
{
  "request_id": "a1b2c3d4-...",
  "chat_room_id": "e36644fa-...",
  "status": "COMPLETED",
  "results": { ... },
  "failure_reason": null
}
// Callback for a request with an external_request_id — key included
{
  "request_id": "a1b2c3d4-...",
  "external_request_id": "order-12345",
  "chat_room_id": "e36644fa-...",
  "status": "COMPLETED",
  "results": { ... },
  "failure_reason": null
}

// Callback for a request without an external_request_id — key is omitted entirely
{
  "request_id": "a1b2c3d4-...",
  "chat_room_id": "e36644fa-...",
  "status": "COMPLETED",
  "results": { ... },
  "failure_reason": null
}
// Callback for a request with an external_request_id — key included
{
  "request_id": "a1b2c3d4-...",
  "external_request_id": "order-12345",
  "chat_room_id": "e36644fa-...",
  "status": "COMPLETED",
  "results": { ... },
  "failure_reason": null
}

// Callback for a request without an external_request_id — key is omitted entirely
{
  "request_id": "a1b2c3d4-...",
  "chat_room_id": "e36644fa-...",
  "status": "COMPLETED",
  "results": { ... },
  "failure_reason": null
}

Requests without an external ID never include the external_request_id key in the callback payload — this preserves compatibility with existing integration code.

Flow 3: Real-Time Streaming




Note: If you don't specify chat_room_id, a chat room may be created automatically. To maintain conversation history, always use the same chat_room_id.

Next Steps

You've learned how to use the Agent API endpoints.

You can now chat with an agent directly from an external service and retrieve its execution results.


  • 🔗 API Release — revisit the endpoint and API key issuance steps.


Frequently Asked Questions

What is the Agent API?

The Agent API lets external services chat with an agent you've built in Agentria via a REST API. It supports creating, listing, and deleting chat rooms, async chat, and SSE streaming chat, and every request is authenticated with an X-API-KEY header.

When should I use the Agent API?

Use it when an external backend server or another service needs to chat with an agent and receive its responses without going through the Agentria UI. For example, it fits cases where you want to call an agent from your own chat interface, or build automated responses that maintain context across multiple turns of conversation.

How is the Agent API different from the Ability API?

The Ability API runs a completed workflow (ability) once and returns the result, while the Agent API exchanges multiple messages within a chat room while maintaining context. The SSE response shape also differs: in the Agent API, every event except the initial request_id event is wrapped in {ability_node_id, ability_node_name, results}, and you need to check results.status for the final status.

Does conversation context persist across multiple messages?

Context persists as long as you keep passing the same chat_room_id. If you don't specify a chat_room_id at request time, a new chat room may be created automatically, so to continue a conversation you need to pass the same chat_room_id you received in a previous response on every subsequent request.

What happens if the real-time streaming (SSE) connection drops?

The server keeps running the agent to completion and records the result regardless of the stream connection. If the connection drops before you receive the final event, don't resend the same request — poll the status/result query API using the request_id (or external_request_id) instead. Resending the same request re-runs the agent and can duplicate the conversation history.