Sanitizer misclassifies tool results due to whitespace in tool_call_id
Cluster 9999 · agent. Data as of
Nothing open on GitHub. Fix merged in #55519 on 30 Jun 2026. Check it covers your case.
The short answer
- Known?
- Yes. 4 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #55519. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #55519. That is separate from the fix event. - Still open
- Nothing open on GitHub.
These issues and fixes address a bug where the run_agent sanitizer incorrectly classifies tool results when the tool_call_id contains surrounding whitespace. The proposed fixes involve normalizing or stripping whitespace from tool_call_id before performing comparisons.
Open issues0
Open PRs0
Fixes on record
-
#55519 fix: normalize tool_call_id whitespace in sanitizer
files:
agent/agent_runtime_helpers.py,run_agent.py,tests/run_agent/test_agent_guardrails.pyShow the diff
-
agent/agent_runtime_helpers.py@@ -2163,7 +2163,7 @@ def sanitize_api_messages(messages: List[Dict[str, Any]]) -> List[Dict[str, Any] result_call_ids: set = set() for msg in messages: if msg.get("role") == "tool": - cid = msg.get("tool_call_id") + cid = (msg.get("tool_call_id") or "").strip() if cid: result_call_ids.add(cid) @@ -2172,7 +2172,7 @@ def sanitize_api_messages(messages: List[Dict[str, Any]]) -> List[Dict[str, Any] if orphaned_results: messages = [ m for m in messages - if not (m.get("role") == "tool" and m.get("tool_call_id") in orphaned_results) + if not (m.get("role") == "tool" and (m.get("tool_call_id") or "").strip() in orphaned_results) ] _ra().logger.debug( "Pre-call sanitizer: removed %d orphaned tool result(s)", -
run_agent.py@@ -3429,8 +3429,8 @@ def _build_system_prompt(self, system_message: str = None) -> str: def _get_tool_call_id_static(tc) -> str: """Extract call ID from a tool_call entry (dict or object).""" if isinstance(tc, dict): - return tc.get("call_id", "") or tc.get("id", "") or "" - return getattr(tc, "call_id", "") or getattr(tc, "id", "") or "" + return (tc.get("call_id", "") or tc.get("id", "") or "").strip() + return (getattr(tc, "call_id", "") or getattr(tc, "id", "") or "").strip() @staticmethod def _get_tool_call_name_static(tc) -> str: -
tests/run_agent/test_agent_guardrails.py@@ -108,6 +108,30 @@ def test_sdk_object_tool_calls(self): assert len(out) == 2 assert out[1]["tool_call_id"] == "c6" + def test_tool_result_with_leading_whitespace_preserved(self): + """Tool result IDs with leading/trailing whitespace should match assistant call IDs.""" + msgs = [ + {"role": "assistant", "tool_calls": [assistant_dict_call("functions.cronjob:24")]}, + tool_result(" functions.cronjob:24"), # leading whitespace + ] + out = AIAgent._sanitize_api_messages(msgs) + # Should NOT inject a stub — the tool result is valid after stripping + assert len(out) == 2 + assert out[1]["role"] == "tool" + assert out[1]["content"] == "ok" + + def test_truly_orphaned_with_whitespace_still_removed(self): + """Truly orphaned tool results with whitespace should still be removed.""" + msgs = [ + {"role": "assistant", "tool_calls": [assistant_dict_call("c_valid")]}, + tool_result(" c_ORPHAN "), # whitespace + no matching call + ] + out = AIAgent._sanitize_api_messages(msgs) + assert len(out) == 2 # assistant + stub for c_valid, orphan removed + tool_msgs = [m for m in out if m["role"] == "tool"] + assert len(tool_msgs) == 1 + assert tool_msgs[0]["tool_call_id"] == "c_valid" + # --------------------------------------------------------------------------- # Phase 2a — _cap_delegate_task_calls
-
2 PRs closed without merging
From the close comments: done elsewhere 1 · duplicate 1
Closed issues · 1
- Closed#9999run_agent sanitizer misclassifies tool results when tool_call_id has surrounding whitespace
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.50: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- agent
- Merged PRs
- #55519
- Closed issues
- 1
- Attempts
- 2 PRs closed without merging
- Fix link checked
- 30 Jun 2026