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

# Ҷавоби ҷараёнӣ

> Ҷавобро токен ба токен тавассути server-sent events гиред.

`POST /v1/agents/{agent_id}/chat/stream` маҳз ҳамон дархостро мегирад, ки эндпоинти синхронии чат мегирад: ҳамон бадан, ҳамон сарлавҳаҳои `Authorization` ва `Idempotency-Key`, ҳамон иҷозати `full`, ҳамон қоидаҳои муколама, пардохт ва кодҳои хато. Танҳо интиқол фарқ мекунад: ҷавоб `text/event-stream` аст.

## Рӯйдодҳо

Ҳар рӯйдод ном дорад ва як сатри JSON-и `data`-ро мебарад.

| Рӯйдод                       | Маълумот                                                                | Кай                                                                             |
| ---------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `response.created`           | `{"request_id", "conversation_id"}`                                     | Ҳамин ки муколама муайян шуд                                                    |
| `response.output_text.delta` | `{"delta": "..."}`                                                      | Барои ҳар порчаи матни ҷавоб ҳангоми тавлиди он аз ҷониби модел; такрор мешавад |
| `response.completed`         | Ҷавоби пурраи чат (`request_id`, `conversation_id`, `message`, `usage`) | Ҳамеша рӯйдоди охирини ҷараёни муваффақ                                         |
| `error`                      | `{"code", "message", "request_id"}`                                     | Ҳамеша рӯйдоди охирини ҷараёни ноком                                            |

```text theme={null}
event: response.created
data: {"request_id":"7f20a5f0-...","conversation_id":"1c2e..."}

event: response.output_text.delta
data: {"delta":"The basic"}

event: response.output_text.delta
data: {"delta":" plan is $19 per month."}

event: response.completed
data: {"request_id":"7f20a5f0-...","conversation_id":"1c2e...","message":{"id":"66e0...","role":"assistant","content":"The basic plan is $19 per month.","created_at":"2026-09-13T12:00:00Z"},"usage":{"prompt_tokens":120,"completion_tokens":45,"total_tokens":165,"charged_usd":"0.00123400"}}
```

<Note>
  Матни мулоҳиза ва фаъолияти абзорҳо ҳеҷ гоҳ қисми ҷараён нестанд. `response.completed` ҳамеша матни пурраи ниҳоиро мебарад, бинобар ин мизоҷе, ки баъзе делтаҳоро аз даст додааст, метавонад аз он барқарор кунад, на аз делтаҳои пайвастшуда.
</Note>

## Хатоҳо дар ҷараён

Нокомиҳо **пеш аз** барқарор шудани ҷараён (калиди нодуруст, санҷиш, `idempotency_conflict`, `conversation_busy`, агенти хомӯшшуда, маҳдудияти дархостҳо) конвертҳои муқаррарии JSON-и [хато](/tj/guides/errors) бо статуси HTTP-и худ мебошанд; пеш аз хондани рӯйдодҳо `response.ok`-ро тафтиш кунед.

Пас аз фиристодани сарлавҳаҳо статус аллакай `200` аст. Нокомӣ пас аз ин лаҳза (масалан `insufficient_balance` ё `internal_error`) ҳамчун рӯйдоди `error` бо ҳамон майдонҳои конверт мерасад ва ҷараёнро мебандад.

## Қатъи пайвастшавӣ ва такрорҳо

Мизоҷе, ки пайвастшавиро қатъ мекунад, ҷавобро қатъ намекунад: он ҳанӯз тавлид ва нигоҳ дошта мешавад, ва сабти идемпотентӣ анҷом меёбад. Такрор бо ҳамон `Idempotency-Key` `response.created`-ро ва бевосита пас аз он `response.completed`-ро бо натиҷаи нигоҳдошташуда мефиристад; делтаҳо такроран пахш намешаванд. Ниг. [Идемпотентӣ](/tj/guides/idempotency).

