Files
claude-code/docs/openai-task-tools.md
bonerush 91ee1428fa Fix bug OpenAI tooluse,Improve error messaging for deferred-loading tools under OpenAI‑compatible models. (#199)
* fix: reorder tool and user messages for OpenAI API compatibility (#168)
Fixes #168
OpenAI requires that an assistant message with tool_calls be immediately
followed by tool messages. Previously, convertInternalUserMessage
output user content before tool results, causing 400 errors.
Now tool messages are pushed first.

* fix: 修复OpenAI兼容层中deferred tools处理问题

  提交描述:
  修复了在使用OpenAI兼容API时TaskCreate工具调用失败的问题。

  问题:
  - 当使用OpenAI兼容API模型时,调用TaskCreate工具出现"InputValidationError: The required
  parameter `subject` is missing"错误
  - OpenAI兼容层没有正确处理deferred tools的过滤逻辑,导致工具schema没有被正确发送给模型

  修复:
  1. 在OpenAI兼容层中添加了与Anthropic API路径一致的deferred tools处理逻辑
  2. 导入必要的工具搜索相关函数: isToolSearchEnabled, extractDiscoveredToolNames,
  isDeferredTool等
  3. 实现工具过滤逻辑:
     - 检查工具搜索是否启用
     - 构建deferred tools集合
     - 过滤工具列表: 只包含非deferred工具或已发现的deferred工具
     - 为deferred tools设置deferLoading标志
  4. 修正了extractDiscoveredToolNames函数的导入路径错误

  影响:
  - 解决了TaskCreate工具调用时的参数验证错误
  - 确保OpenAI兼容层与Anthropic API路径在处理deferred tools时行为一致
  - 支持工具搜索功能在OpenAI兼容模式下正常工作

  修改的文件:
  - src/services/api/openai/index.ts - 主要修复文件

  测试建议:
  1. 使用OpenAI兼容API模型时,TaskCreate工具应该可以正常调用
  2. 如果工具搜索功能启用,可能需要先使用ToolSearchTool来发现TaskCreate工具
  3. 验证工具调用时不再出现"InputValidationError"错误

  这个修复确保了当使用OpenAI兼容API(如Ollama、DeepSeek、vLLM等)时,deferred
  tools(如TaskCreate)能够被正确处理,解决了工具调用失败的问题。

* fix: 更新工具模式未发送提示,增加OpenAI兼容模型使用指南
2026-04-08 18:08:59 +08:00

190 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenAI兼容模型中task工具使用指南
## 问题描述
当使用OpenAI兼容模型如DeepSeek、Ollama、vLLM等调用task工具TaskGet、TaskCreate、TaskUpdate、TaskList可能会出现以下错误
```
Error: InputValidationError: TaskGet failed due to the following issues:
The required parameter `taskId` is missing
An unexpected parameter `task_id` was provided
This tool's schema was not sent to the API — it was not in the discovered-tool set derived from message history. Without the schema in your prompt, typed parameters (arrays, numbers, booleans) get emitted as strings and the client-side parser rejects them. Load the tool first: call ToolSearch with query "select:TaskGet", then retry this call.
```
## 问题原因
### 1. 延迟加载工具Deferred Tools
task工具都是延迟加载的`shouldDefer: true`),这意味着:
- 工具的模式schema不会在初始API调用中发送
- 需要先通过`ToolSearch`工具发现
- 只有在被发现后工具模式才会被发送给API
### 2. 参数名转换问题
- task工具使用驼峰命名`taskId`
- OpenAI兼容模型可能输出蛇形命名`task_id`
- 当工具模式没有被发送时,模型会猜测参数名,可能导致不匹配
## 解决方案
### 方案1先使用ToolSearch推荐
在使用task工具之前先调用`ToolSearch`工具:
```javascript
// 第一步发现task工具
ToolSearch("select:TaskGet,TaskCreate,TaskUpdate,TaskList")
// 第二步正常使用task工具
TaskCreate({ subject: "任务标题", description: "任务描述" })
TaskGet({ taskId: "1" })
TaskUpdate({ taskId: "1", status: "completed" })
TaskList()
```
### 方案2批量发现所有task工具
```javascript
// 一次性发现所有task工具
ToolSearch("select:TaskGet,TaskCreate,TaskUpdate,TaskList")
// 然后可以任意使用task工具
const task = await TaskCreate({ subject: "新任务", description: "任务描述" })
console.log(`创建的任务ID: ${task.id}`)
const taskList = await TaskList()
console.log(`当前有 ${taskList.tasks.length} 个任务`)
```
### 方案3单独发现特定工具
```javascript
// 只发现需要的工具
ToolSearch("select:TaskGet")
// 然后使用该工具
TaskGet({ taskId: "1" })
```
## 参数名注意事项
在使用OpenAI兼容模型时请注意参数名格式
### ✅ 正确(驼峰命名)
```javascript
TaskGet({ taskId: "1" })
TaskCreate({ subject: "标题", description: "描述" })
TaskUpdate({ taskId: "1", status: "completed" })
```
### ❌ 错误(蛇形命名)
```javascript
TaskGet({ task_id: "1" }) // 错误应该使用taskId
TaskCreate({ subject: "标题", description: "描述" }) // 正确
TaskUpdate({ task_id: "1", status: "completed" }) // 错误应该使用taskId
```
## 常见问题解答
### Q1: 为什么需要先使用ToolSearch
A: task工具是延迟加载的它们的模式只有在被`ToolSearch`工具发现后才会发送给API。没有工具模式模型无法知道正确的参数名和类型。
### Q2: 每次会话都需要使用ToolSearch吗
A: 是的每次新的会话都需要先使用ToolSearch发现工具。工具发现状态不会在会话之间保留。
### Q3: 使用Anthropic官方模型也需要这样吗
A: 通常不需要。Anthropic官方模型对延迟加载工具的处理更智能但为了兼容性建议在使用task工具前都先使用ToolSearch。
### Q4: 可以一次性发现所有工具吗?
A: 可以,使用`ToolSearch("select:TaskGet,TaskCreate,TaskUpdate,TaskList")`可以一次性发现所有task工具。
### Q5: 如果忘记使用ToolSearch会怎样
A: 会收到参数验证错误提示需要先使用ToolSearch。按照错误信息的指导操作即可。
## 最佳实践
1. **会话开始时发现工具**在开始使用task工具前先调用ToolSearch
2. **批量发现**一次性发现所有需要的task工具
3. **检查参数名**:确保使用正确的驼峰命名参数
4. **查看错误信息**:如果遇到错误,仔细阅读错误信息中的指导
## 示例工作流
```javascript
// 1. 开始新会话
// 2. 发现task工具
ToolSearch("select:TaskGet,TaskCreate,TaskUpdate,TaskList")
// 3. 创建任务
const newTask = await TaskCreate({
subject: "修复OpenAI兼容性问题",
description: "解决task工具在OpenAI兼容模型下的参数名问题"
})
// 4. 获取任务详情
const taskDetails = await TaskGet({ taskId: newTask.id })
// 5. 更新任务状态
await TaskUpdate({
taskId: newTask.id,
status: "in_progress",
activeForm: "修复OpenAI兼容性问题"
})
// 6. 查看所有任务
const allTasks = await TaskList()
console.log(`当前有 ${allTasks.tasks.length} 个任务`)
// 7. 完成任务
await TaskUpdate({
taskId: newTask.id,
status: "completed"
})
```
## 故障排除
### 错误:参数名不匹配
**症状**`taskId`参数缺失,发现`task_id`参数
**解决**:确保使用驼峰命名的`taskId`,而不是蛇形命名的`task_id`
### 错误:工具模式未发送
**症状**`This tool's schema was not sent to the API`
**解决**:先使用`ToolSearch("select:工具名")`发现工具
### 错误:工具不可用
**症状**:工具调用失败,没有具体错误信息
**解决**:检查工具是否启用(通过`isTodoV2Enabled()`),确保环境变量设置正确
## 相关配置
### 环境变量
```bash
# 启用OpenAI兼容模式
export CLAUDE_CODE_USE_OPENAI=1
export OPENAI_API_KEY=your-api-key
export OPENAI_BASE_URL=https://api.deepseek.com
# 配置模型映射
export OPENAI_DEFAULT_SONNET_MODEL=deepseek-chat
export OPENAI_DEFAULT_OPUS_MODEL=deepseek-chat
export OPENAI_DEFAULT_HAIKU_MODEL=deepseek-chat
```
### 设置文件
通过`/login`命令配置OpenAI兼容模式后设置会保存在`~/.claude/settings.json`
```json
{
"modelType": "openai",
"openai": {
"baseURL": "https://api.deepseek.com",
"apiKey": "your-api-key",
"models": {
"haiku": "deepseek-chat",
"sonnet": "deepseek-chat",
"opus": "deepseek-chat"
}
}
}
```
## 总结
在使用OpenAI兼容模型时task工具需要先通过`ToolSearch`发现才能正常使用。遵循"先发现,后使用"的原则并注意参数名的正确格式驼峰命名可以确保task工具在OpenAI兼容模型下正常工作。