[GH-ISSUE #197] bug: every tool call renders as agent_tool to OpenAI-compatible clients #117

Closed
opened 2026-10-18 14:03:05 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @penradioGables on GitHub (Jul 28, 2026).
Original GitHub issue: https://github.com/open-webui/computer/issues/197

Summary

Every tool call in an assistant response renders to OpenAI-compatible clients as the literal text `agent_tool` — whether it was Bash, Read, Edit, or Grep. Two halves of the code disagree about where the tool name lives.

Verified still present in v0.9.15 — both cptr/utils/agents/claude_code.py and cptr/routers/gateway.py are byte-identical between the v0.9.10 and v0.9.15 tags.

Root cause

The Claude Code and opencode adapters deliberately emit a placeholder name and stash the real one under arguments["title"] (claude_code.py L88):

        AgentToolUpdate(
            call_id=call_id.strip(),
            name="agent_tool",
            status="in_progress",
            arguments={"title": name, **arguments},
        ),

…while the gateway's renderer reads only item["name"] (gateway.py L64–69):

def _format_tool_call(item: dict) -> str | None:
    """Render a tool call as compact markdown for OpenAI-compatible clients."""
    if item.get("type") != "function_call" or item.get("status") != "in_progress":
        return None

    return f"\n\n`{item.get('name', 'tool')}`\n\n"

Adapters that don't use the title convention (codex, pi) render correctly, which is presumably how this survived — it only affects the adapters that set the placeholder.

This is cosmetic but total: in Open WebUI every tool call is indistinguishable from every other one, which reads as noise rather than as signal.

Suggested fix

Prefer arguments["title"] when present, fall back to item["name"]. That is a no-op for codex/pi and fixes claude_code/opencode.

Interaction with the missing-arguments issue, worth deciding together

The natural follow-on — rendering the argument too, e.g. `Bash` — `git status --short` — is impossible while tool arguments are dropped at ingest (filed separately), and still impossible at status == "in_progress" even after that is fixed, because the arguments genuinely have not been streamed yet at that point.

Making that work means moving the render to status == "completed". That costs nothing in latency: "completed" here means the model finished emitting the call, not the tool finished running.

Happy to open a PR for the name fix alone, or for both together if you want the argument rendered.

Originally created by @penradioGables on GitHub (Jul 28, 2026). Original GitHub issue: https://github.com/open-webui/computer/issues/197 ### Summary Every tool call in an assistant response renders to OpenAI-compatible clients as the literal text `` `agent_tool` `` — whether it was Bash, Read, Edit, or Grep. Two halves of the code disagree about where the tool name lives. **Verified still present in v0.9.15** — both `cptr/utils/agents/claude_code.py` and `cptr/routers/gateway.py` are byte-identical between the `v0.9.10` and `v0.9.15` tags. ### Root cause The Claude Code and opencode adapters deliberately emit a placeholder name and stash the real one under `arguments["title"]` (`claude_code.py` L88): ```python AgentToolUpdate( call_id=call_id.strip(), name="agent_tool", status="in_progress", arguments={"title": name, **arguments}, ), ``` …while the gateway's renderer reads only `item["name"]` (`gateway.py` L64–69): ```python def _format_tool_call(item: dict) -> str | None: """Render a tool call as compact markdown for OpenAI-compatible clients.""" if item.get("type") != "function_call" or item.get("status") != "in_progress": return None return f"\n\n`{item.get('name', 'tool')}`\n\n" ``` Adapters that don't use the title convention (codex, pi) render correctly, which is presumably how this survived — it only affects the adapters that set the placeholder. This is cosmetic but total: in Open WebUI every tool call is indistinguishable from every other one, which reads as noise rather than as signal. ### Suggested fix Prefer `arguments["title"]` when present, fall back to `item["name"]`. That is a no-op for codex/pi and fixes claude_code/opencode. ### Interaction with the missing-arguments issue, worth deciding together The natural follow-on — rendering the argument too, e.g. `` `Bash` — `git status --short` `` — is impossible while tool arguments are dropped at ingest (filed separately), **and** still impossible at `status == "in_progress"` even after that is fixed, because the arguments genuinely have not been streamed yet at that point. Making that work means moving the render to `status == "completed"`. That costs nothing in latency: "completed" here means *the model finished emitting the call*, not *the tool finished running*. Happy to open a PR for the name fix alone, or for both together if you want the argument rendered.
Author
Owner

@tjbck commented on GitHub (Jul 31, 2026):

Addressed!

<!-- gh-comment-id:5147977354 --> @tjbck commented on GitHub (Jul 31, 2026): Addressed!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
open-webui/computer#117
No description provided.