# @agentcash/router 中文文档

规范地址：https://npmcn.com/package/%40agentcash/router/

版本：1\.20\.0
npm 元数据更新时间：2026-07-20T18:41:41.112Z
中文译文更新时间：2026-11-06T20:58:27.815Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40agentcash/router
原文对照：https://npmcn.com/package/%40agentcash/router/?lang=original
项目主页：https://github.com/Merit-Systems/agentcash-router#readme
源码仓库：https://github.com/Merit-Systems/agentcash-router

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：560 kB，12 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：10 个
- peer 依赖：zod ^4\.0\.0
- 首次发布：2026-02-14T15:09:41.085Z
- 最新版本发布：2026-07-20T18:41:40.660Z
- 近 30 天下载量：2351（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：356（近 12 个月 356 个）

## 中文简介

Next.js App 路由器 APIs 的统一路由构建器,配置了 x402, MSP, SIWX, 和 API 密钥认证

## 安装

```sh
npm install @agentcash/router
```

也可以使用：`pnpm add @agentcash/router`、`yarn add @agentcash/router`、`bun add @agentcash/router`

## README

![AgentCash](https://agentcash.dev/logo-light-striped.svg)

# @ agentcash/路由器

**X402和MPP上最快的API发货方式.**  
x402和MPP支付,相容的发现,和最小的锅炉板. 使用@ agentcash/routter, 代理在 [代理卡许](https://agentcash.dev/) 从第一天起, 整个代理商的生态系统可以称为终点.

[![npm](https://img.shields.io/npm/v/@agentcash/router.svg?color=111&label=npm)](https://www.npmjs.com/package/@agentcash/router) [![docs](https://img.shields.io/badge/docs-agentcash.dev-111)](https://agentcash.dev/docs) [![runtimes](https://img.shields.io/badge/Next.js%20%C2%B7%20Hono%20%C2%B7%20Bun%20%C2%B7%20Node-framework--agnostic-111)](https://npmcn.com/package/%40agentcash/router/#readme-hosting)

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FMerit-Systems%2Fagentcash-router%2Ftree%2Fmain%2Fexamples%2Fvercel-deploy&project-name=agentcash-fortune-demo&repository-name=agentcash-fortune-demo&demo-title=AgentCash%20Router%20Fortune%20Demo&demo-description=Pay-per-call%20fortune%20API%20on%20x402%20and%20MPP&demo-url=https%3A%2F%2Fagentcash.dev&env=EVM_PAYEE_ADDRESS%2CCDP_API_KEY_ID%2CCDP_API_KEY_SECRET&envDescription=Wallet%20that%20receives%20payments%20%2B%20Coinbase%20Developer%20Platform%20API%20keys%20for%20the%20default%20x402%20facilitator.%20Create%20keys%20in%20the%20generous%20CDP%20free%20tier%3A%20https%3A%2F%2Fportal.cdp.coinbase.com%2Fprojects%2Fapi-keys&envLink=https%3A%2F%2Fgithub.com%2FMerit-Systems%2Fagentcash-router%2Fblob%2Fmain%2Fexamples%2Fvercel-deploy%2FREADME.md%23environment-variables)

* * *

## 安装

```bash
pnpm add @agentcash/router
pnpm add zod  # peer dependency
```

核心是框架不可知性(网络标准) `Request`编号 :`Response`)——Next.js是一个托管选项,而不是依赖. 见 [托管](https://npmcn.com/package/%40agentcash/router/#readme-hosting)。 。 。 .

## 环境

建议的切入点读取其特征: `process.env`复制盘 `.env.example` 住在雷波根头.

### x402(当 `CDP_API_KEY_ID` + 键 `CDP_API_KEY_SECRET` 已设定)

至少必须配置一个支付协议: 设置 x402 的 CDP 密钥对 , `MPP_SECRET_KEY` 或两者兼而有之.

| 瓦尔 | 需求 | 目的 |
| --- | --- | --- |
| `EVM_PAYEE_ADDRESS` | 对 | 接收x402和MPP付款的EVM地址(`0x…`, 20字节). 切入小写 零地址被拒绝 . |
| `CDP_API_KEY_ID`, (中文(简体) ), `CDP_API_KEY_SECRET` | 启用 x402 时 | Coinbase开发者平台为默认的EVM促进器提供证书. 存在切换 x402 上——在启动时从未检查有效性,所以占位符值为本地 dev 工作(见下文的点名) 。 在慷慨的 CDP 自由级创建 API 密钥 [https://portal.cdp.coinbase.com/projects/api-keys 页面存档备份,存于互联网档案馆](https://portal.cdp.coinbase.com/projects/api-keys) (签名需要电话验证,因此提前提供CI/自动设置的密钥). T3 电话 `@t3-oss/env-nextjs` 用户必须在其环境图中声明这些内容. |

> **路由建筑公司给主持人打电话.** 创建路由器可以启动一个背景获取器支持的付款类型,包括期间 `next build`。带有缺失或占位的 CDP 密钥,你会看到 `[x402] facilitator /supported failed, using hardcoded baseline: …` 在构建/dev日志中。 这是一个优雅的倒计时,而不是致命的错误;付费路线仍然服务于正确的402挑战. 占位符密钥是支持的本地- dev路径——真实的密钥仅用于支付验证和结算.

### 索拉纳

| 瓦尔 | 需求 | 目的 |
| --- | --- | --- |
| `X402_BUILDER_CODE` | 没有 | ERC-8021链上归属的基础构建者代码(`^[a-z0-9_]{1,32}$`) (中文(简体) ). 被宣布为每一次x402挑战的应用代码;促进者将其附加到和解调用数据中,将每个结算的付款计入您的应用 [https://dashboard.base.org 页面存档备份,存于互联网档案馆](https://dashboard.base.org/)。登记在 **设置 → 构建器代码**。 。 。 . |
| `SOLANA_PAYEE_ADDRESS` | 没有 | 设定时添加一个索拉纳 `exact` 所以路由器要索拉纳付款. **`.upTo()` 纯基并 `.session()` 仅为 MPP**索拉纳客户只能支付静态价格 `.paid()` 路线. |
| `SOLANA_FACILITATOR_URL` | 没有 | 取代索拉纳x402调解人. 默认为 `DEFAULT_SOLANA_FACILITATOR_URL`。 。 。 . |

### MPP( 自动启用时 `MPP_SECRET_KEY` 设置)

| 瓦尔 | 需求 | 目的 |
| --- | --- | --- |
| `MPP_SECRET_KEY` | 启用 MPP 时 | 服务器端的 MPP 秘密 。 正在切换 MPP . |
| `MPP_CURRENCY` | 启用 MPP 时 | 临时货币地址。 使用 `TEMPO_USDC_ADDRESS` (原始内容存档于2018-03-26) (英语). Tempo UDC. |
| `TEMPO_RPC_URL` | 没有 | Tempo JSON-RPC 链上核电厂的终点。 对公众的默认 `DEFAULT_TEMPO_RPC_URL` (单位:千美元)`https://rpc.tempo.xyz`) (中文(简体) ). 只有在您有指定终点时才能覆盖 . |
| `MPP_OPERATOR_KEY` | 没有 | 签名服务器端关闭/ 设置 。 设定时, 自动启用 MPP 会话模式( 需要 `.session()`:流出和要求-模式/单位计费)。 地址必须等同于收款人. |
| `MPP_FEE_PAYER_KEY` | 没有 | 赞助频道开放/TopUp的客户端气体. 必须下定决心去另一个地址 `MPP_OPERATOR_KEY` (Tempo拒绝付费的txs,如果 `sender === feePayer`) (中文(简体) ). |

> **MPP会话模式需要收款人的私钥.** 与x402(仅地址)不同, `.session()` 路由结算服务器侧, 所以 `MPP_OPERATOR_KEY` 必须是私钥 _联 合 国_ `EVM_PAYEE_ADDRESS`为了本地的发展, 薄荷薄荷 抛出键盘 在那里,两行:
> 
> ```bash
> npm i -D viem  # or pnpm add -D viem
> node -e "const {generatePrivateKey, privateKeyToAccount} = require('viem/accounts');
>   const pk = generatePrivateKey();
>   console.log('EVM_PAYEE_ADDRESS=' + privateKeyToAccount(pk).address);
>   console.log('MPP_OPERATOR_KEY=' + pk);"
> ```

### 其它

| 瓦尔 | 需求 | 目的 |
| --- | --- | --- |
| `BASE_URL` | 在韦尔塞尔之外 | 来源 URL (`https://api.example.com`) (中文(简体) ). 负载:用作402域名,OpenAPI服务器URL,和MPP备忘录前缀. 必须匹配公有领域。 在韦尔塞尔, `createRouterFromEnv` 自动删除此选项 `VERCEL_PROJECT_PRODUCTION_URL`,则 `VERCEL_URL`。 。 。 . |
| `VERCEL_PROJECT_PRODUCTION_URL`, (中文(简体) ), `VERCEL_URL` | 没有 | Vercel system env vars 用作后退 `BASE_URL` 未设定。 不要手动设置这些; Vercel 在构建和运行时提供它们 . |
| `KV_REST_API_URL`, (中文(简体) ), `KV_REST_API_TOKEN` | 没有 | Upstash / Vercel KV (英语). Back SIWX nonce, SIWX 权限, 和 MPP 重放. 记忆回落在无服务器生产中不安全. 提供Kv Store是极好的建议. |

## 快开始

### 1\. 创建路由器

有两种方式可以初始化. 选一.

**备选案文A: `createRouterFromEnv` (建议.** 读取 `process.env`,验证前面的每个值,并丢出一个单数 `RouterConfigError` 和所有的问题同时发生 自动可操作性 x402 当 `CDP_API_KEY_ID`编号 :`CDP_API_KEY_SECRET` 设定, 自动可操作的 MPP 当 `MPP_SECRET_KEY` 设置(至少需要两者之一),自动添加索拉纳在 `SOLANA_PAYEE_ADDRESS` 设置, 当 `MPP_OPERATOR_KEY` 已经设定.

```typescript
// lib/router.ts
import { createRouterFromEnv } from '@agentcash/router';

export const router = createRouterFromEnv({
  title: 'My API',
  description: 'Pay-per-call search.',
  guidance: 'POST /search with { q: string }. Returns top 10 results.',
});
```

> **没有密码吗?** 设置占位符值 `CDP_API_KEY_ID` 编号 : `CDP_API_KEY_SECRET` ——路由器靴,记录倒置警告,付费路线服务于正确的402个挑战. 真实的密钥只需要用于核实和结算实际的付款(而Coinbase的注册需要电话验证,所以不能完全自动化).

**备选案文B:建立 `RouterConfig` 并传递给 `createRouter`。 。 。 .** 需要自定义网络、多个收款人、非标准资产或任何设置时使用此功能 `createRouterFromEnv` 没有暴露. `createRouter` 运行同样的校验 `RouterConfig` 形状.

```typescript
// lib/router.ts
import { createRouter, BASE_MAINNET_NETWORK } from '@agentcash/router';

export const router = createRouter({
  baseUrl: 'https://api.example.com',
  payeeAddress: '0x…',
  network: BASE_MAINNET_NETWORK,
  protocols: ['x402'],
  x402: {
    accepts: [
      /* … */
    ],
  },
  discovery: {
    title: 'My API',
    version: '1.0.0',
    description: 'Pay-per-call search.',
    guidance: 'POST /search with { q: string }. Returns top 10 results.',
  },
});
```

> **`network` 只使用 CAIP-2 标识符** (单位:千美元)`eip155:8453`, (中文(简体) ), `solana:…`)——友好名类 `base` 或者说 `base-sepolia` 失败类型检查并丢弃 `unsupported_x402_network` 在建筑。 导入导出常数( E)`BASE_MAINNET_NETWORK`, (中文(简体) ), `SOLANA_MAINNET_NETWORK`)而不是手写字符串. 这同样适用于 `x402.accepts[i].network`。 。 。 .

### 2\. 登记路线

一个副作用模块记录每个路径. 导入它将包含注册;主机(下一步)为注册的任何东西服务.

```typescript
// lib/routes.ts
import { z } from 'zod';
import { router } from './router';

router
  .route('search')
  .paid('0.01')
  .body(z.object({ q: z.string() }))
  .handler(async ({ body }) => search(body.q));

router
  .route({ path: 'inbox/status', method: 'GET' })
  .siwx()
  .handler(async ({ wallet }) => getStatus(wallet));

router
  .route({ path: 'health', method: 'GET' })
  .unprotected()
  .handler(async () => ({ status: 'ok' }));
```

每个路线都选择一个认证模式 `.paid()`, (中文(简体) ), `.upTo()`, (中文(简体) ), `.session()`, (中文(简体) ), `.siwx()`, (中文(简体) ), `.apiKey()`,或 `.unprotected()` 看到了吗 [Auth 模式](https://npmcn.com/package/%40agentcash/router/#readme-auth-modes)路径可以声明 `{param}` 部分(`drafts/{draftId}/commit` → `ctx.params.draftId`) (中文(简体) ).

### 3\. 为它服务

**Next.js——一个包罗万象的文件** (建议):

```typescript
// app/api/[[...route]]/route.ts
import '@/lib/routes'; // side-effect import: registers all routes
import { router } from '@/lib/router';
import { nextHandlers } from '@agentcash/router/next';

export const { GET, POST, PUT, PATCH, DELETE } = nextHandlers(router);
```

**Hono / Bun / 节点 / 任何获取运行时间 :**

```typescript
import { serve } from '@hono/node-server';
import './routes';
import { router } from './router';

serve({ fetch: router.fetch, port: 3000 });
```

Ưμ㼯A`export const POST = router.route(…)…handler(…)`也工作——见 [托管](https://npmcn.com/package/%40agentcash/router/#readme-hosting) 用于所有三种模式,路径参数,以及 `basePath`。 。 。 .

### 4\. 发现

`router.fetch` (因此,包罗万象) `/{basePath}/openapi.json` 财务报告和审定财务报表 `/{basePath}/llms.txt` 自动,加取出运行时的根别名。 在 Next.js 上,加入两条一行路由文件的常规根路径:

```typescript
// app/openapi.json/route.ts — OpenAPI 3.1 at GET <origin>/openapi.json
import '@/lib/routes';
import { router } from '@/lib/router';
export const GET = router.openapi();
```

```typescript
// app/llms.txt/route.ts — plain-text agent guidance at GET <origin>/llms.txt
import { router } from '@/lib/router';
export const GET = router.llmsTxt();
```

> **折旧:** `router.wellKnown()` (单位:千美元) `/.well-known/x402` 资源清单)不再是推荐的发现表面. 处理器仍然工作,如果你已经为它服务——现有的x402-本土客户不会中断——但新的整合应该依赖 `/openapi.json` 财务报告和审定财务报表 `/llms.txt`。 。 。 .

### Bazaar 目录元数据

x402 主持人坚持从每次结算的付款中获取服务元数据 [巴扎尔](https://docs.x402.org/extensions/bazaar) 发现目录。 路由器从发现配置到402的挑战 `resource` 块 :

```typescript
createRouterFromEnv({
  title: 'Quote API',                          // serviceName defaults to title when it fits (≤32 ASCII chars)
  serviceName: 'Quote API',                    // explicit override
  tags: ['quotes', 'wisdom'],                  // ≤5 tags, each ≤32 chars; defaults to the route's OpenAPI tag
  iconUrl: 'https://example.com/icon.png',     // HTTPS, ≤2048 chars
  ...
});
```

无效的值在以结构化配置问题启动时失败, 而不是被调解人默不作声地丢弃 .

### 5\. 说吧

未支付请求获得 a `402` 挑战存在于标题中(参见 [阅读402项挑战](https://npmcn.com/package/%40agentcash/router/#readme-reading-a-402-challenge):

```bash
curl -i -X POST https://api.example.com/api/search \
  -H 'content-type: application/json' -d '{"q":"hello"}'
```

用任何 x402/ MPP 客户端支付 :

```bash
# AgentCash CLI — auto-negotiates x402 or MPP
npx agentcash fetch https://api.example.com/api/search -m POST -b '{"q":"hello"}'

# mppx CLI — MPP reference client
npx mppx https://api.example.com/api/search -J '{"q":"hello"}'
```

## 托管

路由器会讲网络标准 `Request`编号 :`Response` 通过嵌入式发送 [浩诺](https://hono.dev/) app,所以任何获取运行时间都会运行相同的路由定义. 三种托管模式:

### Next.js 包罗万象(建议)

一个路由文件为每一个注册的路由服务——没有每个路由文件,没有发现桶:

```typescript
// app/api/[[...route]]/route.ts
import '@/lib/routes'; // side-effect import: registers all routes
import { router } from '@/lib/router';
import { nextHandlers } from '@agentcash/router/next';

export const { GET, POST, PUT, PATCH, DELETE } = nextHandlers(router);
```

包罗万象 `/{basePath}/*` (默认) `/api/*`,包括: `/api/openapi.json` 财务报告和审定财务报表 `/api/llms.txt`。无比路径获得 `notFound()` 自动重新发现信封 。 根的发现别名( `/openapi.json`, (中文(简体) ), `/llms.txt`)仍然需要自己的路由文件(`export const GET = router.openapi()`)或中相器重写为通相.

### Ưμ㼯A

每个端点有一个路由文件——当您想要每个路由文件时仍然适合:

```typescript
// app/api/search/route.ts
export const POST = router.route('search').paid('0.01').body(schema).handler(handler);
```

每个文件的三个细节 包罗万象的模式使得过时:

-   **导出 const 名称对 `.method()`。 。 。 .** 您导出的名称( E)`GET`编号 :`POST`Next.js服务的动词控制; `.method()` (或 `route({ method })`控制在发现中公布的动词。 路由器默认为 `POST` (或 `GET` 何时 `.query()` ——任何其他GET路由必须明确声明,或者发现广告是错误的动词.
-   **发现需要一桶.** 接下来,Js懒惰的路由文件 第一次击中,所以 `app/openapi.json/route.ts` 必须 `import '@/lib/routes-barrel'` (一个模块导入每个路由文件)或已卸载的路由不会出现在光谱中. ()`llms.txt` 仅由静态配置而不需要)
-   **无与伦比的路线倒置.** 挂载 `router.notFound()` 包罗万象`app/api/[[...path]]/route.ts`,每个动词一个导出)所以 stale 代理调用得到一个JSON 404,带有再发现链接,而不是HTML错误页.

### Hono / Bun / 节点 / 任何获取运行时间

```typescript
import { serve } from '@hono/node-server';
import { Hono } from 'hono';

const app = new Hono();
app.route('/', router.hono()); // or use router.fetch directly
serve({ fetch: app.fetch, port: 3000 });
```

`router.fetch(request)` 是一个标准的获取处理器; `router.hono()` 将内部的应用程序显示为更大的应用程序。 见 `examples/hono` 一个可运行的服务器.

### 路径参数和 `basePath`

路径可能声明 `{param}` 区段,在每个主机模式下均取:

```typescript
router
  .route('drafts/{draftId}/commit')
  .unprotected()
  .handler(async ({ params }) => commit(params.draftId));
```

`RouterConfig.basePath` (默认) `'api'`控制挂载/广告前缀:线路服务于 `{baseUrl}/{basePath}/{path}`。通过一个空字符串来挂起源根.

## Auth 模式

| 方法 | 目的 |
| --- | --- |
| `.paid(price)` | 固定的,由参数衍生的,或分级支付前期(x402, MPP, 或两者兼有). |
| `.upTo(maxPrice)` | 处理器计算帐单;处理器呼叫 `charge(amount)` 并且请求一次性解决运行中的全部问题. **仅出自x402.** |
| `.session({ unitCost, maxPrice })` | 通过一个MPP支付渠道(MPP)向每个单位开具账单 `session` 意图. `.handler()` 准确的账单 `unitCost`· ; `.stream()` 电话 `charge()` 每个产量. **仅限MPP.** 流动需要这一点。 (`.metered({ tickCost, ... })` 仍为已贬值的别名。 ) |
| `.siwx()` | 钱包的身份,没有报酬。 携带SIWX挑战返回402. |
| `.apiKey(resolver)` | `X-API-Key` 或者说 `Authorization: Bearer <key>`组合 `.paid()` 编号 : `.upTo()` 编号 : `.session()`。 。 。 . |
| `.unprotected()` | 无正觉. |

```typescript
router
  .route({ path: 'admin/users' })
  .apiKey(async (key) => db.admin.findByKey(key)) // null => 401
  .handler(async ({ account }) => db.user.findMany());

router
  .route({ path: 'gated' })
  .apiKey(resolver)
  .paid('0.01') // key AND payment
  .handler(fn);
```

### `.siwx()` 在付费路线上。 支付一次, 身份重播

`.paid()` 财务报告和审定财务报表 `.upTo()` 编曲 `.siwx()` 一个免费的一次性重播模式 第一个请求通常解决(x402付款);一旦成功,钱包将记录在应享权益KV中。 随后为钱包提交有效SIWX签名的请求跳过支付并直接运行处理器. 打开 `.upTo()` 路线, `charge(amount)` 成为SIWX回放路径上的禁放. 处理者可以继续无条件拨打路线.

```typescript
router
  .route({ path: 'inbox' })
  .paid('0.01')
  .siwx() // first call pays $0.01, later calls present a SIWX sig instead
  .handler(async ({ wallet }) => getInbox(wallet));
```

`.session()` 两者相互排斥 `.siwx()` ——每个单位的MPP计费没有权益模式——如果合并,建设者会投注注册.

> **发现:** 无服务器/ 多事件部署必须提供真实 `kvStore` (原始内容存档于2017-09-29). Upstash / Vercel KV. 没有权利,就按程序处理 `Map`,因此在A实例上支付的钱包在B实例上被视为未付,用户再次收费.

## 阅读402项挑战

未偿请求的返回取决于路由的认证模式:

-   **仅付款路线** (单位:千美元)`.paid()`, (中文(简体) ), `.upTo()`, (中文(简体) ), `.session()` 无 `.siwx()`返回 402 与 **空正体**. 整个挑战——接受、价格、计划——以基本64编码于 `PAYMENT-REQUIRED` 响应头 (x402 v2), MPP 在 `WWW-Authenticate`别 `res.json()` 这些; 解码信头 .
-   **SIWX路线** (单位:千美元)`.siwx()`,单独或以定价模式组成)返回 402 并带有 **JSON 躯体** 倒计时 `PAYMENT-REQUIRED` 标题,包括 `sign-in-with-x` 扩展名。 头和身体总是一样.

每402个也带一个 `X-Agent-Identity` 响应头:可选 [挑战](https://www.npmjs.com/package/did-auth-challenge) (notce,域名/路由绑定,过期). 持有 Dod 的客户端可以签名并寄回证明 `X-Agent-Identity` 在重试中; 已核实的DD随后可供处理者使用 `ctx.actor`它完全是可选的——它从未提出过请求,与SIWX或付款无关。 没有DD的客户可以忽略它.

### 当身体被验证时

用于生成的`.paid(fn)`)和分级定价,以及航道 `.validate()` 或退出会话,正文被解析 **在此之前** 402项挑战,使挑战能够引用准确的价格(和 `.validate()` 以自己的身份拒绝。 在所有其他付费路线上,一个赤裸的无酬探测器得到它的402 **不检查尸体** ——一个畸形的身体仍然产生402分,而不是400分. 给钱的再试再剖析并验证身体 _在此之前_ 付款核实和结算,所以400元从不花费打电话者的钱.

`.paid()`, (中文(简体) ), `.upTo()`,以及 `.session()` 是相互排斥的定价模式:每条路线选择一条.

### `.paid()`: 固定、 引出或分级

**静静.**

```typescript
.paid('0.02')
```

**(原始内容存档于2018-10-29). args-entered.** 从被剖出的身体计算出价格. 掷出 `HttpError` 在402挑战之前拒绝.

```typescript
.paid((body) => calculateCost(body), { maxPrice: '5.00' })
.body(genSchema)
```

`maxPrice` 上限计算数量并起到对非`HttpError` 定价函数所抛出的例外(`HttpError` 总是被重新提出。 无 `maxPrice`,该路由完全信任您的功能(没有上限,没有倒置),并在出错时返回500个.

**等级.**

```typescript
.paid({
  field: 'tier',
  tiers: {
    '10mb': { price: '0.02', label: '10 MB' },
    '100mb': { price: '0.20', label: '100 MB' },
  },
})
.body(uploadSchema)
```

### `.upTo()`: 处理器计算,只有x402

处理器呼叫 `charge(amount)` 一次或多次; 请求一次解决累计总数, 上限为 `maxPrice`A级 `charge()` 这会推动运行中的全部过去 `maxPrice` 丢出一个400 `CHARGE_OVER_CAP` 出错(请求失败而一无所获)——它不是默默地被夹住的,所以如果部分工作仍应计费,请注意你的循环. 需要一个 `'upto'` 至少接受一个配置的x402网络(`createRouterFromEnv` (原始内容存档于2017-09-31). auto-adds one on Base.

```typescript
.upTo('0.05')
.body(schema)
.handler(async ({ body, charge }) => {
  await charge('0.001');
  // ... more work ...
  await charge('0.002');
  return result;
});
```

### `.session()`:每个单位,只限MPP

通过一个微额供资方案付款渠道——微额供资方案——每个单位开具账单 [`session` 意图](https://mpp.dev/intents)。要求 `MPP_OPERATOR_KEY` (单位:千美元)`createRouterFromEnv` 设定时自动可操作会话模式). `unitCost` 用于 MPP 会话挑战的地图 `amount`· ; `unitType` 单位名称; `maxPrice` 是一个路由器-强制总上限(MPP本身仅限凭证前厅和存款).

**请求模式.** `.handler()` 准确的账单 `unitCost` 根据每项请求:

```typescript
.session({ unitCost: '0.01', maxPrice: '0.05', unitType: 'request' })
.handler(async ({ body }) => { ... });
```

**流来.** `.stream()` 在SSE上为会话服务 `charge()` 呼叫单单,最多 `maxPrice`数字 :

```typescript
.session({ unitCost: '0.0001', maxPrice: '0.05', unitType: 'token' })
.stream(async function* ({ body, charge }) {
  for await (const token of streamLLM(body.prompt)) {
    await charge();
    yield token;
  }
});
```

> `.metered({ tickCost, ... })` 是一个被折旧的别名,用于 `.session({ unitCost, ... })` 并行为一致.

流线是只使用 MPP . `.stream()` 编号 `.paid()` 编号 : `.upTo()` 编号 : `.unprotected()` 路由抛出注册.

## 预付款确认

对于在引用价格前需要数据库查询的检查:

```typescript
router
  .route({ path: 'domain/register' })
  .paid(calculatePrice, { maxPrice: '10.00' })
  .body(RegisterSchema)
  .validate(async (body) => {
    if (await isDomainTaken(body.domain)) {
      throw Object.assign(new Error('Domain taken'), { status: 409 });
    }
  })
  .handler(async ({ body, wallet }) => registerDomain(body.domain, wallet));
```

这些线路的管道订单: `body parse -> validate -> 402 challenge -> payment -> handler`. (中文(简体) )`.validate()` 是挑战前身体分析的导火索之一 [当身体被验证时](https://npmcn.com/package/%40agentcash/router/#readme-when-the-body-is-validated). ) (中文(简体) )

## 插件钩

```typescript
import { createRouterFromEnv, type RouterPlugin } from '@agentcash/router';

const myPlugin: RouterPlugin = {
  onRequest(meta) {},
  onPaymentVerified(ctx, payment) {},
  onPaymentSettled(ctx, settlement) {},
  onResponse(ctx, response) {},
  onError(ctx, error) {},
  onAlert(ctx, alert) {},
};

export const router = createRouterFromEnv({
  title: 'My API',
  description: '…',
  guidance: '…',
  plugin: myPlugin,
});
```

所有的钩子都是可选的和放火和遗忘的;它们从不拖延反应. 使用钩子为资源寿命周期添加额外的遥测或灵活性.

### 调试中 `onAlert`

路由器报告内部警告和错误( 付款核实失败、 模拟失败、 配置错误) `onAlert`: 由于未注册插件, 这些信件会被默默地丢弃, 因此连接一个日志插件是了解为什么请求失败的最快方式 。 前进 `onAlert` (和 `onError`在您的日志中:

```typescript
const loggingPlugin: RouterPlugin = {
  onAlert(_ctx, alert) {
    (alert.level === 'error' ? console.error : console.warn)(
      `[router:${alert.route}] ${alert.message}`,
      alert.meta ?? '',
    );
  },
  onError(_ctx, error) {
    console.error(`[router] ${error.status} ${error.message} (settled=${error.settled})`);
  },
};
```

## 常见问题

### @agentcash/router 是什么？

Next\.js App 路由器 APIs 的统一路由构建器,配置了 x402, MSP, SIWX, 和 API 密钥认证

### 如何安装 @agentcash/router？

在项目目录运行 npm install @agentcash/router，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：zod（^4\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @agentcash/router 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @agentcash/router 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @agentcash/router 可以商用吗？

@agentcash/router 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @agentcash/router 的下载量有多少？

根据 npm 官方下载统计，@agentcash/router 在 2026/10/05 – 2026/11/03 这 30 天内被下载 2,351 次，日均约 78 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @agentcash/router 还在维护吗？

最新版本 1\.20\.0 发布于 2026/07/21（3 个月前）；至今共发布 356 个版本，其中过去 12 个月发布了 356 个；首次发布于 2026/02/14。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

