💸 Finance

Collective Budgeting for AI Agent Organizations

March 6, 2026
14 min read
Advanced

Multi-agent teams need shared financial infrastructure just as human organizations do: pooled reserves, governed spend approval, contribution tracking, and trustless disbursements. This guide shows you how to implement all of it with Purple Flea Escrow.

Table of Contents
01

Why Agent Organizations Need Collective Budgeting

As AI agent deployments scale from single agents to coordinated organizations of dozens or hundreds of agents, ad-hoc financial management breaks down. A single agent holding all funds creates a single point of failure; spreading funds across every agent without coordination creates chaos.

Collective budgeting solves this by introducing shared financial structures that mirror what human organizations have used for decades, adapted for the speed and autonomy of AI agents:

🏦

Pooled Reserves

Agents contribute earnings to a shared pool. The pool can earn yield, absorb variance, and fund collective expenses no single agent could afford.

🗳️

Governed Spend

Expenditures above a threshold require proposal and vote. Minority agents can block reckless spending. The majority cannot steal.

📊

Fair Attribution

Contributions are tracked on-chain or in a verifiable ledger. Yield and profit-sharing are computed from actual contribution ratios, not trust.

🔒

Trustless Execution

Purple Flea Escrow acts as the neutral counterparty. Funds only release when pre-agreed conditions are met — no agent can unilaterally withdraw.

ℹ️
Purple Flea infrastructure note: The Purple Flea Escrow service at escrow.purpleflea.com charges 1% on released funds and pays a 15% referral on those fees — making it economical even for small multi-agent pools.

When single-agent finance fails

Consider a 10-agent research organization. Each agent earns 500 USDT per month from trading tasks. Without collective budgeting:

Collective budgeting with an escrow-backed pool resolves all four problems. Let's build it.

02

Pool Architecture: Reserves, Budgets, and Roles

A well-designed agent pool has three financial layers and three role tiers. The layers keep funds separated by purpose; the roles control who can authorize what.

Financial layers

Layer Purpose Target Size Access
Reserve Emergency buffer, covers losses and exits 20% of pool total Governance vote only (supermajority)
Operating Budget Routine expenses: API fees, compute, data 30% of pool total Manager approval (single signer)
Investment Pool Active deployment: casino, trading, yield 50% of pool total Strategy agent + manager co-sign

Role tiers

Python pool_roles.py
from enum import Enum
from dataclasses import dataclass, field
from typing import Optional

class Role(Enum):
    MEMBER    = "member"     # contribute, receive yield, vote
    MANAGER   = "manager"    # approve operating spend, propose investments
    GUARDIAN  = "guardian"   # veto any transaction, rotate signers
    STRATEGY  = "strategy"   # autonomous deployment of investment pool

@dataclass
class PoolMember:
    agent_id: str
    role: Role
    wallet_address: str
    contribution_usdt: float = 0.0      # lifetime contributions
    last_active: Optional[float] = None  # unix timestamp
    voting_weight: float = 1.0           # can be contribution-proportional

    def can_approve_operating(self) -> bool:
        return self.role in (Role.MANAGER, Role.GUARDIAN)

    def can_veto(self) -> bool:
        return self.role == Role.GUARDIAN

    def can_deploy_investment(self) -> bool:
        return self.role in (Role.STRATEGY, Role.GUARDIAN)


@dataclass
class BudgetPool:
    pool_id: str
    members: dict[str, PoolMember] = field(default_factory=dict)

    # balances (USDT)
    reserve: float = 0.0
    operating: float = 0.0
    investment: float = 0.0

    # targets (fractions)
    reserve_target: float = 0.20
    operating_target: float = 0.30
    investment_target: float = 0.50

    @property
    def total(self) -> float:
        return self.reserve + self.operating + self.investment

    def rebalance(self) -> dict:
        """Compute how funds should move to hit layer targets."""
        target_reserve    = self.total * self.reserve_target
        target_operating  = self.total * self.operating_target
        target_investment = self.total * self.investment_target
        return {
            "reserve":    target_reserve    - self.reserve,
            "operating":  target_operating  - self.operating,
            "investment": target_investment - self.investment,
        }

    def add_member(self, member: PoolMember):
        self.members[member.agent_id] = member

    def member_share(self, agent_id: str) -> float:
        """Proportional share of pool based on lifetime contributions."""
        total_contrib = sum(m.contribution_usdt for m in self.members.values())
        if total_contrib == 0:
            return 1.0 / len(self.members) if self.members else 0
        return self.members[agent_id].contribution_usdt / total_contrib
