> ## Documentation Index
> Fetch the complete documentation index at: https://docs.voltai.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat Query

> Ask a question to the Voltai agent and continue an existing thread with `chat_id`.

Use `POST /chat/query/` to ask a question and optionally continue the same conversation by sending back the returned `chat_id`. The agent automatically chooses which topics, tools, and subagents to use; you can scope retrieval to specific knowledge topics with `topic_names` and bias the agent's reasoning depth with `reasoning_level`.

Send your API key in the `X-API-KEY` header. The body must include `query` and `user_id`.

## Request Notes

* **`user_id`** (required) — your application's identifier for the end-user making the request. Each `(API key, user_id)` pair is limited to **one concurrent request**. If the same user already has a request in flight, the endpoint returns `429`.
* **`chat_id`** (optional) — must be a valid UUID. Behavior:
  * Omitted → the server mints a fresh UUID and creates a new chat.
  * UUID matches an existing chat in your organization → the new turn is appended to that thread.
  * UUID is well-formed but not yet used → the server creates a new chat under that UUID. This lets clients pin their own thread IDs for idempotency or app-side correlation.
  * UUID already belongs to a chat you cannot resume (different org or soft-deleted) → `409`.
  * UUID malformed → `400`.
* **`reasoning_level`** controls how thorough the agent should be. Defaults to `medium`.

  * `low` — favor quick answers and minimal tool use.
  * `medium` — default.
  * `high` — favor thorough multi-step reasoning with more tool calls.

  Unknown values fall back to `medium`.
* **`mode`** is a legacy field kept for backwards compatibility. The current agent pipeline does not branch on it; whatever you send is echoed back unchanged on the response. Use `reasoning_level` instead.
* **`topic_names`** (optional) — list of knowledge topic **names** to scope retrieval to (e.g. `["Family A", "Family B"]`). Each name must match a topic in your organization (case-insensitive). If omitted or `[]`, topic scope is chosen automatically. If any name does not match a topic, the endpoint returns `400`.
* **`topic_name`** (deprecated) — singular alias for `topic_names`. When `topic_names` is omitted, `topic_name` is wrapped into a one-element list. Prefer `topic_names` for new integrations.

## Response Notes

* The endpoint returns a single JSON object, not an array.
* **`final_answer`** is the cleaned answer text. Internal markup (`<answer>`, `<ref>`, `<abbr>`, citation tokens) is stripped.
* **`chat_id`** is the chat thread UUID. Pass it back on subsequent requests to continue the conversation.
* **`chat_url`** is the web UI link for this thread: `https://voltai.ai/{org_name}/chat/{chat_id}`, where `{org_name}` is the resolved organization's `name`.
* **`conversation_id`** is the integer identifier of this specific question/answer turn. A new `conversation_id` is returned for every `/chat/query/` request, including follow-ups in the same `chat_id`. Use it to fetch the same turn later via [`GET /chat/conversation/{conversation_id}/`](/api-reference/knowledge-agent/chat-conversation).
* **`sources`** lists evidence cited by the agent. Each entry includes:
  * `id` — stable identifier; use it to join citation tokens that appear in `final_answer` (e.g. `[0351-E1]`) back to a specific source.
  * `source_name` — filename for library / PDF chunks; page or item title for web, fetched URLs, and connector sources (Slack, Jira, Confluence, Salesforce, SharePoint, Assembla); display label for part sources.
  * `page` — 1-indexed page number for paginated library sources; `null` otherwise.
  * `type` — source type tag (`text`, `web`, `part`, etc.).
  * `url` — link to view the source. May be `null` for sources without a canonical link.
  * `display_name` — human-readable label for the tool that surfaced the source (e.g. `"Library Search"`, `"Web Search"`, `"Part Detail"`).
