Runnable buyer/seller pairs that exercise the SDK end-to-end. Pick the variant that matches what you're building.
| Folder | Best for |
|---|---|
basic/ |
Default flow — manual control, buyer is its own evaluator. Start here. |
fund-transfer/ |
Fund-transfer hook via createJobFromOffering when requiredFunds; same lifecycle patterns as basic/, optional structured payloads in jobTypes.ts. |
subscription/ |
Jobs that activate (or renew) an on-chain SubscriptionHook package via createJobFromOffering({ packageId }) + setBudgetWithSubscription. |
subscription-fund-transfer/ |
Multi-hook variant: subscription + per-job fund forwarding in a single job (setBudgetWithSubscriptionAndFundRequest). |
llm/ |
Both sides driven by Claude through session.availableTools() + session.executeTool(). Requires ANTHROPIC_API_KEY. |
Each folder has its own README.md with the lifecycle, expected log output,
and any variant-specific gotchas.
Are both sides agents on the same chain settling in USDC?
├─ Yes ──┬─ Need an LLM driving the messages and tool calls?
│ │ ├─ Yes → llm/
│ │ └─ No → basic/
│ ├─ Need to forward funds to a third-party address on submission?
│ │ └─ Yes → fund-transfer/
│ ├─ Need recurring access via an on-chain subscription package?
│ │ └─ Yes → subscription/
│ └─ Need both a subscription package AND per-job fund forwarding?
│ └─ Yes → subscription-fund-transfer/
└─ No → start from basic/ and adapt; see the main README's Provider Adapters section
All examples expect the same .env at the repo root, and you run them with tsx.
Two agents are needed for an end-to-end run — a buyer and a seller. Each must
be registered on the Service Registry. See
the main README — Prerequisites for where to
find walletId and how to generate a signer key.
cp .env.example .env| Var | Format |
|---|---|
*_WALLET_ADDRESS |
0x-prefixed 20-byte address of the Privy server-managed wallet |
*_WALLET_ID |
UUID-like wallet id from the Privy dashboard |
*_SIGNER_PRIVATE_KEY |
Privy authorization key — base64 PKCS#8 P-256 (prime256v1), ~155 chars, starts with MIGH. Not an EOA hex key. Generated under the agent's Signers tab. |
ANTHROPIC_API_KEY |
Only required by the llm/ examples |
basic/andllm/read their credentials from.envviarequireEnv().fund-transfer/still has hardcoded0xBuyerWalletAddress/0xSellerWalletAddressplaceholders — replace them inline before running, or wire them to env vars using the same pattern asbasic/seller.ts.
tsx runs TypeScript files directly without a build step. Open two terminals
and start the seller first so it's listening when the buyer creates a job:
# Terminal 1 — seller listener
npx tsx src/examples/basic/seller.ts
# → [seller] address: 0x...
# → [seller] ready, listening for jobs
# Terminal 2 — once the seller is ready, start the buyer
npx tsx src/examples/basic/buyer.tsCtrl+C cleanly disconnects either side. The buyer scripts call buyer.stop()
themselves once the job reaches a terminal state (job.completed or
job.rejected); the seller stays running to accept more jobs.
| Buyer | Seller | Notes |
|---|---|---|
basic/buyer.ts |
basic/seller.ts |
Happy path: budget → fund → submit → complete. Demonstrates reject points too. |
fund-transfer/buyer.ts |
fund-transfer/seller.ts |
Buyer uses createJobFromOffering with requiredFunds; seller uses setBudgetWithFundRequest (registry, structured samples, or default direct amounts). |
subscription/buyer.ts |
subscription/seller.ts |
Activates/renews an on-chain SubscriptionHook package; first job pays offering + subscription fee, follow-ups within the active window pay only the offering. |
subscription-fund-transfer/buyer.ts |
subscription-fund-transfer/seller.ts |
Multi-hook job combining SubscriptionHook + FundTransferHook via setBudgetWithSubscriptionAndFundRequest; subscription covers offering price after activation, fund transfer fires per job. |
llm/buyer.ts |
llm/seller.ts |
Both sides driven by Claude. Requires ANTHROPIC_API_KEY in .env for both. |
The buyer and seller must use different wallets. The seller's wallet must
also be registered as a provider with at least one offering on the registry for
buyer.browseAgents() (used by basic/buyer.ts) to find it.
Missing required env var: SELLER_WALLET_ADDRESS— your.envis in the wrong directory. Examples calldotenv.config()from the project root.PrivyAlchemyEvmProviderAdapter: either signerPrivateKey or signFn must be provided— the env var is set but empty. Verify withecho "$SELLER_SIGNER_PRIVATE_KEY"after sourcing.env.- Buyer logs
created job Nbut seller never reacts — the buyer paired with a different seller wallet, or the seller's offering is hidden / filtered out. PassshowHidden: truetobrowseAgents(already set inbasic/buyer.ts). Job N not found on chain ...— on-chain creation succeeded but the off-chain chat room hasn't materialized yet; the SDK already retriessendMessage5× with a 2s delay (seeacpAgent.ts), so this should be transient.- Auth-key shape errors from
@privy-io/node— theSIGNER_PRIVATE_KEYis not a hex EOA key. It must be the base64 PKCS#8 P-256 authorization key from the Privy dashboard (MIGH…).