验证 Webhook 请求来源,并可靠处理可能重复投递的事件。
Webhook 当前为 Beta 功能,接口、字段和行为可能在后续版本中调整。
HTTP 请求
事件发生后,Qoder Cloud Agents 会向 Endpoint URL 发送 HTTP POST 请求:
| Header | 说明 |
|---|---|
Webhook-ID | 事件 ID。相同事件重试时保持不变,可用作消费幂等键。 |
Webhook-Event-Type | 事件类型。 |
Webhook-Timestamp | 生成签名时的 Unix 秒时间戳。 |
Webhook-Signature | 请求签名,当前格式为 v1,<base64>。 |
2xx 表示处理成功。建议先完成验签并将事件写入自己的可靠队列,再快速返回响应。
事件结构
Forward 业务事件使用统一信封:
| 字段 | 类型 | 说明 |
|---|---|---|
type | string | 固定为 event。 |
id | string | Webhook 事件 ID,与 Webhook-ID 相同。 |
created_at | string | 事件发生时间,RFC 3339 格式。 |
data.type | string | 事件类型,与 Webhook-Event-Type 相同。 |
data.id | string | 发生事件的资源 ID;管理工具查询或失败事件为 stcall_* 调用记录 ID。 |
data.schema_version | integer | 事件数据版本,当前为 1。 |
Schedule 事件
以下四个 Schedule 事件的 data 均包含 source 和 source_session_id,语义见 Schedule 创建来源。Run 事件继承父 Schedule 的创建来源。
服务部署后新入队的事件始终返回这两个字段;历史事件及其重试可能缺失,客户端应兼容字段缺失。需要时可通过获取 Schedule或获取 Schedule Run查询来源。
forward.schedule.created
Schedule 创建成功时发送:
trigger_policy_type 和 next_trigger_at 仅在有对应值时返回。
forward.schedule.archived
Schedule 首次从未归档状态变为已归档时发送,data.status 固定为 archived。
覆盖以下归档途径:
- 调用归档 API,或在会话中调用
delete_forward_schedule工具。 - 批量归档,每个本次实际归档的 Schedule 分别发送一条事件。
- 一次性任务运行结束,以及触发计划因
stop_at不再有下一次运行时的自动归档。 - 清空 Identity 时的级联归档,以及依赖不可用触发的归档。仅暂停 Schedule 时不发送该事件。
| 字段 | 说明 |
|---|---|
schedule_id | 被归档的 Schedule ID,与 data.id 相同。 |
identity_id、template_id | Schedule 所属的 Identity 和 Template。 |
source、source_session_id | Schedule 的创建来源;不是本次归档操作的来源。通过 API 创建时为 api 和 null,通过工具创建时为 tool 和创建会话 ID。 |
status | 固定为 archived。查询 Schedule 对象时,仍应根据非空 archived_at 判断归档状态。 |
archived_at | 实际归档时间,RFC 3339 格式;外层 created_at 对应该时间。 |
Webhook-ID 去重。已归档的历史数据不会补发通知。
该事件表示 Schedule 已归档,不表示已有 Run 已结束,也不表示清空 Identity 的其他清理步骤全部完成。归档通知与创建、Run 结果通知不保证到达顺序;同步本地状态时,不要用迟到的创建通知把已归档任务恢复为生效状态。
这是独立的 Webhook 通知,不会新增 Session 中的归档事件。已有 Endpoint 需将 forward.schedule.archived 加入 events;订阅 * 的 Endpoint 会自动接收。
forward.schedule_run.succeeded
Schedule Run 成功完成时发送。data.status 为 completed。
forward.schedule_run.failed
Schedule Run 执行失败时发送。结构与成功事件相同,data.status 为 failed,并可能包含 error_type:
Schedule Run 输入版本
forward.schedule_run.succeeded 和 forward.schedule_run.failed 在执行输入版本已知时返回以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
data.initial_events_version | integer(可选) | 本次 Run 的当前执行尝试所选输入版本,与 Run 查询响应一致;未知时省略。 |
data.schema_version 独立。回调重投保留原事件的输入版本,后续修改 Schedule 不会改变已入队的回调;回调不额外携带完整 initial_events。历史事件或无法确认输入版本的 Run 回调可能缺失该字段,接收端应将其视为未知,不要用当前 Schedule 的版本补齐,也不要把缺失视为 0。完整的版本和 attempt 语义见 Schedule 输入版本。
Schedule Run 事件的业务结果应以对应的 Schedule Run 查询接口为准;Webhook 用于通知状态变化。
需要输入全文时,使用回调中的 data.run_id 调用获取 Schedule Run,并传 include_initial_events=true。响应只在本次尝试的输入已绑定且可确认时附带 initial_events;不要用当前 Schedule 的配置代替该次输入。
Schedule 管理工具结果
这些通知覆盖 Forward 内置 MCP 和旧 Custom Tool 路径的创建、查询、归档 Schedule 工具。它们表示一次管理操作的结果,与 Schedule Run 的执行成功或失败相互独立。
| 工具 | 成功事件 | 失败或需要输入的事件 |
|---|---|---|
create_forward_schedule | forward.schedule.created | forward.schedule.create_failed |
list_forward_schedules | forward.schedule.queried | forward.schedule.query_failed |
delete_forward_schedule | forward.schedule.archived | forward.schedule.archive_failed |
schedule_match_ambiguous,要求选择具体 Schedule ID,不会归档候选对象。
查询成功示例
归档需要选择对象的示例
结果字段与关联信息
| 字段 | 说明 |
|---|---|
data.id | stcall_* 调用记录 ID,与 data.tool_call.id 相同。 |
data.source | 固定为 tool。当前调用所在会话见 tool_call.session_id。 |
data.tool_call | 工具调用关联信息,包含 id、name、session_id。MCP 路径还包含 invocation_path=mcp 和可选的 turn_id;旧 Custom Tool 路径包含 source_event_id、tool_use_id 或 custom_tool_use_id,以及可选的 session_thread_id。仅返回来源实际提供的关联字段。 |
data.result | 仅查询成功时返回,包含 schedules、count、has_more、limit。Schedule 摘要只含 ID、名称、状态及触发策略摘要;next_trigger_at 有值时返回,不包含任务指令、完整执行配置或凭据。无匹配时 schedules=[]、count=0。 |
data.error | 失败或需要用户输入时返回,包含 code、category、message、requires_input。错误分类包括 invalid_request、forbidden、not_found、requires_input。 |
tool_call 和 schedule_version;MCP 路径的创建、归档成功仍沿用原有资源事件结构。资源事件的 source 和 source_session_id 继续表示 Schedule 的创建来源,tool_call 才表示本次管理调用。
这些结果通知已默认启用,Endpoint 仍需订阅相应的完整事件名;订阅 * 会接收新增事件,不支持 forward.schedule.* 等前缀通配符。可信调用来源无法确认、基础设施故障或提交结果不确定时,不保证产生业务失败通知。
同一已保存事件的投递重试沿用 Webhook-ID,接收端应据此去重。stcall_* 用于关联通知,不是上游工具调用的幂等键;独立 MCP 请求会独立执行,不能因结果不确定而自动重试创建或归档操作。不要依赖管理通知和 Run 通知的到达顺序。
Managed Agents 资源事件
Forward 也支持订阅 Session、Session Thread、Agent、Environment、Memory Store、Vault 和 Vault Credential 事件。完整事件名及触发时机见支持的公开事件。
这些事件使用相同的外层信封,但 data 仅携带资源引用,不包含 Schedule 事件的 schema_version、业务状态或结果正文。例如,会话进入空闲状态:
| 事件类别 | data.id | 额外字段 |
|---|---|---|
session.status_*、session.updated、session.deleted | Session ID | 无。 |
session.thread_* | 所属 Session ID | session_thread_id:具体线程 ID。 |
agent.* | Managed Agent ID | 无。 |
environment.* | Environment ID | 无。 |
memory_store.* | Memory Store ID | 无。 |
vault.* | Vault ID | 无。 |
vault_credential.* | Vault Credential ID | vault_id:所属 Vault ID。 |
* 仅用于归类,不是可填写到 events 的前缀通配符。收到通知后,可按资源 ID 查询当前详情;删除事件对应的资源可能已无法查询。session.status_idled 不等同于业务成功,应结合会话输出和状态判断。
webhook.test 不使用上述资源事件结构,测试载荷见发送测试事件。
签名校验
创建 Endpoint 时返回的 signing_secret 用于验证请求签名。签名内容由以下三部分组成:
Webhook-Timestamp与当前时间的偏差不超过 5 分钟。Webhook-Signature至少包含一个验签成功的v1签名。- 已处理过的
Webhook-ID不再重复执行有副作用的业务操作。
重试与幂等
Webhook 使用至少一次投递语义。网络失败、超时或接收端返回非 2xx 时,系统可能重试同一事件。
- 使用
Webhook-ID去重,不要使用请求到达时间生成幂等键。 - 同一个
Webhook-ID的重复请求应返回成功,且不得重复执行副作用。 - 处理失败时返回非
2xx;处理成功或已处理过时返回2xx。

