# 服务对话

<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>`，在对话结束时 resolve。

| 字段 | 类型 | 说明 |
|---|---|---|
| `status` | `'completed' \| 'failed' \| 'stopped' \| 'timeout' \| 'cancelled' \| 'model_unavailable'` | 结束方式 |
| `submitted` | `number` | 对话提交的条目数。目前在 Cowork 里始终为 `0`：它没有用来提交的业务工具 |
| `failed` | `number` | 失败的条目数。目前在 Cowork 里始终为 `0` |
| `sessionId` | `string` | 打开了对话时，该对话的 id |
| `error` | `string` | 出了什么问题 |

### 错误

promise 以一个错误 reject，其 `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/extension-sdk/service.md): `ctx.agent` 从哪里来
