diff --git a/agents/agent-kit/ecosystem.mdx b/agents/agent-kit/ecosystem.mdx index 3cec9ad..d240983 100644 --- a/agents/agent-kit/ecosystem.mdx +++ b/agents/agent-kit/ecosystem.mdx @@ -8,7 +8,7 @@ description: "Projects and services that integrate AgentKit." Find places to use AgentKit at [agentbook.world](https://agentbook.world/). To add your project, open a PR to the [AgentBook registry](https://github.com/andy-t-wang/agentbook). -Teach your agent to use its AgentKit registration when accessing x402 endpoints by adding the `agentkit-x402` skill: +If you build an agent that calls x402 APIs, use [`createAgentkitClient`](/agents/agent-kit/sdk-reference#createagentkitclientoptions) and call `agentkit.fetch` so the agent tries AgentKit verification before paying. If you cannot change the agent's HTTP client, add the `agentkit-x402` skill: ```bash npx skills add worldcoin/agentkit agentkit-x402 @@ -22,4 +22,11 @@ npx skills add worldcoin/agentkit agentkit-x402 > Register your agent with World ID to enable human-backed agent benefits. + + Use `agentkit.fetch` before payment fallback. + diff --git a/agents/agent-kit/integrate.mdx b/agents/agent-kit/integrate.mdx index 7fda887..eaa4dc3 100644 --- a/agents/agent-kit/integrate.mdx +++ b/agents/agent-kit/integrate.mdx @@ -11,6 +11,7 @@ Enable agentic traffic to access api endpoints while blocking malicious actors, This quickstart follows a default implementation path: +- Agent-side x402 calls use `agentkit.fetch` from `createAgentkitClient` - Accepts payments on both World Chain and Base - Agent registration on World Chain - AgentBook lookup always resolves on World Chain (caller side is chain-agnostic) @@ -32,7 +33,13 @@ Register the wallet address your agent will sign with: npx @worldcoin/agentkit-cli register ``` -By default, the CLI registers on World Chain and submits through the hosted relay. AgentBook lookup always resolves against the canonical World Chain deployment regardless of which chain your paid route runs on, so there is no chain wiring to do on the lookup side. +Check whether a wallet is already registered: + +```bash +npx @worldcoin/agentkit-cli status +``` + +By default, the CLI registers on World Chain and submits through the hosted relay. AgentBook lookup always resolves against the canonical World Chain deployment. During registration, the CLI: @@ -48,12 +55,34 @@ Once the wallet is registered, AgentKit can resolve it to an anonymous human ide

*Example of the registration flow*

-Add this skill so your agent knows to use it's AgentKit registration when accessing x402 endpoints: +# Step 3: Wrap x402 calls in the agent + +Use this in agents that call paid x402 APIs. Without this client, agents may go straight to payment instead of using their AgentKit registration. + +```typescript +import { createAgentkitClient } from '@worldcoin/agentkit' + +const agentkit = createAgentkitClient({ + signer: { + address: agentWallet.address, + chainId: 'eip155:8453', + type: 'eip191', + signMessage: message => agentWallet.signMessage(message), + }, +}) + +const response = await agentkit.fetch('https://api.example.com/data') +``` + +Use `agentkit.fetch` anywhere the agent would otherwise call `fetch` for x402-protected APIs. It tries AgentKit first, then leaves the normal x402 payment fallback in place. + +If you cannot change the agent's HTTP client, add the fallback skill: + ```bash npx skills add worldcoin/agentkit agentkit-x402 ``` -# Step 3: Wire the hooks-based server flow +# Step 4: Wire the hooks-based server flow The example below shows the maintained Hono wrapper path. AgentKit itself is not Hono-only: Express and Next.js route handlers can use the same hooks and low-level helpers from the [SDK Reference](/agents/agent-kit/sdk-reference). @@ -107,6 +136,7 @@ const hooks = createAgentkitHooks({ const resourceServer = new x402ResourceServer(facilitatorClient) .register(WORLD_CHAIN, evmScheme) + .register(BASE, new ExactEvmScheme()) .registerExtension(agentkitResourceServerExtension) const routes = { @@ -146,9 +176,9 @@ app.get('/data', c => { serve({ fetch: app.fetch, port: 4021 }) ``` -This example accepts payments on both World Chain and Base. AgentBook lookup automatically resolves against the canonical World Chain deployment — you do not need to pass a chain ID or pin a network. +This example accepts payments on both World Chain and Base. AgentBook lookup automatically resolves against the canonical World Chain deployment. -# Step 4: Configure the default mode and storage +# Step 5: Configure the default mode and storage This guide uses `free-trial` mode so registered human-backed agents get 3 free requests before the normal x402 payment flow resumes. `InMemoryAgentKitStorage` is fine for local testing, but production should persist both usage counters and nonces. @@ -156,12 +186,8 @@ This guide uses `free-trial` mode so registered human-backed agents get 3 free r import type { AgentKitStorage } from '@worldcoin/agentkit' class DatabaseAgentKitStorage implements AgentKitStorage { - async getUsageCount(endpoint: string, humanId: string) { - return db.getUsageCount(endpoint, humanId) - } - - async incrementUsage(endpoint: string, humanId: string) { - await db.incrementUsage(endpoint, humanId) + async tryIncrementUsage(endpoint: string, humanId: string, limit: number) { + return db.tryIncrementUsage(endpoint, humanId, limit) } async hasUsedNonce(nonce: string) { @@ -180,4 +206,4 @@ const hooks = createAgentkitHooks({ }) ``` -Need `discount` mode, Solana, custom AgentBook deployments, or the low-level validation helpers? Continue to the [SDK Reference](/agents/agent-kit/sdk-reference). +Need `discount` mode, custom AgentBook deployments, or the low-level validation helpers? Continue to the [SDK Reference](/agents/agent-kit/sdk-reference). diff --git a/agents/agent-kit/sdk-reference.mdx b/agents/agent-kit/sdk-reference.mdx index 4e970f5..02980a4 100644 --- a/agents/agent-kit/sdk-reference.mdx +++ b/agents/agent-kit/sdk-reference.mdx @@ -1,13 +1,11 @@ --- title: "SDK Reference" -description: "Reference for AgentKit modes, APIs, supported chains, and low-level helpers." +description: "Reference for AgentKit modes, APIs, EVM signatures, and low-level helpers." "og:image": "https://raw.githubusercontent.com/worldcoin/developer-docs/main/images/docs/docs-meta.png" "og:description": "Reference for the AgentKit SDK surface and advanced integration behavior." "twitter:image": "https://raw.githubusercontent.com/worldcoin/developer-docs/main/images/docs/docs-meta.png" --- -{/* cspell:ignore DEVNET */} - Use this page when you need the full AgentKit surface area. For the shortest path to a working setup, start with [Integrate AgentKit](/agents/agent-kit/integrate). ## Access modes @@ -22,6 +20,53 @@ Usage counters are tracked per human per endpoint. Two agents backed by the same `discount` mode requires `verifyFailureHook` to be registered on the facilitator. Without it, discounted underpayments fail settlement verification. +## Agent client APIs + +### `createAgentkitClient(options)` + +Use this client in agents that call paid x402 APIs. `agentkit.fetch` inspects `402 Payment Required` responses and retries once with a signed `agentkit` header when the response advertises `extensions.agentkit`. + +```typescript +import { createAgentkitClient } from '@worldcoin/agentkit' + +const agentkit = createAgentkitClient({ + signer: { + address: agentWallet.address, + chainId: 'eip155:8453', + type: 'eip191', + signMessage: message => agentWallet.signMessage(message), + }, +}) +``` + +| Option | Type | Description | +| --------- | ------------------------------------- | ----------- | +| `signer` | `AgentkitSigner` | Agent wallet identity and SIWE signing function. Required. | +| `fetch` | `typeof fetch` | Optional base fetch implementation. Defaults to `globalThis.fetch`. | +| `onEvent` | `(event: AgentkitFetchEvent) => void` | Optional callback for logging and debugging. | + +The client does not create x402 payments. It returns the original response unchanged when AgentKit is unavailable or cannot be used, so your existing x402 payment client can handle fallback. + +### `AgentkitSigner` + +```ts +type AgentkitSigner = { + address: string + chainId: string + type: 'eip191' | 'eip1271' + signMessage(message: string): Promise +} +``` + +Use `eip191` for EOAs and `eip1271` for smart contract wallets. + +The returned client exposes: + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `fetch` | `typeof fetch` | Fetch-compatible function that retries AgentKit-enabled 402 responses once. | +| `createHeader` | `(extension: AgentkitExtension) => Promise` | Creates the base64 `agentkit` HTTP header for custom HTTP clients. | + ## Core server APIs ### `declareAgentkitExtension(options?)` @@ -46,7 +91,7 @@ Register this extension once on your x402 resource server. It turns the declarat - generating the nonce and timestamps - inferring `domain` and `resourceUri` from the incoming request when you omit them -- expanding each supported network into the correct signature types for that chain family +- expanding each supported EVM network into `eip191` and `eip1271` signature types ### `createAgentkitHooks(options)` @@ -97,7 +142,7 @@ That is why Express and Next.js are compatible even though the docs use Hono for ### `createAgentBookVerifier(options?)` -Creates the verifier used to resolve a wallet address to an anonymous human identifier. Lookup **always** resolves against the canonical AgentBook deployment on World Chain (`eip155:480`), regardless of which chain the agent's signature was produced on or which chain your paid route runs on. The caller side is chain-agnostic by design — you never pass a chain ID or pin a network. +Creates the verifier used to resolve a wallet address to an anonymous human identifier. Lookup **always** resolves against the canonical AgentBook deployment on World Chain (`eip155:480`). Canonical deployment: @@ -129,8 +174,7 @@ lookupHuman(address: string): Promise | Method | Description | | ----------------------------------- | ----------- | -| `getUsageCount(endpoint, humanId)` | Return the current usage count for a human on a route. | -| `incrementUsage(endpoint, humanId)` | Increment the usage count after a successful free-trial or discount use. | +| `tryIncrementUsage(endpoint, humanId, limit)` | Atomically increment usage if below the limit. Returns `true` when the use is recorded. | | `hasUsedNonce?(nonce)` | Optional replay check. Return `true` if the nonce has already been seen. | | `recordNonce?(nonce)` | Optional replay recorder. Persist the nonce after validation succeeds. | @@ -156,15 +200,6 @@ Validates message binding, freshness, and optional replay checks. | `maxAge` | `number` | Maximum age for `issuedAt` in milliseconds. Defaults to 5 minutes. | | `checkNonce` | `(nonce: string) => boolean \| Promise` | Optional replay validation hook. | -Validation rules include: - -- `domain` must match the hostname of the protected resource URL -- `uri` must resolve to the same host as the protected resource URL -- `issuedAt` must be valid, not in the future, and not older than `maxAge` -- `expirationTime`, when provided, must still be in the future -- `notBefore`, when provided, must already have passed -- `checkNonce`, when provided, must accept the nonce - Returns: ```ts @@ -182,7 +217,6 @@ Verifies the cryptographic signature and returns the recovered address on succes Behavior: - `eip155:*` payloads are reconstructed into a SIWE message and verified with viem -- `solana:*` payloads are reconstructed into a SIWS message and verified with `tweetnacl` - unsupported chain namespaces return `{ valid: false, error: ... }` Returns: @@ -207,32 +241,13 @@ Returns the JSON schema used in 402 challenge payloads. EVM verification uses viem's `verifyMessage`, which covers EOAs and ERC-1271 smart wallets. Counterfactual wallets can still represent their signature scheme with `signatureScheme: "eip6492"` in the payload schema. -### Solana - -| Export | Description | -| ----------------------------- | ----------- | -| `formatSIWSMessage` | Reconstruct the Sign-In With Solana message used for verification. | -| `verifySolanaSignature` | Verify the detached signature against the reconstructed SIWS message. | -| `decodeBase58` / `encodeBase58` | Decode or encode Base58 values used in Solana payloads. | -| `extractSolanaChainReference` | Extract the chain reference from a CAIP-2 `solana:*` chain ID. | - ## Supported chains and signature behavior -### EVM - - Chain namespace: `eip155:*` - Payload `type`: `eip191` or `eip1271` - Optional `signatureScheme`: `eip191`, `eip1271`, or `eip6492` - Message format: SIWE -### Solana - -- Chain namespace: `solana:*` -- Payload `type`: `ed25519` -- Optional `signatureScheme`: `siws` -- Message format: Sign-In With Solana -- Exported constants: `SOLANA_MAINNET`, `SOLANA_DEVNET`, `SOLANA_TESTNET` - ## Manual usage example Use the low-level helpers directly when you are not using the x402 Hono wrapper or when you want full control over request handling: @@ -272,7 +287,6 @@ async function handleRequest(request: Request) { return { error: verification.error } } - // Always resolves against the canonical World Chain AgentBook const humanId = await agentBook.lookupHuman(verification.address) if (!humanId) { return { error: 'Agent is not registered in the AgentBook' }