* **`tools`** is the ordered list of tool calls the agent made while answering — same data SSE clients receive as `tool_call` / `tool_output` frames. Each entry has `id`, `name`, `display_name`, `title`, `input`, `output`, `status`, and an optional `subagent_instance_id`.
* **`content`** is the raw transcript of the turn: an ordered list of `text` and `tool` items as the agent produced them. `text` items concatenate to `final_answer`; `tool` items mirror `tools`.
* **`thinking`** is retained for backwards compatibility with the legacy multi-agent orchestrator. Under the current agent pipeline it is always `""` — use `tools` and `content` to inspect the reasoning trail.
* **`mode`** echoes whatever value you sent (or `"AUTO"` if omitted). It does not reflect any internal routing decision.

## Concurrency & Sessions

Each `(API key, user_id)` pair is limited to **one concurrent request**. If a second request arrives for the same pair while one is still in progress, the API returns **429** with error code `user_session_limit_exceeded`.

There is also an organization-wide session limit. If all org-level seats are occupied, the API returns **429** with error code `session_limit_exceeded`.

Use [`GET /chat/sessions/`](/api-reference/knowledge-agent/chat-sessions) to check current session usage and see which user IDs are active.

## Streaming with Server-Sent Events

Set `Accept: text/event-stream` to receive incremental output instead of the single JSON response.

The stream begins with one `start` event, then interleaved `text`, `tool_call`, `tool_output`, `todos`, and `interrupt` events as the agent runs, and ends with either one `done` event (success) or one `error` event (failure). Comment frames (`: keepalive`) may appear between frames while the server waits on the model; ignore them.

| Event         | Description                                                                                                                                                                            |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `start`       | Sent once at the top of the stream so clients can render thread context immediately. Carries `chat_id`, `chat_url`, `conversation_id`.                                                 |
| `text`        | Incremental answer text. `msg.delta` is the fragment to append; `msg.subagent_instance_id` is non-null when the delta comes from a subagent (intermediate reasoning, not user-facing). |
| `tool_call`   | The agent started a tool call. `msg` contains `id`, `name`, `display_name`, `title`, `input`, and `subagent_instance_id`.                                                              |
| `tool_output` | The corresponding tool call finished. `msg` contains `id`, `output`, `status` (`running` \| `success` \| `error`).                                                                     |
| `todos`       | Snapshot of the agent's TODO list for multi-step plans. Replaces (not appends) any prior list for the same `subagent_instance_id`.                                                     |
| `interrupt`   | Human-in-the-loop interrupt. The agent is asking you to approve or reject an action.                                                                                                   |
| `done`        | Terminal success frame with the same payload as the non-streaming JSON response (including `tools`, `content`, `sources`).                                                             |
| `error`       | Terminal failure frame. Sent if the stream fails after the 200 response status has been committed.                                                                                     |

Concatenating the `msg.delta` text from every main-agent `text` event (those with `subagent_instance_id == null`) reproduces a close approximation of `final_answer`; rely on the `done` event's `final_answer` for the canonical cleaned string.

## Example Request

```json theme={null}
{
  "query": "What is EMEM?",
  "user_id": "usr_82af91",
  "reasoning_level": "medium"
}
```

### Scoped to one or more topics (optional)

```json theme={null}
{
  "query": "What is the maximum operating temperature?",
  "user_id": "usr_82af91",
  "topic_names": ["Example Product Family"]
}
```

## Follow-up Request (continuing a thread)

```json theme={null}
{
  "query": "What is the maximum operating temperature?",
  "user_id": "usr_82af91",
  "chat_id": "2d8a39d8-29d6-4f0f-bc5f-4c5f0f9c9d54"
}
```

## Example Response

