Composio 与 OpenAI 集成指南:使用 @composio/openai 将工具接入 Responses 与 Chat Completions

Composio 与 OpenAI 集成指南:使用 @composio/openai 将工具接入 Responses 与 Chat Completions Composio 与 OpenAI 集成指南使用 composio/openai 将工具接入 Responses 与 Chat Completions【免费下载链接】composioComposio powers 1000 toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composiocomposio/openai是 Composio 官方提供的 OpenAI 适配层它把 Composio 平台上的 1000 工具包装成 OpenAI 标准的 function calling 格式同时覆盖 Responses API 与 Chat Completions API 两条调用链路。本文以 ts/packages/providers/openai/README.md 为主体结合 OpenAIResponsesProvider.ts、OpenAIProvider.ts 源码与测试、示例完整讲解安装配置、两种 Provider 的选择、工具执行循环的编写以及 strict 模式Structured Outputs的底层实现原理。读完本文你将能在自己的 OpenAI Agent 中快速接入 Composio 工具并跑通完整的模型调用工具 → 工具返回结果 → 模型生成最终答案闭环。安装与前置配置composio/openai与composio/core、官方openaiSDK 一同安装npm install composio/core composio/openai openai从 package.json 可以看到该包的版本约束composio/core需要0.10.0 1.0.0 || 1.0.0-beta.0 1.0.0openaiSDK 需要^6.49.0 || ^7.0.0Node 环境要求22.22.3。安装完成后在环境变量中配置两个密钥COMPOSIO_API_KEYComposio 平台密钥OPENAI_API_KEYOpenAI 平台密钥。两个 ProviderResponses API 与 Chat Completions API该包按 OpenAI 的 API 面导出两个 Provider见 index.tsProvider目标 API特点适用场景OpenAIResponsesProviderResponses APIhandleToolCalls返回按call_id关联的function_call_output条目配合previous_response_id每轮只重发新增输出新的 Agent 流程官方推荐OpenAIProviderChat Completions APIComposio SDK 默认 Providernew Composio()不带参数时自动使用handleToolCalls返回可直接追加的tool消息消息列表由你自己维护扩展现有 Chat Completions 代码库OpenAIProvider实际上定义在composio/core内部见 ts/packages/core/src/provider/OpenAIProvider.tscomposio/openai只是把它作为便捷导出重新暴露而OpenAIResponsesProvider是本包的核心实现见 OpenAIResponsesProvider.ts。快速上手基于 Responses API 的 Agent 循环以下是 README 中的完整 Quickstart 代码。核心思路是为用户创建会话 → 获取工具 → 请求模型 → 若返回function_call则执行工具并把结果回传循环直至模型回复文本import OpenAI from openai; import { Composio } from composio/core; import { OpenAIResponsesProvider } from composio/openai; const composio new Composio({ provider: new OpenAIResponsesProvider(), }); const client new OpenAI(); // Create a session for your user const session await composio.create(user_123); const tools await session.tools(); let response await client.responses.create({ model: gpt-5.2, tools, input: [ { role: user, content: Send an email to johnexample.com with the subject Hello and body Hello from Composio!, }, ], }); // Agentic loop: keep executing tool calls until the model responds with text while (response.output.some(o o.type function_call)) { const results await composio.provider.handleToolCalls(session, response.output); response await client.responses.create({ model: gpt-5.2, tools, previous_response_id: response.id, input: results, }); } // Print final response for (const item of response.output) { if (item.type message item.content[0].type output_text) { console.log(item.content[0].text); } }这个循环有三个关键点工具获取有两种方式session.tools()会话工具或composio.tools.get()直接工具。当使用composio.tools.get()获取工具时handleToolCalls的第一个参数应传用户 ID字符串而不是 session。previous_response_id的妙用在 Responses API 中把上一轮响应的 ID 传回模型上下文自动续接你只需要把新的function_call_output条目作为input传入无需手动拼接全部历史消息。退出条件response.output中存在function_call时继续循环当模型输出纯文本消息output_text时结束。仓库中还提供了一个基于handleResponse的等价写法见 ts/examples/openai/src/responses-api/index.ts它用composio.provider.handleResponse(default, initialResponse)一步完成过滤 function_call → 执行工具 → 生成输出条目并演示了beforeExecute/afterExecute执行修饰器modifiers的用法可用于打点日志、拦截或改写参数。handleToolCalls 与 handleResponse 的内部行为从源码看OpenAIResponsesProvider.tshandleToolCalls会遍历response.output中所有function_call条目逐条执行并生成function_call_output执行成功时返回条目带status: completedoutput为工具结果的 JSON 字符串执行失败抛出异常时同样生成一条function_call_output但status: incompleteoutput是错误消息文本。这样即使某个工具调用失败模型也能看到错误信息并据此调整策略不会因为缺失某条call_id的结果而导致下一次请求报错。测试用例 opeanai-responses.test.ts 中专门验证了会话执行失败时输出incomplete状态且保留call_id与多工具调用按原始顺序返回这两个行为。handleResponse(userId, response)则是handleToolCalls的便捷封装它先从response.output中过滤出function_call条目再交给handleToolCalls处理见 源码 L425-L434。Chat Completions 集成手动维护消息列表OpenAIProvider默认 Provider面向 Chat Completions API。README 中说明handleToolCalls(session, chatCompletion)返回可直接追加的tool消息消息列表由你自己维护。结合示例 ts/examples/openai/src/chat-completions.ts典型用法如下import { Composio } from composio/core; import { OpenAI } from openai; const openai new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); // 不传 provider默认即 OpenAIProvider const composio new Composio({ apiKey: process.env.COMPOSIO_API_KEY }); const tools await composio.tools.get(default, HACKERNEWS_GET_USER); const response await openai.chat.completions.create({ model: gpt-4o, messages: [ { role: system, content: You are a helpful assistant that can use tools to answer questions. }, { role: user, content: Find information about the HackerNews user pg }, ], tools, tool_choice: auto, }); if (response.choices[0].message.tool_calls?.[0].type function) { // 单条工具调用也可直接使用 executeToolCall const toolResult await composio.provider.executeToolCall( default, response.choices[0].message.tool_calls[0], { connectedAccountId: } ); const finalResponse await openai.chat.completions.create({ model: gpt-4o, messages: [ { role: system, content: You are a helpful assistant that can use tools to answer questions. }, { role: user, content: query }, response.choices[0].message, // 携带 tool_calls 的 assistant 消息 { role: tool, tool_call_id: response.choices[0].message.tool_calls[0].id, content: toolResult }, ], }); console.log(finalResponse.choices[0].message.content); }handleToolCalls对应 OpenAIProvider.ts会遍历chatCompletion.choices[0].message.tool_calls为每个 function 调用生成一条{ role: tool, tool_call_id, content }消息。源码中的两个细节值得注意只处理第一个 choice当n 1时其余 choice 是模型生成的备选补全永远不会被继续使用执行它们的工具调用只会产生孤儿tool_call_id测试 openai.test.ts 中有专门用例锁定该行为并行工具调用同一条 assistant 消息可携带多个tool_calls默认开启并行每个都必须有对应的tool结果否则下一次请求会因未应答的tool_call_id而失败。此外OpenAIProvider还保留了面向已弃用 Assistant API 的handleAssistantMessage与waitAndHandleAssistantToolCalls源码中标注了deprecated将在下一个大版本移除新代码不建议使用。深入 strict 模式Structured Outputs 的完整实现OpenAIResponsesProvider构造时可传入{ strict: true }开启 strict 模式默认false见 源码 L89-L92const composio new Composio({ provider: new OpenAIResponsesProvider({ strict: true }), });strict 模式会调用 jsonSchema.ts 中的toStrictJsonSchema对工具 schema 做深度归一化遵循 OpenAI Structured Outputs 的约束每个对象全部封闭所有对象节点都变成 closed object——required列出全部属性并追加additionalProperties: false可选属性变成必填但可空可选属性会被加入required并拓宽为接受null例如type: string变为type: [string, null]或追加anyOf的 null 分支。这是 OpenAI 官方文档认可的模拟可选字段的做法——模型用null表达省略而该null在工具真正执行前会被丢弃详见下文omitNullToolArguments除非源 schema 本身就接受该字段为 null无损改写oneOf转为anyOfoneOf不受支持、剥离default/examples等注解关键字。每次改写都会被记录为changes上限 50 条totalChanges保存真实计数并在 debug 日志中输出具体路径与原因。无法表达 strict 的工具自动降级并告警toStrictJsonSchema会收集所有 strict 模式无法表达的构造unsupported数组包括接受任意键的对象schema 值或true的additionalProperties、patternProperties、无属性的自由对象、allOf、prefixItems、元组形式items、条件/依赖关键字、外部或悬空$ref等。改写这些构造会改变工具的真实语义因此源码选择不压缩而是将整个工具按非 strict 模式发送并打印一条 warning 日志提示该工具因 schema 无法表达为 strict structured outputs 而放弃 strict 模式见 wrapTool 实现 L161-L178。测试 opeanai-responses.test.ts 中验证了含additionalProperties: { type: string }的工具在 strict 模式下会得到strict: false且保留原 schema。另外两个边界行为也在测试中被锁定无参数工具在 strict 模式下输出空的封闭对象{ type: object, properties: {}, required: [], additionalProperties: false }本地$ref指向#/$defs/...会被保留$defs本身也会被归一化可选$ref属性通过anyOf追加 null 分支。执行前的参数修正omitNullToolArgumentsstrict 模式下模型会为可选参数发送null直接透传会撞上工具自身 schema 的校验。因此executeToolCall在执行前会查表strictInputSchemaskeyed by tool slug取出该工具实际看到的 strict schema调用omitNullToolArguments递归删除源 schema 不接受的null值若源 schema 接受 null可空字段、显式清空该值则原样保留见 源码 L287-L304 与 jsonSchema.ts 的 omitNullToolArguments。对应的测试用例验证了{ cfg: { url: u, note: null }, label: null, clearable: null }最终执行时被清洗为{ cfg: { url: u }, clearable: null }。底层执行细节与工具包装无论哪个 Provider工具执行最终都汇聚到两个共用机制上normalizeToolArgumentsOpenAI 总是把工具参数序列化为 JSON 字符串该函数负责解析同时容忍空字符串 / 对象形态的载荷对应 issue #2406 的修复空字符串会被归一为空对象{}deduplicateJsonSchemaRequiredArrays在 vendor schema 的发射边界对required数组去重。JSON Schema 2020-12 不允许required出现重复项而工具 schema 既来自 Composio API 也可能来自直接 provider 调用该归一化保证所有 Provider 收到规范的 schema。测试中确认了required: [input, input]会被折叠为[input]wrapMcpServerResponseResponses Provider 会把 MCP 服务器响应转换为 OpenAI Responses 的 MCP 工具格式type: mcp、server_label、server_url、require_approval: never并且测试保证不会把 MCP URL可能含敏感 token打到 stdout。工具包装的结果是标准的 OpenAI function 声明OpenAIResponsesProvider产出{ type: function, name: slug, description, parameters, strict }OpenAIProvider产出{ type: function, function: { name, description, parameters } }。工具名统一使用 Composio 工具 slug因此从tools.get()/session.tools()拿到的数组可以直接透传给 OpenAI 的tools参数。测试与验证该包在两个测试文件中覆盖了完整的契约opeanai-responses.test.ts验证 Provider 名称、wrapTool的 strict 语义可选属性 required-nullable、嵌套可空对象、$defs引用保留、不可表达构造降级、空参数封闭对象、参数去重与归一化、executeToolCall的参数传递含connectedAccountId、customAuthParams、modifiers、handleToolCalls的排序与错误状态、handleResponse对空输出与缺省输出字段的容错openai.test.ts覆盖OpenAIProvider的工具包装、并行工具调用、n 1时仅处理首个 choice、handleAssistantMessage、以及 Assistant API 的轮询/提交逻辑。运行测试的命令为npm testvitest run。你可以用这些用例作为行为基线验证自己的集成代码是否与 Provider 的预期契约一致。小结composio/openai的价值在于把工具获取、格式适配、参数归一、执行回传全部封装进 Provider让 OpenAI 的两种主流调用方式都能以最少的样板代码接入 Composio 工具生态。新项目推荐使用OpenAIResponsesProvider Responses API previous_response_id的循环模式存量 Chat Completions 代码库则直接用默认的OpenAIProvider手动维护消息列表。若需要模型输出严格符合工具 schema可开启strict: true并理解其必填但可空 执行前剥离 null 无法表达时自动降级的三层机制从而写出既稳定又可控的 Agent 工具循环。【免费下载链接】composioComposio powers 1000 toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考