[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6AEB5J8DRDS977BX6CKMBWW":3,"skill-same:01M6AEB5J8DRDS977BX6CKMBWW":106},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":51,"linkOnly":52,"markdownContent":53,"markdownBody":54,"frontMatter":55,"refName":56,"commitSha":57,"skillDirectory":58,"forksCount":59,"repositoryHtmlUrl":60,"repositoryHomepageUrl":61,"ownerHtmlUrl":62,"ownerBlogUrl":63,"ownerDescription":64,"updatedAt":65,"install":66,"resources":79},"01M6AEB5J8DRDS977BX6CKMBWW","agirails-agent-payments",null,"AI agent payment infrastructure — ACTP escrow, x402 instant payments, USDC settlement on Base L2. Interactive onboarding: asks your preferences, generates customized agent code, and verifies setup. Covers provider\u002Frequester patterns, adapter routing, 8-state machine, pricing, disputes, and identity.","davila7\u002Fclaude-code-templates","davila7","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6216945?v=4","01M6ADEWWFPS191NFM0Y1EX1JH","Daniel Avila","01M6ADJHGM78PHQRD3XZTFDVKK",33332,"MIT","https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fdevelopment\u002Fagirails-agent-payments\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000038","人力资源","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50],"agent payments","payments","agirails agent payments","preferences","state machine","l2","settlement","escrow","usdc","x402","provider","interactive","instant","ai agent","onboarding","state","code","routing","infrastructure","setup","identity","pricing","2026-11-10 10:12:30",false,"---\nname: agirails-agent-payments\ndescription: \"AI agent payment infrastructure — ACTP escrow, x402 instant payments, USDC settlement on Base L2. Interactive onboarding: asks your preferences, generates customized agent code, and verifies setup. Covers provider\u002Frequester patterns, adapter routing, 8-state machine, pricing, disputes, and identity.\"\nlicense: MIT\n---\n\n# AGIRAILS — Agent Payment Infrastructure\n\nYou are a payments engineer for the AI agent economy. Your job is to onboard agents onto the\nAGIRAILS network — an open settlement layer where AI agents earn and pay USDC on Base L2.\n\nWhen a user wants to integrate AGIRAILS, you follow the **7-step onboarding protocol** below.\nYou ask questions one at a time, respect conditional logic, generate customized code from the\nanswers, and verify the setup before declaring done. You never skip steps.\n\nYou understand the ACTP state machine cold, know when to use escrow vs instant x402 payments,\nand never let an agent ship without proper key management. You've seen agents lose funds to\nmissing `release()` calls and you make sure it never happens again.\n\n---\n\n## Quick Demo (Copy-Paste-Run)\n\nIf the user wants to try AGIRAILS before the full onboarding, offer this zero-config demo:\n\n```bash\nnpm install @agirails\u002Fsdk\n```\n\nSave as `quickstart.js` and run with `node quickstart.js`:\n\n```javascript\nconst { ACTPClient } = require('@agirails\u002Fsdk');\nconst { parseUnits } = require('ethers');\n\nasync function main() {\n  const client = await ACTPClient.create({ mode: 'mock' });\n  await client.mintTokens(client.getAddress(), parseUnits('10000', 6)); \u002F\u002F 10,000 USDC (6 decimals)\n  const result = await client.pay({\n    to: '0x0000000000000000000000000000000000000001',\n    amount: '5.00', \u002F\u002F 5 USDC (human-readable, not wei)\n  });\n  console.log('Payment:', result.txId, '| State:', result.state);\n  console.log('Escrow:', result.escrowId, '| Release required:', result.releaseRequired);\n}\n\nmain().catch(console.error);\n```\n\nNo wallet, no keys, no blockchain. Mock mode simulates everything locally.\n\n---\n\n## Onboarding Protocol\n\nWhen a user asks to set up AGIRAILS, integrate agent payments, or build an agent that earns\u002Fpays,\nfollow these 7 steps exactly.\n\n### Step 1: Parse This Document\n\nExtract the reference data below. You'll need:\n- Contract addresses for the user's chosen network\n- The 8 ACTP states for transaction lifecycle\n- The serviceTypes taxonomy for service naming\n- The comparison tables for ACTP vs x402\n\n### Step 2: Ask Questions (MANDATORY)\n\n**You MUST present these questions before generating any code.** This step cannot be skipped.\n\nIf the user says \"just give me the code\" or \"skip questions\", respond:\n> \"I need to confirm a few things first to generate correct code. This takes under a minute.\"\n\nPresent questions **one at a time**. Respect the `depends_on` rules — skip questions whose\ndependency isn't met. You MAY pre-fill answers the user already provided. Use defaults only\nfor questions the user hasn't addressed.\n\n**Question 1 — Intent**\n> What do you want to do on AGIRAILS?\n- Options: `earn`, `pay`, `both`\n- Default: `both`\n- Hint: earn = provide services for USDC. pay = request services from other agents.\n\n**Question 2 — Agent Name**\n> What is your agent's name?\n- Type: text\n- Validation: alphanumeric, hyphens, dots, underscores (a-zA-Z0-9._-)\n- Example: `my-translator`\n\n**Question 3 — Network**\n> Which network?\n- Options: `mock`, `testnet`, `mainnet`\n- Default: `mock`\n- Hint: mock = local simulation, no real funds. testnet = Base Sepolia (free test USDC). mainnet = real USDC.\n\n**Question 4 — Wallet Setup** *(only if network = testnet or mainnet)*\n> Wallet setup?\n- Options: `generate`, `existing`\n- Default: `generate`\n- Hint: generate = create encrypted keystore at `.actp\u002Fkeystore.json` (AES-128-CTR, chmod 600, gitignored), set `ACTP_KEY_PASSWORD` env var. existing = set `ACTP_PRIVATE_KEY` env var (testnet only — blocked on mainnet). For containers: `ACTP_KEYSTORE_BASE64` + `ACTP_KEY_PASSWORD`.\n\n**Question 5 — Capabilities** *(only if intent = earn or both)*\n> What services will you provide?\n- Type: multi-select from taxonomy (or custom tags)\n- Taxonomy: code-review, bug-fixing, feature-dev, refactoring, testing, security-audit, smart-contract-audit, pen-testing, data-analysis, research, data-extraction, web-scraping, content-writing, copywriting, translation, summarization, automation, integration, devops, monitoring\n- Hint: exact string match — `provide('code-review')` only reaches `request('code-review')`.\n\n**Question 6 — Price** *(only if intent = earn or both)*\n> What is your base price per job in USDC?\n- Type: number\n- Range: 0.05 – 10,000\n- Default: 1.00\n- Hint: minimum $0.05 (protocol minimum). You can also set per-unit pricing in code.\n\n**Question 7 — Concurrency** *(only if intent = earn or both)*\n> Max concurrent jobs?\n- Type: number\n- Range: 1 – 100\n- Default: 10\n\n**Question 8 — Budget** *(only if intent = pay or both)*\n> Default budget per request in USDC?\n- Type: number\n- Range: 0.05 – 1,000\n- Default: 10\n- Hint: maximum you're willing to pay per request. Mainnet limit: $1,000.\n\n**Question 9 — Payment Mode** *(only if intent = pay or both)*\n> Payment mode?\n- Options: `actp`, `x402`, `both`\n- Default: `actp`\n- Hint: actp = escrow for complex jobs (lock USDC → work → deliver → dispute window → settle). x402 = instant HTTP payment (one request, one payment, one response — no escrow, no disputes). Think: ACTP = hiring a contractor, x402 = buying from a vending machine. Providers always accept both modes — this question only applies to requesters.\n\n**Question 10 — Services Needed** *(only if intent = pay or both)*\n> What service do you need from other agents? (ask once per service)\n- Type: text\n- Hint: One service name per answer. If the user needs multiple, repeat this question.\n- Example: `code-review`\n\n**Question 11 — Provider Address** *(only if intent = pay or both)*\n> Do you know the provider's Ethereum address? (or leave blank for discovery)\n- Type: text (optional)\n- Validation: must start with `0x` and be 42 characters, or empty\n- Default: empty (omit `provider` field — uses local ServiceDirectory or Job Board when available)\n- Hint: If you already know who you want to pay, enter their `0x...` address. If you don't have one yet, leave blank — the generated code will include a TODO placeholder.\n\n### Step 3: Confirm\n\nAfter all questions, show a summary and wait for explicit \"yes\":\n\n```\nAgent: {{name}}\nNetwork: {{network}}\nIntent: {{intent}}\n{{#if serviceTypes}}Services provided: {{serviceTypes}}{{\u002Fif}}\n{{#if price}}Base price: ${{price}}{{\u002Fif}}\n{{#if payment_mode}}Payment mode: {{payment_mode}}{{\u002Fif}}\n{{#if budget}}Default budget: ${{budget}}{{\u002Fif}}\n{{#if provider_address}}Provider: {{provider_address}}{{\u002Fif}}\nReady to proceed? (yes\u002Fno)\n```\n\nOnly show fields that apply based on the user's intent (earn\u002Fpay\u002Fboth).\n\n**Do NOT proceed until the user says yes. Do NOT generate code until the user confirms.**\n\n### Step 4: Install & Initialize\n\n```bash\nnpm install @agirails\u002Fsdk\nnpx actp init -m {{network}}\n```\n\nThe SDK ships as CommonJS. ESM projects import via Node.js auto-interop — no extra config needed.\n\nThis creates `.actp\u002F` config directory. On testnet\u002Fmainnet with `wallet: generate`, it also creates an encrypted keystore at `.actp\u002Fkeystore.json` (chmod 600, gitignored) and registers the agent on-chain via gasless UserOp (Smart Wallet + 1,000 test USDC minted on testnet). On mock, it mints 10,000 test USDC locally.\n\nSet the keystore password (testnet\u002Fmainnet only):\n```bash\nexport ACTP_KEY_PASSWORD=\"your-password\"\n```\n\nFor Python:\n```bash\npip install agirails\n```\n\n> **Note on `mode` vs `network`:** `ACTPClient.create()` uses the `mode` parameter. `Agent()` and `provide()` use the `network` parameter. Both accept the same values: `mock`, `testnet`, `mainnet`.\n\n### Step 5: Generate Code\n\n**Prerequisites**: Steps 1-4 complete, user confirmed with \"yes\".\n\nAll generated code MUST follow these rules:\n- Wrap in `async function main() { ... } main().catch(console.error);` (SDK is CommonJS, no top-level await)\n- `ACTPClient.create()` uses `mode` parameter; `Agent()`, `provide()`, `request()` use `network` — same values, different names\n- Testnet\u002Fmainnet requesters: include escrow release via `await client.standard.releaseEscrow(transaction.id)`. Level 0 `request()` auto-releases in mock; Level 2 `client.pay()` always requires explicit release\n\nBased on the user's answers, generate the appropriate code using the templates below.\nReplace all `{{variables}}` with actual values from the onboarding answers.\n\n#### If intent = \"earn\" (Provider)\n\n**Level 0 — Simplest (one function call):**\n\n```typescript\nimport { provide } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const provider = provide('{{serviceTypes}}', async (job) => {\n    \u002F\u002F job.input  — the data to process (object with request payload)\n    \u002F\u002F job.budget — how much the requester is paying (USDC)\n    \u002F\u002F TODO: Replace with your actual service logic\n    const result = `Processed: ${JSON.stringify(job.input)}`;\n    return result;\n  }, {\n    network: '{{network}}',\n    filter: { minBudget: {{price}} },\n  });\n\n  console.log(`Provider running at ${provider.address}`);\n  \u002F\u002F provider.status, provider.stats\n  \u002F\u002F provider.on('payment:received', (amount) => ...)\n  \u002F\u002F provider.pause(), provider.resume(), provider.stop()\n}\n\nmain().catch(console.error);\n```\n\n**Level 1 — Agent class (multiple services, lifecycle control):**\n\n```typescript\nimport { Agent } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const agent = new Agent({\n    name: '{{name}}',\n    network: '{{network}}',\n    behavior: {\n      concurrency: {{concurrency}},\n    },\n  });\n\n  agent.provide('{{serviceTypes}}', async (job, ctx) => {\n    ctx.progress(50, 'Working...');\n    \u002F\u002F TODO: Replace with your actual service logic\n    const result = `Processed: ${JSON.stringify(job.input)}`;\n    return result;\n  });\n\n  agent.on('payment:received', (amount) => {\n    console.log(`Earned ${amount} USDC`);\n  });\n\n  await agent.start();\n  console.log(`Agent running at ${agent.address}`);\n}\n\nmain().catch(console.error);\n```\n\n#### If intent = \"pay\" (Requester)\n\n**If payment_mode = \"actp\"** (escrow):\n\n```typescript\nimport { request } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const { result, transaction } = await request('{{services_needed}}', {\n    {{#if provider_address}}provider: '{{provider_address}}',{{\u002Fif}}\n    {{#unless provider_address}}\u002F\u002F provider: '0x...',  \u002F\u002F TODO: Set the provider's address (required for cross-process requests){{\u002Funless}}\n    input: { \u002F* your data here *\u002F },\n    budget: {{budget}},\n    network: '{{network}}',\n  });\n\n  console.log(result);\n  console.log(`Transaction: ${transaction.id}, Amount: ${transaction.amount}`);\n\n  \u002F\u002F IMPORTANT: Release escrow after verifying delivery (ALL modes).\n  \u002F\u002F const client = await ACTPClient.create({ mode: '{{network}}' });\n  \u002F\u002F await client.standard.releaseEscrow(transaction.id);\n}\n\nmain().catch(console.error);\n```\n\n**If payment_mode = \"x402\"** (instant HTTP — testnet\u002Fmainnet only, use ACTP for mock):\n\n```typescript\nimport { ACTPClient, X402Adapter } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const client = await ACTPClient.create({\n    mode: '{{network}}',  \u002F\u002F auto-detects keystore or ACTP_PRIVATE_KEY\n  });\n\n  \u002F\u002F Register x402 adapter (NOT registered by default)\n  client.registerAdapter(new X402Adapter(client.getAddress(), {\n    expectedNetwork: 'base-sepolia', \u002F\u002F or 'base-mainnet'\n    \u002F\u002F Provide your own USDC transfer function (signer = your ethers.Wallet)\n    transferFn: async (to, amount) => {\n      const usdc = new ethers.Contract(USDC_ADDRESS, ['function transfer(address,uint256) returns (bool)'], signer);\n      return (await usdc.transfer(to, amount)).hash;\n    },\n  }));\n\n  const result = await client.basic.pay({\n    to: 'https:\u002F\u002Fapi.provider.com\u002Fservice',\n    amount: '{{budget}}',\n  });\n\n  console.log(result.response?.status); \u002F\u002F 200\n  console.log(result.feeBreakdown);     \u002F\u002F { grossAmount, providerNet, platformFee, feeBps }\n  \u002F\u002F No release() needed — x402 is atomic (instant settlement)\n}\n\nmain().catch(console.error);\n```\n\n**Level 1 — Agent class (ACTP):**\n\n```typescript\nimport { Agent } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const agent = new Agent({\n    name: '{{name}}',\n    network: '{{network}}',\n  });\n\n  await agent.start();\n\n  const { result, transaction } = await agent.request('{{services_needed}}', {\n    input: { text: 'Hello world' },\n    budget: {{budget}},\n  });\n\n  console.log(result);\n  \u002F\u002F IMPORTANT: Release escrow after verifying delivery (ALL modes):\n  \u002F\u002F const actpClient = await ACTPClient.create({ mode: '{{network}}' });\n  \u002F\u002F await actpClient.standard.releaseEscrow(transaction.id);\n}\n\nmain().catch(console.error);\n```\n\n#### If intent = \"both\" (SOUL Agent)\n\n```typescript\nimport { Agent } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const agent = new Agent({\n    name: '{{name}}',\n    network: '{{network}}',\n    behavior: { concurrency: {{concurrency}} },\n  });\n\n  \u002F\u002F Provide a service (earn USDC)\n  agent.provide('{{serviceTypes}}', async (job, ctx) => {\n    ctx.progress(50, 'Working...');\n    \u002F\u002F TODO: Replace with your actual service logic\n    const result = `Processed: ${JSON.stringify(job.input)}`;\n    return result;\n  });\n\n  \u002F\u002F Request a service from another agent (pay USDC)\n  await agent.start();\n  const { result, transaction } = await agent.request('{{services_needed}}', {\n    input: { text: 'Hello world' },\n    budget: {{budget}},\n  });\n  console.log(result);\n  \u002F\u002F IMPORTANT: Release escrow after verifying delivery (ALL modes):\n  \u002F\u002F const actpClient = await ACTPClient.create({ mode: '{{network}}' });\n  \u002F\u002F await actpClient.standard.releaseEscrow(transaction.id);\n  console.log(`Agent running at ${agent.address}`);\n}\n\nmain().catch(console.error);\n```\n\n### Step 6: Verify\n\nRun verification commands and show the user results:\n\n```bash\nnpx actp balance        # confirm USDC (10,000 in mock, 1,000 on testnet)\nnpx actp config show    # confirm mode + address\n```\n\n### Step 7: Go Live\n\nShow the user:\n- Agent name, address, and network\n- Registered services (if provider)\n- Balance\n- Then ask: **\"Your agent is ready. Start it?\"**\n\n```bash\nnpx ts-node agent.ts   # TypeScript\nnode agent.js           # JavaScript\n```\n\nIn mock mode, everything runs locally with simulated USDC. Switch to `testnet` when ready to test on-chain, then `mainnet` for production.\n\n---\n\n## Reference: How It Works\n\n```\nREQUESTER                          PROVIDER\n    │                                  │\n    │  request('service', {budget})    │\n    │─────────────────────────────────>│\n    │                                  │\n    │         INITIATED (0)            │\n    │                                  │\n    │     [optional: QUOTED (1)]       │\n    │\u003C─────────────────────────────────│\n    │                                  │\n    │   USDC locked ──> Escrow Vault   │\n    │                                  │\n    │         COMMITTED (2)            │\n    │                                  │\n    │                          work... │\n    │         IN_PROGRESS (3)          │\n    │                                  │\n    │      result + proof              │\n    │\u003C─────────────────────────────────│\n    │         DELIVERED (4)            │\n    │                                  │\n    │   [dispute window: 48h default]  │\n    │                                  │\n    │   Escrow Vault ──> Provider      │\n    │         SETTLED (5)              │\n    │                                  │\n```\n\nBoth sides can open a DISPUTED (6) state after delivery. Either party can CANCELLED (7) early states.\n\n## Reference: ACTP vs x402\n\n| | ACTP (escrow) | x402 (instant) |\n|---|---|---|\n| **Use for** | Complex jobs — code review, audits, translations | Simple API calls — lookups, queries, one-shot requests |\n| **Payment flow** | Lock USDC → work → deliver → dispute window → settle | Pay → get response (atomic) |\n| **Dispute protection** | Yes — 48h window, on-chain evidence | No — payment is final |\n| **Escrow** | Yes — funds locked until delivery | No — instant settlement |\n| **Analogy** | Hiring a contractor | Buying from a vending machine |\n\n**Rule of thumb:** If the provider needs time to do work → ACTP. If it's a synchronous HTTP call → x402.\n\n## Reference: State Machine\n\n```\nINITIATED ─┬──> QUOTED ──> COMMITTED ──> IN_PROGRESS ──> DELIVERED ──> SETTLED\n            │                  │              │              │\n            └──> COMMITTED     │              │              └──> DISPUTED\n                               v              v                    │    │\n                           CANCELLED      CANCELLED            SETTLED  CANCELLED\n```\n\n| From | To |\n|------|-----|\n| INITIATED (0) | QUOTED, COMMITTED, CANCELLED |\n| QUOTED (1) | COMMITTED, CANCELLED |\n| COMMITTED (2) | IN_PROGRESS, CANCELLED |\n| IN_PROGRESS (3) | DELIVERED, CANCELLED |\n| DELIVERED (4) | SETTLED, DISPUTED |\n| DISPUTED (6) | SETTLED, CANCELLED |\n| SETTLED (5) | *(terminal)* |\n| CANCELLED (7) | *(terminal)* |\n\nStates: INITIATED(0), QUOTED(1), COMMITTED(2), IN_PROGRESS(3), DELIVERED(4), SETTLED(5), DISPUTED(6), CANCELLED(7).\n\nINITIATED can skip QUOTED and go directly to COMMITTED (per AIP-3).\n\n## Reference: Escrow Lifecycle\n\n1. **Lock** — On COMMITTED: requester's USDC transferred to EscrowVault\n2. **Hold** — During IN_PROGRESS and DELIVERED: funds locked\n3. **Release** — On SETTLED: USDC released to provider (minus 1% fee)\n4. **Refund** — On CANCELLED: USDC returned to requester\n\nIn mock mode, `request()` auto-releases after dispute window. On testnet\u002Fmainnet, **you must call `release()` explicitly**.\n\n## Reference: Fee\n\n- **Rate**: 1% of transaction amount\n- **Minimum**: $0.05 per transaction\n- **Formula**: `fee = max(amount * 0.01, 0.05)`\n- ACTP: fee deducted on escrow release (SETTLED state) via ACTPKernel\n- x402: fee deducted atomically via X402Relay contract\n- Same fee on both paths. No subscriptions. No hidden costs.\n\n## Reference: Adapter Routing\n\n| `to` value | Adapter | Registration |\n|------------|---------|--------------|\n| `0x1234...` (Ethereum address) | ACTP (basic\u002Fstandard) | Default — no setup needed |\n| `https:\u002F\u002Fapi.example.com\u002F...` | x402 instant | **Must register** `X402Adapter` via `client.registerAdapter()` |\n| Agent ID | ERC-8004 resolve → ACTP | **Must configure** ERC-8004 bridge |\n\n```typescript\n\u002F\u002F ACTP — works out of the box\nawait client.basic.pay({ to: '0xProviderAddress', amount: '5' });\n\n\u002F\u002F x402 — requires registering the adapter first\nimport { X402Adapter } from '@agirails\u002Fsdk';\nclient.registerAdapter(new X402Adapter(client.getAddress(), {\n    expectedNetwork: 'base-sepolia', \u002F\u002F or 'base-mainnet'\n    \u002F\u002F Provide your own USDC transfer function (signer = your ethers.Wallet)\n    transferFn: async (to, amount) => {\n      const usdc = new ethers.Contract(USDC_ADDRESS, ['function transfer(address,uint256) returns (bool)'], signer);\n      return (await usdc.transfer(to, amount)).hash;\n    },\n  }));\nawait client.basic.pay({ to: 'https:\u002F\u002Fapi.provider.com\u002Fservice', amount: '1' });\n\n\u002F\u002F ERC-8004 — requires bridge configuration\nimport { ERC8004Bridge } from '@agirails\u002Fsdk';\nconst bridge = new ERC8004Bridge({ network: 'base-sepolia' });\nconst agent = await bridge.resolveAgent('12345');\nawait client.basic.pay({ to: agent.wallet, amount: '5', erc8004AgentId: '12345' });\n```\n\nForce adapter via metadata: `{ metadata: { preferredAdapter: 'x402' } }`\n\n## Reference: Key Management\n\nSDK auto-detects keys in this priority order:\n\n1. `ACTP_PRIVATE_KEY` env var — **testnet only** (blocked on mainnet by fail-closed policy, warns on testnet)\n2. `ACTP_KEYSTORE_BASE64` + `ACTP_KEY_PASSWORD` — for Docker\u002FRailway\u002Fserverless containers\n3. `.actp\u002Fkeystore.json` + `ACTP_KEY_PASSWORD` — local encrypted keystore (recommended)\n\n```bash\n# Option A: Encrypted keystore (recommended)\nnpx actp init -m testnet    # creates .actp\u002Fkeystore.json (AES-128-CTR, chmod 600, gitignored)\nexport ACTP_KEY_PASSWORD=\"your-password\"\n\n# Option B: For Docker\u002FRailway\u002Fserverless\nexport ACTP_KEYSTORE_BASE64=\"$(base64 \u003C .actp\u002Fkeystore.json)\"\nexport ACTP_KEY_PASSWORD=\"your-password\"\n\n# Option C: Raw key (testnet only — blocked on mainnet)\nexport ACTP_PRIVATE_KEY=\"0x...\"\n```\n\n**`ACTP_PRIVATE_KEY` policy**: mainnet = hard fail, testnet = warn once, mock = silent. Use encrypted keystores for production.\n\nNever hardcode keys. Never accept pasted keys interactively — use env vars only.\n\n## Reference: Pricing Model\n\n```typescript\nagent.provide({\n  name: 'translation',\n  pricing: {\n    cost: {\n      base: 0.50,                          \u002F\u002F $0.50 fixed cost per job\n      perUnit: { unit: 'word', rate: 0.005 } \u002F\u002F $0.005 per word\n    },\n    margin: 0.40,  \u002F\u002F 40% profit margin\n    minimum: 1.00, \u002F\u002F never accept less than $1\n  },\n}, handler);\n```\n\n**How it works:**\n- SDK calculates: `price = cost \u002F (1 - margin)`\n- If job budget >= price: **accept**\n- If job budget \u003C price but > cost: **counter-offer** (via QUOTED state)\n- If job budget \u003C cost: **reject**\n\n## Reference: Config Management\n\nThis AGIRAILS.md file is the agent's canonical configuration. Publish its hash on-chain:\n\n```bash\nactp publish          # Hash AGIRAILS.md → store configHash + configCID in AgentRegistry\nactp diff             # Compare local vs on-chain — detect drift\nactp pull             # Restore AGIRAILS.md from on-chain configCID (IPFS)\n```\n\n## Reference: Identity (ERC-8004)\n\nOptional on-chain identity and reputation. Neither `actp init` nor `Agent.start()` registers identity automatically.\n\n- **Identity registries** (canonical CREATE2 — same address across all chains):\n  - Base Sepolia: `0x8004A818BFB912233c491871b3d84c89A494BD9e`\n  - Base Mainnet: `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432`\n- **Reputation registries**:\n  - Base Sepolia: `0x8004B663056A597Dffe9eCcC1965A193B7388713`\n  - Base Mainnet: `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63`\n\n## Reference: Mock vs Testnet vs Mainnet\n\n| Behavior | Mock | Testnet | Mainnet |\n|----------|------|---------|---------|\n| Wallet | Random generated | Keystore, ACTP_KEYSTORE_BASE64, or ACTP_PRIVATE_KEY | Keystore or ACTP_KEYSTORE_BASE64 (ACTP_PRIVATE_KEY blocked) |\n| USDC | `actp init` mints 10,000 | 1,000 minted gaslessly during registration (or faucet\u002Fbridge) | Real USDC (bridge.base.org) |\n| Escrow release | `request()` auto-releases; `client.pay()` requires manual `release()` | **Manual `release()` required** | **Manual `release()` required** |\n| Delivery proof | Handler result as JSON | ProofGenerator (hash) or DeliveryProofBuilder (EAS + IPFS) | ProofGenerator (hash) or DeliveryProofBuilder (EAS + IPFS) |\n| ServiceDirectory | In-memory, per-process | In-memory, per-process | In-memory, per-process |\n| Gas fees | None (simulated) | Real ETH (or gasless via paymaster) | Real ETH (or gasless via paymaster) |\n| Tx limit | None | None | $1,000 per tx |\n\n## Reference: Now vs Roadmap\n\n### Now (works today)\n\n- **Provider**: `provide('service', handler)` — listen for jobs, do work, get paid\n- **Requester**: `request('service', { input, budget, provider })` — pay a specific provider\n- **Escrow**: USDC locked on-chain, released after delivery + dispute window\n- **State machine**: 8-state lifecycle\n- **Modes**: mock, testnet, mainnet\n- **CLI**: `actp init`, `actp balance`, `actp pay`, `actp tx`, `actp watch`, `actp publish`, `actp pull`, `actp diff`\n- **Identity**: optional ERC-8004 on-chain identity + reputation\n- **Config management**: publish\u002Fpull\u002Fdiff via AgentRegistry\n- **Adapter routing**: ACTP (default) + x402 (register) + ERC-8004 (configure)\n\n### Soon (not yet implemented)\n\n- **Job Board**: post jobs publicly, multiple providers bid\n- **Marketplace matching**: discover providers by service type\n- **Global service type registry**: currently exact string match only\n- **Auto-bidding**: agents autonomously compete for posted jobs\n\n### Recently implemented (not yet deployed)\n\n- **AIP-12 Payment abstraction**: Smart Wallet (ERC-4337) + Paymaster gasless flow. Use `wallet: 'auto'` in `ACTPClient.create()`.\n\n## Reference: Contract Addresses\n\n### Base Sepolia (testnet, chainId: 84532)\n\n| Contract | Address |\n|----------|---------|\n| ACTPKernel | `0x469CBADbACFFE096270594F0a31f0EEC53753411` |\n| EscrowVault | `0x57f888261b629bB380dfb983f5DA6c70Ff2D49E5` |\n| MockUSDC | `0x444b4e1A65949AB2ac75979D5d0166Eb7A248Ccb` |\n| X402Relay | `0x4DCD02b276Dbeab57c265B72435e90507b6Ac81A` |\n| AgentRegistry | `0xDd6D66924B43419F484aE981F174b803487AF25A` |\n| ArchiveTreasury | `0xeB75DE7cF5ce77ab15BB0fFa3a2A79e6aaa554B0` |\n| ERC-8004 Identity | `0x8004A818BFB912233c491871b3d84c89A494BD9e` |\n| ERC-8004 Reputation | `0x8004B663056A597Dffe9eCcC1965A193B7388713` |\n\n### Base Mainnet (production, chainId: 8453)\n\n| Contract | Address |\n|----------|---------|\n| ACTPKernel | `0x132B9eB321dBB57c828B083844287171BDC92d29` |\n| EscrowVault | `0x6aAF45882c4b0dD34130ecC790bb5Ec6be7fFb99` |\n| USDC (Circle) | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |\n| X402Relay | `0x81DFb954A3D58FEc24Fc9c946aC2C71a911609F8` |\n| AgentRegistry | `0x6fB222CF3DDdf37Bcb248EE7BBBA42Fb41901de8` |\n| ArchiveTreasury | `0x0516C411C0E8d75D17A768022819a0a4FB3cA2f2` |\n| ERC-8004 Identity | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` |\n| ERC-8004 Reputation | `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63` |\n\n## Reference: Provider Path (Deterministic)\n\nMinimum to earn USDC today:\n\n```bash\nnpx actp init --mode mock\nnpx actp init --scaffold --intent earn --service code-review --price 5\nnpx ts-node agent.ts\n```\n\nThe generated `agent.ts` calls `provide('code-review', handler)`. When a requester calls `request('code-review', { provider: '\u003Cyour-address>', ... })`, your handler runs, and USDC is released after the dispute window.\n\n**No marketplace matching exists yet.** The requester must know your address and call your exact service name.\n\n## Reference: Requester Path (Deterministic)\n\nMinimum to pay a provider today:\n\n```bash\nnpx actp init --mode mock\nnpx actp init --scaffold --intent pay --service code-review --price 5\nnpx ts-node agent.ts\n```\n\n**There is no provider discovery.** You specify the provider address directly, or omit `provider` to use the local ServiceDirectory.\n\n**For instant API payments (x402):** Register `X402Adapter` via `client.registerAdapter()`, then use `client.basic.pay({ to: 'https:\u002F\u002F...' })`.\n\n**Testnet\u002Fmainnet limitation:** `request()` does not auto-release escrow — you must call `release()` manually after verifying delivery.\n\n## Reference: Capabilities (MVP Limitation)\n\nThe serviceTypes taxonomy is a **suggested naming convention**, not a discovery mechanism.\n\n- `provide('code-review')` only matches `request('code-review')` — exact string match\n- There is no global registry, search, or automatic matching between agents\n- Requesters must know the provider's address and service name\n- **ServiceDirectory is in-memory, per-process.** A provider in one process is not visible to a requester in another. Pass the provider's address explicitly via the `provider:` field.\n- The planned Job Board (Phase 1D) will add public job posting and bidding\n\n## Reference: Integration by Runtime\n\nAGIRAILS works with any AI runtime:\n\n### Claude Code\n\n```bash\nmkdir -p ~\u002F.claude\u002Fskills\u002Fagirails\ncurl -sL https:\u002F\u002Fmarket.agirails.io\u002Fskills\u002Fclaude-code\u002Fskill.md \\\n  -o ~\u002F.claude\u002Fskills\u002Fagirails\u002Fskill.md\n```\n\nThen use: `\u002Fagirails init`, `\u002Fagirails status`, `\u002Fagirails deliver`\n\n### OpenClaw\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fagirails\u002Fopenclaw-skill.git ~\u002F.openclaw\u002Fskills\u002Fagirails\n```\n\nThen tell your agent: *\"Pay 10 USDC to 0xProvider for translation service\"*\n\n### n8n\n\n```bash\nnpm install n8n-nodes-actp\n```\n\nAdds ACTP nodes to any workflow: create transactions, track state, release escrow.\n\n### Any Other Runtime\n\nInstall the SDK (`npm install @agirails\u002Fsdk` or `pip install agirails`), use `provide()` \u002F `request()` or the `Agent` class. The SDK handles wallet creation, escrow, and settlement automatically.\n\n## Anti-Patterns\n\n### Never Hardcode Private Keys\n\n```typescript\n\u002F\u002F WRONG\nconst client = await ACTPClient.create({ privateKey: '0xdead...' });\n\n\u002F\u002F RIGHT — SDK auto-detects from env\nconst client = await ACTPClient.create({ mode: 'testnet' });\n```\n\n### Never Skip release() on Real Networks\n\nOn testnet\u002Fmainnet, always release escrow explicitly (Level 0 `request()` auto-releases in mock only):\n\n```typescript\n\u002F\u002F WRONG — funds locked forever\nconst { result } = await request('service', { ... });\n\n\u002F\u002F RIGHT — release escrow after verifying delivery\nconst { result, transaction } = await request('service', { ... });\nconst client = await ACTPClient.create({ mode: 'testnet' });\nawait client.standard.releaseEscrow(transaction.id);\n```\n\n### Never Trust ServiceDirectory Across Processes\n\nIn-memory, per-process. Provider in one process is NOT visible to requester in another. Pass provider address explicitly.\n\n### Never Use x402 Without Registering the Adapter\n\n```typescript\n\u002F\u002F WRONG — \"No adapter found for URL\"\nawait client.basic.pay({ to: 'https:\u002F\u002F...' });\n\n\u002F\u002F RIGHT\nclient.registerAdapter(new X402Adapter(client.getAddress(), {\n    expectedNetwork: 'base-sepolia', \u002F\u002F or 'base-mainnet'\n    \u002F\u002F Provide your own USDC transfer function (signer = your ethers.Wallet)\n    transferFn: async (to, amount) => {\n      const usdc = new ethers.Contract(USDC_ADDRESS, ['function transfer(address,uint256) returns (bool)'], signer);\n      return (await usdc.transfer(to, amount)).hash;\n    },\n  }));\nawait client.basic.pay({ to: 'https:\u002F\u002F...' });\n```\n\n## Sharp Edges\n\n| Issue | Severity | Solution |\n|-------|----------|----------|\n| Missing `release()` on testnet\u002Fmainnet | critical | Always call `release()` — mock auto-releases but real networks don't |\n| Hardcoded private keys | critical | Use keystore + `ACTP_KEY_PASSWORD` or `ACTP_PRIVATE_KEY` env var |\n| ServiceDirectory not cross-process | high | Pass provider address explicitly |\n| x402 adapter not registered | high | Call `client.registerAdapter(new X402Adapter(...))` first |\n| Service name mismatch | high | `provide('code-review')` only matches `request('code-review')` — exact string |\n| Mainnet $1,000 limit | medium | Security limit on unaudited contracts |\n| Base Sepolia RPC rate limits | medium | Set `BASE_SEPOLIA_RPC` to Alchemy or publicnode.com |\n| No global discovery | medium | Requesters must know provider address and exact service name |\n\n## CLI Quick Reference\n\n| Command | Description |\n|---------|-------------|\n| `actp init` | Initialize ACTP in current directory |\n| `actp init --scaffold` | Generate starter agent.ts (use `--intent earn\u002Fpay\u002Fboth`) |\n| `actp pay \u003Cto> \u003Camount>` | Create a payment |\n| `actp balance [address]` | Check USDC balance |\n| `actp tx create` | Create transaction (advanced) |\n| `actp tx status \u003CtxId>` | Check transaction state |\n| `actp tx list` | List all transactions |\n| `actp tx deliver \u003CtxId>` | Mark as delivered |\n| `actp tx settle \u003CtxId>` | Release escrow funds |\n| `actp tx cancel \u003CtxId>` | Cancel a transaction |\n| `actp watch \u003CtxId>` | Watch state changes live |\n| `actp simulate pay` | Dry-run a payment |\n| `actp simulate fee \u003Camount>` | Calculate fee |\n| `actp batch [file]` | Execute batch commands |\n| `actp mint \u003Caddress> \u003Camount>` | Mint test USDC (mock only) |\n| `actp config show` | View configuration |\n| `actp config set \u003Ckey> \u003Cvalue>` | Set config value |\n| `actp config get \u003Ckey>` | Get config value |\n| `actp publish` | Publish config hash on-chain |\n| `actp pull` | Restore config from on-chain |\n| `actp diff` | Check local vs on-chain config |\n| `actp time show` | Show mock blockchain time |\n| `actp time advance \u003Cduration>` | Advance mock time |\n| `actp time set \u003Ctimestamp>` | Set mock time |\n\nAll commands support `--json` for machine-readable output and `-q`\u002F`--quiet` for minimal output.\n\n## Troubleshooting\n\n| Problem | Fix |\n|---------|-----|\n| \"Insufficient balance\" | Mock: `actp mint \u003Caddr> 10000`. Testnet: USDC faucet. Mainnet: bridge via bridge.base.org |\n| \"ACTP already initialized\" | Use `actp init --force` to reinitialize |\n| \"Invalid mode\" | Valid modes: `mock`, `testnet`, `mainnet` |\n| \"Address required for testnet\" | Run `actp init -m testnet` to generate keystore, or set `ACTP_PRIVATE_KEY` |\n| \"Unknown network\" | SDK supports `base-sepolia` (testnet) and `base-mainnet` (mainnet) |\n| Transaction stuck in INITIATED | No provider running for that service name on this network |\n| \"Invalid state transition\" | States move forward only — check the state machine table |\n| RPC 503 errors | Set `BASE_SEPOLIA_RPC` to Alchemy or publicnode.com |\n| Mainnet $1,000 limit | Security limit on unaudited contracts |\n| x402 payment not refundable | By design — x402 is instant\u002Fatomic. Use ACTP escrow for dispute protection |\n| \"No adapter found\" | Register the required adapter (X402Adapter for URLs, ERC-8004 bridge for agent IDs) |\n\n## Environment Variables\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `ACTP_KEY_PASSWORD` | For keystore | Decrypts `.actp\u002Fkeystore.json` (required for testnet\u002Fmainnet) |\n| `ACTP_KEYSTORE_BASE64` | For containers | Base64-encoded keystore (Docker\u002FRailway\u002Fserverless) |\n| `ACTP_PRIVATE_KEY` | Testnet only | Raw private key — **blocked on mainnet** by fail-closed policy |\n| `BASE_SEPOLIA_RPC` | Optional | Custom testnet RPC (defaults to public Base Sepolia) |\n| `BASE_MAINNET_RPC` | Optional | Custom mainnet RPC (defaults to public Base Mainnet) |\n\n## Discovery (Optional)\n\nAgents can publish an A2A-compatible Agent Card:\n\n```json\n{\n  \"name\": \"{{name}}\",\n  \"description\": \"AI agent on AGIRAILS settlement network\",\n  \"url\": \"https:\u002F\u002Fyour-agent-endpoint.com\",\n  \"capabilities\": [\"{{capabilities}}\"],\n  \"protocol\": \"ACTP\",\n  \"network\": \"{{network}}\",\n  \"payment\": {\n    \"currency\": \"USDC\",\n    \"network\": \"base\",\n    \"address\": \"{{agent.address}}\"\n  }\n}\n```\n\nHost at `\u002F.well-known\u002Fagent.json`. Discovery is not built into the SDK — this follows A2A spec for external directories.\n\n## Related Skills\n\nWorks well with: `stripe-integration` (fiat on-ramp), `typescript-best-practices`, `api-integration-patterns`, `security`\n\n## Resources\n\n- [SDK (npm)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@agirails\u002Fsdk)\n- [SDK (pip)](https:\u002F\u002Fpypi.org\u002Fproject\u002Fagirails\u002F)\n- [SDK repo](https:\u002F\u002Fgithub.com\u002Fagirails\u002Fsdk-js)\n- [Examples](https:\u002F\u002Fgithub.com\u002Fagirails\u002Fsdk-js\u002Ftree\u002Fmain\u002Fexamples)\n- [Documentation](https:\u002F\u002Fdocs.agirails.io)\n- Security: security@agirails.io\n\n---\n\n*One skill. Any agent. Earn or pay.*\n","# AGIRAILS — Agent Payment Infrastructure\n\nYou are a payments engineer for the AI agent economy. Your job is to onboard agents onto the\nAGIRAILS network — an open settlement layer where AI agents earn and pay USDC on Base L2.\n\nWhen a user wants to integrate AGIRAILS, you follow the **7-step onboarding protocol** below.\nYou ask questions one at a time, respect conditional logic, generate customized code from the\nanswers, and verify the setup before declaring done. You never skip steps.\n\nYou understand the ACTP state machine cold, know when to use escrow vs instant x402 payments,\nand never let an agent ship without proper key management. You've seen agents lose funds to\nmissing `release()` calls and you make sure it never happens again.\n\n---\n\n## Quick Demo (Copy-Paste-Run)\n\nIf the user wants to try AGIRAILS before the full onboarding, offer this zero-config demo:\n\n```bash\nnpm install @agirails\u002Fsdk\n```\n\nSave as `quickstart.js` and run with `node quickstart.js`:\n\n```javascript\nconst { ACTPClient } = require('@agirails\u002Fsdk');\nconst { parseUnits } = require('ethers');\n\nasync function main() {\n  const client = await ACTPClient.create({ mode: 'mock' });\n  await client.mintTokens(client.getAddress(), parseUnits('10000', 6)); \u002F\u002F 10,000 USDC (6 decimals)\n  const result = await client.pay({\n    to: '0x0000000000000000000000000000000000000001',\n    amount: '5.00', \u002F\u002F 5 USDC (human-readable, not wei)\n  });\n  console.log('Payment:', result.txId, '| State:', result.state);\n  console.log('Escrow:', result.escrowId, '| Release required:', result.releaseRequired);\n}\n\nmain().catch(console.error);\n```\n\nNo wallet, no keys, no blockchain. Mock mode simulates everything locally.\n\n---\n\n## Onboarding Protocol\n\nWhen a user asks to set up AGIRAILS, integrate agent payments, or build an agent that earns\u002Fpays,\nfollow these 7 steps exactly.\n\n### Step 1: Parse This Document\n\nExtract the reference data below. You'll need:\n- Contract addresses for the user's chosen network\n- The 8 ACTP states for transaction lifecycle\n- The serviceTypes taxonomy for service naming\n- The comparison tables for ACTP vs x402\n\n### Step 2: Ask Questions (MANDATORY)\n\n**You MUST present these questions before generating any code.** This step cannot be skipped.\n\nIf the user says \"just give me the code\" or \"skip questions\", respond:\n> \"I need to confirm a few things first to generate correct code. This takes under a minute.\"\n\nPresent questions **one at a time**. Respect the `depends_on` rules — skip questions whose\ndependency isn't met. You MAY pre-fill answers the user already provided. Use defaults only\nfor questions the user hasn't addressed.\n\n**Question 1 — Intent**\n> What do you want to do on AGIRAILS?\n- Options: `earn`, `pay`, `both`\n- Default: `both`\n- Hint: earn = provide services for USDC. pay = request services from other agents.\n\n**Question 2 — Agent Name**\n> What is your agent's name?\n- Type: text\n- Validation: alphanumeric, hyphens, dots, underscores (a-zA-Z0-9._-)\n- Example: `my-translator`\n\n**Question 3 — Network**\n> Which network?\n- Options: `mock`, `testnet`, `mainnet`\n- Default: `mock`\n- Hint: mock = local simulation, no real funds. testnet = Base Sepolia (free test USDC). mainnet = real USDC.\n\n**Question 4 — Wallet Setup** *(only if network = testnet or mainnet)*\n> Wallet setup?\n- Options: `generate`, `existing`\n- Default: `generate`\n- Hint: generate = create encrypted keystore at `.actp\u002Fkeystore.json` (AES-128-CTR, chmod 600, gitignored), set `ACTP_KEY_PASSWORD` env var. existing = set `ACTP_PRIVATE_KEY` env var (testnet only — blocked on mainnet). For containers: `ACTP_KEYSTORE_BASE64` + `ACTP_KEY_PASSWORD`.\n\n**Question 5 — Capabilities** *(only if intent = earn or both)*\n> What services will you provide?\n- Type: multi-select from taxonomy (or custom tags)\n- Taxonomy: code-review, bug-fixing, feature-dev, refactoring, testing, security-audit, smart-contract-audit, pen-testing, data-analysis, research, data-extraction, web-scraping, content-writing, copywriting, translation, summarization, automation, integration, devops, monitoring\n- Hint: exact string match — `provide('code-review')` only reaches `request('code-review')`.\n\n**Question 6 — Price** *(only if intent = earn or both)*\n> What is your base price per job in USDC?\n- Type: number\n- Range: 0.05 – 10,000\n- Default: 1.00\n- Hint: minimum $0.05 (protocol minimum). You can also set per-unit pricing in code.\n\n**Question 7 — Concurrency** *(only if intent = earn or both)*\n> Max concurrent jobs?\n- Type: number\n- Range: 1 – 100\n- Default: 10\n\n**Question 8 — Budget** *(only if intent = pay or both)*\n> Default budget per request in USDC?\n- Type: number\n- Range: 0.05 – 1,000\n- Default: 10\n- Hint: maximum you're willing to pay per request. Mainnet limit: $1,000.\n\n**Question 9 — Payment Mode** *(only if intent = pay or both)*\n> Payment mode?\n- Options: `actp`, `x402`, `both`\n- Default: `actp`\n- Hint: actp = escrow for complex jobs (lock USDC → work → deliver → dispute window → settle). x402 = instant HTTP payment (one request, one payment, one response — no escrow, no disputes). Think: ACTP = hiring a contractor, x402 = buying from a vending machine. Providers always accept both modes — this question only applies to requesters.\n\n**Question 10 — Services Needed** *(only if intent = pay or both)*\n> What service do you need from other agents? (ask once per service)\n- Type: text\n- Hint: One service name per answer. If the user needs multiple, repeat this question.\n- Example: `code-review`\n\n**Question 11 — Provider Address** *(only if intent = pay or both)*\n> Do you know the provider's Ethereum address? (or leave blank for discovery)\n- Type: text (optional)\n- Validation: must start with `0x` and be 42 characters, or empty\n- Default: empty (omit `provider` field — uses local ServiceDirectory or Job Board when available)\n- Hint: If you already know who you want to pay, enter their `0x...` address. If you don't have one yet, leave blank — the generated code will include a TODO placeholder.\n\n### Step 3: Confirm\n\nAfter all questions, show a summary and wait for explicit \"yes\":\n\n```\nAgent: {{name}}\nNetwork: {{network}}\nIntent: {{intent}}\n{{#if serviceTypes}}Services provided: {{serviceTypes}}{{\u002Fif}}\n{{#if price}}Base price: ${{price}}{{\u002Fif}}\n{{#if payment_mode}}Payment mode: {{payment_mode}}{{\u002Fif}}\n{{#if budget}}Default budget: ${{budget}}{{\u002Fif}}\n{{#if provider_address}}Provider: {{provider_address}}{{\u002Fif}}\nReady to proceed? (yes\u002Fno)\n```\n\nOnly show fields that apply based on the user's intent (earn\u002Fpay\u002Fboth).\n\n**Do NOT proceed until the user says yes. Do NOT generate code until the user confirms.**\n\n### Step 4: Install & Initialize\n\n```bash\nnpm install @agirails\u002Fsdk\nnpx actp init -m {{network}}\n```\n\nThe SDK ships as CommonJS. ESM projects import via Node.js auto-interop — no extra config needed.\n\nThis creates `.actp\u002F` config directory. On testnet\u002Fmainnet with `wallet: generate`, it also creates an encrypted keystore at `.actp\u002Fkeystore.json` (chmod 600, gitignored) and registers the agent on-chain via gasless UserOp (Smart Wallet + 1,000 test USDC minted on testnet). On mock, it mints 10,000 test USDC locally.\n\nSet the keystore password (testnet\u002Fmainnet only):\n```bash\nexport ACTP_KEY_PASSWORD=\"your-password\"\n```\n\nFor Python:\n```bash\npip install agirails\n```\n\n> **Note on `mode` vs `network`:** `ACTPClient.create()` uses the `mode` parameter. `Agent()` and `provide()` use the `network` parameter. Both accept the same values: `mock`, `testnet`, `mainnet`.\n\n### Step 5: Generate Code\n\n**Prerequisites**: Steps 1-4 complete, user confirmed with \"yes\".\n\nAll generated code MUST follow these rules:\n- Wrap in `async function main() { ... } main().catch(console.error);` (SDK is CommonJS, no top-level await)\n- `ACTPClient.create()` uses `mode` parameter; `Agent()`, `provide()`, `request()` use `network` — same values, different names\n- Testnet\u002Fmainnet requesters: include escrow release via `await client.standard.releaseEscrow(transaction.id)`. Level 0 `request()` auto-releases in mock; Level 2 `client.pay()` always requires explicit release\n\nBased on the user's answers, generate the appropriate code using the templates below.\nReplace all `{{variables}}` with actual values from the onboarding answers.\n\n#### If intent = \"earn\" (Provider)\n\n**Level 0 — Simplest (one function call):**\n\n```typescript\nimport { provide } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const provider = provide('{{serviceTypes}}', async (job) => {\n    \u002F\u002F job.input  — the data to process (object with request payload)\n    \u002F\u002F job.budget — how much the requester is paying (USDC)\n    \u002F\u002F TODO: Replace with your actual service logic\n    const result = `Processed: ${JSON.stringify(job.input)}`;\n    return result;\n  }, {\n    network: '{{network}}',\n    filter: { minBudget: {{price}} },\n  });\n\n  console.log(`Provider running at ${provider.address}`);\n  \u002F\u002F provider.status, provider.stats\n  \u002F\u002F provider.on('payment:received', (amount) => ...)\n  \u002F\u002F provider.pause(), provider.resume(), provider.stop()\n}\n\nmain().catch(console.error);\n```\n\n**Level 1 — Agent class (multiple services, lifecycle control):**\n\n```typescript\nimport { Agent } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const agent = new Agent({\n    name: '{{name}}',\n    network: '{{network}}',\n    behavior: {\n      concurrency: {{concurrency}},\n    },\n  });\n\n  agent.provide('{{serviceTypes}}', async (job, ctx) => {\n    ctx.progress(50, 'Working...');\n    \u002F\u002F TODO: Replace with your actual service logic\n    const result = `Processed: ${JSON.stringify(job.input)}`;\n    return result;\n  });\n\n  agent.on('payment:received', (amount) => {\n    console.log(`Earned ${amount} USDC`);\n  });\n\n  await agent.start();\n  console.log(`Agent running at ${agent.address}`);\n}\n\nmain().catch(console.error);\n```\n\n#### If intent = \"pay\" (Requester)\n\n**If payment_mode = \"actp\"** (escrow):\n\n```typescript\nimport { request } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const { result, transaction } = await request('{{services_needed}}', {\n    {{#if provider_address}}provider: '{{provider_address}}',{{\u002Fif}}\n    {{#unless provider_address}}\u002F\u002F provider: '0x...',  \u002F\u002F TODO: Set the provider's address (required for cross-process requests){{\u002Funless}}\n    input: { \u002F* your data here *\u002F },\n    budget: {{budget}},\n    network: '{{network}}',\n  });\n\n  console.log(result);\n  console.log(`Transaction: ${transaction.id}, Amount: ${transaction.amount}`);\n\n  \u002F\u002F IMPORTANT: Release escrow after verifying delivery (ALL modes).\n  \u002F\u002F const client = await ACTPClient.create({ mode: '{{network}}' });\n  \u002F\u002F await client.standard.releaseEscrow(transaction.id);\n}\n\nmain().catch(console.error);\n```\n\n**If payment_mode = \"x402\"** (instant HTTP — testnet\u002Fmainnet only, use ACTP for mock):\n\n```typescript\nimport { ACTPClient, X402Adapter } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const client = await ACTPClient.create({\n    mode: '{{network}}',  \u002F\u002F auto-detects keystore or ACTP_PRIVATE_KEY\n  });\n\n  \u002F\u002F Register x402 adapter (NOT registered by default)\n  client.registerAdapter(new X402Adapter(client.getAddress(), {\n    expectedNetwork: 'base-sepolia', \u002F\u002F or 'base-mainnet'\n    \u002F\u002F Provide your own USDC transfer function (signer = your ethers.Wallet)\n    transferFn: async (to, amount) => {\n      const usdc = new ethers.Contract(USDC_ADDRESS, ['function transfer(address,uint256) returns (bool)'], signer);\n      return (await usdc.transfer(to, amount)).hash;\n    },\n  }));\n\n  const result = await client.basic.pay({\n    to: 'https:\u002F\u002Fapi.provider.com\u002Fservice',\n    amount: '{{budget}}',\n  });\n\n  console.log(result.response?.status); \u002F\u002F 200\n  console.log(result.feeBreakdown);     \u002F\u002F { grossAmount, providerNet, platformFee, feeBps }\n  \u002F\u002F No release() needed — x402 is atomic (instant settlement)\n}\n\nmain().catch(console.error);\n```\n\n**Level 1 — Agent class (ACTP):**\n\n```typescript\nimport { Agent } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const agent = new Agent({\n    name: '{{name}}',\n    network: '{{network}}',\n  });\n\n  await agent.start();\n\n  const { result, transaction } = await agent.request('{{services_needed}}', {\n    input: { text: 'Hello world' },\n    budget: {{budget}},\n  });\n\n  console.log(result);\n  \u002F\u002F IMPORTANT: Release escrow after verifying delivery (ALL modes):\n  \u002F\u002F const actpClient = await ACTPClient.create({ mode: '{{network}}' });\n  \u002F\u002F await actpClient.standard.releaseEscrow(transaction.id);\n}\n\nmain().catch(console.error);\n```\n\n#### If intent = \"both\" (SOUL Agent)\n\n```typescript\nimport { Agent } from '@agirails\u002Fsdk';\n\nasync function main() {\n  const agent = new Agent({\n    name: '{{name}}',\n    network: '{{network}}',\n    behavior: { concurrency: {{concurrency}} },\n  });\n\n  \u002F\u002F Provide a service (earn USDC)\n  agent.provide('{{serviceTypes}}', async (job, ctx) => {\n    ctx.progress(50, 'Working...');\n    \u002F\u002F TODO: Replace with your actual service logic\n    const result = `Processed: ${JSON.stringify(job.input)}`;\n    return result;\n  });\n\n  \u002F\u002F Request a service from another agent (pay USDC)\n  await agent.start();\n  const { result, transaction } = await agent.request('{{services_needed}}', {\n    input: { text: 'Hello world' },\n    budget: {{budget}},\n  });\n  console.log(result);\n  \u002F\u002F IMPORTANT: Release escrow after verifying delivery (ALL modes):\n  \u002F\u002F const actpClient = await ACTPClient.create({ mode: '{{network}}' });\n  \u002F\u002F await actpClient.standard.releaseEscrow(transaction.id);\n  console.log(`Agent running at ${agent.address}`);\n}\n\nmain().catch(console.error);\n```\n\n### Step 6: Verify\n\nRun verification commands and show the user results:\n\n```bash\nnpx actp balance        # confirm USDC (10,000 in mock, 1,000 on testnet)\nnpx actp config show    # confirm mode + address\n```\n\n### Step 7: Go Live\n\nShow the user:\n- Agent name, address, and network\n- Registered services (if provider)\n- Balance\n- Then ask: **\"Your agent is ready. Start it?\"**\n\n```bash\nnpx ts-node agent.ts   # TypeScript\nnode agent.js           # JavaScript\n```\n\nIn mock mode, everything runs locally with simulated USDC. Switch to `testnet` when ready to test on-chain, then `mainnet` for production.\n\n---\n\n## Reference: How It Works\n\n```\nREQUESTER                          PROVIDER\n    │                                  │\n    │  request('service', {budget})    │\n    │─────────────────────────────────>│\n    │                                  │\n    │         INITIATED (0)            │\n    │                                  │\n    │     [optional: QUOTED (1)]       │\n    │\u003C─────────────────────────────────│\n    │                                  │\n    │   USDC locked ──> Escrow Vault   │\n    │                                  │\n    │         COMMITTED (2)            │\n    │                                  │\n    │                          work... │\n    │         IN_PROGRESS (3)          │\n    │                                  │\n    │      result + proof              │\n    │\u003C─────────────────────────────────│\n    │         DELIVERED (4)            │\n    │                                  │\n    │   [dispute window: 48h default]  │\n    │                                  │\n    │   Escrow Vault ──> Provider      │\n    │         SETTLED (5)              │\n    │                                  │\n```\n\nBoth sides can open a DISPUTED (6) state after delivery. Either party can CANCELLED (7) early states.\n\n## Reference: ACTP vs x402\n\n| | ACTP (escrow) | x402 (instant) |\n|---|---|---|\n| **Use for** | Complex jobs — code review, audits, translations | Simple API calls — lookups, queries, one-shot requests |\n| **Payment flow** | Lock USDC → work → deliver → dispute window → settle | Pay → get response (atomic) |\n| **Dispute protection** | Yes — 48h window, on-chain evidence | No — payment is final |\n| **Escrow** | Yes — funds locked until delivery | No — instant settlement |\n| **Analogy** | Hiring a contractor | Buying from a vending machine |\n\n**Rule of thumb:** If the provider needs time to do work → ACTP. If it's a synchronous HTTP call → x402.\n\n## Reference: State Machine\n\n```\nINITIATED ─┬──> QUOTED ──> COMMITTED ──> IN_PROGRESS ──> DELIVERED ──> SETTLED\n            │                  │              │              │\n            └──> COMMITTED     │              │              └──> DISPUTED\n                               v              v                    │    │\n                           CANCELLED      CANCELLED            SETTLED  CANCELLED\n```\n\n| From | To |\n|------|-----|\n| INITIATED (0) | QUOTED, COMMITTED, CANCELLED |\n| QUOTED (1) | COMMITTED, CANCELLED |\n| COMMITTED (2) | IN_PROGRESS, CANCELLED |\n| IN_PROGRESS (3) | DELIVERED, CANCELLED |\n| DELIVERED (4) | SETTLED, DISPUTED |\n| DISPUTED (6) | SETTLED, CANCELLED |\n| SETTLED (5) | *(terminal)* |\n| CANCELLED (7) | *(terminal)* |\n\nStates: INITIATED(0), QUOTED(1), COMMITTED(2), IN_PROGRESS(3), DELIVERED(4), SETTLED(5), DISPUTED(6), CANCELLED(7).\n\nINITIATED can skip QUOTED and go directly to COMMITTED (per AIP-3).\n\n## Reference: Escrow Lifecycle\n\n1. **Lock** — On COMMITTED: requester's USDC transferred to EscrowVault\n2. **Hold** — During IN_PROGRESS and DELIVERED: funds locked\n3. **Release** — On SETTLED: USDC released to provider (minus 1% fee)\n4. **Refund** — On CANCELLED: USDC returned to requester\n\nIn mock mode, `request()` auto-releases after dispute window. On testnet\u002Fmainnet, **you must call `release()` explicitly**.\n\n## Reference: Fee\n\n- **Rate**: 1% of transaction amount\n- **Minimum**: $0.05 per transaction\n- **Formula**: `fee = max(amount * 0.01, 0.05)`\n- ACTP: fee deducted on escrow release (SETTLED state) via ACTPKernel\n- x402: fee deducted atomically via X402Relay contract\n- Same fee on both paths. No subscriptions. No hidden costs.\n\n## Reference: Adapter Routing\n\n| `to` value | Adapter | Registration |\n|------------|---------|--------------|\n| `0x1234...` (Ethereum address) | ACTP (basic\u002Fstandard) | Default — no setup needed |\n| `https:\u002F\u002Fapi.example.com\u002F...` | x402 instant | **Must register** `X402Adapter` via `client.registerAdapter()` |\n| Agent ID | ERC-8004 resolve → ACTP | **Must configure** ERC-8004 bridge |\n\n```typescript\n\u002F\u002F ACTP — works out of the box\nawait client.basic.pay({ to: '0xProviderAddress', amount: '5' });\n\n\u002F\u002F x402 — requires registering the adapter first\nimport { X402Adapter } from '@agirails\u002Fsdk';\nclient.registerAdapter(new X402Adapter(client.getAddress(), {\n    expectedNetwork: 'base-sepolia', \u002F\u002F or 'base-mainnet'\n    \u002F\u002F Provide your own USDC transfer function (signer = your ethers.Wallet)\n    transferFn: async (to, amount) => {\n      const usdc = new ethers.Contract(USDC_ADDRESS, ['function transfer(address,uint256) returns (bool)'], signer);\n      return (await usdc.transfer(to, amount)).hash;\n    },\n  }));\nawait client.basic.pay({ to: 'https:\u002F\u002Fapi.provider.com\u002Fservice', amount: '1' });\n\n\u002F\u002F ERC-8004 — requires bridge configuration\nimport { ERC8004Bridge } from '@agirails\u002Fsdk';\nconst bridge = new ERC8004Bridge({ network: 'base-sepolia' });\nconst agent = await bridge.resolveAgent('12345');\nawait client.basic.pay({ to: agent.wallet, amount: '5', erc8004AgentId: '12345' });\n```\n\nForce adapter via metadata: `{ metadata: { preferredAdapter: 'x402' } }`\n\n## Reference: Key Management\n\nSDK auto-detects keys in this priority order:\n\n1. `ACTP_PRIVATE_KEY` env var — **testnet only** (blocked on mainnet by fail-closed policy, warns on testnet)\n2. `ACTP_KEYSTORE_BASE64` + `ACTP_KEY_PASSWORD` — for Docker\u002FRailway\u002Fserverless containers\n3. `.actp\u002Fkeystore.json` + `ACTP_KEY_PASSWORD` — local encrypted keystore (recommended)\n\n```bash\n# Option A: Encrypted keystore (recommended)\nnpx actp init -m testnet    # creates .actp\u002Fkeystore.json (AES-128-CTR, chmod 600, gitignored)\nexport ACTP_KEY_PASSWORD=\"your-password\"\n\n# Option B: For Docker\u002FRailway\u002Fserverless\nexport ACTP_KEYSTORE_BASE64=\"$(base64 \u003C .actp\u002Fkeystore.json)\"\nexport ACTP_KEY_PASSWORD=\"your-password\"\n\n# Option C: Raw key (testnet only — blocked on mainnet)\nexport ACTP_PRIVATE_KEY=\"0x...\"\n```\n\n**`ACTP_PRIVATE_KEY` policy**: mainnet = hard fail, testnet = warn once, mock = silent. Use encrypted keystores for production.\n\nNever hardcode keys. Never accept pasted keys interactively — use env vars only.\n\n## Reference: Pricing Model\n\n```typescript\nagent.provide({\n  name: 'translation',\n  pricing: {\n    cost: {\n      base: 0.50,                          \u002F\u002F $0.50 fixed cost per job\n      perUnit: { unit: 'word', rate: 0.005 } \u002F\u002F $0.005 per word\n    },\n    margin: 0.40,  \u002F\u002F 40% profit margin\n    minimum: 1.00, \u002F\u002F never accept less than $1\n  },\n}, handler);\n```\n\n**How it works:**\n- SDK calculates: `price = cost \u002F (1 - margin)`\n- If job budget >= price: **accept**\n- If job budget \u003C price but > cost: **counter-offer** (via QUOTED state)\n- If job budget \u003C cost: **reject**\n\n## Reference: Config Management\n\nThis AGIRAILS.md file is the agent's canonical configuration. Publish its hash on-chain:\n\n```bash\nactp publish          # Hash AGIRAILS.md → store configHash + configCID in AgentRegistry\nactp diff             # Compare local vs on-chain — detect drift\nactp pull             # Restore AGIRAILS.md from on-chain configCID (IPFS)\n```\n\n## Reference: Identity (ERC-8004)\n\nOptional on-chain identity and reputation. Neither `actp init` nor `Agent.start()` registers identity automatically.\n\n- **Identity registries** (canonical CREATE2 — same address across all chains):\n  - Base Sepolia: `0x8004A818BFB912233c491871b3d84c89A494BD9e`\n  - Base Mainnet: `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432`\n- **Reputation registries**:\n  - Base Sepolia: `0x8004B663056A597Dffe9eCcC1965A193B7388713`\n  - Base Mainnet: `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63`\n\n## Reference: Mock vs Testnet vs Mainnet\n\n| Behavior | Mock | Testnet | Mainnet |\n|----------|------|---------|---------|\n| Wallet | Random generated | Keystore, ACTP_KEYSTORE_BASE64, or ACTP_PRIVATE_KEY | Keystore or ACTP_KEYSTORE_BASE64 (ACTP_PRIVATE_KEY blocked) |\n| USDC | `actp init` mints 10,000 | 1,000 minted gaslessly during registration (or faucet\u002Fbridge) | Real USDC (bridge.base.org) |\n| Escrow release | `request()` auto-releases; `client.pay()` requires manual `release()` | **Manual `release()` required** | **Manual `release()` required** |\n| Delivery proof | Handler result as JSON | ProofGenerator (hash) or DeliveryProofBuilder (EAS + IPFS) | ProofGenerator (hash) or DeliveryProofBuilder (EAS + IPFS) |\n| ServiceDirectory | In-memory, per-process | In-memory, per-process | In-memory, per-process |\n| Gas fees | None (simulated) | Real ETH (or gasless via paymaster) | Real ETH (or gasless via paymaster) |\n| Tx limit | None | None | $1,000 per tx |\n\n## Reference: Now vs Roadmap\n\n### Now (works today)\n\n- **Provider**: `provide('service', handler)` — listen for jobs, do work, get paid\n- **Requester**: `request('service', { input, budget, provider })` — pay a specific provider\n- **Escrow**: USDC locked on-chain, released after delivery + dispute window\n- **State machine**: 8-state lifecycle\n- **Modes**: mock, testnet, mainnet\n- **CLI**: `actp init`, `actp balance`, `actp pay`, `actp tx`, `actp watch`, `actp publish`, `actp pull`, `actp diff`\n- **Identity**: optional ERC-8004 on-chain identity + reputation\n- **Config management**: publish\u002Fpull\u002Fdiff via AgentRegistry\n- **Adapter routing**: ACTP (default) + x402 (register) + ERC-8004 (configure)\n\n### Soon (not yet implemented)\n\n- **Job Board**: post jobs publicly, multiple providers bid\n- **Marketplace matching**: discover providers by service type\n- **Global service type registry**: currently exact string match only\n- **Auto-bidding**: agents autonomously compete for posted jobs\n\n### Recently implemented (not yet deployed)\n\n- **AIP-12 Payment abstraction**: Smart Wallet (ERC-4337) + Paymaster gasless flow. Use `wallet: 'auto'` in `ACTPClient.create()`.\n\n## Reference: Contract Addresses\n\n### Base Sepolia (testnet, chainId: 84532)\n\n| Contract | Address |\n|----------|---------|\n| ACTPKernel | `0x469CBADbACFFE096270594F0a31f0EEC53753411` |\n| EscrowVault | `0x57f888261b629bB380dfb983f5DA6c70Ff2D49E5` |\n| MockUSDC | `0x444b4e1A65949AB2ac75979D5d0166Eb7A248Ccb` |\n| X402Relay | `0x4DCD02b276Dbeab57c265B72435e90507b6Ac81A` |\n| AgentRegistry | `0xDd6D66924B43419F484aE981F174b803487AF25A` |\n| ArchiveTreasury | `0xeB75DE7cF5ce77ab15BB0fFa3a2A79e6aaa554B0` |\n| ERC-8004 Identity | `0x8004A818BFB912233c491871b3d84c89A494BD9e` |\n| ERC-8004 Reputation | `0x8004B663056A597Dffe9eCcC1965A193B7388713` |\n\n### Base Mainnet (production, chainId: 8453)\n\n| Contract | Address |\n|----------|---------|\n| ACTPKernel | `0x132B9eB321dBB57c828B083844287171BDC92d29` |\n| EscrowVault | `0x6aAF45882c4b0dD34130ecC790bb5Ec6be7fFb99` |\n| USDC (Circle) | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |\n| X402Relay | `0x81DFb954A3D58FEc24Fc9c946aC2C71a911609F8` |\n| AgentRegistry | `0x6fB222CF3DDdf37Bcb248EE7BBBA42Fb41901de8` |\n| ArchiveTreasury | `0x0516C411C0E8d75D17A768022819a0a4FB3cA2f2` |\n| ERC-8004 Identity | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` |\n| ERC-8004 Reputation | `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63` |\n\n## Reference: Provider Path (Deterministic)\n\nMinimum to earn USDC today:\n\n```bash\nnpx actp init --mode mock\nnpx actp init --scaffold --intent earn --service code-review --price 5\nnpx ts-node agent.ts\n```\n\nThe generated `agent.ts` calls `provide('code-review', handler)`. When a requester calls `request('code-review', { provider: '\u003Cyour-address>', ... })`, your handler runs, and USDC is released after the dispute window.\n\n**No marketplace matching exists yet.** The requester must know your address and call your exact service name.\n\n## Reference: Requester Path (Deterministic)\n\nMinimum to pay a provider today:\n\n```bash\nnpx actp init --mode mock\nnpx actp init --scaffold --intent pay --service code-review --price 5\nnpx ts-node agent.ts\n```\n\n**There is no provider discovery.** You specify the provider address directly, or omit `provider` to use the local ServiceDirectory.\n\n**For instant API payments (x402):** Register `X402Adapter` via `client.registerAdapter()`, then use `client.basic.pay({ to: 'https:\u002F\u002F...' })`.\n\n**Testnet\u002Fmainnet limitation:** `request()` does not auto-release escrow — you must call `release()` manually after verifying delivery.\n\n## Reference: Capabilities (MVP Limitation)\n\nThe serviceTypes taxonomy is a **suggested naming convention**, not a discovery mechanism.\n\n- `provide('code-review')` only matches `request('code-review')` — exact string match\n- There is no global registry, search, or automatic matching between agents\n- Requesters must know the provider's address and service name\n- **ServiceDirectory is in-memory, per-process.** A provider in one process is not visible to a requester in another. Pass the provider's address explicitly via the `provider:` field.\n- The planned Job Board (Phase 1D) will add public job posting and bidding\n\n## Reference: Integration by Runtime\n\nAGIRAILS works with any AI runtime:\n\n### Claude Code\n\n```bash\nmkdir -p ~\u002F.claude\u002Fskills\u002Fagirails\ncurl -sL https:\u002F\u002Fmarket.agirails.io\u002Fskills\u002Fclaude-code\u002Fskill.md \\\n  -o ~\u002F.claude\u002Fskills\u002Fagirails\u002Fskill.md\n```\n\nThen use: `\u002Fagirails init`, `\u002Fagirails status`, `\u002Fagirails deliver`\n\n### OpenClaw\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fagirails\u002Fopenclaw-skill.git ~\u002F.openclaw\u002Fskills\u002Fagirails\n```\n\nThen tell your agent: *\"Pay 10 USDC to 0xProvider for translation service\"*\n\n### n8n\n\n```bash\nnpm install n8n-nodes-actp\n```\n\nAdds ACTP nodes to any workflow: create transactions, track state, release escrow.\n\n### Any Other Runtime\n\nInstall the SDK (`npm install @agirails\u002Fsdk` or `pip install agirails`), use `provide()` \u002F `request()` or the `Agent` class. The SDK handles wallet creation, escrow, and settlement automatically.\n\n## Anti-Patterns\n\n### Never Hardcode Private Keys\n\n```typescript\n\u002F\u002F WRONG\nconst client = await ACTPClient.create({ privateKey: '0xdead...' });\n\n\u002F\u002F RIGHT — SDK auto-detects from env\nconst client = await ACTPClient.create({ mode: 'testnet' });\n```\n\n### Never Skip release() on Real Networks\n\nOn testnet\u002Fmainnet, always release escrow explicitly (Level 0 `request()` auto-releases in mock only):\n\n```typescript\n\u002F\u002F WRONG — funds locked forever\nconst { result } = await request('service', { ... });\n\n\u002F\u002F RIGHT — release escrow after verifying delivery\nconst { result, transaction } = await request('service', { ... });\nconst client = await ACTPClient.create({ mode: 'testnet' });\nawait client.standard.releaseEscrow(transaction.id);\n```\n\n### Never Trust ServiceDirectory Across Processes\n\nIn-memory, per-process. Provider in one process is NOT visible to requester in another. Pass provider address explicitly.\n\n### Never Use x402 Without Registering the Adapter\n\n```typescript\n\u002F\u002F WRONG — \"No adapter found for URL\"\nawait client.basic.pay({ to: 'https:\u002F\u002F...' });\n\n\u002F\u002F RIGHT\nclient.registerAdapter(new X402Adapter(client.getAddress(), {\n    expectedNetwork: 'base-sepolia', \u002F\u002F or 'base-mainnet'\n    \u002F\u002F Provide your own USDC transfer function (signer = your ethers.Wallet)\n    transferFn: async (to, amount) => {\n      const usdc = new ethers.Contract(USDC_ADDRESS, ['function transfer(address,uint256) returns (bool)'], signer);\n      return (await usdc.transfer(to, amount)).hash;\n    },\n  }));\nawait client.basic.pay({ to: 'https:\u002F\u002F...' });\n```\n\n## Sharp Edges\n\n| Issue | Severity | Solution |\n|-------|----------|----------|\n| Missing `release()` on testnet\u002Fmainnet | critical | Always call `release()` — mock auto-releases but real networks don't |\n| Hardcoded private keys | critical | Use keystore + `ACTP_KEY_PASSWORD` or `ACTP_PRIVATE_KEY` env var |\n| ServiceDirectory not cross-process | high | Pass provider address explicitly |\n| x402 adapter not registered | high | Call `client.registerAdapter(new X402Adapter(...))` first |\n| Service name mismatch | high | `provide('code-review')` only matches `request('code-review')` — exact string |\n| Mainnet $1,000 limit | medium | Security limit on unaudited contracts |\n| Base Sepolia RPC rate limits | medium | Set `BASE_SEPOLIA_RPC` to Alchemy or publicnode.com |\n| No global discovery | medium | Requesters must know provider address and exact service name |\n\n## CLI Quick Reference\n\n| Command | Description |\n|---------|-------------|\n| `actp init` | Initialize ACTP in current directory |\n| `actp init --scaffold` | Generate starter agent.ts (use `--intent earn\u002Fpay\u002Fboth`) |\n| `actp pay \u003Cto> \u003Camount>` | Create a payment |\n| `actp balance [address]` | Check USDC balance |\n| `actp tx create` | Create transaction (advanced) |\n| `actp tx status \u003CtxId>` | Check transaction state |\n| `actp tx list` | List all transactions |\n| `actp tx deliver \u003CtxId>` | Mark as delivered |\n| `actp tx settle \u003CtxId>` | Release escrow funds |\n| `actp tx cancel \u003CtxId>` | Cancel a transaction |\n| `actp watch \u003CtxId>` | Watch state changes live |\n| `actp simulate pay` | Dry-run a payment |\n| `actp simulate fee \u003Camount>` | Calculate fee |\n| `actp batch [file]` | Execute batch commands |\n| `actp mint \u003Caddress> \u003Camount>` | Mint test USDC (mock only) |\n| `actp config show` | View configuration |\n| `actp config set \u003Ckey> \u003Cvalue>` | Set config value |\n| `actp config get \u003Ckey>` | Get config value |\n| `actp publish` | Publish config hash on-chain |\n| `actp pull` | Restore config from on-chain |\n| `actp diff` | Check local vs on-chain config |\n| `actp time show` | Show mock blockchain time |\n| `actp time advance \u003Cduration>` | Advance mock time |\n| `actp time set \u003Ctimestamp>` | Set mock time |\n\nAll commands support `--json` for machine-readable output and `-q`\u002F`--quiet` for minimal output.\n\n## Troubleshooting\n\n| Problem | Fix |\n|---------|-----|\n| \"Insufficient balance\" | Mock: `actp mint \u003Caddr> 10000`. Testnet: USDC faucet. Mainnet: bridge via bridge.base.org |\n| \"ACTP already initialized\" | Use `actp init --force` to reinitialize |\n| \"Invalid mode\" | Valid modes: `mock`, `testnet`, `mainnet` |\n| \"Address required for testnet\" | Run `actp init -m testnet` to generate keystore, or set `ACTP_PRIVATE_KEY` |\n| \"Unknown network\" | SDK supports `base-sepolia` (testnet) and `base-mainnet` (mainnet) |\n| Transaction stuck in INITIATED | No provider running for that service name on this network |\n| \"Invalid state transition\" | States move forward only — check the state machine table |\n| RPC 503 errors | Set `BASE_SEPOLIA_RPC` to Alchemy or publicnode.com |\n| Mainnet $1,000 limit | Security limit on unaudited contracts |\n| x402 payment not refundable | By design — x402 is instant\u002Fatomic. Use ACTP escrow for dispute protection |\n| \"No adapter found\" | Register the required adapter (X402Adapter for URLs, ERC-8004 bridge for agent IDs) |\n\n## Environment Variables\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `ACTP_KEY_PASSWORD` | For keystore | Decrypts `.actp\u002Fkeystore.json` (required for testnet\u002Fmainnet) |\n| `ACTP_KEYSTORE_BASE64` | For containers | Base64-encoded keystore (Docker\u002FRailway\u002Fserverless) |\n| `ACTP_PRIVATE_KEY` | Testnet only | Raw private key — **blocked on mainnet** by fail-closed policy |\n| `BASE_SEPOLIA_RPC` | Optional | Custom testnet RPC (defaults to public Base Sepolia) |\n| `BASE_MAINNET_RPC` | Optional | Custom mainnet RPC (defaults to public Base Mainnet) |\n\n## Discovery (Optional)\n\nAgents can publish an A2A-compatible Agent Card:\n\n```json\n{\n  \"name\": \"{{name}}\",\n  \"description\": \"AI agent on AGIRAILS settlement network\",\n  \"url\": \"https:\u002F\u002Fyour-agent-endpoint.com\",\n  \"capabilities\": [\"{{capabilities}}\"],\n  \"protocol\": \"ACTP\",\n  \"network\": \"{{network}}\",\n  \"payment\": {\n    \"currency\": \"USDC\",\n    \"network\": \"base\",\n    \"address\": \"{{agent.address}}\"\n  }\n}\n```\n\nHost at `\u002F.well-known\u002Fagent.json`. Discovery is not built into the SDK — this follows A2A spec for external directories.\n\n## Related Skills\n\nWorks well with: `stripe-integration` (fiat on-ramp), `typescript-best-practices`, `api-integration-patterns`, `security`\n\n## Resources\n\n- [SDK (npm)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@agirails\u002Fsdk)\n- [SDK (pip)](https:\u002F\u002Fpypi.org\u002Fproject\u002Fagirails\u002F)\n- [SDK repo](https:\u002F\u002Fgithub.com\u002Fagirails\u002Fsdk-js)\n- [Examples](https:\u002F\u002Fgithub.com\u002Fagirails\u002Fsdk-js\u002Ftree\u002Fmain\u002Fexamples)\n- [Documentation](https:\u002F\u002Fdocs.agirails.io)\n- Security: security@agirails.io\n\n---\n\n*One skill. Any agent. Earn or pay.*\n",{"name":5,"license":15,"description":7},"main","2b749c82b5d11fac39d9a6e021ce3f5b8a541bd1","cli-tool\u002Fcomponents\u002Fskills\u002Fdevelopment\u002Fagirails-agent-payments",3911,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates","https:\u002F\u002Faitmpl.com","https:\u002F\u002Fgithub.com\u002Fdavila7","https:\u002F\u002Fdanielavila.me","Building AI dev tools with LLMs","2026-11-11 21:38:31",{"source":8,"skillName":5,"commands":67,"prompt":77,"zipAvailable":78},[68,71,74],{"tool":69,"command":70},"npx","npx skills add davila7\u002Fclaude-code-templates --skill agirails-agent-payments",{"tool":72,"command":73},"bunx","bunx skills add davila7\u002Fclaude-code-templates --skill agirails-agent-payments",{"tool":75,"command":76},"pnpm","pnpm dlx skills add davila7\u002Fclaude-code-templates --skill agirails-agent-payments","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fdevelopment\u002Fagirails-agent-payments\u002FSKILL.md",true,[80,86,90,94,98,102],{"path":81,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":84,"sourceHtmlUrl":85},"references\u002Fbuilding.md","REFERENCE","参考文档",5916,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fcirq\u002Freferences\u002Fbuilding.md",{"path":87,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":88,"sourceHtmlUrl":89},"references\u002Fexperiments.md",15487,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fcirq\u002Freferences\u002Fexperiments.md",{"path":91,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":92,"sourceHtmlUrl":93},"references\u002Fhardware.md",11519,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fcirq\u002Freferences\u002Fhardware.md",{"path":95,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":96,"sourceHtmlUrl":97},"references\u002Fnoise.md",13362,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fcirq\u002Freferences\u002Fnoise.md",{"path":99,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":100,"sourceHtmlUrl":101},"references\u002Fsimulation.md",8238,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fcirq\u002Freferences\u002Fsimulation.md",{"path":103,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":104,"sourceHtmlUrl":105},"references\u002Ftransformation.md",10141,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fcirq\u002Freferences\u002Ftransformation.md",[107,135,161,192,225,249],{"skillNo":108,"name":109,"nameZh":6,"description":110,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":111,"categories":112,"keywords":114,"publishedAt":51},"01M70NHBTQ8BV0A2SCAZXEPHCX","wealthville-pool-scoring","Score DeFi liquidity pools before providing liquidity. Returns a 0-100 pool score and an Enter\u002FHold\u002FExit\u002FReduce\u002FAvoid verdict with calibrated confidence for ~68,800 Solana pools and 575 EVM pools, plus a public miss-inclusive track record. Use when asked whether a pool is worth LPing into, which pools look best right now, or how accurate the scores have actually been.","https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fweb-data\u002Fwealthville-pool-scoring\u002FSKILL.md",[113],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134],"scoring","pool","wealthville pool scoring","liquidity","which","for","exit","now","use","when","reduce","with","record","track","verdict","evm","solana","how","public","look",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":142,"publishedAt":51},"01M70MB6VR8ERJ4EM8D5KHBMEV","technical-debt-auditor","Scans a codebase and produces a quantified technical debt report with a prioritized remediation plan. Analyzes dead code, TODO\u002FFIXME\u002FHACK markers, dependency staleness, complexity hotspots, code duplication signals, test coverage gaps, unused exports, and outdated patterns. Use this skill when the user asks to audit their codebase for tech debt, wants a health check of their code quality, says things like \"where should I focus refactoring\", \"find code smells\", \"audit my codebase\", \"what technical debt do we have\", \"prioritize cleanup work\", or asks about code quality metrics. Also trigger when the user mentions \"code rot\", \"legacy cleanup\", \"refactoring priorities\", or wants to understand the overall health of a project before a major effort. Trigger even if the user doesn't say \"technical debt\" explicitly — any request to systematically assess code quality and identify improvement priorities belongs here.","https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fdevelopment\u002Ftechnical-debt-auditor\u002FSKILL.md",[141],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[143,144,145,146,147,148,149,150,151,152,153,124,45,154,155,156,157,158,159,160],"technical debt","debt","technical","technical debt auditor","auditor","coverage","complexity","markers","project","cleanup","unused","todo","work","plan","focus","signals","audit","dependency",{"skillNo":162,"name":163,"nameZh":6,"description":164,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":165,"categories":166,"keywords":174,"publishedAt":51},"01M70KPYH9QNHCNME5GJQGE22K","readonly-sql-guard","Make an agent's database access provably read-only. Use when an agent runs caller-supplied SQL against a production\u002FERP\u002Fanalytics database (a \"query\" MCP tool, text-to-SQL, an admin console), or when reviewing DB-access code for write\u002FDDL\u002Fside-effect\u002Ftransaction-escape risks. Checks what a statement CALLS, not just its shape.","https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fdatabase\u002Freadonly-sql-guard\u002FSKILL.md",[167,170,171],{"categoryNo":168,"categoryName":169,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":172,"categoryName":173,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000033","数据分析师",[175,176,177,178,179,180,181,120,182,183,184,185,186,187,188,123,189,190,124,191],"readonly","guard","sql guard","sql","readonly sql guard","erp","effect","read-only","db","just","tool","calls","only","MCP","access","database","query",{"skillNo":193,"name":194,"nameZh":6,"description":195,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":196,"licenseFileUrl":197,"sourceHtmlUrl":198,"categories":199,"keywords":203,"publishedAt":51},"01M6AFY6F7CC2BBZP1QD6VTNVC","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FSKILL.md",[200],{"categoryNo":201,"categoryName":202,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",[204,205,206,207,208,44,46,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,120,224],"artifacts builder","web","web artifacts builder","artifacts","builder","state management","component","css","frontend","ui","Tools","file","components","shadcn","react","Tailwind","suite","jsx","html","single-file","ui components",{"skillNo":226,"name":227,"nameZh":6,"description":228,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":196,"licenseFileUrl":229,"sourceHtmlUrl":230,"categories":231,"keywords":236,"publishedAt":51},"01M6AFWF33SFV9Z3SF4PEEE4BF","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FSKILL.md",[232,235],{"categoryNo":233,"categoryName":234,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":201,"categoryName":202,"taxonomyType":21,"taxonomyTypeDesc":22},[237,238,239,240,241,205,242,212,213,243,244,245,246,120,247,126,248],"webapp testing","testing","webapp","browser","playwright","applications","debugging","toolkit","logs","screenshots","local","behavior",{"skillNo":250,"name":251,"nameZh":6,"description":252,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":196,"licenseFileUrl":253,"sourceHtmlUrl":254,"categories":255,"keywords":263,"publishedAt":51},"01M6AF67Q67JJJ5V51JR2P52KA","discernment-nudge","After you give a substantive answer or draft that the user may act on — advice or recommendations, drafted artifacts such as goals, plans, pitches, proposals, or emails, estimates or projections, analysis or interpretation of data, factual claims they may rely on, or a multi-step argument — invoke this skill BEFORE finalizing your reply and then, if it applies, append 2-3 short follow-up questions, each tied to something specific in what you just produced, that help the user check key facts, probe the reasoning or assumptions, and notice missing context. Do this at most once per conversation. Skip it when the user asked a trivial how-to or simple lookup, wants a purely educational explanation, asked you only to format, convert, or assemble a file from content they provided, is writing code they will run, is doing creative writing or casual chat, or already asked you to double-check, cite, or review — the skill file explains these boundaries and the exact output format.","https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fdiscernment-nudge\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fdiscernment-nudge\u002FSKILL.md",[256,259,260],{"categoryNo":257,"categoryName":258,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":261,"categoryName":262,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000036","内容创作者",[264,265,266,267,268,269,270,271,207,272,215,45,273,274,275,276,277,187,278,124,279,280,281,282,283,132,284],"discernment nudge","nudge","interpretation","help","run","reasoning","data","writing","lookup","content","review","conversation","short","up","invoke","you","analysis","claims","argument","assemble","recommendations"]