Create Chat Task
Create a new SDK-driven task and kick off its first turn.
Single endpoint does three things atomically from the caller’s perspective:
- Verifies the body’s
agent_idmatches the agent bound to the presented API key. Mismatch -> 404agent_not_found(404 not 403, so the existence of unrelated agents isn’t leaked via error code). - Persists a new :class:
Taskrow owned by the agent’s user, withsource='sdk'andinputset to the user message. Also persists the first user message totask_chat_messagesso the existing background execution path can consume it without special-casing this entry point. - Schedules background execution via
start_task_in_background(which uses the same coroutine the WebSocket handler does). Returns 202 immediately — callers pollGET /v1/chat/tasks/{task_id}to observe the eventualcompleted/failedstatus.
Args:
request: Validated :class:CreateTaskRequest. message.content
is guaranteed non-empty by Pydantic; agent_id is the
target agent the SDK caller wants to invoke.
authed: (Agent, AgentApiKey) tuple resolved by the auth
dependency. The agent here is the key-bound agent, the
single source of truth for what this caller may touch.
db: SQLAlchemy session.
Returns:
:class:CreateTaskResponse with the new task_id,
agent_id, status='running' (the atomic claim inside
the handler flips the row from PENDING to RUNNING before the
response is sent), and created_at for the caller to
start polling from.
Raises:
V1ApiError 401: missing/invalid/revoked key (raised inside
get_agent_from_api_key; envelope is uniform with
other auth failures).
V1ApiError 404: request.agent_id != authed_agent.id.
500 (V1 envelope): any unexpected exception — the global
handler in web/app.py translates to
{"error": {"code": "internal_error", ...}} and the raw
exception message stays out of the response.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Body for POST /v1/chat/tasks.
agent_id is required and must match the agent bound to the
presented API key; the server enforces body.agent_id == authed.agent.id and returns 404 agent_not_found on mismatch.
Target agent's primary key. Must match the agent the presented API key is bound to.
First user message of the task.
Free-form correlation data the SDK caller can pass through (trace_id, request_id, etc). Not interpreted server-side.
Response
Successful Response
POST /v1/chat/tasks -> 202 Accepted response.
The task has been persisted, claimed as RUNNING in the same
transaction, and queued for background execution; callers poll
GET /v1/chat/tasks/{task_id} to observe the transition
running -> completed/failed.
Newly created task primary key.
Agent the task is bound to.
Initial status, 'running' in the 202 response (the atomic claim inside POST commits the status flip before the response is sent). Use GET /v1/chat/tasks/{task_id} to observe later transitions.
UTC creation timestamp.

