Skip to content

Fix bug OpenAI tooluse,Improve error messaging for deferred-loading tools under OpenAI‑compatible models.#199

Merged
claude-code-best merged 4 commits intoclaude-code-best:mainfrom
bonerush:fix-bug-openai-tooluse
Apr 8, 2026
Merged

Fix bug OpenAI tooluse,Improve error messaging for deferred-loading tools under OpenAI‑compatible models.#199
claude-code-best merged 4 commits intoclaude-code-best:mainfrom
bonerush:fix-bug-openai-tooluse

Conversation

@bonerush
Copy link
Copy Markdown
Contributor

@bonerush bonerush commented Apr 8, 2026

PR Title: Improve error messaging for deferred-loading tools under OpenAI‑compatible models

Reference: #188 (resolved; remaining minor bugs addressed separately)

Overview

This commit improves the error hint shown when a deferred‑loading tool (specifically the task family of tools) is invoked before its schema has been discovered, particularly when using OpenAI‑compatible models like DeepSeek, Ollama, vLLM, etc.

Background

When working with OpenAI‑compatible backends, deferred‑loading tools such as TaskGet, TaskCreate, TaskUpdate, and TaskList must first have their schemas discovered via the ToolSearch tool before they can be used correctly. The previous error message did not adequately guide the model toward the required discovery flow.

Changes

File: src/services/tools/toolExecution.ts:589-606

Enhancements:

  • Clearer error structure

    • Explicitly states that the tool is deferred‑loading and must be discovered first.
    • Provides specific steps for OpenAI‑compatible model users.
  • Detailed usage guidance

    • Step‑by‑step instructions: call ToolSearch, then call the target tool.
    • Includes example invocation formats.
  • Important notes

    • Emphasizes that parameter names must use camelCase (e.g., taskId), not snake_case (task_id).
    • Clarifies that all task tools require discovery before use.
    • Shows how to batch‑discover multiple tools at once.

Technical Details

  • Function: buildSchemaNotSentHint()
  • Change: Rewritten error hint generation logic
  • Impact: When a model attempts to use an undiscovered deferred tool, a more helpful and actionable message is displayed.

Example Comparison

Before:

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.

After:

Tool "TaskGet" is deferred-loading and needs to be discovered before use.
When using OpenAI-compatible models (DeepSeek, Ollama, etc.), follow these steps:
1. First discover the tool with ToolSearch: ToolSearch("select:TaskGet")
2. Then call TaskGet tool

Example:
ToolSearch("select:TaskGet") → TaskGet({ ... })

Important notes:
• Use camelCase parameter names (e.g., taskId), not snake_case (task_id)
• All task tools (TaskGet, TaskCreate, TaskUpdate, TaskList) need to be discovered first
• You can discover them all at once: ToolSearch("select:TaskGet,TaskCreate,TaskUpdate,TaskList")

See docs/openai-task-tools.md for detailed guide.

Related Issues

Summary by CodeRabbit

Release Notes

  • Documentation

    • Added comprehensive guide for using task tools with OpenAI-compatible models (DeepSeek, Ollama, vLLM), including troubleshooting and best practices.
  • New Features

    • Implemented tool discovery mechanism enabling proper loading of deferred tools.
  • Bug Fixes

    • Enhanced error messages to guide users through tool discovery process when tools fail to initialize.

bonerush added 4 commits April 7, 2026 17:22
…ude-code-best#168)

Fixes claude-code-best#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.
  提交描述:
  修复了在使用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)能够被正确处理,解决了工具调用失败的问题。
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 8, 2026

📝 Walkthrough

Walkthrough

New documentation for OpenAI-compatible models' task tools usage. Implementation adds conditional tool search to filter deferred tools based on discovery status, reorders tool result messages in conversion logic, and updates error hints to guide users on tool discovery prerequisites.

Changes

