makecindy / makecindy/cindy

Codex runtime 对自定义 OpenAI 兼容供应商发送的 tools 格式不正确,导致 function calling 失败(missing tools.function parameter)

Open
#2,328 1 comment 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
2.7k
Forks
395
Avg merge
21h 48m
Merged PRs (30d)
776

Description

**提交人**: 莫里里
**客户端版本**: 0.1.38

---

## 现象

在模型供应商中添加自定义 OpenAI 兼容供应商(火山方舟豆包 Doubao API),使用 Codex runtime 时:
- **测试连接成功**
- 但实际对话报错:`API Error: 400 The request failed because it is missing 'tools.function' parameter`

同样的 Base URL 和 API Key 在其他 OpenAI 兼容客户端中可以正常调用,说明 API 本身没有问题。

供应商配置:
- Runtime:Codex
- 基础 URL:`https://ark.cn-beijing.volces.com/api/v3`
- 精确请求路径:`/chat/completions`(留空会拼成 `/v1/chat/completions` 导致 404)
- 模型:Doubao-Seed-Evolving(Model ID: `doubao-seed-evolving`,接入点 ID `ep-m-20260704191542-jcbhd` 也试过,均报错)
- 鉴权方式:API 密钥

## 复现步骤

1. 在设置 → 模型供应商中添加自定义供应商
2. 切换到 Codex 标签页,填入火山方舟的 Base URL、API Key
3. 精确请求路径填 `/chat/completions`(因为火山方舟路径是 `/api/v3/chat/completions`,没有 `/v1`)
4. 模型 ID 填入豆包模型 ID 或接入点 ID
5. 测试连接 → 成功
6. 在对话中选择该模型发送消息 → 报错 `missing tools.function parameter`

## 期望行为

Codex runtime 向 `/chat/completions` 端点发送请求时,`tools` 数组应使用标准 Chat Completions 格式:

```json
{
"tools": [
{
"type": "function",
"function": {
"name": "tool_name",
"description": "...",
"parameters": { ... }
}
}
]
}
```

## 实际行为

看起来 Codex runtime 发送的是 OpenAI 最新的 Responses API 格式,`tools` 的参数平铺在外层,缺少 `function` 嵌套层:

```json
{
"tools": [
{
"type": "function",
"name": "tool_name",
"description": "...",
"parameters": { ... }
}
]
}
```

导致第三方 OpenAI 兼容 API(火山方舟豆包)无法识别,返回 `missing tools.function parameter`。普通不带 tools 的请求(测试连接)可以正常通过。

## 建议

当自定义供应商配置的请求路径是 `/chat/completions`(Chat Completions 端点)时,Codex runtime 应将 tools 从 Responses API 格式自动转换为 Chat Completions 格式(嵌套 `function` 字段)。或者提供一个选项让用户选择使用 Chat Completions 协议还是 Responses API 协议。
---
**版本区域**: CN
**OS**: win32 x64 (10.0.19045)
**界面语言**: zh-CN

Contributor guide

Open the contributing guide

Research direction

Start at the Codex runtime request builder for the /chat/completions endpoint and inspect how tool definitions are serialized. Compare the emitted payload with the standard nested function shape described here, then add or update regression coverage so a custom OpenAI-compatible provider sends that shape and the failing request succeeds.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.