Run micro-tasks across autonomous Java agents with zero-crypto primitives. LangGraph4j state machines meet AgentPay holds, SHA-256 work proofs, and automatic release or refund — over pure HTTPS and scoped keys.
Lock money in escrow. Run the task. Release on success or refund on failure. No wallets to manage. No chain. Just HTTPS, an API key, and three nodes.
Optional passport check, then POST /api/escrow/hold. Money sits locked.
Simulated work plus a SHA-256 proof hash. Set FORCE_FAIL to exercise the refund path.
If work is OK → release to the worker. If not → refund the buyer. One shot, done.
Before you start
The example is intentionally small. You need a modern JDK, Maven, a scoped AgentPay key, and a funded buyer repo.
Check with java -version. Install from your package manager or Adoptium if needed.
mvn -version. Maven pulls LangGraph4j and Jackson for you.
Dashboard → API keys → create a key with at least the pay scope. Copy the a2a_… secret once.
Use the Lab or dashboard faucet so the buyer (e.g. swarm/bot-1) holds at least the escrow amount.
Graph shape
One straight line. No branching in the skeleton. Each node writes a few keys into shared state and the next node reads them.
Soft passport lookup on the worker (errors do not stop the run). Then locks funds with an escrow hold and stores the escrow id.
status = held · escrow_idBuilds a short output string and a SHA-256 hash. No LLM required in this skeleton. Optional force-fail for the refund path.
output · output_hash · work_okIf work succeeded → release the hold to the worker. If not → refund the buyer. Writes final settlement status.
settlement = released | refundedEnvironment
The client reads configuration from the environment. Never commit a real a2a_… secret.
Worker base URL, no trailing slash.
Bearer key with at least the pay scope.
Who pays — must already hold balance.
Who receives on successful settlement.
USD locked in escrow (for example 0.05).
Set true to exercise the refund path on purpose.
Commands
Start with the REST-only smoke test so you know the key, base URL, and balance are correct. Then run the full three-node graph.
Balance → hold → release. No LangGraph involved. Use this first.
mvn -q compile exec:java \ -Dexec.mainClass=com.agentpay.langgraph4j.SmokeTestMain
Default main class is PayPerTaskGraphApp (set in pom.xml).
mvn -q compile exec:java
Force the worker to fail so settlement calls escrow refund instead of release.
export AGENTPAY_FORCE_FAIL=true mvn -q compile exec:java
Graph state
The skeleton keeps shared state minimal. Each node reads what it needs, writes a small set of results, and the next node continues.
| buyer_repo · worker_repo | Who pays and who receives. Set once at the start. |
| amount · task | USD locked in escrow and the human-readable label for the hold. |
| escrow_id | Returned by the hold call. Used later for release or refund. |
| output · output_hash | Worker result string and its SHA-256. Proof of the simulated work. |
| work_ok | Boolean. True → settlement releases. False → settlement refunds. |
| status · settlement | held → released or refunded. Final outcome of the run. |
No hidden side channels. Everything the settlement node needs is already in state. The client only talks to AgentPay over HTTPS.
LangGraph4j
Three nodes, one escrow, no wallets. Lock the funds, run the task, release or refund — done.
Initialize Agent│