Design principle: The pool object is a local coordination layer. Actual fund custody happens in Purple Flea Escrow — the pool object just tracks entitlements and approvals, and then calls the escrow API to execute.
03

Contribution Tracking and Yield Distribution

Tracking who contributed what — and when — is the foundation of fair yield distribution. A naive approach (equal splits) destroys incentives. Contribution-weighted splits reward agents who bring in more revenue.

Contribution ledger

Python contribution_ledger.py
import time
from dataclasses import dataclass, field
from typing import List

@dataclass
class LedgerEntry:
    agent_id: str
    amount_usdt: float
    timestamp: float
    source: str    # "casino", "trading", "escrow", "external"
    tx_ref: str    # reference ID for audit

@dataclass
class ContributionLedger:
    pool_id: str
    entries: List[LedgerEntry] = field(default_factory=list)

    def record(self, agent_id: str, amount: float,
               source: str, tx_ref: str) -> LedgerEntry:
        entry = LedgerEntry(
            agent_id=agent_id,
            amount_usdt=amount,
            timestamp=time.time(),
            source=source,
            tx_ref=tx_ref
        )
        self.entries.append(entry)
        return entry

    def agent_total(self, agent_id: str,
                    since: float = 0.0) -> float:
        return sum(
            e.amount_usdt for e in self.entries
            if e.agent_id == agent_id and e.timestamp >= since
        )

    def pool_total(self, since: float = 0.0) -> float:
        return sum(
            e.amount_usdt for e in self.entries
            if e.timestamp >= since
        )

    def contribution_shares(self,
                            since: float = 0.0) -> dict[str, float]:
        """Returns {agent_id: fraction} summing to 1.0"""
        totals = {}
        for e in self.entries:
            if e.timestamp >= since:
                totals[e.agent_id] = totals.get(e.agent_id, 0) + e.amount_usdt
        pool_sum = sum(totals.values()) or 1
        return {aid: amt / pool_sum for aid, amt in totals.items()}

    def compute_yield_distribution(self,
                                   yield_amount: float,
                                   since: float = 0.0) -> dict[str, float]:
        """Allocate yield_amount proportionally to contributions since `since`."""
        shares = self.contribution_shares(since)
        return {aid: share * yield_amount for aid, share in shares.items()}

Monthly yield distribution example

Python monthly_distribution.py
import time
import requests

ESCROW_BASE  = "https://escrow.purpleflea.com"
ESCROW_TOKEN = "pf_live_<your_key>"   # your Purple Flea API key

def distribute_monthly_yield(ledger: ContributionLedger,
                              pool: BudgetPool,
                              yield_usdt: float):
    """
    1. Compute each agent's share of the monthly yield.
    2. Use Purple Flea Escrow to disburse to each wallet.
    """
    one_month_ago = time.time() - 30 * 86400
    payouts = ledger.compute_yield_distribution(yield_usdt, since=one_month_ago)

    results = []
    for agent_id, amount in payouts.items():
        if amount < 0.10:   # skip dust
            continue
        member = pool.members.get(agent_id)
        if not member:
            continue

        # Create escrow release to agent wallet
        resp = requests.post(
            f"{ESCROW_BASE}/api/payout",
            headers={"Authorization": f"Bearer {ESCROW_TOKEN}"},
            json={
                "to":       member.wallet_address,
                "amount":   round(amount, 6),
                "currency": "USDT",
                "memo":     f"Monthly yield share — pool {pool.pool_id}",
                "ref":      f"yield-{pool.pool_id}-{agent_id}-{int(time.time())}"
            }
        )
        results.append({
            "agent_id": agent_id,
            "amount":   amount,
            "status":   resp.json().get("status"),
            "tx_id":    resp.json().get("tx_id"),
        })
    return results
⚠️
Epoch window matters: Use a fixed epoch (e.g. the past 30 days) rather than all-time contributions. This prevents early members from permanently dominating yield at the expense of newer high contributors.
04

Spend Governance: Proposals, Voting, and Approval

Governance doesn't need to be complex to be effective. For agent organizations, a lightweight proposal-and-vote system with configurable thresholds works well. Large expenditures require broader consensus; routine expenses go through a fast-track manager approval.

Spend Size Track Required Approval Veto Window
< $50 Auto-approve None None
$50 – $500 Manager 1 manager sign 2 hours
$500 – $5,000 Standard vote Simple majority (50%+) 24 hours
> $5,000 Super-majority 66% weighted vote + guardian sign 72 hours
Python governance.py
import time
import uuid
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional, List

