跳转至

OpenResponses API

Gateway 可以提供 OpenResponses 兼容的 POST /v1/responses 端点。它默认禁用,并与 Gateway 共享端口(WS + HTTP 复用):http://<gateway-host>:<port>/v1/responses。

请求作为普通的 Gateway 代理运行执行(与 openclaw agent 相同代码路径),因此路由、权限和配置与你的 Gateway 一致。

使用 gateway.http.endpoints.responses.enabled 启用或禁用。启用后,同一兼容接口还提供 GET /v1/models、GET /v1/models/{id} 和 POST /v1/embeddings。

POST /v1/chat/completions 通过 gateway.http.endpoints.chatCompletions.enabled 单独启用。参见 OpenAI Chat Completions。

身份验证、安全性和路由

运行行为与 OpenAI Chat Completions 一致:

  • 身份验证路径与 gateway.auth.mode 匹配:共享密钥(token/password)使用 Authorization: Bearer <token-or-password>;可信代理使用身份感知代理头(同主机回环代理需要 gateway.auth.trustedProxy.allowLoopback = true,当不存在 Forwarded/X-Forwarded-*/X-Real-IP 头时,通过 gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD 进行同主机直连回退);私有入口上的 none 无需身份验证头。参见 可信代理身份验证。
  • 将该端点视为对 gateway 实例的完整操作员访问权限。
  • 共享密钥身份验证模式会忽略更窄的 Bearer 声明的 x-openclaw-scopes,并恢复完整的默认操作员范围集:operator.admin、operator.approvals、operator.pairing、operator.read、operator.talk.secrets、operator.write。此端点上的聊天轮次被视为所有者发送者轮次。
  • 可信身份承载 HTTP 模式(可信代理,或 gateway.auth.mode="none")在存在 x-openclaw-scopes 时遵循它,否则回退到操作员默认范围集。只有当调用方显式缩小范围并省略 operator.admin 时,所有者语义才会丢失。
  • 使用 model: "openclaw"、"openclaw/default"、"openclaw/<agentId>" 或 x-openclaw-agent-id 头选择代理。
  • 使用 x-openclaw-model 覆盖所选代理的后端模型(在身份承载身份验证路径上需要 operator.admin)。
  • 使用 x-openclaw-session-key 进行显式会话路由(如果使用保留命名空间:subagent:、cron:、acp:,则会被拒绝并返回 400 invalid_request_error)。
  • 使用 x-openclaw-message-channel 指定非默认的合成入口通道上下文。

有关代理目标模型、openclaw/default、嵌入直通和后端模型覆盖的权威说明,参见 OpenAI Chat Completions。

参见 操作员范围 和 安全性。

会话行为

默认情况下,该端点每个请求无状态(每次调用都会生成新的会话密钥)。

如果请求包含 OpenResponses user 字符串,Gateway 会从中派生稳定的会话密钥,以便重复调用可以共享代理会话。

当请求保持在同一代理/用户/请求会话范围内(通过身份验证主体、代理 ID 和 x-openclaw-session-key 匹配)时,previous_response_id 会复用先前响应的会话。

延续映射会在 Gateway 重启后保留于共享状态数据库的核心键控存储中(core:openresponses,命名空间 response-sessions),最长保留 30 天,并以 Gateway 范围内最新的 5,000 个响应为上限。这与默认会话维护时长和数量一致;它不会延长底层会话或转录的生命周期。映射仅包含响应/会话标识符、身份验证主体(基于安装密钥的 bearer HMAC 或已验证的代理身份)、代理和请求会话范围,以及存储管理的时间戳。不会复制响应内容,也无需单独的表或架构迁移。键控存储会在查找时立即拒绝过期映射,并在后续写入时以及通过共享插件状态维护扫描移除过期行;该扫描每分钟以有界批次运行一次。如果延续持久化在原本成功的运行之后失败,端点会返回 HTTP 500 或流式 response.failed,而不是报告一个其响应 ID 无法继续的成功。

未知、过期、被逐出或超出范围的 previous_response_id 会返回相同的 HTTP 400 和 invalid_request_error,包括 stream: true 时。要恢复,请重新发送完整的输入历史并省略 previous_response_id;Gateway 绝不会为未解决的延续静默开始新对话。在此存储更改之前发出的响应在旧 Gateway 退出后无法恢复。

隐身响应从不创建延续映射。在隐身会话存活期间,使用相同的 x-openclaw-session-key 显式继续它们;使用其响应 ID 会返回与未知 ID 相同的 400。

显式隐身会话延续

使用 x-openclaw-session-key(sessionKey 覆盖)显式选择或继续隐身对话需要有效的 operator.admin 权限。此规则遵循权限,而非入口:它拒绝没有所有者/管理员权限的可信代理调用方,以及显式将 x-openclaw-scopes 缩小到管理员以下(例如缩小到 operator.write)的私有 gateway.auth.mode="none" 调用方。两者都会收到带有 forbidden 错误的 HTTP 403。在此路径上,无资料的私有无身份验证调用方会收到 missing scope: operator.admin;对于有资料的调用方,响应会以这种错误格式隐藏私有目标(其中 <sessionKey> 是请求的覆盖值):

