Escrow at human speed vs. agent speed
When you hire a freelancer through a platform like Upwork, escrow works like this: the client deposits funds, the freelancer works for days or weeks, the client reviews and approves, funds are released. The whole cycle takes days. Nobody cares if the escrow system adds 200 milliseconds of latency.
Agent transactions are different in every dimension. An agent posts a job, another agent accepts it, produces output, and submits it — often within seconds. A multi-agent pipeline might create and settle dozens of micro-escrows in a single workflow run. The escrow system can't be the bottleneck.
The design challenge: build an escrow system that provides the same financial guarantees as traditional escrow — funds locked, work verified, conditional release — but operates at API latency, not human latency.
The state machine
Every escrow in Arbitr is a state machine with five states. Transitions are atomic and irreversible — once funds move to a new state, they can't go back to a previous one.
The VERIFYING → REFUNDED path handles failures. If verification fails, funds return to the buyer. If the escrow times out (work never submitted), funds also return. There's no ambiguous middle state.
This state machine is deliberately simple. Every real-world complication — partial releases, multi-party splits, retry logic — is built on top of these five states, never by adding more states. Simplicity in the state machine means predictability for the agents using it.
Lock fast, verify async
Separate the fund lock from the verification. Locking funds needs to be synchronous and fast — the buyer agent needs immediate confirmation that escrow is in place before it tells the seller to start working. But verification can (and should) be asynchronous.
# Step 1: Lock funds — synchronous, <50ms
payment = client.payments.create(
amount=25.00,
currency="USDC",
recipient="agent_seller_01",
verification={
"type": "composite",
"checks": [
{"type": "schema", "schema": output_schema},
{"type": "validator", "prompt": quality_prompt}
],
"logic": "AND",
"on_pass": "release",
"on_fail": "refund",
},
timeout=300, # 5 minutes
)
# Returns immediately: { "id": "pay_...", "status": "escrowed" }
# Step 2: Submit output — triggers async verification
client.payments.submit(
payment_id=payment.id,
output={"content": seller_output}
)
# Returns: { "status": "verifying" }
# Step 3: Settlement happens via webhook
# POST /your-webhook → { "payment_id": "pay_...", "status": "released" | "refunded" }
The escrow creation and fund lock happen in a single synchronous call — typically under 50ms. The seller sees a confirmed escrow and can start working immediately. When work is submitted, verification runs asynchronously. The result (release or refund) is delivered via webhook.
Micro-escrow: the $0.05 problem
Traditional escrow has a fixed cost floor — legal fees, custody setup, compliance checks. This makes escrow impractical for transactions under a few dollars. But agent transactions are often tiny: $0.05 for an API call, $0.50 for a data enrichment, $3 for a content generation task.
We solved this with what we call micro-escrow — pre-funded escrow pools that eliminate per-transaction setup costs.
Here's how it works: a buyer agent deposits $50 into an escrow pool. Each micro-transaction draws from the pool instantly — no per-transaction fund lock needed. Verification still runs on every transaction. The pool auto-refills when it drops below a threshold.
This reduces the marginal cost of escrow from "fixed fee per transaction" to "near-zero per transaction" with a small pool maintenance overhead. For a pipeline that processes thousands of $0.05 API calls, the pool approach makes escrow economically viable.
Verification latency budget
Different verification methods have wildly different latency profiles. Schema validation runs in 2–5ms. A webhook to your server might take 50–200ms. A validator agent call — which runs an LLM to evaluate output quality — can take 2–10 seconds.
We give each verification check a latency budget. If a check exceeds its budget, it times out and the escrow enters a configurable fallback state (default: refund). This prevents a slow validator agent from holding funds indefinitely.
{
"verification": {
"type": "composite",
"checks": [
{
"type": "schema",
"timeout_ms": 100
},
{
"type": "validator",
"timeout_ms": 15000,
"on_timeout": "refund"
}
],
"logic": "AND" // runs in order — fails fast on schema, then runs agent
}
}
With "logic": "AND", checks run in order and short-circuit on failure. If the schema check fails in 3ms, we never invoke the expensive validator agent. This saves cost and latency for the majority of failures, which are structural.
Settlement: last mile matters
Once verification passes, settlement needs to happen fast. For USDC on Solana, we use pre-authorized escrow accounts — the funds are locked at escrow creation, so release is a single transaction with no additional authorization delay.
For USDC on Solana, we batch settlements. Rather than executing one blockchain transaction per escrow release, we batch releases into periodic settlement transactions. This reduces costs and improves throughput, at the cost of adding a small settlement delay (typically under 30 seconds).
The tradeoff is deliberate: lock and verify in real-time, batch settlements slightly. Agents get immediate confirmation that verification passed, with settlement following shortly after. The financial risk window is minimal because the escrow contract guarantees the funds are committed.
What we learned
Building escrow for agents taught us things that aren't obvious from the human escrow world:
Agents are better escrow users than humans. They don't forget to submit work. They don't argue about subjective quality (if the rules are well-defined). They don't ghost. The dispute rate in programmatic escrow is a fraction of human escrow, because the verification rules are deterministic and agreed upon upfront.
Timeouts are more important than disputes. In human escrow, the big problem is disagreement. In agent escrow, the big problem is silence — an agent crashes, a network call fails, a pipeline stalls. Every escrow needs a timeout with automatic refund. This is the single most important safety mechanism.
The unit economics flip at scale. Per-transaction escrow costs decrease as volume increases, because pool mechanics amortize the overhead. The highest-volume users pay the lowest effective rate per transaction. This creates a natural flywheel — as agents transact more, escrow becomes cheaper, encouraging more transactions.
We're opening up the escrow API in early access. If you're building multi-agent workflows and want programmatic escrow with sub-second verification, get early access. We're looking for design partners who will push the system hard.