Tool call logging: LoggingToolset

Note

Experimental: this can change or be removed in a minor release of this provider. See Stable and experimental features.

LoggingToolset is a WrapperToolset that intercepts call_tool() to log each tool invocation in real time. AgentOperator applies it automatically (see enable_tool_logging) through ToolLoggingCapability. Applying the wrapper as a capability means logging covers the assembled function toolset, including tools supplied through toolsets=, agent_params={"tools": [...]}, and capabilities such as factory-backed toolsets, nested capabilities, and MCP toolsets. Output tools such as final_result and provider-native tools, including native MCP, are not covered by Airflow’s real-time tool-call logging. Tools added by another capability through its own wrapper toolset, such as ToolSearch’s search_tools and CodeMode’s run_code, are also not covered. A tool hidden with .defer_loading() is logged once the model finds it, and its result is masked like any other (see Progressive tool disclosure).

AgentOperator adds ToolLoggingCapability automatically when enable_tool_logging=True. If capabilities= already contains one, including inside a combined or wrapper capability, the operator does not add another, so the logger on the supplied instance is used.

You can also use LoggingToolset directly with any pydantic-ai Agent:

from airflow.providers.common.ai.toolsets.logging import LoggingToolset
from airflow.providers.common.ai.toolsets.sql import SQLToolset

logged_toolset = LoggingToolset(wrapped=SQLToolset(db_conn_id="my_db"))

Each tool call logs its name and timing at INFO, inside a collapsible ::group:: block in the task log, and its arguments at DEBUG. Control-flow signals that let the model retry, report a failed tool result, defer or skip a call, or wait for approval are logged at INFO and re-raised. Other exceptions, including SkipToolValidation raised by a tool body, are logged at ERROR with a traceback and re-raised. Pass logger to send the lines to a logger other than the toolset module’s own.

Was this entry helpful?