{
  "error": {
    "message": "Incognito session \"<sessionKey>\" was not found.",
    "type": "forbidden"
  }
}

所有者/管理员调用方保留显式隐身会话延续。没有 x-openclaw-scopes 的私有无身份验证请求会收到默认操作员范围,包括 operator.admin,因此被视为所有者/管理员。保留的内部命名空间覆盖(subagent:、cron:、acp:)仍然是单独的验证失败,并仍返回带有 invalid_request_error 的 HTTP 400。

请求形状

字段 支持
input 字符串或条目对象数组。
instructions 合并到系统提示中。
tools 客户端工具定义(函数工具)。
tool_choice "auto"、"none"、"required" 或 { "type": "function", "name": "..." },用于筛选或要求客户端工具。
stream 启用 SSE 流式传输。
max_output_tokens 尽力而为的输出限制(取决于提供商)。
temperature 尽力而为的采样温度。基于 ChatGPT 的 Codex Responses 后端会忽略该值,其使用固定的服务端采样。
top_p 尽力而为的核采样。与 temperature 相同的 Codex Responses 注意事项。
user 稳定的会话路由。
previous_response_id 会话连续性(见上文)。
max_tool_calls、reasoning、metadata、store、truncation 接受但当前忽略。

条目(输入)

message

角色:system、developer、user、assistant。

  • system 和 developer 会追加到系统提示中。
  • 最近的 user 或 function_call_output 条目会成为“当前消息”。
  • 较早的用户/助手消息会作为历史上下文包含在内。

function_call_output(基于轮次的工具)

将工具结果发回模型:

{
  "type": "function_call_output",
  "call_id": "call_123",
  "output": "{\"temperature\": \"72F\"}"
}

reasoning 和 item_reference

为保持模式兼容性而接受,但在构建提示时忽略。

工具(客户端函数工具)

通过 tools: [{ type: "function", name, description?, parameters? }] 提供工具。

如果代理调用工具,响应会返回一个 function_call 输出条目。发送带有 function_call_output 的后续请求以继续该轮次。

如果工具未产生文本,请返回带有其 call_id 的 output: ""。空结果仍会完成该工具调用,并且可以是续传中唯一的新输入条目。

自行管理历史的客户端可以将 response.output 追加到 input,然后追加新的用户消息或 function_call_output 条目。保持返回的助手元数据以及函数调用 ID、名称和参数不变。或者,提供 previous_response_id 以及仅新的输入条目。

对于 tool_choice: "required" 和固定函数的 tool_choice,该端点会缩小暴露的客户端函数工具集,指示运行时在响应前调用客户端工具,并且如果未包含匹配的客户端工具结构化调用,则拒绝该轮次,这与 /v1/chat/completions 契约一致。非流式请求返回带有 api_error 的 502;流式请求发出 response.failed 事件。

图像(input_image)

支持 base64 或 URL 来源:

{
  "type": "input_image",
  "source": { "type": "url", "url": "https://example.com/image.png" }
}

允许的 MIME 类型(默认):image/jpeg、image/png、image/gif、image/webp、image/heic、image/heif。最大大小(默认):10MB。

文件(input_file)

支持 base64 或 URL 来源:

{
  "type": "input_file",
  "source": {
    "type": "base64",
    "media_type": "text/plain",
    "data": "SGVsbG8gV29ybGQh",
    "filename": "hello.txt"
  }
}

允许的 MIME 类型(默认):text/plain、text/markdown、text/html、text/csv、application/json、application/pdf。最大大小(默认):5MB。

当前行为:

  • 从其他未指定类型的字节推断出的文本会保留其检测到的编码,包括 UTF-16 和 Windows-1252。声明的文本字符集仍受支持。
  • 文件内容会被解码并添加到系统提示中,而不是用户消息中,因此它是临时的(不会持久化到会话历史中)。
  • 解码后的文件文本在添加前会被包装为不受信任的外部内容,因此文件字节被视为数据,而不是受信任的指令。注入的块使用显式边界标记(<<<EXTERNAL_UNTRUSTED_CONTENT id="...">>> / <<<END_EXTERNAL_UNTRUSTED_CONTENT id="...">>>)和一行 Source: External 元数据。它有意省略单行数据边界说明,以保留提示预算;边界标记和元数据仍然适用。
  • PDF 会先解析文本。如果找到的文本很少,则会将前几页栅格化为图像并传递给模型,注入的文件块使用占位符 [PDF content rendered to images]。
  • 当页面、文本或图像限制导致提取不完整时,注入的文件块会在不受信任的文件内容边界之外以有界的 [Partial document: ...] 标记开头。

PDF 解析由捆绑的 document-extract 插件提供,该插件使用 clawpdf 及其打包的 PDFium WebAssembly 运行时进行文本提取和页面渲染。

URL 获取默认值:

  • files.allowUrl: true
  • images.allowUrl: true
  • maxUrlParts: 8(每个请求中基于 URL 的 input_file + input_image 部分总数)
  • 请求受到防护(DNS 解析、私有 IP 阻止、重定向上限、超时)。
  • 每种输入类型都支持可选的主机名允许列表(files.urlAllowlist、images.urlAllowlist):精确主机("cdn.example.com")或通配符子域名("*.assets.example.com",不匹配根域)。空允许列表或省略允许列表表示没有主机名允许列表限制。
  • 若要完全禁用基于 URL 的获取,请设置 files.allowUrl: false 和/或 images.allowUrl: false。

文件 + 图像限制

该端点使用内置的 20 MB 请求体限制。文件和图像源策略仍可在 gateway.http.endpoints.responses 下配置:

{
  gateway: {
    http: {
      endpoints: {
        responses: {
          enabled: true,
          maxUrlParts: 8,
          files: {
            allowUrl: true,
            urlAllowlist: ["cdn.example.com", "*.assets.example.com"],
            allowedMimes: [
              "text/plain",
              "text/markdown",
              "text/html",
              "text/csv",
              "application/json",
              "application/pdf",
            ],
            maxBytes: 5242880,
            maxChars: 60000,
            maxRedirects: 3,
            timeoutMs: 10000,
            pdf: {
              maxPages: 4,
              maxPixels: 4000000,
              minTextChars: 200,
            },
          },
          images: {
            allowUrl: true,
            urlAllowlist: ["images.example.com"],
            allowedMimes: [
              "image/jpeg",
              "image/png",
              "image/gif",
              "image/webp",
              "image/heic",
              "image/heif",
            ],
            maxBytes: 10485760,
            maxRedirects: 3,
            timeoutMs: 10000,
          },
        },
      },
    },
  },
}

省略时的默认值:

键 默认值
maxUrlParts 8
files.maxBytes 5MB
files.maxChars 60k
files.maxRedirects 3
files.timeoutMs 10s
files.pdf.maxPages 4
files.pdf.maxPixels 4,000,000
files.pdf.minTextChars 200
images.maxBytes 10MB
images.maxRedirects 3
images.timeoutMs 10s

HEIC/HEIF input_image 源在通过共享的 OpenClaw 图像处理器(Rastermill)交付给提供商之前会被规范化为 JPEG;对于需要外部编解码器支持的格式,它会回退到系统转换器(sips、ImageMagick、GraphicsMagick 或 ffmpeg)。

安全说明:URL 允许列表在获取前以及重定向跳转时强制执行。将主机名加入允许列表不会绕过私有/内部 IP 阻止。对于面向互联网的网关,除应用层防护外,还应应用网络出口控制。参见 安全。

流式传输(SSE)

流式传输会保留来自不同助手消息的重复内容。如果更正无法通过追加到已发送文本来表示,流会发出 response.failed,而不是以不一致的内容完成。

设置 stream: true 以接收 Server-Sent Events:

  • Content-Type: text/event-stream
  • 每个事件行为 event: <type> 和 data: <json>
  • 流以 data: [DONE] 结束

当前发出的事件类型:response.created、response.in_progress、response.output_item.added、response.content_part.added、response.output_text.delta、response.output_text.done、response.content_part.done、response.output_item.done、response.completed、response.incomplete(在输出预算截断时)、response.failed(在错误时)。

失败的 agent 运行(包括整个 agent 超时)会返回失败响应。流式失败会发出 response.failed,随后是 [DONE];部分内容可能已经到达客户端。超时设置遵循 代理循环。

由于 agent 达到其输出 token 预算而结束的回复会以 status: "incomplete" 和 incomplete_details: { "reason": "max_output_tokens" } 返回,并且其最终消息项带有 status: "incomplete"。流式传输会在终止的 response.incomplete 事件上发出这些字段,因此按事件类型分发的客户端也能观察到截断。这与 /v1/chat/completions 上的 finish_reason: "length" 投影一致。

断开 HTTP 客户端会取消正在进行的源 URL 下载和 agent 运行。如果取消发生在准备输入期间,Gateway 会释放该下载,并且不会启动另一个输入下载或 agent 运行。这适用于流式和非流式请求。

用量

当底层提供商报告 token 计数时,会填充 usage。OpenClaw 会在这些计数器到达下游状态/会话界面之前,规范化常见的 OpenAI 风格别名,包括 input_tokens / output_tokens 和 prompt_tokens / completion_tokens。

错误

错误使用如下 JSON 对象:

{ "error": { "message": "...", "type": "invalid_request_error" } }

常见情况:400 无效请求体、401 缺少/无效认证、403 缺少操作员范围、405 方法错误、429 认证失败次数过多(带有 Retry-After)。

示例

非流式:

curl -sS http://127.0.0.1:18789/v1/responses \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'x-openclaw-agent-id: main' \
  -d '{
    "model": "openclaw",
    "input": "hi"
  }'

流式:

curl -N http://127.0.0.1:18789/v1/responses \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'x-openclaw-agent-id: main' \
  -d '{
    "model": "openclaw",
    "stream": true,
    "input": "hi"
  }'

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw