Chat / Tasks API
The /api/chat endpoints create and track chat tasks in the web application. Authenticate with a JWT access token from POST /api/auth/login, sent as a bearer token. Errors use the { "detail": "..." } shape; see the API Reference for the full auth and error model.
App API vs Workspace SDK
These /api/chat/* endpoints are the application surface used by the web app. For stable, versioned programmatic integration, prefer the Workspace SDK (POST /v1/chat/tasks) — a smaller, versioned contract. The two surfaces create tasks independently and return different shapes.
Create a Task — POST /api/chat/task/create
Creates a chat task. Only title is required; supply agent_id to run a specific Agent Builder agent.
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Task title. The only required field. |
| description | string | No | Longer task description. |
| agent_id | integer | No | Agent Builder agent to run. |
| files | array | No | Uploaded file_ids to attach to the task. |
| execution_mode | string | No | One of flash, balanced, think, auto. |
| agent_type | string | No | Default standard. |
| is_visible | boolean | No | Default true. Set is_preview: true for a hidden preview run. |
| llm_ids | array | No | Model ids by slot: [default, fast, vision, compact]. |
| memory_similarity_threshold | number | No | Default 1.5. |
| agent_config | object | No | Inline agent configuration overrides. |
Request:
curl -X POST https://sg-origin.cloud.xagent.co/api/chat/task/create \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"title": "Summarize Q2 report",
"description": "Summarize the attached PDF",
"agent_id": 42,
"execution_mode": "balanced"
}' Response (200): required fields are task_id, title, status, and created_at; the model / channel / agent fields are populated when applicable.
{
"task_id": 1001,
"title": "Summarize Q2 report",
"status": "pending",
"created_at": "2026-07-10T09:20:00Z",
"model_id": "gpt-4o",
"model_name": "gpt-4o",
"small_fast_model_id": null,
"visual_model_id": null,
"compact_model_id": null,
"execution_mode": "balanced",
"channel_id": null,
"channel_name": null,
"agent_id": 42,
"agent_name": "Research Assistant",
"agent_logo_url": "/uploads/agent_logos/agent_42.png",
"connector_runtime_requirements": null
}Also always present: connector_runtime_requirements — see the Connector Runtime Requirements section below. It reports what a task created from the given agent needs (never a stored value), and is null when created through the public widget or share-link paths, which never see connector key names.
Validation error (422): missing or malformed fields return FastAPI's validation shape — an array of per-field errors:
HTTP/1.1 422 Unprocessable Entity
{
"detail": [
{ "loc": ["body", "title"], "msg": "Field required", "type": "missing" }
]
}Errors: 401 (missing/invalid token), 404 "Agent not found or access denied" (bad agent_id), 422 (validation), 500, 503 (the agent's knowledge base could not be resolved against its team — see the note below).
Other Task Endpoints
The rest of the task lifecycle on the application API. All require the same JWT bearer auth and return { "detail": ... } on error.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/chat/tasks | List tasks (paginated: page, per_page, search, and filters). Returns { tasks, pagination }. |
| GET | /api/chat/task/{task_id} | Full task detail. |
| GET | /api/chat/task/{task_id}/status | Lightweight status — poll this while a task runs. |
| PUT | /api/chat/task/{task_id} | Update task details (e.g. title). |
| DELETE | /api/chat/task/{task_id} | Delete a task and its related data. |
| GET | /api/chat/workspace/{task_id}/files | Workspace files produced during the run. |
| GET | /api/chat/workspace/{task_id}/output | Final output files. |
| GET | /api/chat/task/{task_id}/runtime-extensions | Live metadata published by the runtime extensions active on this task. |
| GET | /api/chat/agent/{agent_id}/connector-runtime-requirements | Which runtime inputs a task created from this agent would need, before one exists. |
| GET | /api/chat/task/{task_id}/connector-runtime-requirements | Which of this task's declared connector runtime inputs already have a value. |
Media usage on task detail
Full task detail (GET /api/chat/task/{task_id}) now also returns a media_usage field alongside the existing model_usage token counts — a breakdown, per model, of non-text generation the task performed (images, video seconds, TTS/ASR characters or seconds, music/sound-effect seconds). This is what the chat UI's usage popover now shows next to LLM token counts. As with model_usage, treat the exact shape as informational rather than a stable contract until it appears in the OpenAPI spec.
Runtime Extensions — GET /api/chat/task/{task_id}/runtime-extensions
Returns metadata published by each runtime extension attached to the task. Values are read live from every registered extension on each call rather than served from a stored snapshot, and only fields an extension explicitly publishes are exposed.
Response (200):
{
"task_id": 1001,
"runtime_extensions": {
"example_extension": { "status": "ready" }
},
"runtime_extensions_status": "complete",
"runtime_extensions_omitted": []
}| Field | Description |
|---|---|
runtime_extensions | Extension name → that extension's published metadata. |
runtime_extensions_status | complete when every extension's metadata is included; truncated when some was dropped to stay within the response size cap. |
runtime_extensions_omitted | Names dropped because of that cap. |
The endpoint is fail-closed: if an extension cannot report, the call returns an error rather than partial data. Errors: 404 "Task not found" (also when the task is not yours), 400 or 403 from an extension, 500.
Connector Runtime Requirements
Reports which runtime inputs an agent's connectors declare (context values, secrets, or an auth selector) and whether each one already has a value — never the value itself, and never a connector's URL, headers, or authentication configuration. Two read endpoints return the same shape, and POST /api/chat/task/create's response also includes it (see connector_runtime_requirements below):
| Endpoint | Answers |
|---|---|
GET /api/chat/agent/{agent_id}/connector-runtime-requirements | "Would a task created from this agent right now need further input?" There is no task yet, so every input reads unsatisfied and satisfied is true only when nothing required is declared at all. |
GET /api/chat/task/{task_id}/connector-runtime-requirements | "Does this existing task already have every required value?" This is the only one of the three that consults stored values. |
POST /api/chat/task/{task_id}/connector-runtime-values | Supply context values for a task's already-selected connectors. Returns this same report, reflecting exactly what was just written. |
Response (200):
{
"satisfied": false,
"secrets_expires_at": null,
"connectors": [
{
"connector_ref": { "connector_type": "custom_api", "connector_id": 17 },
"name": "Internal Ticketing API",
"inputs": [
{ "section": "context", "key": "project_key", "type": "string", "required": true, "satisfied": false, "expired": false }
]
}
]
}| Field | Description |
|---|---|
connectors | Empty (never omitted) when nothing selected declares a runtime input. |
inputs[].section | One of context (non-secret; can be supplied), secrets, or auth_selector (both currently always unsatisfiable — no secret store exists yet to hold a value). |
inputs[].satisfied | On the agent-keyed report, always false per input. On the task-keyed report, a real per-key answer. |
secrets_expires_at | Always null at this phase. |
The task-keyed read endpoint's access is plain task ownership and does not extend the admin exception that /task/{task_id}/runtime-extensions has. Errors: 404 (agent or task not found, or not yours).
Submitting Values — POST /api/chat/task/{task_id}/connector-runtime-values
Supplies context values for the connectors a task already has selected. Only context is accepted at this phase — a secrets or auth_selector key in the request body is rejected outright rather than silently accepted and ignored.
{
"items": [
{
"connector_ref": { "connector_type": "custom_api", "connector_id": 17 },
"context": { "project_key": "ENG" }
}
]
}Values merge key by key, and a stored value is never replaced:
- a key the task does not have yet is written;
- a key already stored with the identical value is a no-op;
- a key already stored with a different value fails the whole request with no partial write —
409, error coderuntime_context_immutable.
On success (200), the response is the same requirements report the read endpoints return, reflecting exactly what was just merged in — a 200 means only that the submitted keys were accepted, not that every required input is now present; check the response's own satisfied fields for that. A ref that is not currently visible or was not selected for this task answers the same uniform 404 a read endpoint would.
Errors use a structured envelope, { "error": { "code", "message", "details" } }, rather than the plain-detail shape the read endpoints use:
| Status | code | Meaning |
|---|---|---|
| 404 | connector_not_found | Task not found (not yours), or a referenced connector is not currently visible. |
| 409 | runtime_context_immutable | A submitted key already has a different stored value. |
| 400 | invalid_runtime_context | Malformed or empty request, a duplicate ref in the batch, an oversized value, an unselected connector, or a key/value that fails schema validation. |
| 503 | — | A concurrent write to the same row could not be resolved after one retry. |
Full generated reference
Every application endpoint and its exact schema is available from the live OpenAPI spec — open /docs (Swagger) or /openapi.json on a running instance. This page curates the high-value task endpoints; the generated spec is the exhaustive source.
Next Steps
- Workspace SDK → — the versioned
/v1task API - End-to-End Example →