## Мисолҳо

<CodeGroup>
  ```bash curl theme={null}
  curl -N -X POST "$CHATTLER_BASE_URL/v1/agents/$CHATTLER_AGENT_ID/chat/stream" \
    -H "Authorization: Bearer $CHATTLER_API_KEY" \
    -H "Idempotency-Key: $(uuidgen)" \
    -H "Content-Type: application/json" \
    -d '{"external_user_id": "customer-123", "message": "Tell me more"}'
  ```

  ```python Python theme={null}
  import json
  import os
  import uuid

  import httpx


  def stream_chat(external_user_id: str, message: str) -> dict:
      url = f"{os.environ['CHATTLER_BASE_URL']}/v1/agents/{os.environ['CHATTLER_AGENT_ID']}/chat/stream"
      headers = {
          "Authorization": f"Bearer {os.environ['CHATTLER_API_KEY']}",
          "Idempotency-Key": str(uuid.uuid4()),
      }
      with httpx.stream("POST", url, headers=headers, timeout=120,
                        json={"external_user_id": external_user_id, "message": message}) as response:
          if response.status_code >= 400:
              response.read()
              raise RuntimeError(response.json()["error"])
          event, completed = None, None
          for line in response.iter_lines():
              if line.startswith("event: "):
                  event = line[len("event: "):]
              elif line.startswith("data: "):
                  data = json.loads(line[len("data: "):])
                  if event == "response.output_text.delta":
                      print(data["delta"], end="", flush=True)
                  elif event == "response.completed":
                      completed = data
                  elif event == "error":
                      raise RuntimeError(f"{data['code']}: {data['message']}")
              elif line == "":
                  event = None
          return completed


  stream_chat("customer-123", "Tell me more")
  ```

  ```javascript Node theme={null}
  const baseUrl = process.env.CHATTLER_BASE_URL;
  const agentId = process.env.CHATTLER_AGENT_ID;
  const apiKey = process.env.CHATTLER_API_KEY;

  async function streamChat(externalUserId, message, onDelta) {
    const response = await fetch(`${baseUrl}/v1/agents/${agentId}/chat/stream`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${apiKey}`,
        "Idempotency-Key": crypto.randomUUID(),
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ external_user_id: externalUserId, message }),
    });
    if (!response.ok) {
      const body = await response.json();
      throw new Error(`${body.error.code}: ${body.error.message}`);
    }
    const reader = response.body.getReader();
    const decoder = new TextDecoder();
    let buffer = "";
    let completed = null;
    for (;;) {
      const { value, done } = await reader.read();
      if (done) break;
      buffer += decoder.decode(value, { stream: true });
      let boundary;
      while ((boundary = buffer.indexOf("\n\n")) >= 0) {
        const frame = buffer.slice(0, boundary);
        buffer = buffer.slice(boundary + 2);
        const event = frame.match(/^event: (.+)$/m)?.[1];
        const data = JSON.parse(frame.match(/^data: (.+)$/m)?.[1] ?? "{}");
        if (event === "response.output_text.delta") onDelta(data.delta);
        else if (event === "response.completed") completed = data;
        else if (event === "error") throw new Error(`${data.code}: ${data.message}`);
      }
    }
    return completed;
  }

  const result = await streamChat("customer-123", "Tell me more", (t) => process.stdout.write(t));
  console.log("\n", result.usage);
  ```
</CodeGroup>

<Tip>
  `curl -N`-ро (бе буферизатсия) истифода баред, то рӯйдодҳоро ҳангоми расиданашон бинед. Дар браузерҳо `EventSource` наметавонад баданҳои `POST` ё сарлавҳаҳои фармоиширо фиристад, ва калид ба ҳар ҳол ҳеҷ гоҳ набояд ба браузер расад; аз сервери худ ҷараён гиред ва матнро ба мизоҷ интиқол диҳед.
</Tip>
