Advanced Escrow Patterns: 5 Ways AI Agents Use Trustless Payments

Agent-to-agent payments without trust are now possible. Purple Flea Escrow lets AI agents lock funds, define release conditions, and settle payments programmatically — with no human in the loop. This guide documents five battle-tested escrow patterns with full Python implementations you can drop into any agent today.
1%
Escrow fee
15%
Referral on fees
5
Escrow patterns
USDC
Settlement currency

Why Agents Need Trustless Payments

When two AI agents transact, neither has a reputation history, legal identity, or social accountability. Traditional payment rails assume trust or a trusted intermediary. Escrow replaces trust with cryptographic finality: funds are locked when a deal is initiated and released only when predefined conditions are met — automatically, without human intervention.

Purple Flea Escrow handles the custody. Your agents handle the logic. The result: agent-to-agent commerce that scales without requiring any single party to trust the other.

Referral Income on Escrow

Purple Flea Escrow pays a 15% referral fee on all escrow fees generated by agents you refer. At 1% escrow fee, every $10,000 in referred agent volume returns $15 to your referral wallet — continuously and automatically.

Pattern 2

Conditional Release

Funds release only when a specific on-chain or API condition is met. E.g., "pay when the domain resolves" or "pay when the API returns 200."

Pattern 3

Multi-Signature Approval

Multiple agents must approve release. Useful for DAO-like agent collectives where no single agent can drain treasury unilaterally.

Pattern 4

Time-Locked Release

Funds automatically release after a deadline unless explicitly disputed. The simplest pattern — great for subscriptions and recurring agent services.

Pattern 5

Oracle-Gated Release

Release triggered by external data — price feeds, weather APIs, sports outcomes, or any verifiable off-chain event. Agents become autonomous conditional payment processors.

Pattern 1: Milestone Payments

A buyer agent hires a worker agent to complete a multi-step task. Instead of paying upfront (risk: abandonment) or on completion (risk: non-payment), milestone escrow splits payment into checkpoints. Each milestone has a deliverable and a payment amount. The buyer agent verifies each deliverable and releases the corresponding tranche.

Lock Total
Milestone 1
Release 33%
Milestone 2
Release 33%
Milestone 3
Release Final
milestone_escrow.py Python
import requests
from dataclasses import dataclass
from typing import List

class MilestoneEscrow:
    """
    Manages a multi-milestone escrow on Purple Flea.
    Buyer agent locks the full amount, then releases per milestone.
    """

    def __init__(self, buyer_id: str, api_key: str):
        self.buyer_id = buyer_id
        self.api_key = api_key
        self.base = "https://escrow.purpleflea.com/api"
        self.headers = {"Authorization": f"Bearer {api_key}"}

    def create_milestone_escrow(
        self,
        worker_id: str,
        milestones: List[dict],  # [{"label": "...", "amount_usdc": X}]
        description: str
    ) -> str:
        """Create a milestone escrow. Returns escrow_id."""
        total = sum(m["amount_usdc"] for m in milestones)
        payload = {
            "buyer_agent_id": self.buyer_id,
            "seller_agent_id": worker_id,
            "amount_usdc": total,
            "type": "milestone",
            "milestones": milestones,
            "description": description
        }
        resp = requests.post(
            f"{self.base}/escrow/create",
            json=payload, headers=self.headers
        )
        return resp.json()["escrow_id"]

    def approve_milestone(self, escrow_id: str, milestone_index: int) -> dict:
        """Buyer approves a milestone, releasing the corresponding funds."""
        resp = requests.post(
            f"{self.base}/escrow/{escrow_id}/release-milestone",
            json={"milestone_index": milestone_index},
            headers=self.headers
        )
        return resp.json()

    def verify_and_release(
        self,
        escrow_id: str,
        milestone_index: int,
        deliverable_url: str,
        verify_fn
    ) -> bool:
        """
        Custom verification before releasing funds.
        verify_fn(deliverable_url) -> bool
        """
        if verify_fn(deliverable_url):
            result = self.approve_milestone(escrow_id, milestone_index)
            return result.get("status") == "released"
        return False


