# HTTP 与事件契约 ## 1. 通用请求头 | 字段 | 方向 | 规则 | | --- | --- | --- | | `Authorization` | request | `Bearer `;只经 TLS | | `traceparent` | both | W3C Trace Context;服务边界传播并生成新 span | | `tracestate` | both | 可选;不得包含 PII、密钥或业务正文 | | `baggage` | both | 可选;仅传播登记的低敏、低基数键,不参与授权 | | `Hunjing-Request-ID` | both | 调用方可提供;服务端缺失时生成;最多 64 个 `[A-Za-z0-9_-]` | | `Idempotency-Key` | request | 创建 Run 和副作用操作使用;opaque,作用域和 TTL 由端点定义 | | `request-id` / `x-request-id` | upstream response | 保存供应商原始 request ID,不用本地值覆盖 | `Hunjing-Request-ID` 用于业务请求关联,不能替代 `traceparent` 的父子调用链。字段名大小写不敏感;文档使用固定大小写。新私有字段不使用 `X-` 前缀。 所有自定义字段为单值字段。重复字段、逗号列表、控制字符、空值或超长值返回 `400 invalid_request`,防止代理合并改变语义。 ## 2. Header 转发 ### Client → API 只读取本契约列出的字段。未知 `Hunjing-*` 字段忽略或拒绝,不自动进入插件上下文。 ### API → Provider 仅允许 Adapter 白名单:供应商鉴权、版本、beta、content type、trace 和明确业务所需字段。禁止转发: - 用户 `Authorization`; - `Cookie`; - `Hunjing-Diagnostic-Token`; - 任意用户提交的供应商 API Key Header; - Hop-by-hop fields; - 未登记实验字段。 BYOK 密钥由服务端 Secret Store 注入。 ## 3. 错误响应 ```json { "error": { "code": "permission_denied", "message": "无权执行该操作。", "trace_id": "trace_01...", "details": {} } } ``` 稳定 `code`: | Code | HTTP | | --- | ---: | | `invalid_request` | 400 | | `authentication_required` | 401 | | `permission_denied` | 403 | | `not_found` | 404 | | `conflict` | 409 | | `payload_too_large` | 413 | | `validation_failed` | 422 | | `rate_limited` | 429 | | `provider_error` | 502 | | `provider_unavailable` | 503 | | `provider_timeout` | 504 | | `internal_error` | 500 | 错误消息不得含密钥、完整 Prompt、工具敏感参数或 Provider 原始正文。 ## 4. SSE 事件 envelope: ```json { "id": "event_01...", "type": "content.block.delta", "run_id": "run_01...", "turn_id": "turn_01...", "sequence": 12, "created_at": "2026-09-02T08:00:00Z", "data": {} } ``` - `sequence` 在 Run 内单调递增。 - Block delta 为临时传输;`content.block.completed` 提供 Block 权威快照,`message.completed` 指向持久化 Message。 - HTTP 200 后仍可能发送 `error` 事件。 - 在首个用户可见 delta 发出前,Runtime 可按路由策略重试或故障转移;发出后不得切换上游重新生成另一条内容,只能继续当前流或明确失败。 - 重连使用 `Last-Event-ID`;若服务端无法重放,则客户端先拉取 Run 当前状态再继续流。 - 心跳不写业务数据库。 ## 5. 稳定事件名 ```text run.queued run.started run.waiting_approval run.completed run.failed run.cancelled turn.started turn.completed model.request.started model.request.completed model.request.failed model.cache.observed message.started content.block.started content.block.delta content.block.progress content.block.completed content.block.failed content.block.cancelled message.completed tool.call.requested tool.call.approval_required tool.call.started tool.call.completed tool.call.failed memory.candidate.created memory.candidate.approved memory.candidate.rejected memory.created memory.updated memory.archived memory.deleted plugin.submitted plugin.published plugin.installed plugin.activated plugin.suspended plugin.deactivated plugin.removed media.job.started media.job.completed media.job.failed device.grant.created device.grant.revoked community.content.published community.content.limited community.content.removed moderation.case.created moderation.case.decided workspace.member.added workspace.member.removed release.published listing.published order.created order.paid order.cancelled payment.succeeded payment.failed refund.succeeded dispute.opened entitlement.granted entitlement.revoked ledger.entry.posted settlement.created settlement.paid settlement.failed ``` 事件 payload 只引用敏感对象 ID 和脱敏摘要;原文通过受保护资源 API 读取。支付和 Ledger 事件只能由交易内核产生,插件不能伪造或覆盖。 ## 6. 幂等 - `POST /runs` 接受 `Idempotency-Key`,相同用户、端点和规范化请求体重复提交返回同一 Run。 - ToolCall 的幂等键由 Run、Tool definition、规范化参数和显式业务对象组成。 - 不缓存认证失败、审批拒绝和未知执行结果。