```json theme={null}
{
  "final_answer": "EMEM is embedded memory integrated into the device for storing code and data.",
  "thinking": "",
  "chat_id": "2d8a39d8-29d6-4f0f-bc5f-4c5f0f9c9d54",
  "chat_url": "https://voltai.ai/ExampleOrg/chat/2d8a39d8-29d6-4f0f-bc5f-4c5f0f9c9d54",
  "conversation_id": 184217,
  "sources": [
    {
      "id": "0351-E1",
      "source_name": "example-datasheet.pdf",
      "page": 12,
      "type": "text",
      "url": "https://voltai.ai/ExampleOrg/library?source_name=example-datasheet.pdf&source_type=text&source_page=12",
      "display_name": "Library Search"
    }
  ],
  "mode": "AUTO",
  "tools": [
    {
      "id": "call_8c2f",
      "name": "search_library",
      "display_name": "Library Search",
      "title": "Searching \"EMEM\" in Datasheets",
      "input": { "query": "EMEM", "topic_id": 17 },
      "output": "Found 3 matching chunks…",
      "status": "success",
      "subagent_instance_id": null
    }
  ],
  "content": [
    {
      "type": "tool",
      "id": "call_8c2f",
      "name": "search_library",
      "display_name": "Library Search",
      "title": "Searching \"EMEM\" in Datasheets",
      "input": { "query": "EMEM", "topic_id": 17 },
      "output": "Found 3 matching chunks…",
      "status": "success",
      "subagent_instance_id": null
    },
    {
      "type": "text",
      "text": "EMEM is embedded memory integrated into the device for storing code and data.",
      "subagent_instance_id": null
    }
  ]
}
```

## Example SSE Stream

```text theme={null}
data: {"type":"start","chat_id":"2d8a…","chat_url":"https://voltai.ai/ExampleOrg/chat/2d8a…","conversation_id":184217}

data: {"type":"tool_call","msg":{"id":"call_8c2f","name":"search_library","display_name":"Library Search","title":"Searching \"EMEM\" in Datasheets","input":{"query":"EMEM"},"subagent_instance_id":null}}

data: {"type":"tool_output","msg":{"id":"call_8c2f","output":"Found 3 matching chunks…","status":"success"}}

data: {"type":"text","msg":{"delta":"EMEM is embedded memory","subagent_instance_id":null}}

data: {"type":"text","msg":{"delta":" integrated into the device.","subagent_instance_id":null}}

data: {"type":"done","final_answer":"EMEM is embedded memory integrated into the device.","thinking":"","chat_id":"2d8a…","chat_url":"https://voltai.ai/ExampleOrg/chat/2d8a…","conversation_id":184217,"sources":[...],"mode":"AUTO","tools":[...],"content":[...]}
```

## 409 — Chat ID conflict

```json theme={null}
{
  "detail": "chat_id is already in use."
}
```

## 429 — Per-User Limit

```json theme={null}
{
  "error": "user_session_limit_exceeded",
  "message": "user_id 'usr_82af91' already has an active request. Please wait for it to complete.",
  "user_id": "usr_82af91"
}
```

## 429 — Org-Level Limit

```json theme={null}
{
  "error": "session_limit_exceeded",
  "message": "You have exceeded the session quota limit for your organization. Please try again later.",
  "total_seats": 10,
  "active_seats": 10,
  "available_seats": 0
}
```


## OpenAPI

````yaml chat-query.json POST /chat/query/
openapi: 3.1.0
info:
  title: Voltai API Docs
  description: .
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
  version: 1.0.0
servers:
  - url: https://api-prod.voltai.ai
security:
  - ApiKeyAuth: []
paths:
  /chat/query/:
    post:
      description: >-
        Ask a question to the Voltai agent and optionally continue an existing
        chat thread.


        Set the request header `Accept: text/event-stream` to receive the
        response as a Server-Sent Events stream of incremental answer chunks,
        tool-call frames, and a terminal payload. Without this header (the
        default) the response is returned as a single JSON object once the agent
        completes.
      parameters:
        - in: header
          name: Accept
          required: false
          description: >-
            Set to `text/event-stream` to opt into Server-Sent Events streaming.
            Any other value (or omitting the header) returns the standard JSON
            response.
          schema:
            type: string
            enum:
              - application/json
              - text/event-stream
      requestBody:
        description: Query payload for the Voltai agent.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatQuery'
        required: true
      responses:
        '200':
          description: >-
            Agent response. Returned as a single JSON object by default, or as a
            Server-Sent Events stream when the request includes `Accept:
            text/event-stream`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatResponse'
            text/event-stream:
              schema:
                $ref: '#/components/schemas/ChatStreamEvent'
        '400':
          description: >-
            Invalid request (missing `query`/`user_id`, malformed `chat_id`,
            unknown `mode`, unknown `topic_names`, etc.)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            Invalid or missing API key, or the organization has reached its
            message limit.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            `chat_id` was supplied but the UUID is already in use by a chat the
            API key cannot resume (a different organization, or a soft-deleted
            chat). Pick a different UUID, or omit `chat_id` to let the server
            mint one.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: >-
            Concurrent session limit exceeded: either the same `user_id` already
            has an in-flight request (`user_session_limit_exceeded`), or the
            organization-wide seat cap is reached (`session_limit_exceeded`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionLimitError'
components:
  schemas:
    ChatQuery:
      required:
        - query
        - user_id
      type: object
      description: >-
        Provide `query` and `user_id`. Topic scope is chosen automatically
        unless you pass `topic_names`. The agent decides its own reasoning depth
        — use `reasoning_level` to bias it.
      properties:
        query:
          description: The user's question.
          type: string
        user_id:
          description: >-
            Your application's identifier for the end-user making the request.
            Used for per-user session tracking and concurrency enforcement. Each
            `(API key, user_id)` pair is limited to one concurrent request.
          type: string
          maxLength: 255
        chat_id:
          description: >-
            Existing chat thread to continue. Must be a valid UUID. If it
            matches a chat in your organization, the new turn is appended; if
            the UUID is well-formed but not yet used, the server creates a new
            chat under that UUID (useful for client-side idempotency /
            correlation). Omit to let the server mint a fresh UUID. A UUID that
            already belongs to a chat the API key cannot resume returns `409`.
          type: string
          format: uuid
        reasoning_level:
          description: >-
            Bias for how much intermediate reasoning the agent should do. `low`
            favors quick answers, `high` favors thorough multi-step reasoning.
            Unknown values fall back to `medium`.
          type: string
          enum:
            - low
            - medium
            - high
          default: medium
        mode:
          description: >-
            Legacy reasoning-mode selector kept for backwards compatibility with
            older clients. Under the current agent pipeline this is a no-op —
            the value is validated and echoed back on the response, but it does
            not change behavior. Use `reasoning_level` instead.
          type: string
          enum:
            - AGENTIC
            - FAST
            - AUTO
          default: AUTO
        topic_names:
          description: >-
            Optional. Names of knowledge topics to scope retrieval to. Each must
            match a topic in your organization (case-insensitive). If omitted or
            empty, topic scope is chosen automatically. If any name does not
            match a topic, the request returns 400.
          type: array
          items:
            type: string
        topic_name:
          description: >-
            Deprecated singular alias for `topic_names`. When `topic_names` is
            omitted, `topic_name` (if present) is wrapped into a one-element
            list. Prefer `topic_names` for new integrations.
          type: string
          deprecated: true
    ChatResponse:
      description: Agent response.
      type: object
      required:
        - final_answer
        - thinking
        - chat_id
        - chat_url
        - conversation_id
        - sources
        - mode
        - tools
        - content
      properties:
        final_answer:
          type: string
          description: >-
            Cleaned answer text returned by the agent. Internal markup
            (`<answer>`, `<ref>`, `<abbr>`, citation tokens) is stripped.
        thinking:
          type: string
          description: >-
            Aggregated reasoning string from the legacy multi-agent
            orchestrator: per-agent entries are concatenated in execution order,
            each prefixed by a header line and separated by a blank line. Empty
            under the current agent pipeline — use `tools` and `content` to
            inspect the reasoning trail instead.
        chat_id:
          type: string
          format: uuid
          description: >-
            Thread identifier: the `Chat` UUID for this conversation. Reuse this
            value in subsequent requests to continue the same thread.
        chat_url:
          type: string
          format: uri
          description: >-
            Web UI link to this thread:
            `https://voltai.ai/{organization_name}/chat/{chat_id}` using the
            resolved organization's `name`.
        conversation_id:
          type: integer
          description: >-
            Identifier of the specific question/answer turn within the thread. A
            new `conversation_id` is generated for every `/chat/query/` request.
            Use it with `GET /chat/conversation/{conversation_id}/` to fetch
            this exact turn later.
        sources:
          type: array
          description: >-
            Evidence cited by the agent. Each entry is annotated with the tool
            that surfaced it (`display_name`) and a stable `id` for joining back
            to citation tokens in `final_answer`.
          items:
            $ref: '#/components/schemas/Source'
        mode:
          type:
            - string
            - 'null'
          description: >-
            Echo of the request `mode`. Retained for backwards compatibility;
            current agent behavior does not depend on it.
        tools:
          type: array
          description: >-
            Every tool call the agent made while answering this turn, in
            execution order. Lets non-streaming clients see the same reasoning
            trail that SSE clients receive as live `tool_call` / `tool_output`
            frames.
          items:
            $ref: '#/components/schemas/ToolInvocation'
        content:
          type: array
          description: >-
            Raw agent transcript for the turn: an ordered list of `text` and
            `tool` items as the agent produced them. `text` items concatenate to
            `final_answer`; `tool` items mirror the entries in `tools`.
          items:
            $ref: '#/components/schemas/ContentItem'
    ChatStreamEvent:
      description: >-
        One Server-Sent Event frame delivered when the request includes `Accept:
        text/event-stream`. Each frame is a single JSON object on a `data: ...`
        line, terminated by a blank line.


        The stream begins with one `start` event, then interleaved `text`,
        `tool_call`, `tool_output`, `todos`, and `interrupt` events as the agent
        runs, and ends with either one `done` event (success) or one `error`
        event (failure). The server may also send SSE comment frames (`:
        keepalive`) every few seconds while it waits on the model; clients
        should ignore them.


        Clients that need a fully cleaned answer should use `final_answer` from
        the `done` event; concatenating `text` deltas reproduces the same string
        but may briefly include internal markup that the parser strips at the
        end.
      oneOf:
        - type: object
          description: >-
            Sent once before any other frames so clients can render the thread
            shell immediately.
          required:
            - type
            - chat_id
            - chat_url
            - conversation_id
          properties:
            type:
              type: string
              enum:
                - start
            chat_id:
              type: string
              format: uuid
            chat_url:
              type: string
              format: uri
            conversation_id:
              type: integer
              description: >-
                Identifier of this specific question/answer turn within the
                thread. Use with `GET /chat/conversation/{conversation_id}/` to
                fetch the persisted turn later.
        - type: object
          description: Incremental answer text from the agent.
          required:
            - type
            - msg
          properties:
            type:
              type: string
              enum:
                - text
            msg:
              type: object
              required:
                - delta
              properties:
                delta:
                  type: string
                  description: >-
                    New text fragment to append to the in-progress answer.
                    Multiple `text` events should be concatenated in order.
                subagent_instance_id:
                  type:
                    - string
                    - 'null'
                  description: >-
                    When non-null, this delta comes from a subagent and is
                    intermediate reasoning, not user-facing answer text.
        - type: object
          description: >-
            Emitted when the agent starts a tool call. Pair with a later
            `tool_output` frame on the same `id`.
          required:
            - type
            - msg
          properties:
            type:
              type: string
              enum:
                - tool_call
            msg:
              type: object
              required:
                - id
                - name
              properties:
                id:
                  type: string
                  description: >-
                    Tool-call identifier (same value emitted on the matching
                    `tool_output`).
                name:
                  type: string
                display_name:
                  type: string
                title:
                  type: string
                input:
                  type:
                    - object
                    - 'null'
                subagent_instance_id:
                  type:
                    - string
                    - 'null'
        - type: object
          description: >-
            Emitted when a tool call finishes. The `sources` field that lives on
            internal tool items is stripped from the wire payload — sources are
            surfaced once, deduped, on the terminal `done` frame's `sources`
            array.
          required:
            - type
            - msg
          properties:
            type:
              type: string
              enum:
                - tool_output
            msg:
              type: object
              required:
                - id
                - status
              properties:
                id:
                  type: string
                output:
                  type:
                    - string
                    - 'null'
                status:
                  type: string
                  enum:
                    - running
                    - success
                    - error
        - type: object
          description: >-
            Snapshot of the agent's current TODO list (used by long-running
            multi-step plans). Replaces, not appends to, the prior list with the
            same `subagent_instance_id`.
          required:
            - type
            - msg
          properties:
            type:
              type: string
              enum:
                - todos
            msg:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                subagent_instance_id:
                  type:
                    - string
                    - 'null'
        - type: object
          description: >-
            Human-in-the-loop interrupt: the agent is asking the caller to
            approve or reject an action. Only emitted for tools that require
            explicit user authorization.
          required:
            - type
            - msg
          properties:
            type:
              type: string
              enum:
                - interrupt
            msg:
              type: object
        - type: object
          description: >-
            Terminal success frame. Carries the same fields as the non-streaming
            `ChatResponse` body.
          required:
            - type
            - final_answer
            - thinking
            - chat_id
            - chat_url
            - conversation_id
            - sources
            - mode
            - tools
            - content
          properties:
            type:
              type: string
              enum:
                - done
            final_answer:
              type: string
            thinking:
              type: string
            chat_id:
              type: string
              format: uuid
            chat_url:
              type: string
              format: uri
            conversation_id:
              type: integer
            sources:
              type: array
              items:
                $ref: '#/components/schemas/Source'
            mode:
              type:
                - string
                - 'null'
            tools:
              type: array
              items:
                $ref: '#/components/schemas/ToolInvocation'
            content:
              type: array
              items:
                $ref: '#/components/schemas/ContentItem'
        - type: object
          description: >-
            Terminal error frame. Sent if the stream fails after the response
            status has already been committed (200). The HTTP status remains
            200; clients must inspect this event.
          required:
            - type
            - detail
          properties:
            type:
              type: string
              enum:
                - error
            detail:
              type: string
    Error:
      type: object
      properties:
        detail:
          type: string
          description: Human-readable error description.
    SessionLimitError:
      type: object
      description: Returned when a concurrent session limit is exceeded.
      required:
        - error
        - message
      properties:
        error:
          type: string
          description: >-
            Error code. `user_session_limit_exceeded` when the same `user_id`
            already has an in-flight request. `session_limit_exceeded` when the
            organization-wide session cap is reached.
          enum:
            - user_session_limit_exceeded
            - session_limit_exceeded
        message:
          type: string
          description: Human-readable error description.
        user_id:
          type: string
          description: >-
            The `user_id` that triggered the per-user limit. Present only for
            `user_session_limit_exceeded`.
        total_seats:
          type: integer
          description: >-
            Total allowed concurrent sessions for the organization. Present only
            for `session_limit_exceeded`.
        active_seats:
          type: integer
          description: >-
            Currently active sessions. Present only for
            `session_limit_exceeded`.
        available_seats:
          type: integer
          description: >-
            Remaining available sessions. Present only for
            `session_limit_exceeded`.
    Source:
      type: object
      description: >-
        A single piece of evidence cited by the agent. Two shapes are returned
        interchangeably depending on the producing tool:


        - Library / PDF chunks: `source_name` is the source filename, `page` is
        the page number, and `url` is either the document's external link (when
        configured on the source) or a Voltai library deep-link.

        - Web pages, fetched URLs, and connector items (Slack, Jira, Confluence,
        Salesforce, SharePoint, Assembla): `source_name` is the page or item
        title, `page` is `null`, and `url` is the original link.

        - Part-detail / part-comparison / part-replacement sources:
        `source_name` is the display label and `url` may be `null` when the
        source has no canonical link.
      required:
        - source_name
        - page
        - url
      properties:
        id:
          type:
            - string
            - 'null'
          description: >-
            Stable identifier for the source within this response. Use it to
            join citation tokens that appear in `final_answer` (e.g.
            `[0351-E1]`) back to a specific source entry.
        source_name:
          type: string
          description: >-
            Display label for the source. Filename for library chunks; page or
            item title for web / connector / fetched URL sources; display name
            for part sources.
        page:
          type:
            - integer
            - 'null'
          description: >-
            1-indexed page number for paginated sources (library PDFs). `null`
            for web pages, connector items, and part sources.
        type:
          type:
            - string
            - 'null'
          description: >-
            Source type tag from the producing tool (`text`, `web`, `part`,
            ...). Defaults to `text` when the tool did not stamp one.
        url:
          type:
            - string
            - 'null'
          description: >-
            Link to view the source. For library chunks this is either the
            source's configured external URL or a Voltai library deep-link with
            `source_name` / `source_page` parameters. For web and connector
            sources it is the original link. May be `null` when no canonical
            link exists.
        display_name:
          type: string
          description: >-
            Human-readable label for the tool that surfaced the source (e.g.
            `"Web Search"`, `"Library Search"`, `"Part Detail"`). Present
            whenever the agent successfully attributed the source to a tool
            call.
    ToolInvocation:
      type: object
      description: >-
        One tool call the agent performed while producing its answer. The full
        list is returned in execution order on `ChatResponse.tools` and `done`
        SSE events.
      required:
        - id
        - name
        - status
      properties:
        id:
          type: string
          description: >-
            Tool-call identifier. Stable for the lifetime of the conversation
            and used to correlate `tool_call` and `tool_output` SSE frames.
        name:
          type: string
          description: >-
            Internal tool name (e.g. `search_library`, `search_web`,
            `fetch_url`, `part_detail`, `task`).
        display_name:
          type: string
          description: >-
            Human-readable label for the tool (e.g. `"Library Search"`). Falls
            back to a title-cased version of `name` when no friendly label is
            registered.
        title:
          type: string
          description: >-
            One-line, argument-aware summary suitable for showing in a UI (e.g.
            `'Searching "EMEM" in Datasheets'`).
        input:
          type:
            - object
            - 'null'
          description: >-
            Arguments the agent passed to the tool. `null` for private tools
            whose inputs are not surfaced to the API.
        output:
          type:
            - string
            - 'null'
          description: >-
            Raw text output the tool returned to the agent. `""` for private
            tools whose results are hidden from the API surface.
        status:
          type: string
          enum:
            - running
            - success
            - error
          description: Final status of the tool call.
        subagent_instance_id:
          type:
            - string
            - 'null'
          description: >-
            If this tool was invoked by a subagent (delegated via a parent
            `task` call), the parent task's `id`. Top-level tools have `null`.
    ContentItem:
      oneOf:
        - type: object
          description: >-
            Text fragment emitted by the agent (main agent or a subagent).
            Concatenate all main-agent text items in order to reconstruct the
            agent's prose.
          required:
            - type
            - text
          properties:
            type:
              type: string
              enum:
                - text
            text:
              type: string
              description: Text content of this fragment.
            subagent_instance_id:
              type:
                - string
                - 'null'
              description: >-
                When non-null, this text was produced by a subagent and is read
                by the main agent as a tool result rather than shown directly to
                the user.
        - type: object
          description: >-
            Tool call interleaved into the agent's output stream. The same
            fields as `ToolInvocation` (with `sources` stripped — they are
            surfaced on top-level `sources`).
          required:
            - type
            - id
            - name
            - status
          allOf:
            - $ref: '#/components/schemas/ToolInvocation'
            - properties:
                type:
                  type: string
                  enum:
                    - tool
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````