Skip to content

bug: ToolManager promises type coercion but passes strings to tools #276

@BhoomiAgrawal12

Description

@BhoomiAgrawal12

Describe the bug
ToolManager claims to perform automatic type coercion, but _process_tool_call() passes LLM JSON string values directly to tools. Tools annotated with float/int receive strings and fail (often returning an error string in tool responses).

Expected behavior
If a tool parameter is annotated as float or int, values like "35.0" or "5" from LLM JSON should be coerced to 35.0 and 5 before the tool is invoked.

To Reproduce

  1. Create a tool with an annotated numeric parameter (float or int).
  2. Invoke it through ToolManager.call_tools() with JSON string values.
  3. Observe the tool fails or returns an error response.

Minimal reproducible example:

from mesa_llm.tools.tool_decorator import tool
from mesa_llm.tools.tool_manager import ToolManager
import json
from unittest.mock import MagicMock

tm = ToolManager()

@tool(tool_manager=tm)
def set_value(agent, amount: float) -> str:
    return f"Set to {amount:.2f}"

tool_call = MagicMock()
tool_call.function.name = "set_value"
tool_call.function.arguments = json.dumps({"amount": "35.0"})  # string from LLM
tool_call.id = "tc_001"

class FakeAgent:
    model = MagicMock()

results = tm.call_tools(FakeAgent(), MagicMock(tool_calls=[tool_call]))
print(results)
# Expected: [{'response': 'Set to 35.00', ...}]
# Actual:   [{'response': "Error: Unknown format code 'f' for object of type 'str'", ...}]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions