Skip to content

Send tool results as user messages when the template can't show them - #14

Merged
JenD86 merged 1 commit into
mainfrom
fix/tool-role-fallback
Nov 1, 2026
Merged

JenD86 merged 1 commit into
mainfrom
fix/tool-role-fallback

Conversation

@JenD86

@JenD86 JenD86 commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Some chat templates can't show role tool messages, so the model never learns whether its steer/drop/report calls worked:

  • OLMo-2 silently drops them.
  • Mistral-7B-Instruct-v0.3 rejects them: it requires tool-call IDs and strict user/assistant alternation.

Changes

  • modulo/chat.py: supports_tool_role(tokenizer) renders a probe conversation once per tokenizer and caches the result. When tool messages aren't shown, adapt_messages() sends them as user messages starting with [Tool result] and merges consecutive user messages. chat_prompt() applies this automatically. The caller's messages are not modified.
  • agent/loop.py: the session header records tool_role.
  • tests/test_chat.py: CPU tests with stub tokenizers that mimic each failure.
  • AGENTS.md: a support table for the tested models (Qwen2.5, Llama-3.1, OLMo-2, Mistral v0.3, Gemma-2).

Testing

  • CPU tests pass (112 across test_chat, test_agent_logic and test_cli).
  • GPU smoke run, one 3-turn session per model on an RTX 4090:
    • tool_role is True for Qwen2.5 and Llama-3.1, and False for OLMo-2 and Mistral v0.3.
    • All four sessions exited cleanly.
    • OLMo-2 steered creativity +7.5 and later added optimism +8.5, so it now sees its tool results.
    • Mistral no longer errors on tool messages.

🤖 Generated with Claude Code

OLMo-2's chat template silently drops role "tool" messages, and
Mistral-7B-Instruct-v0.3's rejects them (it wants tool-call IDs and strict
user/assistant alternation). Either way the model never learned whether its
steer calls worked.

chat.supports_tool_role() probes the template once per tokenizer. Where tool
messages aren't shown, adapt_messages() sends them as user messages starting
with "[Tool result]" and merges consecutive user messages. Session logs record
tool_role. Checked on a GPU: OLMo-2 now sees its tool results and stacks a
second vector on the first; Mistral no longer errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JenD86
JenD86 merged commit d942d5e into main Nov 1, 2026
1 check 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.

1 participant