From 250232ff91550752d2fbd984eb992365a6b55e83 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Sun, 16 Aug 2026 10:45:10 -0700 Subject: [PATCH] Revert "fix(agent): harden canonical tool call deduplication" This reverts commit 8fc4189edd23dde055232cc07ea14d1d525e44ee. --- run_agent.py | 15 +++--------- tests/run_agent/test_agent_guardrails.py | 31 ------------------------ 2 files changed, 3 insertions(+), 43 deletions(-) diff --git a/run_agent.py b/run_agent.py index b46cf9fdd1..a3da633bba 100644 --- a/run_agent.py +++ b/run_agent.py @@ -4900,28 +4900,19 @@ class AIAgent: Valid JSON arguments are canonicalized so equivalent objects do not evade deduplication merely because their keys or whitespace differ. - Duplicate object keys use the parser's last-value-wins semantics, - matching downstream argument parsing. Malformed or excessively nested - arguments retain their raw representation rather than being repaired - here. Only the first occurrence of each unique pair is kept. + Malformed arguments retain their raw representation rather than being + repaired here. Only the first occurrence of each unique pair is kept. Returns the original list if no duplicates were found. """ - seen_raw: set = set() seen: set = set() unique: list = [] for tc in tool_calls: - raw_key = (tc.function.name, tc.function.arguments) - if raw_key in seen_raw: - logger.warning("Removed duplicate tool call: %s", tc.function.name) - continue - seen_raw.add(raw_key) - arguments = tc.function.arguments try: arguments = json.dumps( json.loads(arguments), separators=(",", ":"), sort_keys=True ) - except (RecursionError, TypeError, ValueError): + except (TypeError, ValueError): pass key = (tc.function.name, arguments) if key not in seen: diff --git a/tests/run_agent/test_agent_guardrails.py b/tests/run_agent/test_agent_guardrails.py index ec5d97b207..e94363089f 100644 --- a/tests/run_agent/test_agent_guardrails.py +++ b/tests/run_agent/test_agent_guardrails.py @@ -7,7 +7,6 @@ Covers three static methods on AIAgent (inspired by PR #1321 — @alireza78a): - _uniquify_tool_call_ids() — Phase 2c: duplicate-id repair (lossless pairing) """ -import json import types import pytest @@ -213,36 +212,6 @@ class TestDeduplicateToolCalls: assert out == [first, distinct] - def test_recursion_error_uses_raw_string_for_deduplication(self, monkeypatch): - def raise_recursion_error(_arguments): - raise RecursionError("maximum recursion depth exceeded") - - monkeypatch.setattr("run_agent.json.loads", raise_recursion_error) - first = make_tc("terminal", '{"command":"one"}') - duplicate = make_tc("terminal", '{"command":"one"}') - - out = AIAgent._deduplicate_tool_calls([first, duplicate]) - - assert out == [first] - - def test_byte_identical_duplicate_is_parsed_only_once(self, monkeypatch): - original_loads = json.loads - calls = 0 - - def track_loads(arguments): - nonlocal calls - calls += 1 - return original_loads(arguments) - - monkeypatch.setattr("run_agent.json.loads", track_loads) - first = make_tc("terminal", '{"command":"one"}') - duplicate = make_tc("terminal", '{"command":"one"}') - - out = AIAgent._deduplicate_tool_calls([first, duplicate]) - - assert out == [first] - assert calls == 1 -