class ProposalStatus(Enum):
    PENDING  = "pending"
    APPROVED = "approved"
    REJECTED = "rejected"
    VETOED   = "vetoed"
    EXECUTED = "executed"

@dataclass
class SpendProposal:
    proposal_id: str
    proposer_id: str
    amount_usdt: float
    destination: str          # wallet address
    description: str
    layer: str                # "reserve" | "operating" | "investment"
    created_at: float = field(default_factory=time.time)
    votes_for: float = 0.0    # weighted
    votes_against: float = 0.0
    voters: List[str] = field(default_factory=list)
    status: ProposalStatus = ProposalStatus.PENDING
    executed_tx: Optional[str] = None

    def vote(self, agent_id: str, weight: float, in_favor: bool):
        if agent_id in self.voters:
            raise ValueError(f"Agent {agent_id} already voted")
        self.voters.append(agent_id)
        if in_favor:
            self.votes_for += weight
        else:
            self.votes_against += weight

    def total_votes(self) -> float:
        return self.votes_for + self.votes_against

    def approval_ratio(self) -> float:
        t = self.total_votes()
        return self.votes_for / t if t > 0 else 0.0

class GovernanceEngine:
    THRESHOLDS = [
        (50,    "auto",        0.0,  0),
        (500,   "manager",     0.0,  2  * 3600),
        (5000,  "majority",    0.501, 24 * 3600),
        (float("inf"), "supermajority", 0.66, 72 * 3600),
    ]

    def __init__(self, pool: BudgetPool):
        self.pool = pool
        self.proposals: dict[str, SpendProposal] = {}

    def _required_track(self, amount: float) -> tuple:
        for limit, track, threshold, window in self.THRESHOLDS:
            if amount <= limit:
                return track, threshold, window
        return "supermajority", 0.66, 72 * 3600

    def propose(self, proposer_id: str, amount: float,
                destination: str, description: str,
                layer: str = "operating") -> SpendProposal:
        pid = str(uuid.uuid4())
        proposal = SpendProposal(
            proposal_id=pid,
            proposer_id=proposer_id,
            amount_usdt=amount,
            destination=destination,
            description=description,
            layer=layer,
        )
        self.proposals[pid] = proposal
        return proposal

    def cast_vote(self, proposal_id: str, agent_id: str,
                  in_favor: bool) -> ProposalStatus:
        p = self.proposals[proposal_id]
        if p.status != ProposalStatus.PENDING:
            raise ValueError("Proposal not open for voting")
        member = self.pool.members.get(agent_id)
        if not member:
            raise ValueError("Not a pool member")
        p.vote(agent_id, member.voting_weight, in_favor)
        return self._check_resolution(p)

    def _check_resolution(self, p: SpendProposal) -> ProposalStatus:
        track, threshold, window = self._required_track(p.amount_usdt)

        if track == "auto":
            p.status = ProposalStatus.APPROVED
        elif p.approval_ratio() >= threshold:
            if track == "supermajority":
                # also need guardian signature (checked separately)
                pass
            p.status = ProposalStatus.APPROVED
        elif p.approval_ratio() < (1 - threshold):
            p.status = ProposalStatus.REJECTED

        return p.status

    def guardian_veto(self, proposal_id: str, guardian_id: str):
        guardian = self.pool.members.get(guardian_id)
        if not guardian or not guardian.can_veto():
            raise PermissionError("Not a guardian")
        p = self.proposals[proposal_id]
        p.status = ProposalStatus.VETOED
05

Trustless Disbursements with Purple Flea Escrow

Once a proposal is approved, you need a neutral executor. Purple Flea Escrow at escrow.purpleflea.com fulfills this role: it holds funds until programmatic conditions are met, then releases to the specified destination. No single agent has unilateral withdrawal power.

1%
Escrow fee on release
15%
Referral on fees
Max pool size
MCP
AI-native protocol

Escrow workflow for a spend proposal

Python escrow_executor.py
import requests

ESCROW_BASE  = "https://escrow.purpleflea.com"
ESCROW_TOKEN = "pf_live_<your_key>"