Cohort / File(s) Summary
Documentation
docs/openai-task-tools.md
New guide for OpenAI-compatible models on task tools (TaskGet/TaskCreate/TaskUpdate/TaskList), covering InputValidationError cases, ToolSearch discovery patterns, camelCase vs snake_case parameter naming, best practices, troubleshooting, and complete workflow examples.
Tool Search & Filtering
src/services/api/openai/index.ts
Implements conditional tool search: checks isToolSearchEnabled(), filters tools to exclude deferred tools unless discovered via extractDiscoveredToolNames(), sets deferLoading flag per tool schema, and adds debug logging for tool search status.
Tool Result Message Ordering
src/services/api/openai/convertMessages.ts
Reorders tool result conversion in convertInternalUserMessage: tool_result blocks now appended immediately after collection and before user message content, ensuring correct OpenAI tool_call message ordering.
Tool Execution Hints
src/services/tools/toolExecution.ts
Updates buildSchemaNotSentHint with user-facing tool names, explicit ToolSearch discovery step-by-step instructions with examples, camelCase/snake_case notes, and reference to docs/openai-task-tools.md documentation.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant OpenAI_API as OpenAI Handler<br/>(index.ts)
    participant ToolSearch
    participant Deferred_Loader
    participant Converter as Message Converter<br/>(convertMessages.ts)

    Client->>OpenAI_API: queryModelOpenAI(messages, tools)
    OpenAI_API->>OpenAI_API: isToolSearchEnabled()?
    
    alt Tool Search Enabled
        OpenAI_API->>ToolSearch: extractDiscoveredToolNames(messages)
        ToolSearch-->>OpenAI_API: discovered tool names
        
        OpenAI_API->>Deferred_Loader: isDeferredTool(tool) for each tool
        Deferred_Loader-->>OpenAI_API: deferred tool names set
        
        OpenAI_API->>OpenAI_API: filterTools: keep non-deferred<br/>+ ToolSearchTool<br/>+ discovered deferred tools
    else Tool Search Disabled
        OpenAI_API->>OpenAI_API: use all tools
    end
    
    OpenAI_API->>OpenAI_API: build tool schemas<br/>with deferLoading flag
    OpenAI_API->>Client: send filtered tools to API
    
    Client-->>OpenAI_API: tool_result in response
    OpenAI_API->>Converter: convertInternalUserMessage()
    
    Converter->>Converter: append tool_results<br/>BEFORE user content
    Converter-->>OpenAI_API: converted messages
    OpenAI_API-->>Client: processed message stream
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

  • PR #177: Modifies convertMessages.ts to reorder tool messages so tool_call results emit immediately, directly related to tool result message ordering changes in this PR.
  • PR #193: Implements conditional tool search and deferred-tool filtering logic in index.ts, directly related to the core tool search feature added here.

Suggested reviewers

  • KonghaYao

Poem

🐰 A rabbit hops through deferred tool trails,
Searching for tasks before loading sails,
camelCase names in the burrow so deep,
Discovery first, then promises to keep! 🔍✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main changes: fixing a bug in OpenAI tool use and improving error messaging for deferred-loading tools, which align with the commits and file modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/services/api/openai/convertMessages.ts (1)

95-102: Update placeholder issue reference.

Line 99 references #xxx which appears to be a placeholder. Consider updating to the actual issue number (likely #168 based on commit messages) or removing if not needed.

📝 Proposed fix
-    // See: https://github.com/anthropics/claude-code/issues/xxx
+    // See: https://github.com/anthropics/claude-code/issues/168
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/services/api/openai/convertMessages.ts` around lines 95 - 102, Update the
placeholder issue reference in the comment above the tool message loop: replace
the `#xxx` placeholder with the correct issue number (likely `#168`) or remove
the reference entirely; the relevant context is the comment immediately
preceding the for-loop that iterates over `toolResults` and calls
`convertToolResult(tr)` to push into `result`, so edit that comment text to
include the real issue link or drop it.
docs/openai-task-tools.md (1)

7-13: Add language specifier to fenced code block.

The error example code block is missing a language specifier, which affects rendering and accessibility.

