#40881·长链

`on_tool_error` 不接收来自调用者的 `**kwargs`,而 `on_tool_start` 和 `on_tool_end` 则接收。

作者: Iris070308创建于 2026年9月28日更新于 2026年9月28日
标签bugcoreexternal

Repro: on_tool_error does not get the **kwargs that on_tool_start and on_tool_end do. BaseTool.run's docstring says the keyword arguments go to the tool callbacks. Exit code 1 means one of the callback events lost them.

Reproduction Steps / Example Code (Python)

python
import asyncio 
from typing import Any 
 
from langchain_core.callbacks import BaseCallbackHandler 
from langchain_core.tools import StructuredTool, ToolException 
 
 
class Capture(BaseCallbackHandler): 
    def __init__(self): 
        self.events = {} 
 
    def on_tool_start(self, serialized, input_str, **kwargs: Any): 
        self.events["start"] = kwargs 
 
    def on_tool_end(self, output, **kwargs: Any): 
        self.events["end"] = kwargs 
 
    def on_tool_error(self, error, **kwargs: Any): 
        self.events["error"] = kwargs 
 
 
def boom(x: int) -> str: 
    """Fail on purpose.""" 
    raise ToolException("boom") 
 
 
def fine(x: int) -> str: 
    """Succeed.""" 
    return "ok" 
 
 
fail_tool = StructuredTool.from_function(boom) 
ok_tool = StructuredTool.from_function(fine) 
 
 
def probe(fail): 
    handler = Capture() 
    tool = fail_tool if fail else ok_tool 
    try: 
        tool.invoke({"x": 1}, {"callbacks": [handler]}, tenant="acme") 
    except Exception: 
        pass 
    return handler.events 
 
 
async def aprobe(fail): 
    handler = Capture() 
    tool = fail_tool if fail else ok_tool 
    try: 
        await tool.ainvoke({"x": 1}, {"callbacks": [handler]}, tenant="acme") 
    except Exception: 
        pass 
    return handler.events 
 
 
def report(label, failing, succeeding): 
    got = { 
        "on_tool_start": "tenant" in failing.get("start", {}), 
        "on_tool_end": "tenant" in succeeding.get("end", {}), 
        "on_tool_error": "tenant" in failing.get("error", {}), 
    } 
    missing = { 
        "on_tool_start": "tenant" not in failing.get("start", {}), 
        "on_tool_end": "tenant" not in succeeding.get("end", {}), 
        "on_tool_error": "tenant" not in failing.get("error", {}), 
    } 
 

内容来源: langchain-ai/langchain