Skip to content

Conversation

@enyst
Copy link
Collaborator

@enyst enyst commented Nov 7, 2025

Closes #1085

Summary

  • Port behavior from fix - number and boolean type coercion for function calls OpenHands#9604 into agent-sdk (agent core for V1)
  • Adds type coercion in non-native tool/function call parsing for JSON Schema types:
    • integer (existing), float, number, boolean, array (existing)
  • Ensures boolean values are serialized as lowercase true/false in <parameter=...> blocks
  • Adds unit tests covering round-trip conversion and invalid cases

Motivation
MCP servers often define parameters with JSON Schema types number/boolean. LLMs frequently emit these values as strings in non-native tool call format. Without coercion, calls fail (e.g., "parameter line_number is not of type number"). This change brings agent-sdk in line with the V0 fix to improve MCP tool compatibility.

What changed

  • openhands-sdk/openhands/sdk/llm/mixins/fn_call_converter.py
    • convert_tool_call_to_string: serialize bools using lower-case
    • _extract_and_validate_params: add coercion for float, number, and boolean; preserve existing integer/array handling
  • tests/sdk/llm/test_llm_fncall_converter.py
    • New COERCE_TOOLS schema and tests verifying conversions and validation errors

Backward compatibility

  • No API changes; behavior only extends accepted inputs
  • Existing flows remain intact; only additional coercions are applied when schema declares types

Tests

  • Ran: uv run pre-commit run --files
  • Ran: uv run pytest -q tests/sdk/llm/test_llm_fncall_converter.py
  • All added tests pass

Notes on prior regression in V0 PR
The prior PR reported a slight evaluation decrease. Likely causes include:

  • Over-permissive boolean aliases causing unintended coercion of free-form text
  • LLM behavior changes with stricter/looser parsing affecting prompt-following
  • Distribution variance in eval runs; change is small and may not be statistically significant

Mitigations and improvements (follow-ups proposed):

  • Narrow boolean aliases to strict {'true','false','1','0'} or feature-gate extended aliases
  • Add opt-in flag (or environment variable) to disable coercion per deployment
  • Expand unit tests to include arrays/objects nested in parameters and ensure no silent coercion of invalid forms

Co-authored-by: patonw 4967614-patonw@users.noreply.gitlab.com
Co-authored-by: openhands openhands@all-hands.dev

@enyst can click here to continue refining the PR


Agent Server images for this PR

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python amd64, arm64 nikolaik/python-nodejs:python3.12-nodejs22 Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:240814f-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-240814f-python \
  ghcr.io/openhands/agent-server:240814f-python

All tags pushed for this build

ghcr.io/openhands/agent-server:240814f-golang-amd64
ghcr.io/openhands/agent-server:v1.0.0_golang_tag_1.21-bookworm_binary-amd64
ghcr.io/openhands/agent-server:240814f-golang-arm64
ghcr.io/openhands/agent-server:v1.0.0_golang_tag_1.21-bookworm_binary-arm64
ghcr.io/openhands/agent-server:240814f-java-amd64
ghcr.io/openhands/agent-server:v1.0.0_eclipse-temurin_tag_17-jdk_binary-amd64
ghcr.io/openhands/agent-server:240814f-java-arm64
ghcr.io/openhands/agent-server:v1.0.0_eclipse-temurin_tag_17-jdk_binary-arm64
ghcr.io/openhands/agent-server:240814f-python-amd64
ghcr.io/openhands/agent-server:v1.0.0_nikolaik_s_python-nodejs_tag_python3.12-nodejs22_binary-amd64
ghcr.io/openhands/agent-server:240814f-python-arm64
ghcr.io/openhands/agent-server:v1.0.0_nikolaik_s_python-nodejs_tag_python3.12-nodejs22_binary-arm64
ghcr.io/openhands/agent-server:240814f-golang
ghcr.io/openhands/agent-server:240814f-java
ghcr.io/openhands/agent-server:240814f-python

About Multi-Architecture Support

  • Each variant tag (e.g., 240814f-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 240814f-python-amd64) are also available if needed

… parsing; lowercase bool serialization

- Port of OpenHands/OpenHands#9604 behavior to agent-sdk
- Adds tests for numeric/boolean coercion

Co-authored-by: patonw <4967614-patonw@users.noreply.gitlab.com>
Co-authored-by: openhands <openhands@all-hands.dev>
@github-actions
Copy link
Contributor

github-actions bot commented Nov 7, 2025

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-sdk/openhands/sdk/llm/mixins
   fn_call_converter.py38834910%74–76, 366–381, 383–384, 386, 395–396, 398–401, 403–404, 406–407, 409–410, 412–415, 417–418, 420–421, 423–425, 427, 434, 436, 457–464, 466–470, 474–482, 484–489, 493–501, 503–506, 508, 510–512, 515, 518–520, 522, 527–533, 536–539, 544–545, 548, 550, 555, 557–558, 567, 569–570, 574–578, 582–587, 589, 591, 596, 599, 601–602, 605, 608, 610–614, 620, 642, 647, 657–660, 666–669, 674–680, 682, 684, 688, 691, 693–694, 696–699, 704, 706, 710–711, 715, 721, 723, 726, 734, 736–738, 740–742, 744–746, 752–755, 758–759, 766–772, 775–779, 782–786, 788–790, 793–800, 803–807, 812, 815, 819, 823, 828–829, 832–834, 837, 842–844, 846–847, 863, 875–877, 881–882, 884–887, 889–890, 892–894, 896, 899, 901, 903–905, 907–908, 911–912, 915–917, 919–922, 925, 929, 936–937, 940–941, 955, 961–963, 966–967, 971–972, 978–979, 982, 994, 997–1004, 1008–1009, 1014–1015, 1020, 1026–1029, 1039–1040, 1045, 1051–1052, 1057–1058, 1065, 1068–1070, 1073–1074, 1076, 1082, 1087, 1090, 1094, 1102, 1104–1105, 1108–1110, 1112–1113, 1119–1121, 1123–1124, 1126, 1128, 1132, 1134, 1139, 1141–1142, 1145
TOTAL11777544953% 

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.

[Bug]: mcp tool "number" field incorrect format

2 participants