I tried using a custom tool, but when I ran it, it only returned some errors

I tried using a custom tool, but when it, it only returned some errors.

exception:

Traceback (most recent call last):
  File "e:\AgentDemo\AgentWarDemo\main.py", line 13, in <module>
    asyncio.run(game.loop_game())
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 195, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\asyncio\base_events.py", line 691, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "e:\AgentDemo\AgentWarDemo\game\GameBoard.py", line 59, in loop_game
    await self.excute_turn()
  File "e:\AgentDemo\AgentWarDemo\game\GameBoard.py", line 154, in excute_turn
    role.decision_agent.plan()
  File "e:\AgentDemo\AgentWarDemo\AgnoAgent\DecisionAgent.py", line 32, in plan
    response:RunResponse = self.agent.run(dedent("""
                           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\site-packages\agno\agent\agent.py", line 981, in run
    return next(resp)
           ^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\site-packages\agno\agent\agent.py", line 696, in _run
    model_response = self.model.response(messages=run_messages.messages)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\site-packages\agno\models\base.py", line 175, in response
    assistant_message, has_tool_calls = self._process_model_response(
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\site-packages\agno\models\base.py", line 328, in _process_model_response
    assistant_message.log(metrics=True)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\site-packages\agno\models\message.py", line 321, in log
    for k, v in json.loads(tool_call_arguments).items():
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'items'

I try to print the tools call:

tool_calls: [{'id': '0195d2b98cfd43cc27de31735eec0a52', 'function': {'arguments': '{}', 'name': 'get_role_sight'}, 'type': 'function'}]
tool_calls: [{'id': '0195d2b9923254e3e79f596f213b9b24', 'function': {'arguments': '"{}"', 'name': 'get_role_pass_sight'}, 'type': 'function'}]

The issue is likely due to the arguments of the second call not being a JSON string, but rather a regular string.

my tool code:

lass AgentTools(Toolkit):


    def __init__(self, role: 'Role' =None):
        super().__init__(name="AgentTools")
        self.description = "获取当前角色身上的相关信息以及规则"
        self.mine = role
        self.register(self.get_role_sight)
        self.register(self.get_role_pass_sight)
        self.register(self.get_role_bag)
        self.register(self.get_role_status)
        self.register(self.get_role_relationship)
        self.register(self.get_game_rule)


    def get_role_sight(self) -> str:
        """
        获取当前角色的视野内容
        这个函数会返回当前回合角色的视野内容

        参数:
            无
        返回:
            当前角色的视野内容

        """
        result = ""
        for cell in self.mine.map_memory:
            if not cell.is_observed or not cell.is_searched:
                continue;
            cell_str = f"在({cell.pos[0]},{cell.pos[1]})的地形是{MapConfig.GetName(cell.terrain)}({cell.terrain})"
            if(len(cell.items) > 0):
                cell_str += f",有物品:{cell.items}"
            if(len(cell.roles) > 0):
                cell_str += f",有角色:{cell.roles}"

            if(cell.is_searched):
                cell_str += f",这个格子已经搜索过了"
            else:
                cell_str += f",这个格子没有搜索过"
            result += cell_str + "。\n"
        return result
    


    def get_role_pass_sight(self) -> str:
        """
        获取当前角色的曾经看到的视野内容
        这个函数会返回当前角色在之前回合看到过的视野内容

        参数:
            无
        返回:
            当前角色的曾经看到的视野内容
        """
        result = ""
        for cell in self.mine.map_memory:
            if not cell.is_observed or cell.is_searched:
                continue;
            cell_str = f"在({cell.pos[0]},{cell.pos[1]})的地形是{MapConfig.GetName(cell.terrain)}({cell.terrain})"
            if(len(cell.items) > 0):
                cell_str += f",有物品:{cell.items}"
            if(len(cell.roles) > 0):
                cell_str += f",有角色:{cell.roles}"

            if(cell.is_searched):
                cell_str += f",这个格子已经搜索过了"
            else:
                cell_str += f",这个格子没有搜索过"
            result += cell_str + "。\n"
        return result



    def get_role_bag(self) -> str:
        """
        获取当前角色的背包内容
        这个函数会返回当前角色的背包内容

        参数:
            无
        返回:
            当前角色的背包道具列表
        """
        if len(self.mine.bag) == 0:
            return "背包没有任何东西"
        return f"背包里有{self.mine.bag}"



    def get_role_status(self) -> str:
        """
        获取当前角色的属性状态
        这个函数会返回当前角色的属性状态

        参数:
            无
        返回:
            当前角色的属性数值
        """
        return f"""{{
            "名字": "{self.mine.name}",
            "位置": {self.mine.pos},
            "生命值": {self.mine.hp},
            "攻击力":{self.mine.atk},
            "移动距离": {self.mine.spd},
            "攻击距离": 1,
            "交流距离": 1,
        }}"""
    


    def get_role_relationship(self, other:str) -> str:
        """
        获取当前角色和其他玩家的关系
        这个函数会返回当前角色和其他玩家的关系

        参数:
            other(str): 你想要查询的角色名
        返回:
            返回你和目标角色的关系
        """
        relation =self.mine.get_relationship(other)
        return f"你和{other}的关系是{relation}"

Looking forward to your response, thank you!

Hey @komiya ! Which Model are you using with your Agent? I see that the issue here is that the model is returning “{}” as the Argument whereas it should be returning just “”. This is causing the error. Your custom toolkit is perfect!

I am using the [Qwen/Qwen2.5-14B-Instruct] model, which comes from the model provider https://siliconflow.cn/.
Use OpenAILike to integrate this model.
Thank you for your response.

I also tried using the deepseek-ai/DeepSeek-R1-Distill-Qwen-7B model on this platform, attempting to connect with DeepSeek, but I also received an error message.

tool_calls: [{'id': '0195d54d2816840b2fc8cfa562e8d605', 'function': {'arguments': 'null', 'name': 'get_role_sight'}, 'type': 'function'}]
Traceback (most recent call last):
  File "e:\AgentDemo\AgentWarDemo\main.py", line 13, in <module>
    asyncio.run(game.loop_game())
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 195, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\asyncio\base_events.py", line 691, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "e:\AgentDemo\AgentWarDemo\game\GameBoard.py", line 59, in loop_game
    await self.excute_turn()
  File "e:\AgentDemo\AgentWarDemo\game\GameBoard.py", line 154, in excute_turn
    role.decision_agent.plan()
  File "e:\AgentDemo\AgentWarDemo\AgnoAgent\DecisionAgent.py", line 33, in plan
    response:RunResponse = self.agent.run(dedent("""
                           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\site-packages\agno\agent\agent.py", line 981, in run
    return next(resp)
           ^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\site-packages\agno\agent\agent.py", line 696, in _run
    model_response = self.model.response(messages=run_messages.messages)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\site-packages\agno\models\base.py", line 175, in response
    assistant_message, has_tool_calls = self._process_model_response(
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\site-packages\agno\models\base.py", line 328, in _process_model_response
    assistant_message.log(metrics=True)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\site-packages\agno\models\message.py", line 321, in log
    for k, v in json.loads(tool_call_arguments).items():
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'items'
PS E:\AgentDemo\AgentWarDemo> 

Should I add a default parameter to the tool?

Hello @komiya ! Thanks for sharing! I can see that this is an issue with the model returning incorrect tool_call_arguments. Can you please also share the tool call for deepseek-ai/DeepSeek-R1-Distill-Qwen-7B since I tested with no parameters. That is {} but could not replicate your error.

Sorry, the relevant code has been modified. However, I later added an invalid parameter to the function that doesn’t require parameters, and this resolved the issue.

We are happy to know that Komiya.