INTEGRATION GUIDE

    xBPP + CrewAI

    Payment Governance for CrewAI Agents

    CrewAI is a natural fit for multi-agent systems where several agents collaborate on a task. It's also a natural fit for a common failure mode: one agent in the crew gets the ability to spend money, and suddenly every agent in the crew inherits that capability through delegation. This guide shows how to wire xBPP into a CrewAI crew so every agent operates under a shared, declarative policy.

    Install

    pip install crewai vanar-xbpp

    xBPP is a policy engine - it evaluates transactions locally and synchronously. It does not call any external service and does not depend on CrewAI.

    Pattern 1 - Pay tool on a single agent

    The simplest CrewAI integration is one agent with a payment tool. Put the policy check inside the tool's _run method.

    from crewai_tools import BaseTool
    from pydantic import BaseModel, Field
    from xbpp import evaluate
    import json
    
    with open('policies/crew-agent.json') as f:
        POLICY = json.load(f)
    
    class PayInput(BaseModel):
        amount: float = Field(..., description="Amount in USDC")
        recipient: str = Field(..., description="Recipient address or URL")
    
    class PayTool(BaseTool):
        name: str = "pay"
        description: str = "Send a USDC payment to a recipient"
        args_schema: type[BaseModel] = PayInput
    
        def _run(self, amount: float, recipient: str) -> str:
            verdict = evaluate(
                {"amount": amount, "currency": "USDC", "recipient": recipient},
                POLICY
            )
    
            if verdict.decision == "BLOCK":
                return json.dumps({
                    "status": "blocked",
                    "reasons": verdict.reasons,
                    "message": verdict.message
                })
    
            if verdict.decision == "ESCALATE":
                approved = human_approval.request({
                    "amount": amount,
                    "recipient": recipient,
                    "verdict": verdict.to_dict()
                })
                if not approved:
                    return json.dumps({"status": "declined_by_human"})
    
            tx = execute_payment(amount, recipient)
            return json.dumps({"status": "sent", "tx_hash": tx.hash})

    Attach PayTool() to whichever Agent needs payment capability. CrewAI's LLM will call it like any other tool; xBPP evaluates every call before money moves.

    Pattern 2 - Shared policy across the whole crew

    CrewAI's multi-agent model means any agent in a crew can end up calling a tool indirectly. If you want the same governance rules to apply everywhere, load the policy once and reuse it:

    from crewai import Agent, Task, Crew
    from xbpp import evaluate
    import json
    
    POLICY = json.load(open('policies/crew-agent.json'))
    
    def make_pay_tool(agent_name: str):
        """Create a scoped pay tool that tags the agent in the policy log."""
        class ScopedPayTool(BaseTool):
            name: str = "pay"
            description: str = "Send a USDC payment"
            args_schema: type[BaseModel] = PayInput
    
            def _run(self, amount: float, recipient: str) -> str:
                verdict = evaluate(
                    {
                        "amount": amount,
                        "currency": "USDC",
                        "recipient": recipient,
                        "agent": agent_name  # metadata carried through audit log
                    },
                    POLICY
                )
                # ... same handling as before
        return ScopedPayTool()
    
    researcher = Agent(
        role="Researcher",
        goal="Buy data reports on demand",
        tools=[make_pay_tool("researcher")]
    )
    
    buyer = Agent(
        role="Buyer",
        goal="Purchase API credits",
        tools=[make_pay_tool("buyer")]
    )
    
    crew = Crew(agents=[researcher, buyer], tasks=[...])

    Now both agents share the same policy - same daily budget, same counterparty rules, same escalation thresholds - but each tool call is tagged with which agent made it. Your audit log becomes a clean per-agent accounting of who spent what and why.

    Delegated work stays governed

    One of CrewAI's signature features is agent delegation - an agent can ask another agent to do part of a task. This is where ad-hoc spending controls tend to break down: agent A thinks it's delegating "research" but agent B ends up paying for things, and A's constraints never propagate.

    With xBPP at the tool level, this failure mode goes away. Agent B's payment tool evaluates the shared policy regardless of who called it. You don't need to trace the delegation chain and hope constraints transfer - the policy runs at the point of execution, which is the only place that matters.

    Crew-level budget patterns

    Three patterns we see in production crews:

    1. Global daily budget

    One policy file, one daily cap shared across all agents. Simplest to reason about. Best for crews working on a single shared objective (e.g. research team buying reports for one client).

    2. Per-agent sub-budgets with a crew-level ceiling

    Each agent gets its own daily cap and a shared crew-level ceiling. A researcher gets $500/day but the whole crew collectively can't exceed $2,000/day. This prevents one agent from unilaterally draining the crew budget.

    3. Task-scoped policies

    Each CrewAI Task carries its own policy, loaded when the Task runs. Good for crews that handle projects with different budget envelopes - a $50-budget personal task and a $50,000 client project can run on the same crew code with different policy files.

    def build_task(name: str, budget_file: str) -> Task:
        policy = json.load(open(f'policies/{budget_file}.json'))
        # bind the policy to this task's tools
        ...

    Human-in-the-loop integration

    CrewAI doesn't have a first-class "pause for approval" primitive, but xBPP's ESCALATE verdict gives you the hook. Wire human_approval.request() to whatever your team uses - Slack, a dashboard, email, a CLI prompt during dev. As long as it's synchronous (or awaited), the CrewAI tool call will block on it correctly.

    For production, a lightweight pattern:

    1. ESCALATE returns the verdict + structured context
    2. Your handler posts to a Slack channel with approve/deny buttons
    3. The handler holds the tool call open (via polling a Redis key, or similar)
    4. On approval, the handler returns and the tool resumes

    Under 50 lines of glue code and your crew has real human-in-the-loop governance.

    FAQ

    Does this work with CrewAI hierarchical processes?

    Yes. Hierarchical crews still call tools at leaf agents, which is where xBPP lives. The hierarchy doesn't change anything.

    Can I use different policies for different crew members?

    Yes. Load a separate policy file for each agent's tools, or use the shared-with-agent-tag pattern above.

    Does xBPP block CrewAI's task delegation?

    No. Delegation happens at the Crew level; xBPP runs at the tool level. They don't interfere.

    Is there a Python version of the SDK?

    Yes. The API mirrors the TypeScript version - same policy format, same verdict shape.

    Further reading