# 服務對話

<Badge type="warning" text="尚未發布" />

背景任務可以把一批檔案交給一個 AI 對話，由它讀取這些檔案，並用 Extension 宣告的工具採取行動。這個對話會像其他對話一樣顯示在 Cowork 裡，使用者可以跟著看。

## dozin.agent

| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
| `brief` | `string` | 是 | 套件裡的一個 `.md` 檔案：對話的指示 |
| `model` | `{ id, effort? }` | 否 | 要使用的模型；`effort` 為 `max`、`xhigh`、`high`、`medium` 或 `low` |
| `tools` | `string[]` | 否 | 對話可以使用的業務工具，最多 8 個。Cowork 目前還沒有可提供的工具，所以先不要填 |
| `secret` | `string` | 否 | 這些工具使用的 `dozin.secrets` 中的一個 `env` |

## ctx.agent.handoff(input) <Badge type="warning" text="尚未發布" />

| 名稱 | 類型 | 必填 | 說明 |
|---|---|---|---|
| `input.title` | `string` | 是 | 對話標題；超過 120 個字元的部分會被截掉 |
| `input.files` | `string[]` | 是 | `dataDir` 內的 1–50 個檔案，相對或絕對路徑 |
| `input.summary` | `string` | 否 | 這批內容是什麼；超過 4000 個字元的部分會被截掉 |

### 回傳值

`Promise<HandoffResult>`，在對話結束時解析。

| 欄位 | 類型 | 說明 |
|---|---|---|
| `status` | `'completed' \| 'failed' \| 'stopped' \| 'timeout' \| 'cancelled' \| 'model_unavailable'` | 結束的方式 |
| `submitted` | `number` | 對話提交的項目數。目前在 Cowork 裡永遠是 `0`：它沒有可用來提交的業務工具 |
| `failed` | `number` | 失敗的項目數。目前在 Cowork 裡永遠是 `0` |
| `sessionId` | `string` | 開啟了對話時，該對話的 id |
| `error` | `string` | 出了什麼錯 |

### 錯誤

promise 會以一個錯誤拒絕，其 `code` 為：

| `code` | 意思 |
|---|---|
| `AGENT_NOT_DECLARED` | `package.json` 裡沒有 `dozin.agent` |
| `BAD_REQUEST` | 缺少 `title`，或 `files` 為空或超過 50 個 |
| `FILE_NOT_FOUND` | 有檔案不存在、是資料夾，或資料資料夾不存在 |
| `FILE_OUTSIDE_DATA` | 有檔案在 `dataDir` 之外，或是連結 |
| `AGENT_BUSY` | 已有一個對話在執行，且已有一個在等待 |
| `NOT_AVAILABLE` | 這個 Cowork 裡無法使用服務對話 |
| `RUN_ENDED` | 發出這次呼叫的那次執行已經結束 |

每個任務同一時間只執行一個對話，另外最多一個可以等待；其餘的會被拒絕。

## 示例

```js
await ctx.writeJson('batches/0001.json', changedPatients);
const result = await ctx.agent.handoff({ title: 'Patients changed', files: ['batches/0001.json'], summary: '3 patients' });
ctx.status(`Handoff ${result.status}`);
```

## 相關

- [背景任務](https://docs.micromeet.ai/zh-tw/extension-sdk/service.md): `ctx.agent` 從哪裡來