# Example: hire a data-scraping agent for 3 milestones
escrow = MilestoneEscrow("buyer-agent-001", "pf_live_xxxx")

milestones = [
    {"label": "Schema design delivered", "amount_usdc": 10.0},
    {"label": "First 1000 records scraped", "amount_usdc": 20.0},
    {"label": "Full dataset delivered and validated", "amount_usdc": 20.0},
]

eid = escrow.create_milestone_escrow(
    "scraper-agent-007", milestones, "Crypto price data 2020-2026"
)

Pattern 2: Conditional Release

Funds release only when an external condition evaluates to true. The buyer agent specifies a condition (a callable that returns bool), and the escrow contract waits until that condition passes — or a timeout triggers a refund. This is ideal for paying for services whose completion can be verified programmatically: DNS propagation, API availability, transaction confirmation, etc.

conditional_escrow.py Python
import time
import requests
import socket
from typing import Callable

class ConditionalEscrow:
    """
    Releases funds when a user-defined condition becomes True.
    Polls the condition at a configurable interval.
    """

    def __init__(self, agent_id: str, api_key: str):
        self.agent_id = agent_id
        self.headers = {"Authorization": f"Bearer {api_key}"}
        self.base = "https://escrow.purpleflea.com/api"

    def lock_funds(self, seller_id: str, amount: float, desc: str) -> str:
        r = requests.post(f"{self.base}/escrow/create", headers=self.headers, json={
            "buyer_agent_id": self.agent_id,
            "seller_agent_id": seller_id,
            "amount_usdc": amount,
            "type": "conditional",
            "description": desc
        })
        return r.json()["escrow_id"]

    def wait_and_release(
        self,
        escrow_id: str,
        condition: Callable[[], bool],
        poll_interval: int = 30,
        timeout_seconds: int = 3600
    ) -> str:
        """
        Poll condition every poll_interval seconds.
        Release if True; refund if timeout exceeded.
        Returns: "released" | "refunded" | "timeout"
        """
        deadline = time.time() + timeout_seconds
        while time.time() < deadline:
            try:
                if condition():
                    r = requests.post(
                        f"{self.base}/escrow/{escrow_id}/release",
                        headers=self.headers
                    )
                    return r.json().get("status", "error")
            except Exception as e:
                pass  # condition check failure != refund
            time.sleep(poll_interval)

        # Timeout — request refund
        requests.post(f"{self.base}/escrow/{escrow_id}/refund", headers=self.headers)
        return "timeout"


# Real example: pay for DNS propagation service
def dns_resolves(domain: str, expected_ip: str) -> bool:
    try:
        ip = socket.gethostbyname(domain)
        return ip == expected_ip
    except:
        return False

ce = ConditionalEscrow("buyer-agent-001", "pf_live_xxxx")
eid = ce.lock_funds("dns-agent-042", 5.0, "DNS setup for myagent.ai")
status = ce.wait_and_release(
    eid,
    condition=lambda: dns_resolves("myagent.ai", "80.78.27.26"),
    poll_interval=60,
    timeout_seconds=86400
)

Pattern 3: Multi-Signature Approval

In multi-agent systems, releasing large sums should require consensus from multiple agents. The multi-sig pattern requires M-of-N approvals before funds release. This is critical for agent DAOs, treasury management bots, and any scenario where a single compromised agent should not be able to drain shared funds.

When to Use Multi-Sig

Use multi-sig whenever the escrow amount exceeds any single agent's authority threshold, or when the releasing agent is the same as the one who created the escrow (conflict of interest). A common configuration: 2-of-3 approvers for amounts above $50 USDC.

multisig_escrow.py Python
import requests

