Skip to content

fix(chat_completions): strip tool_name from messages for strict providers#28958

Closed
savanne-kham wants to merge 1 commit into
NousResearch:mainfrom
savanne-kham:fix/strip-tool-name-strict-providers
Closed

fix(chat_completions): strip tool_name from messages for strict providers#28958
savanne-kham wants to merge 1 commit into
NousResearch:mainfrom
savanne-kham:fix/strip-tool-name-strict-providers

Conversation

@savanne-kham

@savanne-kham savanne-kham commented May 19, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

The internal tool_name key on role=tool messages — stored in the
messages.tool_name SQLite column for FTS indexing — is not part of the
OpenAI Chat Completions schema. Strict OpenAI-compatible providers, notably
Moonshot AI (Kimi), reject any request containing it with HTTP 400:

Error from provider: Extra inputs are not permitted,
field: 'messages[N].tool_name', value: 'execute_code'

This PR adds tool_name to the sanitize block in
ChatCompletionsTransport.convert_messages, alongside the existing
Codex Responses API fields (codex_reasoning_items, codex_message_items),
so it is popped before the request is sent.

The strip is unconditional (matches the existing Codex-strip pattern):
tool_name is never part of any documented OpenAI Chat Completions payload,
so removing it before send is safe for every provider while fixing the
strict ones. Permissive backends (MiniMax, OpenRouter on most routes) were
ignoring the extra field and masking the bug.

Related Issue

Fixes #

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • agent/transports/chat_completions.py — extend the needs_sanitize
    detection and the per-message pop step in convert_messages to cover
    the tool_name key.
  • tests/agent/transports/test_chat_completions.py — add
    test_convert_messages_strips_tool_name covering both the strip on the
    returned list and the deepcopy-on-demand contract (original input
    untouched).

How to Test

Reproducer:

hermes chat --model kimi-k2.6
> list the top 5 Hacker News stories

Before the fix:

  1. assistant emits tool_call(execute_code)
  2. the tool result message is persisted with tool_name='execute_code'
  3. the next-turn payload includes messages[N].tool_name
  4. Kimi rejects with HTTP 400 (Extra inputs are not permitted, field: 'messages[N].tool_name')

After the fix:

  1. Same flow, but convert_messages strips tool_name before send.
  2. Request succeeds, multi-turn tool-using conversations complete normally
    on kimi-k2.6 (verified end-to-end on macOS 15.x, Hermes Agent v0.14.0).

Automated:

pytest tests/agent/transports/test_chat_completions.py -q

The new test (test_convert_messages_strips_tool_name) asserts:

  • tool_name is removed from the returned message
  • tool_call_id and content are preserved
  • the original input list is unmodified (deepcopy-on-demand contract)

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(chat_completions): …)
  • I searched for existing PRs/issues — none target this specific field
  • My PR contains only changes related to this fix
  • I've run pytest tests/agent/transports/test_chat_completions.py -q and all tests pass
  • I've added a test for the fix
  • I've tested on my platform: macOS 15.x (Apple Silicon)

Documentation & Housekeeping

  • N/A — no public docs reference the internal tool_name field
  • N/A — no config keys added/changed
  • N/A — no architectural or workflow changes
  • Cross-platform: the change is a pure dictionary pop, no platform-specific behavior
  • N/A — no tool descriptions/schemas changed

…ders

The 'tool_name' key on role=tool messages is an internal Hermes field
(stored in the messages.tool_name SQLite column for FTS indexing) that
is not part of the OpenAI Chat Completions schema. Strict OpenAI-compatible
providers — notably Moonshot AI (Kimi) — reject it with HTTP 400:

  Error from provider: Extra inputs are not permitted,
  field: 'messages[N].tool_name', value: 'execute_code'

Add 'tool_name' to the sanitize block in ChatCompletionsTransport.convert_messages
alongside the existing Codex Responses API fields (codex_reasoning_items,
codex_message_items) so it is popped before the request is sent.

