agent.achat() now route through the same safety mechanisms as sync execution, including approval checks, timeouts, and Loop Guard’s doom-loop / no-progress protection (PR #4005). The sync-only execute_tool_with_circuit_breaker wrapper is not reused on the async path (it uses time.sleep); circuit-breaker state tracked elsewhere still applies.
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:Loop Guard on the async path
Every async tool call inagent.achat() now runs through Loop Guard the same way sync calls always did (PR #4005). Repeated identical calls, repeated timeouts, and repeated exceptions all accumulate toward WARN → BLOCK → HALT on the current turn.
- Async tool timeouts (
asyncio.wait_forfiring aftertool_timeoutseconds) are recorded as failures and count toward the BLOCK/HALT thresholds. Previously they early-returned and bypassed the streak. - Async tool exceptions are also recorded as failures — a tool that keeps raising escalates the same way a tool that keeps returning
{"error": …}does. - A Loop Guard
HALTpropagates asToolExecutionError(is_retryable=False). The async retry wrapper honours bothloop_blocked(in the returned dict) and the exception, so no custom retry policy can re-run a terminally blocked call.
Retry parity on the async path
Raised exceptions onagent.achat(...) / agent.execute_tool_async(...) are now retried under ToolConfig(retry_policy=RetryPolicy(...)), matching the sync path (PR #4141) — programming errors (ValueError, TypeError, AttributeError) and ToolExecutionError(is_retryable=False) (including Loop Guard HALT) stay terminal. See Tool Retry Policy for the full policy reference.
Timeout Controls
Async tool execution respects timeout settings:Wrapper-Level Timeout (YAML / framework: praisonai)
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 raisesToolTimeoutError (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_executorinagents_generator.py); on timeout the future is best-effort cancelled. A call that already started cannot be interrupted, sobackground_work_may_continueisTrue. - Async tools are wrapped with
asyncio.wait_for(...), which cancels the underlying task cleanly, sobackground_work_may_continueisFalse.
tool_config=ToolConfig(timeout=…).
Exception raised on wrapper-level timeout:
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.
Task-Scoped Tools
Thetools_override parameter allows tasks to provide their own tool set for async execution:
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 mechanismsBest Practices
Handle Approval in Async Context
Handle Approval in Async Context
When using approval in async environments, ensure your event loop can handle user input:
Configure Timeouts for Async Tools
Configure Timeouts for Async Tools
Set appropriate timeouts for async tool execution:
Monitor Circuit Breaker in Async Workflows
Monitor Circuit Breaker in Async Workflows
Circuit breaker state affects all calls - monitor in async workflows:
Task Tools Override Agent Tools
Task Tools Override Agent Tools
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 throughConsoleBackend 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.
Related
Approval
Tool approval configuration
Tool Circuit Breaker
Tool failure protection
Tool Approval
Safe-by-default behaviour, bypass flags, and risk levels
Loop Guard
Always-on per-turn tool-call guardrails, now on both sync and async paths
Footnotes
-
The async column was broken before PR #4141 — a raised exception was retried zero times regardless of
RetryPolicy. See Tool Retry Policy → Sync / async parity. ↩

