> ## Documentation Index
> Fetch the complete documentation index at: https://tfh-docs-audit-world-id-content-fixes.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Reference

> Reference for AgentKit modes, APIs, EVM signatures, and low-level helpers.

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

Usage counters are tracked per human per endpoint. Two agents backed by the same human share the same counter.

| Mode | Fields | Behavior |
| - | - | - |
| `free` | `{ type: "free" }` | Registered human-backed agents always bypass payment. |
| `free-trial` | `{ type: "free-trial"; uses?: number }` | Registered human-backed agents bypass payment the first `N` times. Default `uses` is `1`. |
| `discount` | `{ type: "discount"; percent: number; uses?: number }` | Registered human-backed agents can underpay by the configured percentage for the first `N` times. |

`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 theme={"system"}
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 theme={"system"}
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?)`

Use this helper in your x402 route config to declare the `agentkit` extension that should be returned in a `402 Payment Required` response.

| Parameter | Type | Description |
| - | - | - |
| `domain` | `string` | Server hostname. Usually auto-derived from the request URL. |
| `resourceUri` | `string` | Full protected resource URI. Usually auto-derived from the request URL. |
| `network` | `string \| string[]` | CAIP-2 network or list of networks. If omitted, the extension derives them from `accepts[].network`. |
| `statement` | `string` | Human-readable signing purpose. |
| `version` | `string` | CAIP-122 version. Defaults to `"1"`. |
| `expirationSeconds` | `number` | Challenge lifetime in seconds. |
| `mode` | `AgentkitMode` | Access mode clients should expect after verification. |

Returns a record keyed by `agentkit` that can be attached directly to an x402 route declaration.

### `agentkitResourceServerExtension`

Register this extension once on your x402 resource server. It turns the declaration returned by `declareAgentkitExtension(...)` into a full 402 challenge by:

* generating the nonce and timestamps
* inferring `domain` and `resourceUri` from the incoming request when you omit them
* expanding each supported EVM network into `eip191` and `eip1271` signature types

### `createAgentkitHooks(options)`

Creates the request-time verification hooks used by the golden path integration.

| Option | Type | Description |
| - | - | - |
| `agentBook` | `AgentBookVerifier` | Verifier used to resolve the agent wallet to a human identifier. Required. |
| `mode` | `AgentkitMode` | Access mode. Defaults to `{ type: "free" }`. |
| `storage` | `AgentKitStorage` | Required for `free-trial` and `discount`. Optional for `free`. |
| `rpcUrl` | `string` | Custom EVM RPC used during signature verification. |
| `onEvent` | `(event: AgentkitHookEvent) => void` | Optional logging/debug callback. |

Returns:

| Field | Type | Description |
| - | - | - |
| `requestHook` | `function` | Runs before payment settlement and can grant access for `free` or `free-trial`. |
| `verifyFailureHook` | `function \| undefined` | Present only for `discount` mode. Register it on the facilitator so discounted underpayments can be recovered. |

`requestHook` expects a context shaped like:

```ts theme={"system"}
{
  adapter: {
    getHeader(name: string): string | undefined
    getUrl(): string
  }
  path: string
}
```

That is why Express and Next.js are compatible even though the docs use Hono for the concrete example: you can adapt any server framework to this minimal contract.

### `AgentkitHookEvent`

`onEvent` receives one of these event shapes:

| Event type | Fields |
| - | - |
| `agent_verified` | `resource`, `address`, `humanId` |
| `agent_not_verified` | `resource`, `address` |
| `validation_failed` | `resource`, `error?` |
| `discount_applied` | `resource`, `address`, `humanId` |
| `discount_exhausted` | `resource`, `address`, `humanId` |

## AgentBook lookup

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

Canonical deployment:

* World Chain mainnet: `0xA23aB2712eA7BBa896930544C7d6636a96b944dA`

| Option | Type | Description |
| - | - | - |
| `rpcUrl` | `string` | Custom World Chain RPC URL. Defaults to the chain's default public RPC. Ignored if `client` is provided. |
| `contractAddress` | `` `0x${string}` `` | Custom AgentBook contract address on World Chain. Defaults to the canonical deployment. |
| `client` | `PublicClient` | Advanced override. Inject a fully custom viem public client (useful for tests or non-standard deployments). |

In the common case call it with no arguments:

```typescript theme={"system"}
const agentBook = createAgentBookVerifier()
```

The returned object exposes:

```ts theme={"system"}
lookupHuman(address: string): Promise<string | null>
```

## Storage and replay protection

### `AgentKitStorage`

`AgentKitStorage` is the persistence interface used for free-trial counters, discount counters, and optional nonce replay protection.

| Method | Description |
| - | - |
| `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. |

### `InMemoryAgentKitStorage`

`InMemoryAgentKitStorage` is the reference implementation exported by the package.

* Good for local development, demos, and tests
* Not appropriate for production because usage counters and nonce history disappear on restart

## Validation and verification helpers

### `parseAgentkitHeader(header)`

Parses the base64-encoded `agentkit` header into a structured payload. It throws if the header is not valid base64, is not valid JSON, or does not match the expected schema.

### `validateAgentkitMessage(payload, resourceUri, options?)`

Validates message binding, freshness, and optional replay checks.

| Option | Type | Description |
| - | - | - |
| `maxAge` | `number` | Maximum age for `issuedAt` in milliseconds. Defaults to 5 minutes. |
| `checkNonce` | `(nonce: string) => boolean \| Promise<boolean>` | Optional replay validation hook. |

Returns:

```ts theme={"system"}
{ valid: boolean; error?: string }
```

### `verifyAgentkitSignature(payload, rpcUrl?)`

Verifies the cryptographic signature and returns the recovered address on success.

| Option | Type | Description |
| - | - | - |
| `rpcUrl` | `string` | Optional custom RPC endpoint for EVM verification. |

Behavior:

* `eip155:*` payloads are reconstructed into a SIWE message and verified with viem
* unsupported chain namespaces return `{ valid: false, error: ... }`

Returns:

```ts theme={"system"}
{ valid: boolean; address?: string; error?: string }
```

### `buildAgentkitSchema()`

Returns the JSON schema used in 402 challenge payloads.

## Chain utilities

### EVM

| Export | Description |
| - | - |
| `formatSIWEMessage` | Reconstruct the SIWE message used for EVM signing and verification. |
| `verifyEVMSignature` | Verify an EVM signature for the reconstructed SIWE message. |
| `extractEVMChainId` | Convert a CAIP-2 `eip155:*` chain ID to its numeric chain ID. |

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.

## Supported chains and signature behavior

* Chain namespace: `eip155:*`
* Payload `type`: `eip191` or `eip1271`
* Optional `signatureScheme`: `eip191`, `eip1271`, or `eip6492`
* Message format: SIWE

## 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:

```typescript theme={"system"}
import {
	AGENTKIT,
	createAgentBookVerifier,
	declareAgentkitExtension,
	parseAgentkitHeader,
	validateAgentkitMessage,
	verifyAgentkitSignature,
} from '@worldcoin/agentkit'

const extensions = declareAgentkitExtension({
	domain: 'api.example.com',
	resourceUri: 'https://api.example.com/data',
	network: 'eip155:480',
	statement: 'Verify your agent is backed by a real human',
})

const agentBook = createAgentBookVerifier()

async function handleRequest(request: Request) {
	const header = request.headers.get(AGENTKIT)
	if (!header) return

	const payload = parseAgentkitHeader(header)

	const validation = await validateAgentkitMessage(payload, 'https://api.example.com/data')
	if (!validation.valid) {
		return { error: validation.error }
	}

	const verification = await verifyAgentkitSignature(payload)
	if (!verification.valid || !verification.address) {
		return { error: verification.error }
	}

	const humanId = await agentBook.lookupHuman(verification.address)
	if (!humanId) {
		return { error: 'Agent is not registered in the AgentBook' }
	}

	return { humanId }
}
```

## Production notes

* Treat `InMemoryAgentKitStorage` as a demo-only implementation.
* If you need limited free uses, persistent storage is part of the integration, not an optional enhancement.
* If you need `discount` mode, wire `verifyFailureHook` into the facilitator before you ship.
* Use Hono as a reference example, not as a framework restriction. The package surface is generic enough to be adapted to Express or Next.js handlers.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.