Reproducer:
  hermes chat --model kimi-k2.6
  > list the top 5 Hacker News stories
  -> assistant emits tool_call(execute_code)
  -> tool result message gets tool_name='execute_code'
  -> next turn's payload includes messages[N].tool_name -> 400

Permissive backends (MiniMax, OpenRouter on most routes) ignore the extra
field and were masking the bug.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent loop, run_agent.py, prompt builder provider/kimi Kimi / Moonshot labels May 19, 2026
teknium1 added a commit that referenced this pull request May 20, 2026
Salvage follow-up to PR #28958 (savanne-kham):

- convert_messages() docstring now explicitly documents the tool_name strip
  alongside Codex fields, names which providers reject it (Fireworks,
  Moonshot/Kimi), and why permissive providers (OpenRouter, MiniMax)
  masked the bug.
- AUTHOR_MAP entry for savanne.kham@protonmail.com -> savanne-kham.
@teknium1

Copy link
Copy Markdown
Contributor

Merged via #29126 on current main — your commit cab9bc5 landed with your authorship preserved via rebase-merge. Thanks for the clean repro and the minimal pattern-match fix.

Merge commit: 42c4288

Lillard01 pushed a commit to Lillard01/hermes-agent that referenced this pull request May 21, 2026
Salvage follow-up to PR NousResearch#28958 (savanne-kham):

- convert_messages() docstring now explicitly documents the tool_name strip
  alongside Codex fields, names which providers reject it (Fireworks,
  Moonshot/Kimi), and why permissive providers (OpenRouter, MiniMax)
  masked the bug.
- AUTHOR_MAP entry for savanne.kham@protonmail.com -> savanne-kham.
@savanne-kham savanne-kham deleted the fix/strip-tool-name-strict-providers branch May 22, 2026 13:24
Gpapas pushed a commit to Gpapas/hermes-agent that referenced this pull request May 23, 2026
Salvage follow-up to PR NousResearch#28958 (savanne-kham):

- convert_messages() docstring now explicitly documents the tool_name strip
  alongside Codex fields, names which providers reject it (Fireworks,
  Moonshot/Kimi), and why permissive providers (OpenRouter, MiniMax)
  masked the bug.
- AUTHOR_MAP entry for savanne.kham@protonmail.com -> savanne-kham.
Mucky010 pushed a commit to Mucky010/hermes-agent that referenced this pull request May 24, 2026
Salvage follow-up to PR NousResearch#28958 (savanne-kham):

- convert_messages() docstring now explicitly documents the tool_name strip
  alongside Codex fields, names which providers reject it (Fireworks,
  Moonshot/Kimi), and why permissive providers (OpenRouter, MiniMax)
  masked the bug.
- AUTHOR_MAP entry for savanne.kham@protonmail.com -> savanne-kham.
Bryce-huang pushed a commit to wbkunlun/hermes-agent that referenced this pull request May 29, 2026
Salvage follow-up to PR NousResearch#28958 (savanne-kham):

- convert_messages() docstring now explicitly documents the tool_name strip
  alongside Codex fields, names which providers reject it (Fireworks,
  Moonshot/Kimi), and why permissive providers (OpenRouter, MiniMax)
  masked the bug.
- AUTHOR_MAP entry for savanne.kham@protonmail.com -> savanne-kham.

#AI commit#
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
Salvage follow-up to PR NousResearch#28958 (savanne-kham):

- convert_messages() docstring now explicitly documents the tool_name strip
  alongside Codex fields, names which providers reject it (Fireworks,
  Moonshot/Kimi), and why permissive providers (OpenRouter, MiniMax)
  masked the bug.
- AUTHOR_MAP entry for savanne.kham@protonmail.com -> savanne-kham.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder P2 Medium — degraded but workaround exists provider/kimi Kimi / Moonshot type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants