OpenHands / OpenHands/software-agent-sdk

[Bug]: Tool calls return incorrect/weird syntax with Synthetic Provider

Open
#4,540 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug llm priority:medium ready-for-dev
Dominant language
Python
Stars
1.1k
Forks
539
Avg merge
1d 19h
Merged PRs (30d)
137

Description

Operating System

Linux

Installation Method

Docker (ghcr.io/openhands/agent-canvas)

Agent Canvas Version

1.14.0

Bug Description

I'm using the Synthetic provider and noticed that whenever a model attempts to make a tool call, it sometimes returns the tool call as strange/raw syntax instead of actually invoking the tool.

I've observed this behavior with both:

GLM 5.2
Kimi K3

Normal text responses work correctly. The issue appears specifically when tool/function calling is involved.

Steps to Reproduce
  1. Use llm from synthetic provider
  2. Get weird syntax when tool call involved
Actual Behavior

Calling the SDK converter on main leaves the raw wrapper as text and produces no tool call:

from openhands.sdk.llm.mixins.fn_call_converter import (
    convert_non_fncall_messages_to_fncall_messages,
)

tools = [{"type": "function", "function": {"name": "terminal", "parameters": {"type": "object", "properties": {"command": {"type": "string"}}}}}]
messages = [
    {"role": "user", "content": "run ls"},
    {"role": "assistant", "content": "<tool_call>terminal\n<parameter=command>ls</parameter>\n</tool_call>"},
]
result = convert_non_fncall_messages_to_fncall_messages(messages, tools)
# Expected: a structured tool_call for `terminal`.
# Observed on main: no tool call; raw <tool_call> syntax stays in the text.
Expected Behavior

The model should return a properly formatted tool call that the client can recognize and execute.

Relevant Logs

Acceptance Criteria
  • A <tool_call>-wrapped model response is converted into a structured tool call rather than leaking into the assistant text.
  • Plain prose mentioning <tool_call> is not converted into a call.
Screenshots
Image
Additional Context

Somehow it's working fine with the free kimi k3 from openhand.
Tested with native toolcall both enabled and disabled with same issue.
API Mode is using /chat

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in openhands/sdk/llm/mixins/fn_call_converter.py at convert_non_fncall_messages_to_fncall_messages, using the supplied Synthetic-provider reproduction as the first check. Trace how the wrapped terminal response is parsed and compare it with plain prose containing the same marker. Done means wrapped responses become structured tool calls while ordinary prose remains unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.