📝 Proposed fix
-```
+```text
 Error: InputValidationError: TaskGet failed due to the following issues:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/openai-task-tools.md` around lines 7 - 13, The fenced code block that
begins with the line "Error: InputValidationError: TaskGet failed due to the
following issues:" is missing a language specifier; update the opening
triple-backtick so it reads ```text (i.e., add the "text" language specifier) to
ensure proper rendering and accessibility of the example error block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/services/tools/toolExecution.ts`:
- Around line 593-595: The code assigns toolDisplayName directly from
tool.userFacingName(undefined) which can be an empty string; change the
assignment so it falls back to tool.name when userFacingName returns a
falsy/empty value. Update the toolDisplayName expression in toolExecution.ts
(the variable named toolDisplayName) to call tool.userFacingName(undefined),
trim the result and if it's empty or falsy use tool.name instead (e.g., result =
tool.userFacingName ? (tool.userFacingName(undefined)?.trim() || tool.name) :
tool.name). Ensure this covers tools like TeamCreateTool, TodoWriteTool,
TeamDeleteTool, ToolSearchTool, TaskStopTool that return "".

---

Nitpick comments:
In `@docs/openai-task-tools.md`:
- Around line 7-13: The fenced code block that begins with the line "Error:
InputValidationError: TaskGet failed due to the following issues:" is missing a
language specifier; update the opening triple-backtick so it reads ```text
(i.e., add the "text" language specifier) to ensure proper rendering and
accessibility of the example error block.

In `@src/services/api/openai/convertMessages.ts`:
- Around line 95-102: Update the placeholder issue reference in the comment
above the tool message loop: replace the `#xxx` placeholder with the correct
issue number (likely `#168`) or remove the reference entirely; the relevant
context is the comment immediately preceding the for-loop that iterates over
`toolResults` and calls `convertToolResult(tr)` to push into `result`, so edit
that comment text to include the real issue link or drop it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9839912e-101b-407d-8ce6-bbb52491f059

📥 Commits

Reviewing files that changed from the base of the PR and between d52300f and 734e5d7.

📒 Files selected for processing (4)
  • docs/openai-task-tools.md
  • src/services/api/openai/convertMessages.ts
  • src/services/api/openai/index.ts
  • src/services/tools/toolExecution.ts

Comment on lines +593 to +595
const toolDisplayName = tool.userFacingName
? tool.userFacingName(undefined)
: tool.name
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if any deferred tools define userFacingName that could return undefined
ast-grep --pattern $'shouldDefer: true'
echo "---"
# Check userFacingName implementations in tool files
rg -n "userFacingName" --type=ts -A 3 | head -80

Repository: claude-code-best/claude-code

Length of output: 4793


Handle case where userFacingName returns an empty string.

Several tools (TeamCreateTool, TodoWriteTool, TeamDeleteTool, ToolSearchTool, TaskStopTool) define userFacingName to return an empty string. The current code will assign an empty string to toolDisplayName instead of falling back to tool.name, resulting in confusing error messages like Tool "" is deferred-loading....

🛡️ Proposed fix with fallback
-  const toolDisplayName = tool.userFacingName
-    ? tool.userFacingName(undefined)
-    : tool.name
+  const toolDisplayName = tool.userFacingName?.(undefined) || tool.name
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const toolDisplayName = tool.userFacingName
? tool.userFacingName(undefined)
: tool.name
const toolDisplayName = tool.userFacingName?.(undefined) || tool.name
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/services/tools/toolExecution.ts` around lines 593 - 595, The code assigns
toolDisplayName directly from tool.userFacingName(undefined) which can be an
empty string; change the assignment so it falls back to tool.name when
userFacingName returns a falsy/empty value. Update the toolDisplayName
expression in toolExecution.ts (the variable named toolDisplayName) to call
tool.userFacingName(undefined), trim the result and if it's empty or falsy use
tool.name instead (e.g., result = tool.userFacingName ?
(tool.userFacingName(undefined)?.trim() || tool.name) : tool.name). Ensure this
covers tools like TeamCreateTool, TodoWriteTool, TeamDeleteTool, ToolSearchTool,
TaskStopTool that return "".

@claude-code-best claude-code-best merged commit 91ee142 into claude-code-best:main Apr 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants