OpenAI 聊天补全
Gateway 可以提供一个兼容 OpenAI 的小型 Chat Completions 接口。它默认处于禁用状态。
启用后,它会在与 Gateway 相同的端口(WS + HTTP 多路复用)上提供以下所有接口:
| 方法 | 路径 |
|---|---|
| POST | /v1/chat/completions |
| GET | /v1/models |
| GET | /v1/models/{id} |
| POST | /v1/embeddings |
POST /v1/responses 通过 gateway.http.endpoints.responses.enabled 单独启用。参见 OpenResponses API。
请求以普通 Gateway agent 运行方式执行(与 openclaw agent 相同的代码路径),因此路由、权限和配置都与你的 Gateway 匹配。
启用该端点¶
将 enabled 设为 false(或省略该字段)即可禁用。
安全边界(重要)¶
请将此端点视为对 Gateway 实例的完整 operator 访问权限:
- 此端点的有效 Gateway token/password 等同于 owner/operator 凭证,而不是狭窄的单用户作用域。
- 请求会与受信任的 operator 操作走相同的控制平面 agent 路径,因此,如果目标 agent 的策略允许使用敏感工具,此端点也可以使用它们。
- 请仅将其保留在 loopback/tailnet/私有入口。不要将其暴露到公共互联网。
认证矩阵:
| 认证路径 | 行为 |
|---|---|
gateway.auth.mode="token" 或 "password" + Authorization: Bearer ... |
证明调用方拥有共享的 Gateway 机密。忽略任何 x-openclaw-scopes 请求头,并恢复完整的默认 operator 作用域集合:operator.admin、operator.approvals、operator.pairing、operator.read、operator.talk.secrets、operator.write。将聊天轮次视为由 owner 作为发送者发起的轮次。 |
携带可信身份的 HTTP(trusted-proxy 认证,或在私有入口上使用 gateway.auth.mode="none") |
当存在 x-openclaw-scopes 时遵循其中定义的作用域;不存在时回退到默认的 operator 作用域集合。仅当调用方显式收窄作用域并省略 operator.admin 时,才会失去 owner 语义。对于 x-openclaw-model 等 owner 级控制,需要 operator.admin。 |
参见 Operator scopes、Security 和 Remote access。
认证¶
使用 Gateway 的认证配置(该模式的详细信息参见 Trusted proxy auth):
| 模式 | 认证方式 |
|---|---|
gateway.auth.mode="token" |
Authorization: Bearer <token>。通过 gateway.auth.token 或 OPENCLAW_GATEWAY_TOKEN 设置。 |
gateway.auth.mode="password" |
Authorization: Bearer <password>。通过 gateway.auth.password 或 OPENCLAW_GATEWAY_PASSWORD 设置。 |
gateway.auth.mode="trusted-proxy" |
通过所配置的身份感知代理进行路由;该代理会注入所需的身份请求头。同主机上的 loopback 代理需要显式设置 gateway.auth.trustedProxy.allowLoopback = true。 |
gateway.auth.mode="none" |
无需认证请求头(仅限私有入口)。 |
注意:
- 在
trusted-proxy网关上绕过代理的同主机调用方,可以直接回退到gateway.auth.password/OPENCLAW_GATEWAY_PASSWORD。只要存在Forwarded、X-Forwarded-*或X-Real-IP请求头,请求就会保持在 trusted-proxy 路径上,而不是回退。 - 如果配置了
gateway.auth.rateLimit,且认证失败次数过多,该端点将返回429,并附带Retry-After请求头。
何时使用此端点¶
- 当你的集成只是同一 Gateway 的另一个 operator/client 界面时,请优先使用此端点,而不是添加新的内置 channel。
- 对于直接连接到远程 Gateway 的原生移动客户端,请优先使用 WebChat 或采用 paired-device bootstrap/device-token 流程的 Gateway Protocol,这样设备就不需要共享的 HTTP token/password。
- 在集成拥有自己的用户、房间、webhook 投递或出站传输的外部消息网络时,应改为构建 channel 插件。参见 Building plugins。
以 Agent 为先的模型契约¶
OpenClaw 将 OpenAI 的 model 字段视为 agent 目标,而不是原始的 provider 模型 ID。
model 值 |
路由到 |
|---|---|
model 值 |
路由到 |
|---|---|
openclaw |
已配置的默认代理 |
openclaw/default |
已配置的默认代理(稳定别名;即使真实默认代理 ID 在不同环境之间变化,也可以安全地硬编码) |
openclaw/<agentId> 或 openclaw:<agentId> |
特定代理 |
agent:<agentId> |
特定代理(兼容性别名) |
可选请求头:
| 请求头 | 效果 |
|---|---|
x-openclaw-model: <provider/model-or-bare-id> |
覆盖所选代理的后端模型。共享密钥 bearer 调用方可以直接使用;携带身份的调用方(trusted-proxy,或带有 x-openclaw-scopes 的私有无认证入口)需要 operator.admin,否则返回 403 missing scope: operator.admin。 |
x-openclaw-agent-id: <agentId> |
代理选择的兼容性覆盖。 |
x-openclaw-session-key: <sessionKey> |
显式会话路由。如果使用保留的内部命名空间(subagent:、cron:、acp:),会以 400 invalid_request_error 拒绝。 |
x-openclaw-message-channel: <channel> |
为通道感知的提示/策略设置合成入口通道上下文。 |
/v1/models 列出顶层代理目标(openclaw、openclaw/default、openclaw/<agentId>),而不是后端提供商模型,也不是子代理;子代理保持为内部执行拓扑。如果省略 x-openclaw-model,所选代理将使用其正常配置的模型运行。
模型列表和详情端点需要 operator.read 或包含它的 scope,因为它们会暴露全局代理目标清单。
/v1/embeddings 使用相同的代理目标 model ID。发送 x-openclaw-model(来自共享密钥调用方,或具有 operator.admin 的携带身份调用方)以选择特定的嵌入模型;否则请求将使用所选代理的正常嵌入配置。
会话行为¶
默认情况下,该端点每次请求无状态(每次调用都会生成新的会话密钥)。
如果请求包含 OpenAI user 字符串,Gateway 会从中派生稳定的会话密钥,以便重复调用可以共享一个代理会话。对于自定义应用,请在每个对话线程中复用相同的 user 值;除非你希望多个对话/设备共享同一个 OpenClaw 会话,否则避免使用账户级标识符。仅当需要在多个客户端/线程之间进行显式路由控制时,才使用 x-openclaw-session-key,并使用由应用拥有的密钥,避免上述保留命名空间。
显式隐身会话延续¶
使用 x-openclaw-session-key(即 sessionKey 覆盖)显式选择或继续隐身对话,需要有效的 operator.admin 权限。该规则遵循权限,而不是入口:它既拒绝没有 owner/admin 权限的 trusted-proxy 调用方,也拒绝显式将 x-openclaw-scopes 缩小到 admin 以下的私有 gateway.auth.mode="none" 调用方(例如缩小到 operator.write)。两者都会收到带有 forbidden 错误的 HTTP 403。在此路径上,无 profile 的私有无认证调用方会得到 missing scope: operator.admin;对于基于 profile 的调用方,响应会以以下错误格式隐藏私有目标(其中 <sessionKey> 是请求的覆盖值):
{
"error": {
"message": "Incognito session \"<sessionKey>\" was not found.",
"type": "forbidden"
}
}
Owner/admin 调用方保留显式隐身会话延续。没有 x-openclaw-scopes 的私有无认证请求会获得默认 operator scopes,包括 operator.admin,因此被视为 owner/admin。保留的内部命名空间覆盖(subagent:、cron:、acp:)仍然是单独的验证失败,并返回 HTTP 400 和 invalid_request_error。
请求限制¶
该端点使用内置限制:每个请求体 20 MB,来自最新用户消息的 8 个 image_url 部分,以及累计 20 MB 的已解码图像数据。图像源策略仍可在 gateway.http.endpoints.chatCompletions.images 下配置:
{
gateway: {
http: {
endpoints: {
chatCompletions: {
enabled: true,
images: {
allowUrl: false,
urlAllowlist: ["cdn.example.com", "*.assets.example.com"],
allowedMimes: [
"image/jpeg",
"image/png",
"image/gif",
"image/webp",
"image/heic",
"image/heif",
],
maxBytes: 10485760,
maxRedirects: 3,
timeoutMs: 10000,
},
},
},
},
},
}
图像设置默认为:
| 键 | 默认值 |
|---|---|
images.allowUrl |
false(未启用时,来自 URL 的 image_url 部分会被拒绝) |
images.maxBytes |
每张图像 10MB |
images.maxRedirects |
3 |
images.timeoutMs |
10s |
接受 HEIC/HEIF image_url 源,并通过共享的 OpenClaw 图像处理器(Rastermill)在交付给提供商之前将其规范化为 JPEG;对于需要外部编解码器支持的格式,它会回退到系统转换器(sips、ImageMagick、GraphicsMagick 或 ffmpeg)。
安全说明:将主机名加入允许列表不会绕过私有/内部 IP 阻止。对于暴露在互联网上的网关,除应用层防护外,还应应用网络出站控制。参见 安全。
聊天工具契约¶
/v1/chat/completions 支持与常见 OpenAI Chat 客户端兼容的函数工具子集。
支持的请求字段¶
| 字段 | 说明 |
|---|---|
tools |
{ "type": "function", "function": { ... } } 数组 |
tool_choice |
"auto"、"none"、"required" 或 { "type": "function", "function": { "name": "..." } } |
messages[*].role: "tool" |
后续轮次 |
messages[*].tool_call_id |
将工具结果绑定回先前的工具调用 |
max_completion_tokens |
正的安全整数;每次调用对总 completion token 数(包括推理 token)的上限。当前字段名;当两个字段均非空时使用。为 null 或省略时保持未设置。 |
max_tokens |
正的安全整数;旧版别名。当 max_completion_tokens 非空时仍会验证,然后因优先级而被忽略。为 null 或省略时保持未设置。 |
temperature |
0-2 的数字;尽力而为,转发给上游提供商。超出范围时返回 400 invalid_request_error。 |
top_p |
0-1 的数字;尽力而为。超出范围时返回 400 invalid_request_error。 |
frequency_penalty |
-2.0 到 2.0 的数字;尽力而为。超出范围时返回 400 invalid_request_error。 |
presence_penalty |
-2.0 到 2.0 的数字;尽力而为。超出范围时返回 400 invalid_request_error。 |
seed |
整数;尽力而为。非整数值返回 400 invalid_request_error。 |
stop |
字符串或最多 4 个字符串的数组;尽力而为。超过 4 个序列或包含非字符串/空条目时返回 400 invalid_request_error。 |
所有采样和 token 上限字段都通过同一个代理流参数通道传输,并尽力转发:
- token 上限:传输字段名由提供商传输层选择:OpenAI 系端点使用
max_completion_tokens,仅接受旧版名称的提供商(Mistral、Chutes)使用max_tokens。 stop映射到传输层的停止字段:Chat Completions 后端使用stop,Anthropic 使用stop_sequences。OpenAI Responses API 没有 stop 参数,因此在基于 Responses 的模型上不会应用stop。- 基于 ChatGPT 的 Codex Responses 后端使用固定的服务器端采样,并在请求到达该后端之前移除
temperature/top_p(以及max_output_tokens、metadata、prompt_cache_retention、service_tier)。
不支持的变体¶
以下情况返回 400 invalid_request_error:
- 非数组的
tools、非 function 工具条目,或缺少tool.function.name tool_choice变体,例如allowed_tools和custom- 与所提供工具不匹配的
tool_choice.function.name值
对于 tool_choice: "required" 和固定函数的 tool_choice,端点会缩小暴露的客户端函数工具集,指示运行时在响应前调用客户端工具,并在代理响应中没有匹配的客户端工具结构化调用时返回错误。这适用于调用方提供的 HTTP tools 列表,而不是每个内部 OpenClaw 代理工具。
非流式工具响应结构¶
当代理调用工具时,响应使用:
choices[0].finish_reason = "tool_calls"- 带有
id、type: "function"、function.name、function.arguments(JSON 字符串)的choices[0].message.tool_calls[]条目 - 工具调用前的助手评论,位于
choices[0].message.content(可能为空)
流式工具响应结构¶
当 stream: true 时,工具调用会以增量 SSE 块到达:一个初始 assistant 角色增量、可选的 assistant 评论增量、一个或多个携带工具标识和参数片段的 delta.tool_calls 块,然后是一个带有 finish_reason: "tool_calls" 和 data: [DONE] 的最终块。
对于必需或固定到函数的工具选择,文本会被暂缓,直到匹配调用被确认。当运行返回最终文本时,流会使用该文本,而不是临时增量。
如果 stream_options.include_usage=true,会在 [DONE] 之前发出一个尾随 usage 块。
工具后续循环¶
收到 tool_calls 后,执行请求的函数,并发送一个后续请求,其中包含之前的 assistant 工具调用消息,以及一个或多个带有匹配 tool_call_id 的 role: "tool" 消息。这会继续同一个 agent 推理循环以生成最终答案。
如果工具没有产生文本,仍应使用 content: "" 或空文本部分数组包含其结果。空结果会完成该调用;省略结果则不会。旧版 role: "function" 结果可以与其函数 name 一起使用 content: null。
流式(SSE)¶
流式会保留来自不同 assistant 消息的重复内容。如果某个更正无法通过追加到已发送文本来表示,流会报告错误,而不是以不一致的内容完成。
设置 stream: true 以接收服务器发送事件(SSE):
Content-Type: text/event-stream- 每个事件行是
data: <json> - 流以
data: [DONE]结束
失败的 agent 运行(包括整个 agent 超时)会返回错误,而不是成功完成。流式失败会发出一个 error 对象,随后是 [DONE];部分内容可能已经到达客户端。超时设置遵循 代理循环。
断开 HTTP 客户端会取消正在进行的 source-URL 下载和 agent 运行。如果取消发生在准备输入期间,Gateway 会释放该下载,并且不会启动另一个输入下载或 agent 运行。这适用于流式和非流式请求。
Open WebUI 快速设置¶
- 基础 URL:
http://127.0.0.1:18789/v1 - macOS 上 Docker 的基础 URL:
http://host.docker.internal:18789/v1 - API 密钥:你的 Gateway bearer token
- 模型:
openclaw/default
预期行为:GET /v1/models 会列出 openclaw/default,Open WebUI 会将其用作聊天模型 id。对于特定的后端提供商/模型,请设置 agent 的常规默认模型,或发送 x-openclaw-model(共享密钥调用方,或具有 operator.admin 的携带身份调用方)。
快速冒烟测试:
如果返回 openclaw/default,大多数 Open WebUI 配置可以使用相同的基础 URL 和 token 连接。
示例¶
为单个应用会话保持稳定会话:
curl -sS http://127.0.0.1:18789/v1/chat/completions \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"model": "openclaw/default",
"user": "conv:YOUR_CONVERSATION_ID",
"messages": [{"role":"user","content":"Summarize my tasks for today"}]
}'
在该会话的后续调用中复用相同的 user 值,以继续同一个 agent 会话。
非流式:
curl -sS http://127.0.0.1:18789/v1/chat/completions \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"model": "openclaw/default",
"messages": [{"role":"user","content":"hi"}]
}'
流式:
curl -N http://127.0.0.1:18789/v1/chat/completions \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-H 'x-openclaw-model: openai/gpt-5.4' \
-d '{
"model": "openclaw/research",
"stream": true,
"messages": [{"role":"user","content":"hi"}]
}'
列出模型:
获取单个模型:
curl -sS http://127.0.0.1:18789/v1/models/openclaw%2Fdefault \
-H 'Authorization: Bearer YOUR_TOKEN'
创建嵌入:
curl -sS http://127.0.0.1:18789/v1/embeddings \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-H 'x-openclaw-model: openai/text-embedding-3-small' \
-d '{
"model": "openclaw/default",
"input": ["alpha", "beta"]
}'
/v1/embeddings 支持将 input 作为字符串或字符串数组。
提供商故障使用与 chat completions 相同的错误映射:缺少提供商凭据会返回 401 authentication_error 并附带设置指导,未知的提供商模型会返回 404 invalid_request_error,提供商过载会返回 503 api_error。凭据值会被脱敏。意外故障会返回 500 api_error 并带有 internal error。
对于支持的模型,正整数 dimensions 用于请求输出向量大小。它会覆盖所选 agent 当前生效的 memory.search.outputDimensionality,并且在禁用记忆搜索时也会生效。省略它会保留已配置或提供商默认大小。
相关¶
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw