OpenClaw Gateway OpenAI 兼容 HTTP API 实战指南:让 /v1/chat/completions 驱动你的 Agent
【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 🦞项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw
OpenClaw Gateway 内置了一个与 OpenAI Chat Completions 兼容的 HTTP 端点面(默认关闭),启用后可以让任何「只认 OpenAI 协议」的客户端、SDK 或工具直接驱动 OpenClaw Agent,请求走的是与openclaw agent完全相同的控制平面运行路径。本文以 docs/gateway/openai-http-api.md 为主体,结合 src/gateway/openai-http.ts 的源码实现,完整讲解端点启用、认证与安全边界、Agent 优先的 model 契约、会话行为、工具调用(function calling)、SSE 流式、图片输入限制,以及 Open WebUI 等场景的实战接入,让你读完即可安全、正确地接入这一端点。
端点概览:一个端口,四种 OpenAI 兼容路径
Gateway 本身是 WS + HTTP 多路复用(multiplex)的单一端口。启用 OpenAI 兼容端点后,它会在与 Gateway 相同的端口上额外提供以下四个路径:
| Method | Path |
|---|---|
| POST | /v1/chat/completions |
| GET | /v1/models |
| GET | /v1/models/{id} |
| POST | /v1/embeddings |
注意:
POST /v1/responses由独立的开关gateway.http.endpoints.responses.enabled控制,对应 OpenResponses API(见 docs/gateway/openresponses-http-api.md),不在本端点范围内。
从源码结构看(src/gateway/openai-http.ts),handleOpenAiHttpRequest将请求绑定到/v1/chat/completions路径,并复用 Gateway 的通用 JSON POST 端点处理框架(handleGatewayPostJsonEndpoint),传入requiredOperatorMethod: "chat.send"。这意味着请求并非独立服务,而是作为一个普通 Gateway agent run 被执行——路由、权限、配置均与你的 Gateway 完全一致。这一设计是理解本端点一切行为(尤其是安全模型)的出发点。
启用端点:一行配置
端点默认关闭,需要在 Gateway 配置中显式开启:
{ gateway: { http: { endpoints: { chatCompletions: { enabled: true }, }, }, }, }设置enabled: false(或直接省略该字段)即关闭。除此之外,chatCompletions下还支持图片输入策略images子配置,详见下文「请求限制与图片策略」。
安全边界(重要):这是操作员级入口
请把该端点视为对 Gateway 实例的完整操作员访问(full operator access),而不是一个窄范围的普通用户接口。具体含义:
- 持有该端点的有效 Gateway token/password,等价于持有 owner/operator 凭证;
- 请求运行在与受信操作员动作相同的控制平面 Agent 路径上,因此如果目标 Agent 的策略允许敏感工具,该端点就能使用它们;
- 只应暴露在 loopback / tailnet / 私有入口(private ingress)上,严禁暴露到公网。
源码中的注释也印证了这一点(src/gateway/openai-http.ts):“Compat HTTP uses a different scope model from generic HTTP helpers: shared-secret bearer auth is treated as full operator access here”(兼容 HTTP 使用与通用 HTTP 辅助不同的 scope 模型:共享密钥 bearer 认证在此被视为完整操作员访问)。
认证矩阵
| Auth path | 行为 |
|---|---|
gateway.auth.mode="token"或"password"+Authorization: Bearer ... | 证明持有共享 Gateway 密钥。忽略任何x-openclaw-scopes头,恢复完整默认操作员 scope 集:operator.admin、operator.approvals、operator.pairing、operator.read、operator.talk.secrets、operator.write。聊天轮次按 owner-sender 轮次处理。 |
受信身份 HTTP(trusted-proxy 认证,或私有入口上的gateway.auth.mode="none") | 存在x-openclaw-scopes时予以尊重;缺失时回退到默认操作员 scope 集。仅当调用方显式收窄 scopes 且省略operator.admin时才失去 owner 语义。owner 级控制(如x-openclaw-model)要求operator.admin。 |
相关文档:Operator scopes、Security、Remote access。
认证方式:复用 Gateway 认证配置
该端点直接使用 Gateway 的认证配置(trusted-proxy 模式的细节见 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-proxyGateway 上绕过代理的同主机调用方,可以直接回退使用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 或 Gateway Protocol 的 paired-device bootstrap / device-token 流程,让设备无需共享 HTTP token/password。
- 接入外部消息网络(有独立用户、房间、webhook 投递或出站传输):应构建 channel 插件,参见 Building plugins。
Agent-first 模型契约:model不是提供商模型 ID
OpenClaw 把 OpenAI 的model字段当作Agent 目标(agent target),而不是原始提供商模型 ID。这是理解本端点最关键的概念差异:
model值 | 路由到 |
|---|---|
openclaw | 已配置的默认 Agent |
openclaw/default | 已配置的默认 Agent(稳定别名;即使真实默认 Agent ID 在不同环境间变化,也可安全硬编码) |
openclaw/<agentId>或openclaw:<agentId> | 指定 Agent |
agent:<agentId> | 指定 Agent(兼容别名) |
可选请求头
| Header | 效果 |
|---|---|
x-openclaw-model: <provider/model-or-bare-id> | 覆盖所选 Agent 的后端模型。共享密钥 bearer 调用方可直接使用;身份承载调用方(trusted-proxy,或私有 no-auth 入口且带x-openclaw-scopes)需要operator.admin,否则返回403 missing scope: operator.admin。 |
x-openclaw-agent-id: <agentId> | Agent 选择的兼容性覆盖。 |
x-openclaw-session-key: <sessionKey> | 显式会话路由。若使用保留内部命名空间(subagent:、cron:、acp:),返回400 invalid_request_error。 |
x-openclaw-message-channel: <channel> | 设置合成入口 channel 上下文,供 channel-aware 提示/策略使用。 |
从源码看(src/gateway/openai-http.ts),请求上下文解析由resolveGatewayRequestContext完成,其中sessionPrefix: "openai"、defaultMessageChannel: "webchat",并启用useMessageChannelHeader——也就是说请求头的解析、会话键前缀和默认 message channel 都在这一层落地;模型覆盖则由resolveOpenAiCompatModelOverride在运行前解析(src/gateway/openai-http.ts)。
/v1/models与/v1/embeddings的契约
/v1/models列出顶层 Agent 目标(openclaw、openclaw/default、openclaw/<agentId>),不是后端提供商模型,也不包含子 Agent(sub-agents 属于内部执行拓扑)。如果省略x-openclaw-model,所选 Agent 使用其正常配置的模型运行。/v1/embeddings使用同样的 Agent 目标modelID。发送x-openclaw-model(共享密钥调用方,或带operator.admin的身份承载调用方)可指定具体嵌入模型;否则请求使用所选 Agent 的常规嵌入设置。/v1/embeddings支持input为字符串或字符串数组;对支持的模型,正整数dimensions可请求输出向量大小,它会覆盖所选 Agent 的memory.search.outputDimensionality配置(即使禁用 memory search 也生效),省略则保持配置或提供商默认大小。
会话行为:默认无状态,user派生稳定会话
默认情况下端点是每请求无状态的(每次调用都会生成一个新的 session key)。
- 若请求包含 OpenAI 的
user字符串,Gateway 会从中派生稳定会话键,使重复调用可以共享同一 Agent 会话。自定义应用中,同一个会话线程请复用相同的user值;避免使用账户级标识符,除非你确实希望多个会话/设备共享一个 OpenClaw 会话。 - 仅当你需要在多个客户端/线程之间显式控制路由时,才使用
x-openclaw-session-key,并确保使用应用自有键、避开上述保留命名空间。
显式 incognito 会话续接(权限收紧)
使用x-openclaw-session-key显式选择或续接一个 incognito 会话,需要有效的operator.admin权限。该规则跟随权限而非入口:
- trusted-proxy 调用方若没有 owner/admin 权限,会被拒绝;
- 私有
gateway.auth.mode="none"调用方若显式把x-openclaw-scopes收窄到低于 admin(例如只给operator.write),同样被拒绝。
以上两种情况均返回 HTTP403与forbidden错误。无 profile 的私有 no-auth 调用方在此路径上得到missing scope: operator.admin;对 profile 支持的调用方,响应会隐藏私有目标,错误形状如下(<sessionKey>为请求的覆盖值):
{ "error": { "message": "Incognito session \"<sessionKey>\" was not found.", "type": "forbidden" } }Owner/admin 调用方可继续显式续接 incognito 会话。私有 no-auth 请求若不带x-openclaw-scopes,会获得默认操作员 scopes(含operator.admin),因此被视为 owner/admin。保留内部命名空间覆盖(subagent:、cron:、acp:)属于另一类校验失败,仍返回 HTTP400与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, }, }, }, }, }, }图片设置默认值:
| Key | 默认值 |
|---|---|
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 屏蔽。对于暴露在公网的 Gateway,除应用层防护外还应施加网络出口(egress)控制,参见 Security。
Chat 工具契约:function calling 子集
/v1/chat/completions支持与常见 OpenAI Chat 客户端兼容的 function-tool 子集。
支持的请求字段
| 字段 | 说明 |
|---|---|
tools | { "type": "function", "function": { ... } }数组 |
tool_choice | "auto"、"none"、"required",或{ "type": "function", "function": { "name": "..." } } |
messages[*].role: "tool" | 后续轮次 |
messages[*].tool_call_id | 把工具结果绑定回先前的工具调用 |
max_completion_tokens | 正整数安全整数;每次调用的总完成 token 上限(含推理 token)。当前字段名;两个字段都非空时使用它。Null 或省略则不设置。 |
max_tokens | 正整数安全整数;遗留别名。当max_completion_tokens非空时仍会校验,但优先级被忽略。Null 或省略则不设置。 |
temperature | 数值 0-2;best-effort,转发给上游提供商。越界返回400 invalid_request_error。 |
top_p | 数值 0-1;best-effort。越界返回400 invalid_request_error。 |
frequency_penalty | 数值 -2.0 到 2.0;best-effort。越界返回400 invalid_request_error。 |
presence_penalty | 数值 -2.0 到 2.0;best-effort。越界返回400 invalid_request_error。 |
seed | 整数;best-effort。非整数返回400 invalid_request_error。 |
stop | 字符串或最多 4 个字符串的数组;best-effort。超过 4 个序列或包含非字符串/空条目时返回400 invalid_request_error。 |
源码中可以看到这些校验的具体实现(src/gateway/openai-http.ts):resolveStopSequences严格限制最多 4 条且条目必须为非空字符串;resolveChatCompletionTokenCap通过asPositiveSafeInteger保证正安全整数;随后validateOpenAiSamplingParams统一校验采样参数范围。
所有采样与 token 上限字段走同一条 Agent stream-param 通道,best-effort 转发:
- Token 上限:线字段名由提供商传输层决定——OpenAI 系端点用
max_completion_tokens,只接受旧名称的提供商(Mistral、Chutes)用max_tokens。 stop映射到传输层的 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"和 function 固定的tool_choice,端点会收窄暴露给客户端的 function-tool 集、指示运行时在响应前先调用客户端工具,并在 Agent 响应中没有匹配的结构化客户端工具调用时报错。注意这作用于调用方提供的 HTTPtools列表,而非 OpenClaw 的每一个内部 Agent 工具。
非流式工具响应形状
Agent 调用工具时,响应使用:
choices[0].finish_reason = "tool_calls"choices[0].message.tool_calls[]条目包含id、type: "function"、function.name、function.arguments(JSON 字符串)- 工具调用前的助手评论性文本位于
choices[0].message.content(可能为空)
源码中(src/gateway/openai-http.ts),resolveStopReasonAndPendingToolCalls从运行 meta 中提取stopReason与pendingToolCalls(工具参数统一序列化为 JSON 字符串),随后按上述形状组装chat.completion响应。一个值得注意的实现细节:tool_choice约束在运行之后通过结构化pendingToolCalls强制执行(而不是相信模型口头说调用了工具)——约束未满足时返回 HTTP502、type: "api_error"(src/gateway/openai-http.ts),这在源码注释中被明确解释为“tool_choiceis an HTTP client-tool contract. The provider may still ignore the prompt, so enforce after the run”。
流式工具响应形状
stream: true时,工具调用以增量 SSE 块到达:先是初始的 assistant role delta,然后是可选助手评论 delta,接着一个或多个携带工具身份与参数片段的delta.tool_calls块,最后是携带finish_reason: "tool_calls"的收尾块与data: [DONE]。
- 对 required 或 function 固定的 tool_choice,评论性文本会暂缓直到匹配调用被确认。当运行返回最终确定的文本时,流使用该文本而非临时 delta。
- 如果
stream_options.include_usage=true,会在[DONE]前发出一个 trailing usage 块。
工具后续循环(tool follow-up loop)
收到tool_calls后,执行请求的函数,并发送一个包含先前 assistant tool-call 消息 + 一个或多个带匹配tool_call_id的role: "tool"消息的后续请求,从而继续同一 Agent 推理循环,得到最终答案。
- 如果工具无文本输出,仍需用
content: ""或空文本部件数组包含其结果。空结果完成调用;省略结果则不会。 - 遗留的
role: "function"结果可用content: null携带其函数name。
流式(SSE)行为
流式会保留来自不同 assistant 消息的重复内容。如果某个修正无法通过追加到已发送文本的方式表达,流会报告错误而不是以不一致内容完成。
设置stream: true即可接收 Server-Sent Events:
Content-Type: text/event-stream- 每个事件行为
data: <json> - 流以
data: [DONE]结束
失败语义:
- Agent 运行失败(包括整个 Agent 超时)返回错误而非成功完成;流式失败先发出
error对象再发[DONE],此时部分内容可能已到达客户端。超时设置遵循 agent loop。 - HTTP 客户端断开会取消正在进行的源 URL 下载和 Agent 运行;若取消发生在准备输入阶段,Gateway 会释放该下载且不启动另一个输入下载或 Agent 运行。该行为对流式与非流式请求均适用。
源码中流式实现的几个关键点(src/gateway/openai-http.ts):进入流式路径后先setSseHeaders(res);收尾阶段用resolveAssistantTextCompletion比较最终文本与已流式文本,若最终文本不以已流式文本开头(即无法用 append-only 方式表达),则finishStreamWithError返回api_error;工具调用以writeAssistantToolCallsIncrementalChunks增量写出;正常收尾时writeAssistantFinishChunk带finish_reason(工具场景为"tool_calls")。
Open WebUI 快速接入
- Base URL:
http://127.0.0.1:18789/v1 - Docker on macOS Base URL:
http://host.docker.internal:18789/v1 - API key:你的 Gateway bearer token
- Model:
openclaw/default
预期行为:GET /v1/models列出openclaw/default,Open WebUI 将其作为聊天模型 ID。要为指定后端提供商/模型运行,请设置 Agent 的常规默认模型,或发送x-openclaw-model(共享密钥调用方,或带operator.admin的身份承载调用方)。
快速冒烟测试:
curl -sS http://127.0.0.1:18789/v1/models \ -H 'Authorization: Bearer YOUR_TOKEN'如果返回openclaw/default,大多数 Open WebUI 环境即可用相同 Base URL 和 token 连接。
完整示例
单应用会话的稳定会话(同一对话线程复用相同的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", "user": "conv:YOUR_CONVERSATION_ID", "messages": [{"role":"user","content":"Summarize my tasks for today"}] }'非流式:
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"}] }'流式(-N关闭 curl 缓冲,并演示x-openclaw-model覆盖后端模型、openclaw/research指定 Agent):
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 \ -H 'Authorization: Bearer YOUR_TOKEN'获取单个模型(注意 Agent ID 中的/需 URL 编码为%2F):
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"] }'底层实现:一次请求的完整调用链
理解端点如何落到普通 Agent run 的调用链,能帮你更准确地预估行为(均基于 src/gateway/openai-http.ts 的源码结构):
- 认证与授权:
handleOpenAiHttpRequest通过handleGatewayPostJsonEndpoint进入,按上文矩阵解析 scopes(resolveOpenAiCompatibleHttpOperatorScopes);随后authorizeOpenAiCompatibleHttpModelOverride校验模型覆盖权限,resolveOpenAiCompatibleHttpSenderIsOwner判定 sender 是否 owner。 - 请求解析与校验:
parseGatewayJsonRequest用OpenAiChatCompletionRequestSchema校验 JSON;token 上限、采样参数、response_format、stop依次解析校验,任何失败即返回400 invalid_request_error。 - 上下文解析:
resolveGatewayRequestContext解析agentId、sessionKey(前缀openai)与messageChannel(默认webchat);authorizeGatewaySessionCreation与authorizeOpenAiCompatibleHttpSession分别校验会话创建与 incognito 续接权限(后者对应文档中的403 forbidden语义)。 - 工具契约组装:
extractClientToolsFromChatRequest提取客户端函数工具,applyToolChoice把tool_choice转成运行时约束(required/固定函数时收窄工具集并注入 extra system prompt)。 - 运行执行:
buildAgentCommandInput组装 prompt、图片、客户端工具、模型覆盖、streamParams 等,最终经agentCommandFromGatewayIngress以 Gateway ingress 的普通 Agent run 方式执行——这正是文档「同一 codepath」论断的代码落点。 - 响应整形:非流式按
stop/length/tool_calls三种 finish_reason 整形为chat.completion;流式按 SSE 增量块输出,收尾校验 append-only 一致性。
该端点的测试覆盖见 src/gateway/openai-http.test.ts 与 src/gateway/openai-compatible-http.test-helpers.ts,需要深入边界行为(如tool_choice约束、流式一致性、incognito 权限)时可以继续翻阅。
小结
OpenAI 兼容 HTTP 端点是 OpenClaw Gateway 对外开放能力中最轻量的一层:它不引入新的消息网络抽象,而是把「任何会讲 OpenAI 协议的工具」直接映射到你的 Agent 拓扑上。使用时的三个核心心法:按操作员入口对待安全边界(仅私有网络暴露)、把model当作 Agent 目标而非提供商模型、用user或x-openclaw-session-key显式管理会话路由。把握住这三点,你就能用 Open WebUI、自定义 SDK 或任意 OpenAI 兼容客户端,安全稳定地驱动 OpenClaw Agent。
Related
- Configuration reference
- Operator scopes
- OpenAI
【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 🦞项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考