Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion agents/agent-kit/ecosystem.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -22,4 +22,11 @@ npx skills add worldcoin/agentkit agentkit-x402
>
Register your agent with World ID to enable human-backed agent benefits.
</Card>
<Card
title="SDK Reference"
icon="code"
href="/agents/agent-kit/sdk-reference#createagentkitclientoptions"
>
Use `agentkit.fetch` before payment fallback.
</Card>
</CardGroup>
50 changes: 38 additions & 12 deletions agents/agent-kit/integrate.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -32,7 +33,13 @@ Register the wallet address your agent will sign with:
npx @worldcoin/agentkit-cli register <agent-address>
```

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 <agent-address>
```

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:

Expand All @@ -48,12 +55,34 @@ Once the wallet is registered, AgentKit can resolve it to an anonymous human ide

<p className="text-center text-sm">*Example of the registration flow*</p>

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).

Expand Down Expand Up @@ -107,6 +136,7 @@ const hooks = createAgentkitHooks({

const resourceServer = new x402ResourceServer(facilitatorClient)
.register(WORLD_CHAIN, evmScheme)
.register(BASE, new ExactEvmScheme())
.registerExtension(agentkitResourceServerExtension)

const routes = {
Expand Down Expand Up @@ -146,22 +176,18 @@ 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.

```typescript
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) {
Expand All @@ -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).
88 changes: 51 additions & 37 deletions agents/agent-kit/sdk-reference.mdx
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<string>
}
```

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<string>` | Creates the base64 `agentkit` HTTP header for custom HTTP clients. |

## Core server APIs

### `declareAgentkitExtension(options?)`
Expand All @@ -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)`

Expand Down Expand Up @@ -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:

Expand Down Expand Up @@ -129,8 +174,7 @@ lookupHuman(address: string): Promise<string | null>

| 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. |

Expand All @@ -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<boolean>` | 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
Expand All @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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' }
Expand Down
Loading