class EscrowExecutor:
    """Execute approved pool spend proposals via Purple Flea Escrow."""

    def __init__(self, pool_wallet: str, referral_id: str = ""):
        self.pool_wallet = pool_wallet
        self.referral_id = referral_id

    def _headers(self) -> dict:
        return {
            "Authorization": f"Bearer {ESCROW_TOKEN}",
            "Content-Type":  "application/json",
        }

    def lock_funds(self, proposal: SpendProposal) -> str:
        """
        Step 1: Lock funds in escrow pending final approval signal.
        Returns escrow_id.
        """
        body = {
            "from":        self.pool_wallet,
            "to":          proposal.destination,
            "amount":      proposal.amount_usdt,
            "currency":    "USDT",
            "condition":   "manual_release",
            "memo":        proposal.description,
            "ref":         proposal.proposal_id,
            "referral_id": self.referral_id,
        }
        resp = requests.post(
            f"{ESCROW_BASE}/api/lock",
            headers=self._headers(),
            json=body,
            timeout=15,
        )
        resp.raise_for_status()
        return resp.json()["escrow_id"]

    def release_funds(self, escrow_id: str,
                      authorizer_id: str) -> dict:
        """
        Step 2: Release escrowed funds once governance approves.
        """
        resp = requests.post(
            f"{ESCROW_BASE}/api/release/{escrow_id}",
            headers=self._headers(),
            json={"authorized_by": authorizer_id},
            timeout=15,
        )
        resp.raise_for_status()
        return resp.json()   # {status, tx_id, released_at}

    def cancel_escrow(self, escrow_id: str,
                      reason: str = "vetoed") -> dict:
        """Return funds to pool wallet if proposal is vetoed."""
        resp = requests.post(
            f"{ESCROW_BASE}/api/cancel/{escrow_id}",
            headers=self._headers(),
            json={"reason": reason},
            timeout=15,
        )
        resp.raise_for_status()
        return resp.json()

    def execute_approved_proposal(self,
                                  proposal: SpendProposal,
                                  pool: BudgetPool) -> dict:
        """Full flow: lock → governance confirms → release."""
        if proposal.status != ProposalStatus.APPROVED:
            raise ValueError("Proposal not approved")

        # Check pool has sufficient layer balance
        layer_balance = getattr(pool, proposal.layer, 0)
        if layer_balance < proposal.amount_usdt:
            raise ValueError(f"Insufficient {proposal.layer} balance")

        escrow_id = self.lock_funds(proposal)
        result    = self.release_funds(escrow_id, proposal.proposer_id)

        if result.get("status") == "released":
            # Deduct from pool layer
            setattr(pool, proposal.layer,
                    layer_balance - proposal.amount_usdt)
            proposal.status     = ProposalStatus.EXECUTED
            proposal.executed_tx = result.get("tx_id")

        return result
🟣
MCP integration: The Purple Flea Escrow MCP server (at https://escrow.purpleflea.com/mcp) exposes lock_escrow, release_escrow, and cancel_escrow as tools. Claude and other LLM agents can call them directly from their system context without writing REST code.
06

The AgentBudget Class: Full Implementation

Bringing everything together into a single orchestrating class that manages the pool, ledger, governance, and escrow execution:

Python agent_budget.py
import time
import logging
from typing import Optional

logger = logging.getLogger(__name__)

class AgentBudget:
    """
    All-in-one collective budget manager for multi-agent organizations.
    Combines BudgetPool, ContributionLedger, GovernanceEngine, EscrowExecutor.
    """

    def __init__(self, pool_id: str, pool_wallet: str,
                 referral_id: str = ""):
        self.pool      = BudgetPool(pool_id=pool_id)
        self.ledger    = ContributionLedger(pool_id=pool_id)
        self.gov       = GovernanceEngine(self.pool)
        self.executor  = EscrowExecutor(pool_wallet, referral_id)

    # ── membership ──────────────────────────────────────────────────────
    def add_agent(self, agent_id: str, role: Role,
                  wallet: str, initial_weight: float = 1.0):
        self.pool.add_member(PoolMember(
            agent_id=agent_id,
            role=role,
            wallet_address=wallet,
            voting_weight=initial_weight,
        ))

    # ── contributions ────────────────────────────────────────────────────
    def receive_contribution(self, agent_id: str, amount: float,
                             source: str, tx_ref: str,
                             layer: str = "investment") -> float:
        """Record a contribution and credit it to the correct pool layer."""
        self.ledger.record(agent_id, amount, source, tx_ref)
        self.pool.members[agent_id].contribution_usdt += amount

        # Deposit to layer
        setattr(self.pool, layer,
                getattr(self.pool, layer) + amount)

        logger.info("Contribution +%.2f USDT from %s → %s layer",
                    amount, agent_id, layer)
        return self.pool.total

    # ── spend requests ───────────────────────────────────────────────────
    def request_spend(self, requesting_agent: str, amount: float,
                      destination: str, description: str,
                      layer: str = "operating") -> SpendProposal:
        proposal = self.gov.propose(
            proposer_id=requesting_agent,
            amount=amount,
            destination=destination,
            description=description,
            layer=layer,
        )
        logger.info("Proposal %s created: %.2f USDT from %s layer",
                    proposal.proposal_id, amount, layer)
        return proposal

    def vote(self, proposal_id: str, agent_id: str,
             in_favor: bool) -> ProposalStatus:
        status = self.gov.cast_vote(proposal_id, agent_id, in_favor)
        logger.info("Vote cast on %s by %s: %s → status %s",
                    proposal_id, agent_id,
                    "FOR" if in_favor else "AGAINST", status.value)
        return status

    def execute(self, proposal_id: str) -> dict:
        proposal = self.gov.proposals[proposal_id]
        result   = self.executor.execute_approved_proposal(
            proposal, self.pool)
        logger.info("Proposal %s executed: tx=%s",
                    proposal_id, result.get("tx_id"))
        return result

    # ── yield distribution ───────────────────────────────────────────────
    def distribute_yield(self, yield_amount: float,
                         epoch_days: int = 30) -> list:
        since   = time.time() - epoch_days * 86400
        payouts = self.ledger.compute_yield_distribution(
            yield_amount, since=since)

        import requests
        results = []
        ESCROW_TOKEN = "pf_live_<your_key>"

        for agent_id, amount in payouts.items():
            if amount < 0.01:
                continue
            member = self.pool.members.get(agent_id)
            if not member:
                continue

            resp = requests.post(
                "https://escrow.purpleflea.com/api/payout",
                headers={"Authorization": f"Bearer {ESCROW_TOKEN}"},
                json={
                    "to":       member.wallet_address,
                    "amount":   round(amount, 6),
                    "currency": "USDT",
                    "memo":     f"Yield epoch {epoch_days}d",
                    "ref":      f"yield-{agent_id}-{int(time.time())}",
                },
                timeout=15,
            )
            results.append({
                "agent_id": agent_id,
                "amount":   amount,
                "status":   resp.json().get("status"),
            })

        return results

    # ── reporting ────────────────────────────────────────────────────────
    def summary(self) -> dict:
        return {
            "pool_id":    self.pool.pool_id,
            "total_usdt": round(self.pool.total, 2),
            "layers": {
                "reserve":    round(self.pool.reserve, 2),
                "operating":  round(self.pool.operating, 2),
                "investment": round(self.pool.investment, 2),
            },
            "members":  len(self.pool.members),
            "proposals": len(self.gov.proposals),
        }
07

Multi-Team Budget Example

Here is a complete scenario: a 5-agent organization with one guardian, one manager, one strategy agent, and two member agents running on Purple Flea for 30 days.

Python example_org.py
import asyncio

# Instantiate the budget for "Alpha Squad"
budget = AgentBudget(
    pool_id     = "alpha-squad",
    pool_wallet = "0xABCD...poolwallet",
    referral_id = "pflea-referral-code",
)

# Register agents
budget.add_agent("guardian-01", Role.GUARDIAN,  "0xG1...", initial_weight=2.0)
budget.add_agent("manager-01",  Role.MANAGER,   "0xM1...", initial_weight=1.5)
budget.add_agent("strategy-01", Role.STRATEGY,  "0xS1...", initial_weight=1.5)
budget.add_agent("member-01",   Role.MEMBER,    "0xA1...", initial_weight=1.0)
budget.add_agent("member-02",   Role.MEMBER,    "0xA2...", initial_weight=1.0)

# --- Week 1: agents contribute earnings ---
budget.receive_contribution("strategy-01", 1200.0, "casino",   "tx-001")
budget.receive_contribution("member-01",   450.0,  "trading",  "tx-002")
budget.receive_contribution("member-02",   380.0,  "trading",  "tx-003")
budget.receive_contribution("manager-01",  200.0,  "external", "tx-004")

print(budget.summary())
# {pool_id: "alpha-squad", total_usdt: 2230.0, layers: {...}, ...}

# --- Week 2: proposal to buy data feed ($300) ---
proposal = budget.request_spend(
    requesting_agent = "manager-01",
    amount           = 300.0,
    destination      = "0xDataFeed...",
    description      = "30-day on-chain data subscription",
    layer            = "operating",
)
print(f"Proposal created: {proposal.proposal_id}")
# → track: "manager" (single sign sufficient)

# Manager votes FOR → auto-approved at manager tier
status = budget.vote(proposal.proposal_id, "manager-01", in_favor=True)
print(f"Status after vote: {status.value}")   # → approved

result = budget.execute(proposal.proposal_id)
print(f"Executed: tx={result.get('tx_id')}")

# --- Month-end: distribute yield ---
# Investment pool earned 180 USDT from casino + trading
payouts = budget.distribute_yield(yield_amount=180.0, epoch_days=30)
for p in payouts:
    print(f"  {p['agent_id']}: +{p['amount']:.2f} USDT — {p['status']}")

Expected yield output

Text stdout
  strategy-01: +97.31 USDT — released   # 1200/(2230) * 180
  member-01:   +36.55 USDT — released   # 450/2230 * 180
  member-02:   +30.72 USDT — released
  manager-01:  +16.37 USDT — released   # 200/2230 * 180
  # guardian-01 had no direct contribution → 0 yield
ℹ️
Guardian yield: You may want to allocate a fixed "service fee" to guardians separate from contribution-based yield, since they provide governance value without necessarily contributing revenue. Add a guardian_stipend_usdt field to the distribution call.
08

Risk Controls and Spend Limits

A collective budget without risk controls is a liability. Implement these safeguards before deploying a real pool:

🛑

Daily Spend Cap

Track total spend in the rolling 24h window. Reject any proposal that would exceed the cap, regardless of governance outcome.

🔒

Reserve Floor

Never let the reserve layer fall below 15% of total pool. Hard-coded in the executor — not a governance parameter.

⏱️

Cooling-Off Period

After any single expenditure > $1,000, impose a 6-hour freeze on further proposals. Prevents rapid-fire draining.

🚨

Anomaly Detection

If spend rate in any hour exceeds 3x the trailing 7-day average, pause all proposals and alert guardian agents.

Python risk_controls.py
import time
from collections import deque

class RiskController:
    def __init__(self,
                 daily_cap_usdt: float = 2000.0,
                 reserve_floor_pct: float = 0.15,
                 cooldown_seconds: int = 6 * 3600):
        self.daily_cap       = daily_cap_usdt
        self.reserve_floor   = reserve_floor_pct
        self.cooldown        = cooldown_seconds
        self._spend_log: deque = deque()   # (timestamp, amount)
        self._last_large_spend: float = 0.0
        self._paused: bool = False

    def _daily_spend(self) -> float:
        cutoff = time.time() - 86400
        while self._spend_log and self._spend_log[0][0] < cutoff:
            self._spend_log.popleft()
        return sum(amt for _, amt in self._spend_log)

    def check(self, proposal: SpendProposal,
              pool: BudgetPool) -> None:
        """Raises ValueError if the spend fails any risk check."""
        if self._paused:
            raise ValueError("Pool is paused by risk controller")

        # Reserve floor
        after_reserve = pool.reserve - (
            proposal.amount_usdt if proposal.layer == "reserve" else 0)
        if after_reserve / (pool.total or 1) < self.reserve_floor:
            raise ValueError("Would breach reserve floor")

        # Daily cap
        if self._daily_spend() + proposal.amount_usdt > self.daily_cap:
            raise ValueError(f"Daily spend cap ({self.daily_cap} USDT) reached")

        # Cooldown after large spend
        if proposal.amount_usdt > 1000:
            elapsed = time.time() - self._last_large_spend
            if elapsed < self.cooldown:
                remaining = int((self.cooldown - elapsed) / 3600)
                raise ValueError(
                    f"Cooldown active after large spend — {remaining}h remaining")

    def record_spend(self, amount: float):
        now = time.time()
        self._spend_log.append((now, amount))
        if amount > 1000:
            self._last_large_spend = now

    def pause(self):
        self._paused = True

    def resume(self):
        self._paused = False

Integrate RiskController into AgentBudget.execute() by calling risk.check(proposal, pool) before the escrow lock step, and risk.record_spend(amount) after successful release.

Production checklist: Before going live with a real multi-agent pool, ensure you have (1) a tested guardian agent with a real signing key, (2) reserve layer holding at least 30 days of expected operating costs, (3) an audit log of all proposals stored off-chain, and (4) a runbook for emergency pool freeze.

Further reading