OpenAI Responses 接入
Workflow Code 可以把已适配的 Conversation 项目作为 OpenAI Responses API 服务调用。Desktop 默认在 127.0.0.1:7135 启动本地网关;本地项目直接在 Desktop 执行,服务器项目由 Desktop 透明流式转发到当前连接的 Workflow Server。也可以绕过 Desktop,直接调用 Server 的 /v1。
该入口只实现 Responses、Conversations 和 Models 子集,不提供 /v1/chat/completions 或旧 /v1/completions。
在 Desktop 获取调用信息
所有 Conversation 项目的工具目录都会显示 OpenAI API:
- 打开 Conversation 项目详情,在 New Tab 中选择 OpenAI API。
- 检查项目适配器、Desktop 网关和 Server 服务状态。
- 选择当前账号可用的模型。
- 为当前用户和当前项目创建 Key,或轮换已有 Key。
- 复制 base URL、Responses URL 和 curl、Node.js 或 Python 示例。
Desktop 网关只监听 loopback,不接受局域网连接。默认地址为:
Base URL: http://127.0.0.1:7135/v1
Responses URL: http://127.0.0.1:7135/v1/responses
服务器项目还会显示 Server 直连 base URL。通过 Desktop 地址调用服务器项目时,请求和 SSE 会原样流式转发到当前 Server;Key 仍由 Server 校验。
如果 7135 已被占用,只有 OpenAI 网关会停用,Desktop 其它功能继续运行。OpenAI API 页会显示端口错误,释放端口并重启 Desktop 后即可恢复。
未声明适配器的 Conversation 项目仍显示 OpenAI API 页和接入文档入口,但不能创建、轮换或使用项目 Key。
Key 与身份边界
项目 Key 使用 wfpk_* 格式,并同时绑定:
- 当前登录用户;
- 一个 Conversation 项目;
- 该项目当前可用的 OpenAI 适配器。
因此公开请求保持标准 /v1/responses,不需要项目 Header 或自定义项目参数。/v1 只接受项目专属 Key;Desktop 登录凭据、账号 API Key和 Server 管理员 Key不能代替它。
完整 Key 只在创建或轮换后显示一次。Desktop SQLite 和 Server PostgreSQL 只保存 SHA-256 哈希与可识别前缀,之后无法重新读取完整值。Key 遗失时必须轮换;轮换和吊销立即使旧 Key 失效,但不会删除已有 Response 或 Conversation 资源。
不要把项目 Key 写入源码、项目环境文件、浏览器 bundle、截图或日志。推荐通过进程环境变量提供:
export OPENAI_API_KEY='wfpk_...'
export OPENAI_BASE_URL='http://127.0.0.1:7135/v1'
调用示例
curl
curl "$OPENAI_BASE_URL/responses" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "provider/model-id",
"input": "请概括这段内容。"
}'
Node.js
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
baseURL: process.env.OPENAI_BASE_URL,
});
const response = await client.responses.create({
model: "provider/model-id",
input: "请概括这段内容。",
});
console.log(response.output_text);
Python
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["OPENAI_API_KEY"],
base_url=os.environ["OPENAI_BASE_URL"],
)
response = client.responses.create(
model="provider/model-id",
input="请概括这段内容。",
)
print(response.output_text)
先调用 GET /v1/models 获取当前 Key 实际可用的模型 ID。Server 会按当前用户的 Provider 偏好选择第一个提供该模型的有效凭据。图片等硬能力不支持时会返回明确错误;已接受的可选采样参数会继续转交 Provider。若 Provider 以 unsupported 或 compatibility warning 表示某个采样参数不可用,调用仍会继续,具体降级信息保留在响应的 Provider metadata 中。
支持的接口
| 资源 | 接口 |
|---|---|
| Responses | POST /v1/responses |
| Response 资源 | GET /v1/responses/{id}、DELETE /v1/responses/{id} |
| 取消 | POST /v1/responses/{id}/cancel |
| Response 输入 | GET /v1/responses/{id}/input_items |
| Conversations | POST /v1/conversations、GET/POST/DELETE /v1/conversations/{id} |
| Conversation items | GET/POST /v1/conversations/{id}/items、GET/DELETE /v1/conversations/{id}/items/{item_id} |
| Models | GET /v1/models、GET /v1/models/{model} |
列表接口接受 after、limit 和 order=asc|desc,并返回 object: "list"、data、first_id、last_id 和 has_more。
POST /v1/responses 支持以下请求字段:
| 字段 | 支持范围 |
|---|---|
model | 必填,必须来自当前 Key 的 /v1/models。 |
input | 字符串,或 user / assistant / system / developer message 数组。 |
instructions | 可选的本轮顶层指令。 |
temperature、top_p、max_output_tokens | 转交给项目和 Provider;实际支持由模型能力决定。 |
text | 仅支持纯文本 format.type: "text";verbosity 接受 low、medium 或 high。 |
include | 仅接受兼容值 reasoning.encrypted_content;当前子集不生成 reasoning item,因此不会增加额外输出。 |
store | 默认 true。控制 Response 资源保留,不删除显式 Conversation items。 |
stream | 返回标准 Responses SSE。不能与 background 同时使用。 |
background | 立即返回 queued,之后可轮询或取消。 |
previous_response_id | 继续一个状态为 completed 或 incomplete 且仍保留的 Response。与 conversation 互斥。 |
conversation | 使用持久 Conversation ID 或 { "id": "conv_*" };对象形式必须包含有效的 id。 |
metadata | 最多 16 个字符串键值对,保存在 API 资源中。 |
未知字段、冲突字段和协议子集之外的参数返回 invalid_request_error,不会被忽略。已接受的可选参数若仅被底层 Provider 标记为不支持,则按 Provider 的 warning 降级并继续执行。错误格式统一为:
{
"error": {
"message": "...",
"type": "invalid_request_error",
"param": "input",
"code": "invalid_value"
}
}
Response 对象只有在 status: "completed" 时才会填写 completed_at;queued、in_progress、failed、cancelled 和 incomplete 均返回 null。
当 Provider 的 finish reason 表示达到输出上限或触发内容过滤时,网关返回 status: "incomplete",并分别填写 incomplete_details.reason: "max_output_tokens" 或 "content_filter"。已经生成的文本会保留在 output 中,对应 message item 的状态同样为 incomplete。
输入与图片
message 内容支持字符串,或以下 content part:
- 用户:
input_text、input_image; - 助手历史:
output_text,也接受并规范化input_text; system/developer:input_text,由内置适配器作为高优先级模型指令处理;- 图片:HTTP/HTTPS URL 或图片 data URL。
内置 Conversation、Codex、OpenCode 和小助手适配器都会显式应用 text.verbosity,不会只接受字段后忽略其语义。小助手复用 OpenCode 的适配和稳定输出项。include: ["reasoning.encrypted_content"] 是 OpenAI 仍接受的旧客户端兼容值;它不代表当前网关已实现 reasoning item。
最终有效输入必须包含用户文本或图片。图片只接受 JPEG、PNG、WebP 和 GIF;SVG 与普通文件不在首版范围。
图片进入受限下载和现有文件存储流程:每张最大 10 MiB、单请求合计最大 20 MiB、最多 16 张、下载超时 10 秒、最多 3 次重定向。网关校验实际文件签名与 MIME 类型,拒绝压缩 HTTP 响应、URL 内嵌凭据、loopback、私网、link-local、保留地址、云元数据地址及任何重定向后的非公网目标。
多轮状态
有两种互斥方式:
previous_response_id:把上一条状态为completed或incomplete的 Response 输入和输出加入本轮上下文;conversation:从持久 Conversation 读取 items,成功后原子追加本轮输入与输出。
previous_response_id 不会继承上一轮顶层 instructions。需要稳定指令时,每轮都重新发送:
const first = await client.responses.create({
model,
input: "第一问",
instructions: "始终使用简体中文回答。",
});
const second = await client.responses.create({
model,
input: "继续说明",
previous_response_id: first.id,
instructions: "始终使用简体中文回答。",
});
显式 Conversation 会在运行完成或以 incomplete 结束时追加本轮输入和已有输出;失败或取消不会追加。删除 Conversation 只删除 Conversation 资源,已有 items 及其图片引用按 Responses 协议保留。删除单个 item 返回更新后的 Conversation 对象,并在该图片不再被其它资源引用时回收文件。
流式与后台执行
stream: true 使用标准 Responses SSE 事件,顺序包括:
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.completed 结束;达到输出上限或触发内容过滤时保留部分文本,并以 response.incomplete 结束。流内失败发送 error 和 response.failed。流末尾不发送 Chat Completions 的 [DONE]。前台客户端断开时,Desktop 或 Server 会取消底层运行。
background: true 与 stream: true 在首版互斥。后台创建立即返回 queued;使用 GET /v1/responses/{id} 轮询,使用 POST /v1/responses/{id}/cancel 幂等取消。Desktop 或 Server 重启时,遗留的 queued / in_progress 会标记为 failed,公开错误为 server_error,内部审计分类为 server_restart;首版不跨进程恢复任务。
反向代理 SSE
Server 在项目 OpenAI 调用信息中优先使用 WORKFLOW_API_PUBLIC_BASE_URL。该值必须是无内嵌凭据的 HTTP(S) URL,并会规范化为 origin;生产反向代理应显式设置它。未配置或配置无效时,Server 使用当前请求的协议和 Host,只有 Express 明确信任直连代理时才采用 X-Forwarded-Proto / X-Forwarded-Host,普通客户端发送这些 Header 不会改变展示地址。
反向代理必须关闭 SSE 缓冲和缓存,例如 Nginx:
location /v1/ {
proxy_pass http://127.0.0.1:7130;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
add_header X-Accel-Buffering no;
}
不要在 CDN、Ingress 或应用代理层重新聚合 text/event-stream 数据块。
保留、删除与隐私
| 资源 | 默认保留 |
|---|---|
store: true 或缺省的 Response | 30 天。 |
前台 store: false Response | 请求结束后清除,不能再 retrieve。 |
后台 store: false Response | 终态后保留 10 分钟,供轮询。 |
| Conversation | 保留到显式删除。 |
| Conversation items | 保留到逐项删除;删除所属 Conversation 不会删除 items。 |
显式 Conversation items 不受 Response 的 store: false 影响。Desktop 启动及定时清理 SQLite;Server 启动及定时清理 PostgreSQL。删除或过期 Response、删除单个 Conversation item 时,会同时回收不再被其它资源引用的托管图片;删除 Conversation 本身不会回收其 items 使用的图片。
API 资源库按上述策略保存请求正文和输出。每次 OpenAI 调用开始时,都会立即在对应项目的运行记录中创建一条 OpenAI Responses 记录,完成、失败或取消后原位更新;Desktop 或 Server 重启也会把已开始但未完成的记录更新为失败终态。详情完整保存并展示标准化请求、标准 Response、Workflow 执行报告、节点输入输出、stdout、stderr、错误、finish reason 和 Provider metadata。store: false 只控制 Responses 协议资源的保留,不会裁剪项目运行记录。
完整 wfpk_* Key 和 Provider 凭据不写入运行记录;运行记录只保存 Key ID 与前缀。审计记录继续只保存身份、项目、模型、状态、时间、usage、错误分类和内部 run ID,不复制业务正文。普通 Conversation 历史也不会因 API 调用自动新增一份重复消息。
项目适配器
框架负责 HTTP 协议、Key、认证与权限、ID、校验、状态机、SSE、后台任务、持久化、图片安全、清理和审计。Conversation 项目开发者只负责把类型化 host input 映射到业务输入,并从声明的文本 output item 返回答案。
适配器声明位于 executor 的 conversation.openai:
const ANSWER_ITEM_ID = "assistant-response";
export const executor = workflow.defineExecutor({
projectType: "conversation",
workflow: conversationWorkflow,
conversation: {
openai: {
enabled: true,
outputItemId: ANSWER_ITEM_ID,
},
},
});
项目运行时通过 workflow.readOpenAIConversationHostInput(context) 读取:
- 标准化后的全部
messages; - 本轮
instructions; model;temperature、topP、maxOutputTokens和verbosity;- API Conversation ID 和项目运行记录正文持久化设置。
项目必须保持 outputItemId 稳定,把流式 delta 和最终文本写入该 item。项目可以针对自身无法表示的硬能力或参数做显式校验;使用 Core AI SDK Provider 时,Provider 返回的可选参数 unsupported / compatibility warning 不会自动阻断运行。框架会把完整调用信息和执行报告写入项目运行记录;项目无需再把同一份正文复制到普通 Conversation、KV 或审计记录,除非业务本身明确需要。
暂不支持
以下能力是框架后续 TODO。两个已知端点当前由网关显式返回 OpenAI 格式的 404 invalid_request_error;其它能力尚未实现,也不会被静默忽略:
/v1/responses/compact、/v1/responses/input_tokens;- Structured Outputs、reasoning 参数与 reasoning item、普通文件、Web Search、File Search、MCP、音频;
- WebSocket、logprobs、prompt cache、service tier;
- function/tool calling 的标准 item、call ID、流事件和状态恢复。
/compact 不是要求项目开发者额外实现的命令。工具调用需要框架先完成协议和恢复能力,之后项目开发者才负责工具定义、权限与业务执行。
/v1/chat/completions 和 /v1/completions 是明确不支持的旧协议,不属于兼容 TODO。