Create a new SDK-driven task and kick off its first turn.
Single endpoint does three things atomically from the caller’s perspective:
agent_id matches the agent bound to
the presented API key. Mismatch -> 404 agent_not_found
(404 not 403, so the existence of unrelated agents isn’t
leaked via error code).Task row owned by the agent’s user,
with source='sdk' and input set to the user message.
Also persists the first user message to
task_chat_messages so the existing background execution
path can consume it without special-casing this entry point.start_task_in_background (which uses the same coroutine
the WebSocket handler does). Returns 202 immediately —
callers poll GET /v1/chat/tasks/{task_id} to observe the
eventual completed / failed status.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.
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
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.
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.