feat: protect against anthropic nested tool args (#2250)

This commit is contained in:
cthomas
2025-05-19 16:01:59 -07:00
committed by GitHub
parent 6e5ab8b151
commit 5df7bd5af6
3 changed files with 15 additions and 5 deletions

View File

@@ -488,8 +488,11 @@ class LettaAgent(BaseAgent):
try:
tool_args = json.loads(tool_call_args_str)
assert isinstance(tool_args, dict), "tool_args must be a dict"
except json.JSONDecodeError:
tool_args = {}
except AssertionError:
tool_args = json.loads(tool_args)
# Get request heartbeats and coerce to bool
request_heartbeat = tool_args.pop("request_heartbeat", False)

View File

@@ -1,3 +1,4 @@
import json
from datetime import datetime, timezone
from enum import Enum
from typing import AsyncGenerator, List, Union
@@ -89,7 +90,13 @@ class AnthropicStreamingInterface:
def get_tool_call_object(self) -> ToolCall:
"""Useful for agent loop"""
return ToolCall(id=self.tool_call_id, function=FunctionCall(arguments=self.accumulated_tool_call_args, name=self.tool_call_name))
# hack for tool rules
tool_input = json.loads(self.accumulated_tool_call_args)
if "id" in tool_input and tool_input["id"].startswith("toolu_") and "function" in tool_input:
arguments = str(json.dumps(tool_input["function"]["arguments"], indent=2))
else:
arguments = self.accumulated_tool_call_args
return ToolCall(id=self.tool_call_id, function=FunctionCall(arguments=arguments, name=self.tool_call_name))
def _check_inner_thoughts_complete(self, combined_args: str) -> bool:
"""

View File

@@ -369,11 +369,11 @@ class AnthropicClient(LLMClientBase):
content = strip_xml_tags(string=content_part.text, tag="thinking")
if content_part.type == "tool_use":
# hack for tool rules
input = json.loads(json.dumps(content_part.input))
if "id" in input and input["id"].startswith("toolu_") and "function" in input:
arguments = str(input["function"]["arguments"])
tool_input = json.loads(json.dumps(content_part.input))
if "id" in tool_input and tool_input["id"].startswith("toolu_") and "function" in tool_input:
arguments = str(tool_input["function"]["arguments"])
else:
arguments = json.dumps(content_part.input, indent=2)
arguments = json.dumps(tool_input, indent=2)
tool_calls = [
ToolCall(
id=content_part.id,