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

# エージェント会話を差分で継続する

> delta_v1で最新のユーザーメッセージだけを送り、サーバー側のrolling windowでAPI会話を継続します。

`POST /agent/runs` の `delta_v1` は、会話履歴全体ではなく最新のユーザーメッセージだけを送ります。
QAIP は保存済みの現在枝から、モデルの上限に収まる rolling context を再構築します。

API キーには `inference:run` scope が必要です。すべての `delta_v1` request に、一意で非空の
`Idempotency-Key` を付けてください。

```bash theme={null}
export QAIP_BASE_URL="https://developer.qaip.com/api/v1"
export QAIP_API_KEY="your-api-key-here"
```

## 新しい会話を開始する

新規会話では `threadId` と `baseRunId` を省略します。

```bash theme={null}
curl --request POST "$QAIP_BASE_URL/agent/runs" \
  --header "x-api-key: $QAIP_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: turn-0001" \
  --data '{
    "input": {
      "inputHistoryMode": "delta_v1",
      "agentId": "019c0000-0000-7000-8000-000000000001",
      "newUserMessage": {
        "id": "message-0001",
        "role": "user",
        "content": "売上データの要点を教えてください"
      },
      "uiStateDelta": {},
      "tools": [],
      "context": [],
      "forwardedProps": {}
    }
  }'
```

`202` response の `thread_id` と `run_id` を保存します。同じ request の response を受け取れなかった場合は、
body と `Idempotency-Key` を変えずに再送してください。同じ run に収束します。

## current\_run\_idから継続する

`GET /agent/threads` で `agent_id` と `current_run_id` を取得します。

```bash theme={null}
curl "$QAIP_BASE_URL/agent/threads?limit=50" \
  --header "x-api-key: $QAIP_API_KEY"
```

```json theme={null}
{
  "threads": [
    {
      "thread_id": "thread-123",
      "agent_id": "019c0000-0000-7000-8000-000000000001",
      "current_run_id": "run-0001",
      "latest_run_id": "run-0001",
      "status": "SUCCEEDED",
      "run_count": 1
    }
  ]
}
```

`current_run_id` は continuation の権威値です。`latest_run_id` は最新作成 run の表示情報であり、
`baseRunId` には使わないでください。

```bash theme={null}
curl --request POST "$QAIP_BASE_URL/agent/runs" \
  --header "x-api-key: $QAIP_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: turn-0002" \
  --data '{
    "input": {
      "inputHistoryMode": "delta_v1",
      "agentId": "019c0000-0000-7000-8000-000000000001",
      "threadId": "thread-123",
      "baseRunId": "run-0001",
      "newUserMessage": {
        "id": "message-0002",
        "role": "user",
        "content": "前月との違いも説明してください"
      }
    }
  }'
```

別の request が先に thread を進めた場合は `409 THREAD_ADVANCED` になります。最新の thread 一覧を取得し、
利用者に競合を示してから再送してください。自動 merge や自動再送はしないでください。

## 失敗したrunを再試行する

現在の run が `FAILED` または `CANCELLED` の場合だけ sibling retry を作れます。`retryRunId` と
`baseRunId` に同じ current run ID を指定し、元 run と同じ `newUserMessage` を送ります。新しい
`Idempotency-Key` を使ってください。

```json theme={null}
{
  "input": {
    "inputHistoryMode": "delta_v1",
    "agentId": "019c0000-0000-7000-8000-000000000001",
    "threadId": "thread-123",
    "baseRunId": "run-failed",
    "retryRunId": "run-failed",
    "newUserMessage": {
      "id": "message-failed",
      "role": "user",
      "content": "前月との違いも説明してください"
    }
  }
}
```

## rolling contextの状態を確認する

Agent run response は次を返します。

* `input_history_mode`: `legacy_full` または `delta_v1`
* `context_start_run_id`: 再構築した文脈に含まれる最古の run。過去文脈が不要なら `null`
* `context_truncated`: モデルの context budget に合わせて古い run を除外した場合は `true`

`context_truncated=true` でも保存履歴は削除されません。モデルへ渡す文脈だけが短くなります。

## legacy\_fullと混在させない

既存 client は、`inputHistoryMode` を省略して full-history の `messages` と `state` を送る
`legacy_full` を引き続き利用できます。

* `legacy_full` に `baseRunId`、`retryRunId`、`newUserMessage`、`uiStateDelta` は指定できません。
* `delta_v1` に `state` または `parentRunId` は指定できません。`messages` を送る場合は空配列だけです。
* 異なる mode の field を混在させると `422` になります。

## Dashboard会話とは分離される

API キーで作成した thread の origin は `api_key` です。`GET /agent/threads` は同じ API key principal と
`api_key` origin の thread だけを返します。Dashboard で作成した会話は返さず、Dashboard の履歴画面にも
API key の会話は表示されません。Dashboard 専用の履歴検索、snapshot、rename、delete API は API キー向け
公開 API ではありません。

| HTTP  | error.type                 | 対応                          |
| ----- | -------------------------- | --------------------------- |
| `409` | `THREAD_ADVANCED`          | 最新の `current_run_id` を再取得する |
| `409` | `THREAD_ACTIVE`            | 現在の run が terminal になるまで待つ  |
| `409` | `RETRY_NOT_ALLOWED`        | retry対象と user message を確認する |
| `409` | `IDEMPOTENCY_CONFLICT`     | keyを別のrequestへ再利用しない        |
| `413` | `TURN_TOO_LARGE`           | 最新のuser turnを短くする           |
| `422` | `IDEMPOTENCY_KEY_REQUIRED` | 非空で一意なheaderを付ける            |
