#Agent v2 API(Threads / Turns)
新一代 codex 风格 Agent 执行引擎的 HTTP 接口。以 Thread(会话线程)→ Turn(一次执行)→ Item(原子事件) 三级模型组织对话,统一 SSE 事件流贯穿引擎、SDK 与前端。
基础路径: /v2
相较 v1 Chat API 的核心增强:
- 采样循环引擎:不限固定轮数,模型持续调用工具直至任务完成(needs_follow_up 驱动)
- 并行工具执行:只读工具并发、写类工具串行(读写锁语义)
- 运行中干预:steer(追加输入)、interrupt(中断)、审批、用户输入均可在 turn 执行中进行
- 上下文自动压缩:token 超预算时 pre-turn / mid-turn 自动摘要压缩
- 沙箱与安全:exec_command / apply_patch 在沙箱内执行,approval × sandbox 二维策略 + 危险命令规则引擎
- 可恢复:thread 全量持久化,支持 resume / fork / rollback
#认证
X-Organization-Id(必填):组织 ID,缺失时返回 404Tenant context missingX-API-Key或Authorization: Bearer <token>:身份凭证(见认证)X-Project-Id/X-User-Id(可选):项目 / 用户上下文
#创建 Thread
POST /v2/threads
#请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
agentId | string | 是 | 绑定的 Agent ID |
title | string | 否 | 线程标题,默认 New Thread |
#响应
json{
"id": "thr_abc123",
"agentId": "agent_abc123",
"title": "New Thread",
"status": "active"
}
#列出 Threads
GET /v2/threads?agentId=agent_abc123
| 查询参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
agentId | string | 否 | 按 Agent 筛选 |
返回最近 100 条活跃线程(按更新时间倒序):
json[
{ "id": "thr_abc123", "agentId": "agent_abc123", "title": "New Thread", "updatedAt": "2026-07-04T12:00:00.000Z" }
]
#读取 Thread(Resume)
GET /v2/threads/:id
返回线程与全部 Item(按 seq 排序),用于恢复/渲染完整历史:
json{
"id": "thr_abc123",
"agentId": "agent_abc123",
"title": "New Thread",
"status": "active",
"tokenUsage": { "inputTokens": 1200, "outputTokens": 480, "totalTokens": 1680 },
"items": [
{ "id": "item_1", "seq": 0, "type": "user_message", "status": "completed", "payload": { "content": [{ "type": "text", "text": "你好" }] } },
{ "id": "item_2", "seq": 1, "type": "agent_message", "status": "completed", "payload": { "content": "你好!有什么可以帮你?" } }
]
}
#Item 类型
| type | 说明 |
|---|---|
user_message | 用户输入(含 steer 追加) |
agent_message | 模型回复文本 |
reasoning | 推理过程(o 系 / DeepSeek 等支持 reasoning 的模型) |
tool_call | 工具调用(通用) |
command_execution | 沙箱命令执行(exec_command) |
file_edit | 文件修改(apply_patch / turn 末统一 diff) |
web_search | 联网搜索 |
plan | 执行计划(update_plan) |
error | 错误 |
#运行 Turn(SSE 流式)
POST /v2/threads/:id/turns
Content-Type: application/json
Accept: text/event-stream
#请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | string 或 MessageContentPart[] | 是 | 纯文本,或多模态分段(如 [{"type":"text","text":"..."},{"type":"image_url","imageUrl":{"url":"..."}}]) |
bashcurl -N -X POST "https://your-domain.com/v2/threads/thr_abc123/turns" \
-H "X-API-Key: sk_your_api_key_here" \
-H "X-Organization-Id: org_abc123" \
-H "Content-Type: application/json" \
-d '{"input": "查一下今天的新闻并总结"}'
#SSE 事件流(AgentEvent)
每行 data: 是一个 JSON 序列化的 AgentEvent,流末尾发送 data: [DONE]。
| kind | 载荷 | 说明 |
|---|---|---|
turn.started | threadId, turnId | Turn 开始 |
item.started | item | 新 Item 开始(如工具调用发起) |
item.updated | itemId, turnId, delta | Item 增量更新(文本流式、工具参数流式、命令输出) |
item.completed | item | Item 完成(含最终 payload) |
token.count | turnId, usage | 每次采样后的累计 token 用量 |
context.compacted | turnId, phase(pre_turn/mid_turn/manual), freedTokens | 上下文压缩发生 |
approval.requested | requestId, turnId, toolCallId, toolName, arguments, risk | 写类/危险操作等待审批 |
user_input.requested | requestId, turnId, prompt | 模型向用户提问(request_user_input) |
plan.updated | turnId, steps[{step,status}] | 执行计划发布/更新 |
turn.diff | turnId, diff | 本 turn 全部文件变更的统一 diff |
sub_agent.activity | turnId, childThreadId, status, summary? | 子代理(spawn_agent)生命周期 |
turn.completed | threadId, turnId, usage | Turn 成功结束(含总用量;计费在此时点记录) |
turn.failed | threadId, turnId, error | Turn 失败 |
turn.interrupted | threadId, turnId | Turn 被中断 |
客户端断开连接会自动中断正在运行的 turn。
#事件归约建议
前端只需按 item.{started,updated,completed} 三段式归约渲染(delta 字段做增量合并),turn/thread 生命周期事件用于状态机控制——与 codex SDK 契约一致。
#运行中干预
#追加输入(Steer)
向正在运行的 turn 追加用户输入(mailbox 机制,模型在下一次采样前消费):
POST /v2/turns/:id/steer
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | string 或 MessageContentPart[] | 是 | 追加的输入 |
响应 { "ok": true };turn 不存在或已结束返回 404。
#中断(Interrupt)
POST /v2/turns/:id/interrupt
取消令牌贯穿引擎与所有执行中的工具。响应 { "ok": true }。
#审批决议
收到 approval.requested 事件后,调用:
POST /v2/approvals/:requestId
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
approved | boolean | 是 | 允许 / 拒绝 |
同类审批(相同命令 + 目录 + 权限)在会话内缓存,不会重复询问。
#回答用户输入请求
收到 user_input.requested 事件后,调用:
POST /v2/user-input/:requestId
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
value | string | 是 | 用户的回答 |
#Fork / Rollback
#Fork(分叉线程)
复制全部历史到新线程(记录 forkedFromId),原线程不受影响:
POST /v2/threads/:id/fork
json{ "id": "thr_new456", "forkedFromId": "thr_abc123", "title": "New Thread (fork)" }
#Rollback(回滚)
删除线程尾部 N 个 turn 及其 Item:
POST /v2/threads/:id/rollback
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
turns | number | 否 | 回滚的 turn 数,默认 1 |
json{ "removed": 1 }
#Agent 行为配置(settings)
以下 Agent settings 字段控制 v2 引擎行为:
| 字段 | 值 | 默认 | 说明 |
|---|---|---|---|
sandboxMode | read_only / workspace_write / full_access | workspace_write | 沙箱写权限 |
approvalPolicy | untrusted / on_request / never | on_request | 审批策略(与 sandboxMode 正交组合) |
toolTimeoutMs | number | 30000 | 单个工具执行超时 |
toolRetryAttempts | number | 2 | 工具失败重试次数(指数退避) |
toolMaxOutputTokens | number | 10000 | 工具输出 head-tail 截断上限 |
hooks | HookConfig[] | [] | 生命周期钩子(SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / PreCompact / Stop) |
#计费
v2 引擎完整接入计量计费:turn 开始前校验组织用量限额(超限返回错误),turn.completed 时按模型费率记录用量与成本。用量查询接口与 v1 相同(见 Billing / Usage)。
#TypeScript SDK
服务端配套 SDK(sdk-v2/)封装了全部 v2 能力:
typescriptimport { Creatoria } from '@creatoria/sdk-v2';
const client = new Creatoria({
baseUrl: 'https://your-domain.com',
organizationId: 'org_abc123',
apiKey: 'sk_your_api_key_here',
});
const thread = await client.startThread('agent_abc123');
// 缓冲运行:等待完成并返回最终结果
const result = await thread.run('帮我调研这个课题');
// 流式运行:Item 三段式事件
let turnId = '';
for await (const event of thread.runStreamed('继续深入第二点')) {
if (event.kind === 'turn.started') turnId = event.turnId;
if (event.kind === 'item.completed') console.log(event.item);
}
// 干预与线程管理
await thread.steer('补充:只看中文来源', turnId);
await thread.interrupt(turnId);
await client.resolveApproval('req_id', true);
await client.resolveUserInput('req_id', '我的回答');
const forked = await thread.fork();
await thread.rollback(1);
const resumed = client.resumeThread(thread.id);
#与 v1 Chat API 的关系
- v1
/agent/chat、/agent/chat/stream、/agentic/run仍可用,但已标记Deprecation响应头;设置AGENTIC_LEGACY_DISABLED=true后返回410 Gone并指向 v2。 - 历史会话可通过迁移脚本(
npm run migrate:legacy-v2)转换为 v2 Thread/Item。 - 新集成一律使用 v2 接口。