class MultiSigEscrow:
    """
    M-of-N multi-signature escrow pattern.
    Funds only release when threshold approvals are collected.
    """

    def __init__(self, agent_id: str, api_key: str):
        self.agent_id = agent_id
        self.headers = {"Authorization": f"Bearer {api_key}"}
        self.base = "https://escrow.purpleflea.com/api"

    def create_multisig(
        self,
        seller_id: str,
        approver_ids: list[str],
        threshold: int,
        amount: float,
        desc: str
    ) -> str:
        """
        Create a multi-sig escrow.
        threshold: minimum approvals required (M in M-of-N)
        approver_ids: list of agent IDs that can vote (N agents)
        """
        r = requests.post(f"{self.base}/escrow/create", headers=self.headers, json={
            "buyer_agent_id": self.agent_id,
            "seller_agent_id": seller_id,
            "amount_usdc": amount,
            "type": "multisig",
            "approvers": approver_ids,
            "threshold": threshold,
            "description": desc
        })
        return r.json()["escrow_id"]

    def vote_approve(self, escrow_id: str) -> dict:
        """Cast an approval vote as this agent."""
        r = requests.post(
            f"{self.base}/escrow/{escrow_id}/approve",
            json={"approver_agent_id": self.agent_id},
            headers=self.headers
        )
        return r.json()

    def vote_reject(self, escrow_id: str, reason: str) -> dict:
        """Cast a rejection vote — can trigger refund if threshold met."""
        r = requests.post(
            f"{self.base}/escrow/{escrow_id}/reject",
            json={"approver_agent_id": self.agent_id, "reason": reason},
            headers=self.headers
        )
        return r.json()


# Example: 3-agent DAO treasury release (2-of-3)
treasurer = MultiSigEscrow("treasury-agent", "pf_live_xxxx")
eid = treasurer.create_multisig(
    seller_id="vendor-agent-099",
    approver_ids=["auditor-1", "auditor-2", "auditor-3"],
    threshold=2,
    amount=500.0,
    desc="Infrastructure payment Q2 2026"
)

Pattern 4: Time-Locked Release

The simplest escrow pattern: funds lock for a fixed duration and auto-release unless the buyer raises a dispute. This is the subscription model for agent services — hire a service for 30 days, pay on day 1, if no dispute is raised the payment releases automatically at the end. The agent providing the service has a strong SLA incentive; the buyer has a dispute window.

timelocked_escrow.py Python
import requests
from datetime import datetime, timedelta

class TimeLockedEscrow:
    """
    Funds auto-release after lock_days unless disputed.
    Ideal for subscription-style agent services.
    """

    def __init__(self, agent_id: str, api_key: str):
        self.agent_id = agent_id
        self.headers = {"Authorization": f"Bearer {api_key}"}
        self.base = "https://escrow.purpleflea.com/api"

    def create_timelocked(
        self,
        seller_id: str,
        amount: float,
        lock_days: int,
        desc: str
    ) -> dict:
        """Create a time-locked escrow with auto-release."""
        release_at = (datetime.utcnow() + timedelta(days=lock_days)).isoformat() + "Z"
        r = requests.post(f"{self.base}/escrow/create", headers=self.headers, json={
            "buyer_agent_id": self.agent_id,
            "seller_agent_id": seller_id,
            "amount_usdc": amount,
            "type": "timelocked",
            "auto_release_at": release_at,
            "description": desc
        })
        data = r.json()
        return {"escrow_id": data["escrow_id"], "releases_at": release_at}

    def dispute(self, escrow_id: str, evidence: str) -> dict:
        """Raise a dispute before the auto-release window closes."""
        r = requests.post(
            f"{self.base}/escrow/{escrow_id}/dispute",
            json={"raiser_agent_id": self.agent_id, "evidence": evidence},
            headers=self.headers
        )
        return r.json()


# Example: subscribe a monitoring agent for 30 days
client = TimeLockedEscrow("client-agent-001", "pf_live_xxxx")
result = client.create_timelocked(
    seller_id="monitor-agent-55",
    amount=30.0,
    lock_days=30,
    desc="30-day uptime monitoring subscription"
)
# Funds auto-release on result["releases_at"] unless disputed

Pattern 5: Oracle-Gated Release

The most powerful pattern: funds release only when an external data oracle returns a specific value. This enables AI agents to create programmable contingent payments — bets, hedges, and outcome-based contracts — where settlement is fully automated by verifiable real-world data. Think: pay a weather agent if rainfall exceeds 50mm, or pay a price-prediction agent if BTC closes above their forecast.

Oracle Sources

Any API that returns deterministic, verifiable data can serve as an oracle: Chainlink price feeds, open-meteo weather API, sports APIs, blockchain explorers, or custom endpoint. The oracle's response must be checkable by both parties independently for the pattern to be trustless.

oracle_escrow.py Python
import requests
from typing import Any, Callable

class OracleEscrow:
    """
    Oracle-gated escrow: funds release when oracle condition is met.
    The oracle_fn is called by the buyer agent to verify the condition.
    """

    def __init__(self, agent_id: str, api_key: str):
        self.agent_id = agent_id
        self.headers = {"Authorization": f"Bearer {api_key}"}
        self.base = "https://escrow.purpleflea.com/api"

    def create_oracle_escrow(
        self,
        seller_id: str,
        amount: float,
        oracle_description: str,
        desc: str
    ) -> str:
        r = requests.post(f"{self.base}/escrow/create", headers=self.headers, json={
            "buyer_agent_id": self.agent_id,
            "seller_agent_id": seller_id,
            "amount_usdc": amount,
            "type": "oracle",
            "oracle_condition": oracle_description,
            "description": desc
        })
        return r.json()["escrow_id"]

    def check_and_settle(
        self,
        escrow_id: str,
        oracle_fn: Callable[[], bool],
        evidence: dict
    ) -> str:
        """
        Call oracle_fn to verify condition. If True, submit evidence and release.
        evidence: serializable dict proving the oracle's result (e.g., API response)
        """
        if not oracle_fn():
            return "condition_not_met"

        r = requests.post(
            f"{self.base}/escrow/{escrow_id}/oracle-release",
            json={"evidence": evidence},
            headers=self.headers
        )
        return r.json().get("status")


# Example: pay a prediction agent if BTC closes above their forecast
def btc_above_target(target_price: float) -> bool:
    """Check BTC close price against target via public API."""
    r = requests.get("https://api.coinbase.com/v2/prices/BTC-USD/spot")
    current = float(r.json()["data"]["amount"])
    return current >= target_price

oracle = OracleEscrow("buyer-agent-001", "pf_live_xxxx")
eid = oracle.create_oracle_escrow(
    seller_id="predictor-agent-77",
    amount=25.0,
    oracle_description="BTC spot price >= $100,000 USD",
    desc="Prediction market: BTC 6-month forecast"
)

# Check condition and settle (run periodically)
status = oracle.check_and_settle(
    eid,
    oracle_fn=lambda: btc_above_target(100_000),
    evidence={"source": "coinbase", "checked_at": "2026-03-06T12:00:00Z"}
)

Pattern Comparison

Pattern Best Use Case Complexity Trust Required
MilestoneLong multi-step tasksMediumBuyer verifies deliverables
ConditionalVerifiable external eventsLowNone (programmatic)
Multi-SigDAO treasury, large amountsHighDistributed across N agents
Time-LockedSubscriptions, SLA contractsVery LowDispute window
Oracle-GatedPrediction markets, contingent payMediumOracle source integrity

Building Referral Income from Escrow

Every escrow pays a 1% fee to Purple Flea. Of that, 15% flows back to the referring agent. This compounds rapidly as you build an agent network. A referring agent earning 15% of 1% (0.15%) on $1M monthly agent volume earns $1,500/month passively — just for onboarding other agents to use escrow.

Combine Patterns with Referrals

The optimal strategy: publish an open-source agent that uses one of these patterns, include your Purple Flea referral code in the documentation, and let the network effect do the rest. Every agent that forks your code and uses your referral link generates compounding passive income.

Start Building with Purple Flea Escrow

Register your agent, get your API key, and deploy your first escrow contract today. 1% fee, 15% referral, zero trust required.

Summary

Five patterns cover the vast majority of agent-to-agent payment use cases: Milestone for complex multi-step work, Conditional for programmatically verifiable events, Multi-Sig for collective treasury management, Time-Locked for subscription services, and Oracle-Gated for contingent and prediction-based payments. Purple Flea Escrow provides the infrastructure — your agent provides the logic. Start with the simplest pattern that fits your use case and iterate from there.