Skip to content

Commit 37575be

Browse files
jsonbaileyclaude
andcommitted
fix: Demote diagnostic logs to debug and exclude handoff tools from tracking
Chat input and graph structure logs were at INFO level from debugging. Demote both to DEBUG so they don't surface in production log output. Handoff tools (transfer_to_*) are a routing workaround, not real tool calls, so exclude them from LD tool call tracking. on_tool_end now skips any tool not present in fn_name_to_config_key rather than falling back to the raw function name. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 85ed502 commit 37575be

3 files changed

Lines changed: 11 additions & 8 deletions

File tree

packages/ai-providers/server-ai-langchain/src/ldai_langchain/langgraph_agent_graph_runner.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def _message_content_len(msg: Any) -> int:
136136
def _format_chat_messages_for_log(msgs: List[Any]) -> str:
137137
"""
138138
One line per message index — matches OpenAI error indices (e.g. messages.[5]).
139-
Logged at INFO before each model ainvoke.
139+
Logged at DEBUG before each model ainvoke.
140140
"""
141141
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage, ToolMessage
142142

@@ -271,7 +271,7 @@ async def invoke(state: WorkflowState) -> dict:
271271
msgs = _coalesce_tool_messages_for_openai(list(state['messages']))
272272
if node_instructions:
273273
msgs = [SystemMessage(content=node_instructions)] + msgs
274-
log.info(
274+
log.debug(
275275
'LangGraphAgentGraphRunner node=%s: CHAT_INPUT (%s messages)\n%s',
276276
nk,
277277
len(msgs),
@@ -340,7 +340,7 @@ async def invoke(state: WorkflowState) -> dict:
340340

341341
tracker = self._graph.get_tracker()
342342
graph_key_str = tracker.graph_key if tracker else 'unknown'
343-
log.info(
343+
log.debug(
344344
f"LangGraphAgentGraphRunner: graph='{graph_key_str}', root='{root_key}', "
345345
f"structure: {' | '.join(graph_structure)}"
346346
)

packages/ai-providers/server-ai-langchain/src/ldai_langchain/langgraph_callback_handler.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,10 @@ def on_tool_end(
167167
if node_key is None:
168168
return
169169

170-
config_key = self._fn_name_to_config_key.get(name, name)
170+
config_key = self._fn_name_to_config_key.get(name)
171+
if config_key is None:
172+
# Tool is not a registered functional tool (e.g. a handoff tool) — skip tracking.
173+
return
171174
if node_key not in self._node_tool_calls:
172175
self._node_tool_calls[node_key] = []
173176
self._node_tool_calls[node_key].append(config_key)

packages/ai-providers/server-ai-langchain/tests/test_langgraph_callback_handler.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,13 +289,13 @@ def test_on_tool_end_records_tool_call():
289289
assert handler.node_tool_calls.get('root-agent') == ['get_weather_open_meteo']
290290

291291

292-
def test_on_tool_end_falls_back_to_fn_name_when_no_mapping():
293-
"""Tool end uses the raw function name when no config key mapping exists."""
292+
def test_on_tool_end_skips_unregistered_tools():
293+
"""Tool end is ignored for tools not in the fn_name_to_config_key map (e.g. handoff tools)."""
294294
handler = LDMetricsCallbackHandler({'root-agent'}, {})
295295
tools_run_id = uuid4()
296296
handler.on_chain_start({}, {}, run_id=tools_run_id, name='root-agent__tools')
297-
handler.on_tool_end('result', run_id=uuid4(), parent_run_id=tools_run_id, name='my_tool')
298-
assert handler.node_tool_calls.get('root-agent') == ['my_tool']
297+
handler.on_tool_end('result', run_id=uuid4(), parent_run_id=tools_run_id, name='transfer_to_child')
298+
assert handler.node_tool_calls.get('root-agent') is None
299299

300300

301301
def test_on_tool_end_multiple_tools_accumulated():

0 commit comments

Comments
 (0)