Skip to main content
Async tool calls in agent.achat() now route through the same safety mechanisms as sync execution, including approval checks, circuit breakers, and timeouts.
The user runs tools via achat(); approvals, circuit breakers, and timeouts apply the same way as synchronous execution.

Quick Start

1

Async Tool with Approval

2

Task-Scoped Tools


How It Works

Architecture: The unified async dispatcher now calls execute_tool_async for tool invocations, so long-running tools no longer block the event loop.

Safety Mechanisms

Approval Checks

User approval prompts now appear during async tool execution:

Circuit Breaker Protection

Tool failure rates are tracked across async calls:

Timeout Controls

Async tool execution respects timeout settings:

Wrapper-Level Timeout (YAML / framework: praisonai)

Two ToolTimeoutError classes exist in PraisonAI. This section covers praisonai.agents_generator.ToolTimeoutError — the wrapper-level version raised on YAML/CLI tool_timeout (seconds). The SDK tool-call executor has its own praisonaiagents.tools.ToolTimeoutError (milliseconds, llm={"tool_timeout_ms": N}), surfaced as a ToolResult.error with error_kind="timeout". See Tool Call Executor Timeout.
When running through YAML or the CLI, the wrapper wraps every tool with a timeout-enforcing shim before handing the agent to the SDK. This provides defense-in-depth timeout enforcement even for pathological tools. On timeout the wrapper raises ToolTimeoutError (a TimeoutError subclass) instead of returning a JSON dict. This preserves each tool’s declared return-type contract — a typed return value is never silently downgraded to a string. Framework adapters catch it and translate it per framework. The wrapper handles sync and async tools differently:
  • Sync tools run in an instance-owned ThreadPoolExecutor (see _get_tool_timeout_executor in agents_generator.py); on timeout the future is best-effort cancelled. A call that already started cannot be interrupted, so background_work_may_continue is True.
  • Async tools are wrapped with asyncio.wait_for(...), which cancels the underlying task cleanly, so background_work_may_continue is False.
In Python, configure with tool_config=ToolConfig(timeout=…). Exception raised on wrapper-level timeout:
To catch the executor-level version instead, use from praisonaiagents.tools import ToolTimeoutError — see Tool Call Executor Timeout. ToolTimeoutError carries three attributes:
Once half the pool’s workers are permanently leaked to stuck sync tools, the pool is automatically recycled: leaked threads continue until their syscall returns, but new tool calls get a fresh pool instead of queueing behind them.
See Tool Configuration for full details and Concurrency for shape comparison.

Task-Scoped Tools

The tools_override parameter allows tasks to provide their own tool set for async execution:
For users, this manifests as task-specific tools being available during async chat:

Trace Events

Async tool execution now emits the same trace events as sync execution:

Migration Notes

No code changes required - async tool safety is automatically enabled: Before: Async calls bypassed safety mechanisms
After: Async calls use full safety pipeline

Best Practices

When using approval in async environments, ensure your event loop can handle user input:
Set appropriate timeouts for async tool execution:
Circuit breaker state affects all calls - monitor in async workflows:
Design task tools to be self-contained since they override agent tools:

Safe Defaults

On a fresh interactive session, the runtime now routes dangerous tools through ConsoleBackend automatically — no approval= kwarg needed. Off-TTY (pipes, CI) keeps deny-by-default. See Tool Approval → Default Behaviour for the precedence ladder and bypass flags.

Approval

Tool approval configuration

Tool Circuit Breaker

Tool failure protection

Tool Approval

Safe-by-default behaviour, bypass flags, and risk levels