CrewAI¶
pip install 'agent-once[crewai]'
once.integrations.crewai.once_tool wraps a CrewAI tool function. Put @tool on top, and give the function a docstring, since CrewAI requires one:
from crewai import Crew
from crewai.tools import tool
from once import Once
from once.integrations.crewai import once_tool
once = Once("once.db")
@tool("refund_order")
@once_tool(once, name="refund_order", scope_arg="order_id")
def refund_order(order_id: str, amount: int) -> str:
"""Refund an order."""
return payments.refund(order_id, amount)
crew = Crew(agents=[support], tasks=[handle_ticket])
with once.scope("ticket_789"):
crew.kickoff()
once_tool(once, fn=None, /, *, name=None, timeout=None, ttl=None, verify=None, scope_arg=None)
CrewAI tools get no run context, so the scope is:
- the value of the
scope_argtool argument, if set. - the enclosing
once.scope(), if any.
Wrap crew.kickoff() in with once.scope(run_id):. CrewAI copies context variables into its worker threads, so the tools see the scope.
For a BaseTool subclass, decorate _run (or _arun) and pass name=. self is left out of the key.
Note
The crewai and openai-agents extras can't be installed together: CrewAI pins openai<3 and the OpenAI Agents SDK needs openai>=3.
An idempotency_key parameter gets the computed key and is hidden from the model. name, timeout, ttl and verify work as in @once.tool.
examples/crewai_example.py runs offline. It calls the tool directly, the way a retried task would.