What is BaseTool._arun()?
_arun(**kwargs) is the awaitable counterpart of _run. CrewAI awaits it when the crew executes under kickoff_async so httpx.AsyncClient, aiohttp sessions, or async database drivers can share the same event-loop budget as the orchestrator. Arguments still flow through args_schema validation exactly like _run; only the execution model changes.
Implement both _run and _arun only when you must support synchronous kickoff() and async kickoff_async() with the same tool class — keep behavior aligned so switching execution modes does not change semantics. If your dependency stack is entirely async, you can lean on _arun alone when you control callers, but many codebases still need _run for scripts and notebooks.
Watch thread-pool misuse: dropping time.sleep or blocking boto3 calls inside _arun still stalls the loop. Offload truly blocking work to asyncio.to_thread or rewrite with native async clients.
Use Cases
- • Async APIs
- • Async DB queries
Key Features
- ✓ Awaitable
- ✓ Concurrent with other async work
When NOT to Use
Sync-only operations — _run() is enough.
Notes
kickoff() vs kickoff_async()
If agents still call kickoff(), CrewAI may never await _arun. Keep blocking IO in _run for sync paths, or standardize on kickoff_async end-to-end.
Client lifecycle
Creating a new AsyncClient per invocation adds TLS handshakes. Prefer injecting a shared client via __init__ when tools fire frequently.
Cancellation
When asyncio cancels the crew task, pending awaits inside _arun should exit cleanly — use async context managers and avoid swallowing CancelledError.
Return strings for the LLM
Mirroring _run, return text the model can consume. Serialize structured results with json.dumps instead of returning raw ORM rows.
Parameters
| Parameter | Type | Required | Purpose |
|---|---|---|---|
| **kwargs | Any | No | Fields from args_schema. |
Code Examples
Async fetch
async def _arun(self, url: str) -> str:
async with httpx.AsyncClient() as c:
return (await c.get(url)).text
Bounded parallel fetches inside one tool
import asyncio
import httpx
from crewai.tools import BaseTool
class MultiFetch(BaseTool):
name = 'multi_fetch'
description = 'GET several URLs concurrently'
async def _arun(self, urls: list[str]) -> str:
async with httpx.AsyncClient(timeout=20) as c:
tasks = [c.get(u) for u in urls[:5]]
resps = await asyncio.gather(*tasks, return_exceptions=True)
return '\n'.join(str(r) for r in resps)
Delegate blocking SDK to a thread
import asyncio
from crewai.tools import BaseTool
class LegacySdkTool(BaseTool):
async def _arun(self, query: str) -> str:
return await asyncio.to_thread(self._sdk.search, query)
When to Use
Tools wrapping httpx/aiohttp clients or async DB drivers.
Common Mistakes
❌ Calling sync requests inside _arun
✅ Use httpx.AsyncClient or run sync code in a thread.
Related: @tool decorator reference, Agent class reference, and the first Crew tutorial.
BaseTool._arun() FAQ
What is BaseTool._arun() in CrewAI?
Async body of a tool — implemented when the tool wraps async I/O or external services. _arun(**kwargs) is the awaitable counterpart of _run. CrewAI awaits it when the crew executes under kickoff_async so httpx.AsyncClient, aiohttp sessions, or async database drivers can share the same event-loop budget as the orchestrator. Arguments still flow through args_schema validation exactly like _run; only the execution model changes. Implement both _run and _arun only when you must support synchronous kickoff() and async kickoff_async() with the same tool class — keep…
Which CrewAI types expose the method BaseTool._arun()?
DevShelfHub documents BaseTool._arun() on Custom Tools. The reference maps it to Python module crewai.tools.BaseTool — pin your installed crewai version and match imports to the snippet on this page.
When should I use BaseTool._arun()?
Tools wrapping httpx/aiohttp clients or async DB drivers.
When should I avoid BaseTool._arun()?
Sync-only operations — _run() is enough.
How do I call BaseTool._arun() from Python?
async def _arun(self, **kw): return await do(**kw)
Where can I explore more CrewAI API reference pages?
Open the CrewAI API reference index on DevShelfHub to search classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.