---
title: "Create conversation with streaming response"
method: POST
path: "/conversations/stream"
tags: ["Conversations"]
---

# Create conversation with streaming response

`POST /conversations/stream`

Start a new conversation and stream the AI response over Server-Sent
Events (SSE). Behaves like `POST /conversations` but emits tokens,
tool activity, and status updates incrementally instead of returning
a single JSON response at the end.

**Lifecycle**

1. The server validates `query`, persists an in-progress
   conversation, then opens the SSE stream with HTTP `200`.
2. A `connected` event is emitted immediately with the new
   `conversationId` so the client can link the stream (sidebar,
   parallel tabs, deep links) without an extra request.
3. AI-backend events stream through (token chunks, tool calls,
   status, etc.).
4. On success a single `complete` event is emitted carrying the
   full persisted conversation.
5. On failure an `error` event is emitted and the conversation is
   marked FAILED before the stream closes.

**Event vocabulary**

Three events have stable, server-defined `data` shapes:

- `connected` — `{ "message": string, "conversationId": string,
  "title": string }`
- `complete` — `{ "conversation": Conversation,
  "meta": { "requestId": string, "timestamp": string,
  "duration": number } }`
- `error` — `{ "error": string, "details"?: string }`

The forwarded events are `status`, `answer_chunk`, `tool_calls`,
`restreaming`, `metadata`, and `tool_execution_complete`. Their
payloads come from the Python query service and may evolve. Note
that raw `tool_call` / `tool_success` / `tool_error` / `tool_result`
events emitted by the LLM tool runtime are rewrapped as `status` by
the upstream wrapper before they reach this route, so clients on
`/conversations/stream` never see those names directly. Clients
should ignore unknown event names rather than treating them as
errors.

**Agent mode**

When `chatMode` selects an agent mode (for example `agent:auto`),
the optional `tools` list restricts which tools the agent may
invoke for this turn. Outside agent modes the `tools` field is
ignored.

## Request body

- CreateConversationRequest — Request body for creating a new AI conversation. **Query Processing:** The query is processed through PipesHub's AI pipeline which: - Performs semantic search across indexed knowledge bases - Retrieves relevant context from matching documents - Generates a response with citations to source materials - Suggests follow-up questions based on the conversation
  - `query` string, required — The user's question or prompt to start the conversation. Supports natural language queries of any complexity.
  - `recordIds` string[] — Limit the AI's knowledge scope to specific records/documents. When provided, only these records will be searched for context.
  - `filters` Filters — App connector instance ids and knowledge-base / record-group ids that narrow retrieval for a turn. For **org assistant** chat streams, send explicit `apps` / `kb` lists. For **agent** chat streams, send explicit id lists, or **omit** `filters` (and `tools`) to let the service use the agent’s stored knowledge and tool configuration. Sending `{ "apps": [], "kb": [] }` on an agent stream means **no** knowledge sources for that turn (it is not “full org default”).
    - `apps` string[] — Connector instance ids to scope retrieval for this turn. Each element must be a UUID (connector instance id, record-group id, etc.) or the org knowledge-base collection sentinel `knowledgeBase_<orgId>` (pattern `knowledgeBase_[a-zA-Z0-9_-]+`). Gateway validation matches Zod `appOrKbIdSchema`.
    - `kb` string[] — Knowledge-base / record-group ids to scope retrieval for this turn. Each element uses the same accepted formats as `apps`: a UUID or `knowledgeBase_<orgId>` (pattern `knowledgeBase_[a-zA-Z0-9_-]+`).
  - `appliedFilters` AppliedFilters — Rich filter state selected by the user, used for display and persistence only. This mirrors the active selection shown in the UI and is distinct from the machine-readable `filters` field used for retrieval scoping.
    - `apps` AppliedFilterNode[] — Applied app/connector filter nodes
      - `id` string — Unique identifier of the filter node
      - `name` string — Display name of the filter node
      - `nodeType` string — Type of the node (e.g. app, recordGroup, folder, record)
      - `connector` string — Connector identifier associated with this node
    - `kb` AppliedFilterNode[] — Applied knowledge-base filter nodes
      - `id` string — Unique identifier of the filter node
      - `name` string — Display name of the filter node
      - `nodeType` string — Type of the node (e.g. app, recordGroup, folder, record)
      - `connector` string — Connector identifier associated with this node
  - `attachments` ChatAttachmentRef[] — Uploaded chat attachments to associate with this conversation turn (see `POST /conversations/attachments/upload`).
    - `recordId` string, required — Attachment record id returned from the upload endpoint.
    - `recordName` string — Original display name of the file when known.
    - `mimeType` string — MIME type of the uploaded file.
    - `extension` string — File extension (e.g. `pdf`).
    - `virtualRecordId` string — Optional synthetic record id used by the graph layer.
  - `modelKey` string — Identifier for the AI model configuration to use. Available models depend on organization settings.
  - `modelName` string — Display name of the AI model
  - `modelFriendlyName` string — Friendly display name of the selected model
  - `chatMode` 'web_search' | 'internal_search' — Chat mode affecting response behavior.
  - `timezone` string — IANA timezone identifier from the client (top-level field). Used to provide time-aware context to the AI.
  - `currentTime` string, date-time — ISO 8601 / RFC 3339 datetime from the client (top-level field; UTC `Z` or numeric offset).
  - `tools` string[] — Optional list of tool identifiers (fully-qualified action names such as "jira.create_issue") that the AI agent is permitted to invoke for this request. When omitted the agent may use any configured tool. Applicable only when chatMode is an agent mode (e.g. "agent:auto").

## Response `200`

SSE stream established. The body is a sequence of
`text/event-stream` frames using the event vocabulary described
above.

## Other responses

- `400` — Invalid request — `query` is missing, empty, or exceeds the 100000-character limit, or another field fails validation (for example a malformed `recordIds` or `currentTime`).
- `401` — Unauthorized — valid bearer token required.
- `403` — Forbidden — the caller's token does not include the `conversation:chat` OAuth scope.
- `500` — Internal error before the SSE stream is established (for example, the initial conversation row could not be persisted). Once the stream is open, terminal failures are surfaced as an `error` SSE event instead of an HTTP status change.

---

[API](https://skmtc.net/pipeshub-ai/apis/pipeshub-api.md) · [All operations](https://skmtc.net/pipeshub-ai/apis/pipeshub-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/pipeshub-ai/pipeshub-api/versions/abd27cfefc73/schema)
