@ agent- score/ 商业
整个商场SDK 代理记分:一个安装中的代理商务. 船舶身份标志 支付铁路帮手 402个挑战建设者 MPP发现 和花纹多链支持. 由AgentScore所建造和维护;与生态系统中的任何x402/MPP商家合作,AgentScore配对与否.
安装
npm install @agent-score/commerce
# or
bun add @agent-score/commerce
框架 + 协议包是可选的对等分页;只安装您使用的内容 :
npm install hono mppx @x402/core @x402/evm @solana/mpp @solana/kit stripe # whatever your stack needs
包裹里有什么
| 子路径 | 它提供的东西 |
|---|---|
/identity/{hono,express,fastify} | 信任门中件:KYC,制裁(账户名+签名钱包),年龄,管辖权. 背景图案 : agentscoreGate(opts) 中间软件+ getAgentScoreData(ctx) 编号 : getGateDegradedState(ctx) 编号 : getGateQuotaInfo(ctx) 编号 : getSignerVerdict(ctx) 用户, captureWallet(...)拒绝援助者(denialReasonStatus, (中文(简体) ), denialReasonToBody, (中文(简体) ), buildSignerMismatchBody, (中文(简体) ), buildContactSupportNextSteps, (中文(简体) ), verificationAgentInstructions, (中文(简体) ), isFixableDenial, (中文(简体) ), FIXABLE_DENIAL_REASONS从顶层导出) @agent-score/commerce而不是适应器. |
/identity/policy | 为多产品商提供产品合规帮助(每个产品都有自己的政策:硬门对软口对无,每产品航运许可清单): PolicyBlock, (中文(简体) ), GateResult, (中文(简体) ), EnforcementMode, (中文(简体) ), IdentityStatus, (中文(简体) ), buildGateFromPolicy, (中文(简体) ), runGateWithEnforcement, (中文(简体) ), shippingCountryAllowed, (中文(简体) ), shippingStateAllowed, (中文(简体) ), validateShippingAgainstPolicy (一通电话国家+国家认证人 CheckoutValidationError 带着信封在小姐身上. |
/identity/{nextjs,web} | 相同的门, 包装图案 : withAgentScoreGate(opts, handler) 编号 : createAgentScoreGate(opts) => guard(req)编辑 data + 键 degraded + 键 infraReason + 键 getSignerVerdict 字段直接降落在处理器 arg / 守护结果上( 没有单独的获取) 。 加号 captureWallet。 。 。 . |
/payment | networks, (中文(简体) ), USDC, (中文(简体) ), rails 登记册; paymentDirective, (中文(简体) ), buildPaymentDirective, (中文(简体) ), wwwAuthenticateHeader, (中文(简体) ), paymentRequiredHeader, (中文(简体) ), aliasAmountFields (opt- in v1↔v2 量- field shim: 添加两者 amount 财务报告和审定财务报表 maxAmountRequired 到一个条目。 402 构建者默认不应用它, 严格 x402 v2 和解通过精确比较匹配代理端的回放要求, 因此服务器重建要求的额外字段缺少解析; 仅在您知道客户端被硬码读取时使用 maxAmountRequired, (中文(简体) ), settlementOverrideHeader, (中文(简体) ), dispatchSettlementByNetwork, (中文(简体) ), extractPaymentSigner (基于请求;从x402 EIP-3009中回收签名器) payload.authorization.from 或 MPP 软件 Authorization: Payment <base64> did:pkh:eip155:<chain>:<addr> 编号 : did:pkh:solana:<genesis>:<addr> 资料来源,包括索拉纳 TransferChecked 权限在 @solana/kit 已安装), extractPaymentSignerFromAuth (标题字符串的变体,指已经拥有 Authorization 价值在手), detectRailFromHeaders (回报) "x402" 编号 : "mpp" 编号 : null 以入境信封报答; createX402Server, (中文(简体) ), createMppxServer (Solana铁路以预先供资的USDC ATA为固定金库接收人结算; @solana/mpp 使主收件人的ATA超出客户端的范围,因此不产生分拆 @solana/mpp 0.7.0 拒绝在收费赞助模式下将初级受援人分为两类), buildDefaultCheckoutRails({tempo?, x402Base?, solanaMpp?, stripe?}) (四号线) rails dict 工厂: 翻转 network 独自获得权利 token + 键 chainId, Base Sepolia → Sepolia USDC + 链Id 84532, Solana devnet → devnet USDC 薄荷. 索拉纳的 network 接受 CAIP-2 和原始数据 @solana/mpp 表单 mainnet-beta 编号 : devnet 编号 : localnet明确推翻总是赢, buildMppxComposeRails({amountUsd, tempoRecipient?, solanaRecipient?, ...}) (点名意向工厂取代手卷 [['tempo/charge',{...}],['solana/charge',{...}],['stripe/charge',{...}]] 阵列; 索拉纳的自动处理 USD 原子转换; 自动投放 stripe/charge 何时 amountUsd < 0.50 frede的固定收费~0.30美元 使得50分分以下的收费无利可图,50分以下的API通过 includeStripe: false 明确关闭警告); 滴入 x402 帮助者 : validateX402NetworkConfig (启动时守卫), verifyX402Request (parse + 验证输入的 X- 支付), processX402Settle (确认当时的settle 一个电话), classifyX402SettleResult (将标记的结算结果显示为推荐的 HTTP 状态 / 代码 / 下一个Steps , 使商家得到一个控制的信封, 而无需与特定促进者错误文本相配合), classifyOrchestrationError (同样的) ClassifiedX402Error 形状,但用于在管弦乐中向其他地方抛出未发现的例外;返回 null 对于未知的错误,商人们将重掷,而不吞咽; zeroAmountCarveOut (skip 上游验证+ settle for $0 结算上游无法处理: x402 值= 0 有效载荷和不可防伪的 MPP 证书,例如,一个代理签名反对非零报价的商家在结算时重新定价为0美元;解析证书、升降机签名+网络,返回 a ZeroSettleResult 形状与成功路径完全相同 所以调用者在铁路上分支,而不是结果形状。 组合 proof 证书不刻出 : Checkout 代表mppx的原生零载验证, mppCredentialPayloadType (读取) payload.type 从一个 Authorization: Payment 无 mppx 依赖性的标题; 该代表团背后的路由器; usdToAtomic (基于大项的美元-原子值,ROUND HALF UP,用于Tempo/Solana/USDC基数建造). |
/discovery | isDiscoveryProbeRequest, (中文(简体) ), buildDiscoveryProbeResponse (可选) x402Sample 用于x402-有意识的爬行者,例如:. awal x402 details; 样本信封总是带有 v2 resource (说明,从 resourceUrl,或者从域合成),因为信封验证器需要它,而线程可选 extensions (例如,用输入/输出计数的Bazaar块)进入头和身体,从而发现引擎可以建立有效的后续探测器; Checkout 由它自己填补 url编号 :resourceInfo编号 :discoveryExtensions 自动), sampleX402AcceptForNetwork (USDC为已知的CAIP-2网络提供样本-接受器), buildWellKnownMpp, (中文(简体) ), buildLlmsTxt + 键 llmsTxtIdentitySection + 键 llmsTxtPaymentSection (协作+动词模式),, buildSkillMd (与技能相匹配) /skill.md * 特工发现表;严格地说,只有特工发现数据,没有内部姿态, buildRedemptionSkillMd (交付中性救赎码模板、印刷邮件、电子邮件编码、API试算卡都覆盖;); endpointPath编号 :deliveryIntro编号 :bodyShape编号 :bodyRules编号 :extraRecoveryRows 对非货物形状的覆盖, agentscoreOpenApiSnippets, (中文(简体) ), createBazaarDiscovery, (中文(简体) ), noindexNonDiscoveryPaths (无中相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相 X-Robots-Tag: noindex 除了发现物剂的表面; 纯帮助者之外, 在每一个路径上 isDiscoveryPath + 键 defaultDiscoveryPaths (d) 非霍尔诺框架, buildMerchantIndexJson (动画) / 发现尸体, standardEndpointDescriptions({kind}) (canonical method+path → 货物对阿皮商的描述图;可选) includeOrderStatusRoute 货物, buildSuccessNextSteps (通用护照活动成功障碍), buildAgentscoreOnboardingSteps (canonical technology.md为货物或API商人登机). 加上UCP/JWKS发布表面: buildSignedUcpResponse, (中文(简体) ), buildSignedJwksResponse, (中文(简体) ), wellKnownPreflightResponse, (中文(简体) ), defaultA2aServices, (中文(简体) ), bootstrapUcpSigningKey中性框架 SignedDiscoveryResponse + 按框架包装 signedResponse{Hono,Express,Fastify,Nextjs,Web}。 。 。 . |
/challenge | build402Body, (中文(简体) ), buildAcceptedMethods, (中文(简体) ), buildIdentityMetadata, (中文(简体) ), buildHowToPay, (中文(简体) ), buildAgentInstructions (每个铁路自动起爆) compatible_clients: 代理人应使用经烟雾验证的CLI; 支持供应商覆盖; 纯帮助器 compatibleClientsByRails(rails) 返回供应商自定义 402s 的同一地图, buildPricingBlock, (中文(简体) ), firstEncounterAgentMemory, (中文(简体) ), Receipt (canonic 200-收受外形返回后套接字,通用:货物商填充发货/充值/产品槽;API商只填充通用田地; respond402,402出击,保留mppx的 WWW-Authenticate 和分层 x402's PAYMENT-REQUIRED。 。 。 . buildValidationError: 有结构的4xx车体构造器({error: {code, message}, required_fields?, example_body?, next_steps?, ...extra}所以卖家用名字来编造身体形状,而不是在每个验证站点内衬. |
/stripe-multichain | createMultichainPaymentIntent (回报) { paymentIntentId, depositAddresses }读取 depositAddresses[network] 直接, createPayToAddressFromStripePI({request, amountCents, stripe, piCache, networks?, staticRecipients?, metadata?, orderId?, preferredNetwork?})解析器:在结算段上,重复使用买方签定的支付方式从MPP证书中付款 piCache.hasAddress 检查或a staticRecipients 匹配时,静态地址总是被接受,因为商家拥有它; 在发现腿上,薄荷为没有覆盖的栏杆提供新鲜的PI staticRecipients,缓存合并的地图,登记静态地址 piCache.cacheAddress 所以验证脚检查通过. mintMultichainRecipients({...same opts}), 结构变量返回 { recipients: Record<string,string>, paymentIntentId?, reusedFromCredential }; 更喜欢当您 mintRecipients 钩子需要完整的每个铁路地图(典型的多铁路商家). Solana MPP 需要一个静态接收器:通过 staticRecipients: { solana: '<wallet>' } 并且从任何外部钱包中为UDC ATA提供一次资金。 旋转( 按顺序, 条纹闪烁) 索拉纳 收件人不会结算, 因为结算交易不会创建收件人的令牌账户; SDK 在计票时记录警告 。 静态接收器被永久重用,每个结算只支付 simulateCryptoDeposit, (中文(简体) ), createMppxStripe· ; createPiCache (TTL'd PI / 存款地址缓存,当 redisUrl 以物配主, simulateDepositIfTestMode (门打开 sk_test_ 帮你查查PI, STRIPE_TEST_TX_HASH_SUCCESS 编号 : STRIPE_TEST_TX_HASH_FAILED 常数。 端点调试 stripe。 。 。 . |
/api | 一切从 @agent-score/sdk 在一个地点再出口: AgentScore + 键 AgentScoreError, (中文(简体) ), AGENTSCORE_TEST_ADDRESSES + 键 isAgentScoreTestAddress。 。 。 . 别加 @agent-score/sdk 作为单独的解析器;两者可以漂移版本并引起微妙类型不匹配. |
/middleware/{hono,express,fastify,nextjs,web} | 框架专用的速率限制中间软件. Hono / Express / 快速曝光中间软件工厂(rateLimitHono, (中文(简体) ), rateLimitExpress, (中文(简体) ), rateLimitFastify); 下个.js 曝光 withRateLimit(opts, handler); Web 获取曝光 createRateLimit(opts) => guard(req)。共享选项: windowSeconds (违约60起), maxRequests (违约60起), keyResolver (默认第一个跳出) x-forwarded-for, (中文(简体) ), redisUrl (懒惰进口) ioredis 设定时, 记忆 Map 否则, keyPrefix。 。 。 . ioredis 是一个可选的对等端代码,仅在您想要分布限制时安装它. |
@agent-score/commerce (顶级) | Checkout 乐团+ CheckoutContext + 键 CheckoutGateConfig + 键 CheckoutValidationError + 键 DiscoveryProbeConfig + 键 MountUcpRoutesOptions + 键 SettleOutcome + 键 MppxComposeOutcome + 键 PricingResult (一个配置对象,用于Validate/compute前置/pricing/onSettled/mint Receptions/composeMppx,自动衍生出x402+mppx服务器,每帧适配器) handleHono编号 :handleExpress编号 :handleFastify编号 :handleNextjs编号 :handleWeb,通过 mountUcpRoutes{Hono,Express,Fastify}(三); pricingResult (单位:美分计分) PricingResult 内嵌 PricingBlock(三); validationResponse{Hono,Express,Fastify,Nextjs,Web} (每个框架4xx信封包装); loadUCPSigningKeyFromEnv (UCP 签名密钥的嵌入式加载器,读作 UCP_SIGNING_KEY_JWK_PRIVATE JSON JWK,从外形上检测到 alg,在未设置时会回落到麻黄,消毒出错,因此密钥字节永远无法到达日志,通过"承诺"被绑定的缓存同时安全; 3; hashOperatorToken (简写为sha256六) opc_...,对于持续商人 operator_token_id 用于自己的数据库,而从未存储过平话; extractOwnerScope(headers) → { walletAddress?, operatorTokenHash? } (canonial owner-identity 提取器,用于呼叫者范围的资源查询,读作 X-Wallet-Address 编号 : X-Operator-Token将信物挥之不去,使文句永不离开请求; hasPaymentHeader 编号 : hasX402Header 编号 : hasMppxHeader (要求歧视者,任何证书诉×402诉MPP); malformedPaymentCredential (电线-形状门:非基数64 JSON和非符号-形状的付款头在商钩跑出前被拒; Checkout 默认应用,选择退出 credentialPreCheck: false(三); createResultCache (中性按键 JSON 值缓存,并带有稳定的机身-hash 键构建器;缓存一个探测腿结果,如在 preValidate加上计算出的第一个形状 createQuoteCache 在此基础上建立; defaultReadOnlyOnDenied(reason) (动画) onDenied 只读资源门: 401 + Cache-Control: no-store 还在扩散 denialReasonToBody; 加上交叉复仇者出版社 buildA2AAgentCard + 键 buildUCPProfile (返回未署名的有效载荷:销售者标志+出版物). |
快开始
速率限制( Hono / Express / fastify / Next.js / Web)
在任何支付途径之前 上全球山 所以探险和安顿腿 共用同一个桶。 默认值: 60 req / 60s / IP. 重置时间 REDIS_URL 设定, 否则会倒计时.
import { Hono } from "hono";
import { rateLimitHono } from "@agent-score/commerce/middleware/hono";
const app = new Hono();
app.use("*", rateLimitHono());
// ... your routes ...
每个框架的工厂形状相同: rateLimitExpress, (中文(简体) ), rateLimitFastify (前汉德勒钩子), withRateLimit(opts, handler) 用于 Next.js App路由器,以及 createRateLimit(opts) => guard(req) 用于 Web 获取 。 覆盖 maxRequests 编号 : windowSeconds 编号 : keyResolver 编号 : redisUrl 编号 : keyPrefix 视需要而定.
身份门(呼诺)
import { Hono } from "hono";
import {
agentscoreGate,
captureWallet,
getAgentScoreData,
getSignerVerdict,
} from "@agent-score/commerce/identity/hono";
const app = new Hono();
const _gate = agentscoreGate({
apiKey: process.env.AGENTSCORE_API_KEY!,
requireKyc: true,
minAge: 21,
allowedJurisdictions: ["US"],
createSessionOnMissing: { apiKey: process.env.AGENTSCORE_API_KEY!, context: "wine-purchase" },
// With an EMPTY policy (no KYC), add kind: "sign_in" so the minted session is a plain
// account sign-in (no identity documents) that still yields an operator token.
});
// Run the gate CONDITIONALLY: when a payment credential is attached, or when the buyer asks
// for a verification session with `X-Verification-Session: create` and no identity. Anonymous
// discovery flows through to the handler so any spec-compliant x402 wallet can read the 402
// challenge with rails + pricing without first proving identity; identity is verified at settle
// time, or earlier on request. Advertise the early path by spreading `buildIdentityBootstrap()`
// into your 402 body as `identity_bootstrap` (Checkout does this for you).
import { shouldRunConditionalGate } from "@agent-score/commerce/payment";
app.use("/purchase", async (c, next) => {
if (!shouldRunConditionalGate(c.req.raw)) { await next(); return; }
return _gate(c, next);
});
app.post("/purchase", async (c) => {
const data = getAgentScoreData(c);
// ... settle payment ...
// After payment, capture the signer wallet for cross-merchant attribution
await captureWallet(c, { walletAddress: signer, network: "evm", idempotencyKey: paymentIntentId });
return c.json({ ok: true });
});
退出乐团
Checkout 是固定价格一发端点的光子商座表面:一个配置对象,为商座所特有的部件提供钩子,而SDK的手柄有402发出,身份吉他,x402验证+settle,mppx作曲,0美元外出,以及每帧适配器. 大部分固定价格的商家 Checkout 先说.
对于 可变成本按成果计薪 端点(每结果搜索,每端 LLM,每字节转码),达到 computeFirstCheckout: 相同的配置外形, 但探测腿运行工作, 缓存通过身体内容-hash, 用 EXACT 计算出的价格输出出 402 。 重试支付准确的金额并接收被缓存的身体. 每条精确的铁路(x402-精确基站、节奏/充电、索兰娜/充电、花旗小组委员会)的工程没有达到/许可2/定居-管理。 权衡:工作在无报酬的探测腿上进行,所以挂起 rateLimitHono (从) @agent-score/commerce/middleware/hono在全球,它是负载。 见 examples/compute-first-merchant.ts。 。 。 .
import { Checkout, pricingResult } from "@agent-score/commerce";
import { defaultA2aServices } from "@agent-score/commerce/discovery";
import { validateShippingAgainstPolicy } from "@agent-score/commerce/identity/policy";
const checkout = new Checkout({
rails: {
tempo: { recipient: process.env.TEMPO_RECIPIENT! },
x402_base: { recipient: process.env.X402_BASE_RECIPIENT!, network: "eip155:8453" },
solana_mpp:{ recipient: process.env.SOLANA_RECIPIENT!, network: "solana:mainnet" },
stripe: { profileId: process.env.STRIPE_PROFILE_ID! },
},
url: "https://merchant.example/purchase",
preValidate: async (ctx) => {
const body = (ctx.request.body ?? {}) as { product_slug?: string; shipping?: { country?: string; state?: string } };
const product = await lookupProduct(body.product_slug);
validateShippingAgainstPolicy({ country: body.shipping?.country ?? "", state: body.shipping?.state ?? "", policy: product, productName: product.name });
return { product };
},
computePricing: async (ctx) => pricingResult({
subtotalCents: ctx.state.product.priceCents,
taxCents: ctx.state.product.taxCents,
taxRate: ctx.state.product.taxRate,
taxState: ctx.state.product.taxState,
}),
onSettled: async (ctx, outcome) => ({ ok: true, order_id: ctx.referenceId, tx_hash: outcome.txHash }),
cdpApiKeyId: process.env.CDP_API_KEY_ID,
cdpApiKeySecret: process.env.CDP_API_KEY_SECRET,
mppxSecretKey: process.env.MPP_SECRET_KEY,
gate: {
apiKey: process.env.AGENTSCORE_API_KEY!,
merchantName: "Merchant",
requireKyc: true, requireSanctionsClear: true, minAge: 21, allowedJurisdictions: ["US"],
},
// Optional: empty-body POSTs without a payment header auto-route to a sample 402
// so x402 crawlers (awal x402 details, x402-proxy, ...) can discover the surface.
discoveryProbe: {
realm: "merchant.example",
sampleRail: "tempo-mainnet",
sampleAmountUsd: 1.0,
sampleRecipient: process.env.TEMPO_RECIPIENT!,
},
});
// Mount the signed UCP profile + JWKS + OPTIONS preflights in one call.
// (For Express / Fastify use `mountUcpRoutesExpress` / `mountUcpRoutesFastify`.
// Next.js / Web Fetch use file-based routing, call buildSignedUcpResponse
// directly inside the route handler.)
checkout.mountUcpRoutesHono(app, {
name: "Merchant",
services: defaultA2aServices({ agentCardUrl: "https://merchant.example/.well-known/agent-card.json" }),
signingKid: "merchant-2026-05",
});
app.post("/purchase", (c) => checkout.handleHono(c));
402体检出自动附着器 identity_mode + 键 required_signer + 键 signer_constraint (和 linked_wallets 当时,有一道城门 X-Wallet-Address 信头是存在的,所以物剂在发现时会自我纠正,而不是在403重试时.
助付人员
import {
buildPaymentDirective,
extractPaymentSigner,
networks,
paymentRequiredHeader,
wwwAuthenticateHeader,
} from "@agent-score/commerce/payment";
// Build paymentauth.org directives by symbolic rail name (decimals + currency from registry)
const directives = [
buildPaymentDirective({ rail: "tempo-mainnet", id: "chg_t", realm: "ex.com", recipient: TEMPO_ADDR, amountUsd: 0.01 }),
buildPaymentDirective({ rail: "x402-base-mainnet", id: "chg_b", realm: "ex.com", recipient: BASE_ADDR, amountUsd: 0.01 }),
buildPaymentDirective({ rail: "mpp-solana-mainnet", id: "chg_s", realm: "ex.com", recipient: SOL_ADDR, amountUsd: 0.01 }),
];
const wwwAuth = wwwAuthenticateHeader(directives);
// Recover the on-chain signer from the inbound credential; returns {address, network}.
// Covers x402 EIP-3009 (EVM `from` address), Tempo MPP (`did:pkh:eip155` source),
// and Solana MPP `solana/charge` (via `did:pkh:solana` source when set, else by
// decoding the credential's signed-tx payload; `@solana/kit` optional peer).
const signer = await extractPaymentSigner(req, req.headers.get("x-payment") ?? undefined);
x402 + MPP 服务器设置
import { createX402Server, createMppxServer } from "@agent-score/commerce/payment";
const x402 = await createX402Server({
facilitator: "coinbase", // or "http", or pass a custom facilitator instance
rails: ["x402-base-mainnet", "x402-base-mainnet-upto"],
});
const mppx = await createMppxServer({
rails: {
tempo: { recipient: process.env.TEMPO_RECIPIENT! },
solana: {
recipient: process.env.SOLANA_RECIPIENT!,
// Optional fee sponsor: pass any `TransactionPartialSigner` from `@solana/kit`.
// signer: solanaFeePayerSigner,
},
stripe: { profileId: process.env.STRIPE_PROFILE_ID!, secretKey: process.env.STRIPE_SECRET_KEY! },
},
secretKey: process.env.MPP_SECRET_KEY!,
});
402个建筑工
import {
build402Body,
buildAcceptedMethods,
buildAgentInstructions,
buildHowToPay,
buildIdentityMetadata,
} from "@agent-score/commerce/challenge";
const acceptedMethods = buildAcceptedMethods({
tempo: { recipient: TEMPO_ADDR },
x402_base: { recipient: BASE_ADDR },
solana_mpp: { recipient: SOL_ADDR, feePayerKey: SOLANA_FEE_PAYER },
stripe: { profileId: STRIPE_PROFILE_ID },
});
const howToPay = buildHowToPay({
url: req.url,
retryBodyJson: JSON.stringify(body),
totalUsd: "10.00",
rails: { tempo: { recipient: TEMPO_ADDR }, x402_base: { recipient: BASE_ADDR } },
});
const responseBody = build402Body({
acceptedMethods,
agentInstructions: buildAgentInstructions({ howToPay }),
identityMetadata: buildIdentityMetadata({ mode: "wallet", wallet: claimedAddress }),
pricing: buildPricingBlock({ subtotalCents: 1000, taxCents: 80, shippingCents: 999, taxRate: 0.08, taxState: "CA" }),
amountUsd: "10.80",
retryBody: body,
// First-encounter merchants attach the cross-merchant agent_memory hint so agents persist the AgentScore pattern.
agentMemory: firstEncounterAgentMemory({ firstEncounter: !merchant.hasSeenOperator(opToken) }),
});
过 x402: { accepts, version, resource, extensions } 以表面显示体内的x402 v2字段. resource 是一个 ResourceInfo (单位:千美元)url 加可选 serviceName 编号 : tags 编号 : description 编号 : mimeType 编号 : iconUrl这样符合规格的爬行者和发现客户可以读取资源是什么; extensions 载运已声明的x402扩展件(例如来自 createBazaarDiscovery) (中文(简体) ). respond402 镜像相同 resource 进入付费-REQUIED标题.
buildPricingBlock • 美元冲程换算(带有可选运输)。 过 discountCents 赎回码/券: subtotal 保留列表价格, 块表面 discount 作为一美元冲刺,和 total 变成 subtotal + tax + shipping - discount (底数为0). pricingResult 接受相同的建议 discountCents 并传播给 block.discount 因此,代理阅读402 看到储蓄线。 过 decimals: N (默认) 2用于中分单位定价的辅助工具,例如:. decimals: 4 广告 $0.0005-精度比四舍五入小数两分 设定 decimals 打开 PricingResult 和SDK的线条 buildHowToPay, (中文(简体) ), buildPricingBlock,则 x402 结算 price 自动字符串 cents 输入接受该模式下的分数值(每字节单位定价). firstEncounterAgentMemory 返回条形提示或 undefined 以一等商旗为主. Receipt 是一个通用的 TS 界面,用于结算后200 响应形状,货物商充斥了发运/完成/跟踪槽,API商只填充了通用域(id,create at, project, pay status, next steps).
同上, " Powerency-key " + " 多铁路头包 "
import { buildIdempotencyKey, buildPaymentHeaders } from "@agent-score/commerce/payment";
// Stable per-payment key: Stripe PI id wins, falls back to pi-{orderId}-{amountCents}.
const idempotencyKey = buildIdempotencyKey({ paymentIntentId, orderId, amountCents });
// One-call WWW-Authenticate + PAYMENT-REQUIRED bundle from a single rails declaration.
const headers = buildPaymentHeaders({
orderId,
realm: "agents.merchant.example",
rails: [
{ rail: "tempo-mainnet", amountUsd: "10.00", recipient: TEMPO_ADDR },
{ rail: "x402-base-mainnet", amountUsd: "10.00", recipient: BASE_ADDR },
{ rail: "stripe", amountUsd: "10.00", networkId: STRIPE_PROFILE_ID },
],
x402: { accepts: x402Accepts, version: 2 },
});
return new Response(JSON.stringify(responseBody), { status: 402, headers });
身份公布(跨供应商标准)
import {
buildA2AAgentCard,
buildUCPProfile,
mppPaymentHandler,
stripeSptPaymentHandler,
ucpA2AExtension,
x402PaymentHandler,
} from "@agent-score/commerce";
// A2A v1.0 Agent Card; publish at /.well-known/agent-card.json.
// Per UCP §A2A binding, the card MUST declare the canonical UCP extension URI in
// `capabilities.extensions[]`; pass `ucpA2AExtension()` with empty capabilities
// until you bind formal UCP capabilities (dev.ucp.shopping.checkout, etc.).
// Skills are top-level AgentSkill objects. The card is returned unsigned: to sign it,
// compute RFC 7515 JWS entries over the card body and pass them as `signatures`.
const card = buildA2AAgentCard({
name,
description,
url,
version: "1.0.0",
skills: [{ id: "purchase", name: "Purchase", description: "Buy products via agent payments.", tags: ["commerce", "payment"] }],
extensions: [ucpA2AExtension()],
});
// Google Universal Commerce Protocol; publish at /.well-known/ucp
// Output shape: { ucp: { version, services, capabilities, payment_handlers,
// name?, supported_versions? }, keys: [...], signature?: "..." }
// services / capabilities / payment_handlers are MAPS keyed by reverse-DNS
// service / capability / handler name (UCP spec §3 + §6).
const profile = buildUCPProfile({
name,
services: {
'dev.ucp.shopping': [
{ version: '2026-08-25', spec: 'https://ucp.dev/2026-08-25/specification/overview',
transport: 'mcp', endpoint: 'https://merchant.example/api/ucp/mcp',
schema: 'https://ucp.dev/services/shopping/mcp.openrpc.json' },
],
},
payment_handlers: {
...mppPaymentHandler({ networks: [{ network: 'tempo-mainnet', chain_id: 4217, recipient: TEMPO_ADDR }] }),
...x402PaymentHandler({ networks: [{ network: 'base-8453', recipient: BASE_ADDR }] }),
...stripeSptPaymentHandler({ spec: { profileId: 'profile_5xKvNqM9BaH' } }),
},
keys,
// Optional: declare the merchant's gate policy as an `com.agentscore.identity` capability
// binding inside the public profile. Static policy declaration only, no per-operator data.
// Per-operator identity attestation lives on the AP2 risk-signal endpoint, not here.
agentscore_gate: { require_kyc: true, min_age: 21, allowed_jurisdictions: ['US'] },
});
UCP §6不授权配置图-机构JWS签名;生产UCP商船通常没有签名. 代理分数 agentscore-profile+jws 是对选择可审计概况的信托模式核查人(规范商业、AP2-aware)的供应商延伸。 通过可选选项签名 + 校验 jose per dep (针对 jose v6.x 测试; pin jose@^6:
import { buildJWKSResponse, generateUCPSigningKey, signUCPProfile, verifyUCPProfile, UCPVerificationError } from "@agent-score/commerce";
const { privateKey, publicJWK } = await generateUCPSigningKey({ kid: "merchant-2026-05" });
const profile = buildUCPProfile({ name, services, payment_handlers, keys: [publicJWK] });
const signed = await signUCPProfile(profile, { signingKey: privateKey, kid: publicJWK.kid, alg: "EdDSA" });
const jwks = buildJWKSResponse([publicJWK]);
verifyUCPProfile 执行 JWS 保护头 typ: "agentscore-profile+jws" (vendor-name-spaced; UCP §6 不定义一个 profile-as-JWS 类型),限制 alg 改为 EdDSA 编号 : ES256,需要 kid,拒绝JWKS中重复的孩子们,并将犬形体字节与JWS有效载荷进行比较,以捕捉互换后信号被篡改. 失败投出 UCPVerificationError 歧视 code (单位:千美元)no_signature 编号 : missing_kid 编号 : kid_not_found 编号 : duplicate_kid 编号 : unsupported_alg 编号 : wrong_typ 编号 : signature_invalid 编号 : body_mismatch 编号 : malformed_jws 编号 : malformed_jwks 编号 : unusable_key 编号 : unrecognized_critical_header) (中文(简体) ). malformed_jwks 覆盖一个 JWKS 论点,这不是 { keys: [...] } 文档. unusable_key 覆盖一个匹配的JWK use 没有 sig (例如:. enc) (中文(简体) ). unrecognized_critical_header 涵盖一个JWS: crit 头条列出一个验证人不理解的扩展(RFC 7515 第4.1.1.).
signUCPProfile 拒绝包含非整数的配置文件 Number 值和外接整数 Number.MAX_SAFE_INTEGER (跨语言浮标线化不稳定;超过2^53的值在JS核查者重新剖开浮标线时失去精确度). 使用十进制字符串进行货币或分数字段和任何可能超过安全范围的整数.
坚持私人JWK. 薄荷一次通过 generateUCPSigningKey(),导出为 jose.exportJWK(privateKey) 获取 JSON 可序列表,存储在您的秘密管理器( AWS 秘密管理器, GCP 秘密管理器等) 。 在每一个容器开始,读 秘密, jose.importJWK(jwk, alg) 以再水合剂。 远程指示器流(KMS后置的不对称密钥)需要一个适配器层,以曝光一个 KeyLike jose可以打电话; jose 不在本地包装 KMS 端点.
键旋转. 将新密钥装入新密钥 kid,在您的 JWKS 端点上加上公共 JWK,然后用新键在新配置文件上签名。 正在获取 JWKS 的验证器将两者都取出;任何由旧密钥签名的飞行中信封,直到从 JWKS 中取出 JWK 为止,仍然在验证. 设定 Cache-Control: public, max-age=300 打开 /.well-known/jwks.json 并在发布新密钥后至少等待那么长时间,然后去除旧的JWK.
剖面图中的内置JWK与独立的JWKS端点. UCP 第6节授权单独 /.well-known/jwks.json 作为犬科信任源的终点. 简介 keys[] 是信息; 验证器 MUST 将孩子解决于 JWKS( 不是嵌入式复制), 以防止在敌对角色用自己的内置密钥替换后进行互换后签名攻击 .
非加太公司(Stripe + OpenAI Agentic Commerce Protocol)是一种没有身份公布表层的交易取出协议;非加太公司商人通过现有的 build402Body + 键 buildPaymentHeaders + Flede 防范小组委员会铁路.
条纹多链( 在 stripe(中文(简体) )
import {
createMultichainPaymentIntent,
createPiCache,
simulateCryptoDeposit,
simulateDepositIfTestMode,
} from "@agent-score/commerce/stripe-multichain";
const result = await createMultichainPaymentIntent({
stripe: stripeClient,
amount: 1000,
networks: ["tempo", "base", "solana"],
metadata: { order_id: orderId },
idempotencyKey: orderId,
});
const baseAddress = result.depositAddresses.base;
const solanaAddress = result.depositAddresses.solana;
// PI / deposit-address cache. Redis-backed when REDIS_URL is set, in-memory otherwise.
// Multi-task deployments need Redis so a deposit lands on whichever task settles it.
const piCache = createPiCache({ redisUrl: process.env.REDIS_URL });
for (const addr of Object.values(result.depositAddresses)) {
await piCache.cacheAddress(addr);
piCache.cachePaymentIntent(addr, result.paymentIntentId);
}
piCache.cacheNetworkAddresses(result.paymentIntentId, result.depositAddresses);
// Testnet helper: gates on sk_test_ and looks up the PI for you. No-op on live keys.
await simulateDepositIfTestMode({
getPaymentIntentId: piCache.getPaymentIntentId,
depositAddress: baseAddress!,
network: "base",
stripeSecretKey: process.env.STRIPE_SECRET_KEY!,
});
为 402 挑战构建 x402 接受条目
import { buildX402AcceptsFor402 } from '@agent-score/commerce/payment';
const x402Accepts = await buildX402AcceptsFor402(x402Server, {
network: X402_BASE,
price: `$${totalUsd}`,
payTo: process.env.TREASURY_BASE_RECIPIENT!,
maxTimeoutSeconds: 300,
});
返回准备用于402个天体的平地天体列表 accepts[]。 。 。 . extra.name 来源于注册的计划元数据,因此EIP-712域名与链上USDC合同相匹配.
滴入402+结算(x402)
import {
classifyX402SettleResult,
processX402Settle,
validateX402NetworkConfig,
verifyX402Request,
} from "@agent-score/commerce/payment";
import { respond402 } from "@agent-score/commerce/challenge";
// Boot-time guard: raises if a configured network isn't supported.
validateX402NetworkConfig({ baseNetwork: X402_BASE });
app.post("/purchase", async (c) => {
// Path A: agent presented an x402 X-Payment header
if (c.req.header("payment-signature") || c.req.header("x-payment")) {
const verified = await verifyX402Request({
request: c.req.raw,
isCachedAddress: piCache.hasAddress,
acceptedNetwork: X402_BASE,
});
if (!verified.ok) return c.json(verified.body, verified.status);
const settle = await processX402Settle({
x402Server,
payload: verified.payload,
resourceConfig: { scheme: "exact", network: verified.signedNetwork, price: `$${total}`, payTo: verified.signedPayTo, maxTimeoutSeconds: 300 },
resourceMeta: { url: c.req.url, mimeType: "application/json" },
});
const classified = classifyX402SettleResult(settle);
if (classified) {
// Log raw `settle` server-side; return controlled phase-based response to the agent.
console.error("[x402-settle]", { phase: settle.success ? null : settle.phase, raw: settle });
return c.json({ error: { code: classified.code, message: classified.message }, next_steps: classified.nextSteps }, classified.status);
}
if (!settle.success) throw new Error("unreachable: classified covers every non-success phase");
const headers: Record<string, string> = {};
if (settle.paymentResponseHeader) headers["payment-response"] = settle.paymentResponseHeader;
return c.json({ ok: true }, { headers });
}
// Path B: cold call (or Authorization: Payment for mppx). After mppx.compose() returns 402,
// respond402 PRESERVES mppx's WWW-Authenticate and ADDS x402's PAYMENT-REQUIRED.
return respond402({
mppxChallenge: mppxResult.challenge as Response,
body: { acceptedMethods, agentInstructions, pricing, amountUsd: total, retryBody: body },
x402: { x402Version: 2, accepts: x402Accepts, resource: { url: c.req.url, mimeType: "application/json" } },
});
});
失败行为
默认 AgentScore Gate 失败关闭:任何 AgentScore-side 基础设施故障(HTTP 429, 5xx, 网络超时)都返回给买主503. 设定 failOpen: true 打开 agentscoreGate({...}) 选择优雅地退化:
import { agentscoreGate, getGateDegradedState } from '@agent-score/commerce/identity/hono';
const gate = agentscoreGate({ apiKey: process.env.AGENTSCORE_API_KEY!, failOpen: true });
app.use('/purchase', gate);
app.post('/purchase', async (c) => {
const { degraded, infraReason } = getGateDegradedState(c);
if (degraded) {
// Compliance was NOT enforced this request; log/alert/refund-async/etc.
console.warn(`[gate] degraded: ${infraReason}`);
}
// ...rest of handler
});
何时 failOpen: true 失败是次形状的 大门载着 degraded: true + 键 infraReason: 'quota_exceeded' | 'api_error' | 'network_timeout' 这样商家就可以在不解析控制台输出的情况下进行日志/提醒. 拒绝遵守(制裁、年龄、管辖权、签字人-签字人-签字人比对) failOpen· ; failOpen 只有"AgentScore不能告诉我们" 从来没有"AgentScore说不"
对于受管制的商业(酒精、有年龄关系、受制裁管辖权相关),保留默认 failOpen: false:出局是正确的姿态,绕过下行故障的遵守是一个遵守漏洞. 对于低价商业或高时段的 SLA ,选择并使用 degraded 作为审计线索.
这个 getGateDegradedState 帮助器由上下文调整器(Hono, Express, Fastify)导出. 用于包装式适配器(Next.js,Web Fetch通过 withAgentScoreGate 编号 : createAgentScoreGate页:1 degraded + 键 infraReason 土地直接在 gate 对象传递给您的处理器,没有单独的获取器.
实例
这个 实例/ 目录有8个可运行的单文件Hono应用程序,涵盖常见的商家情景;复制-粘贴模板,而非框架. 见 实例/README.md 整个桌子.
供应商简介实例
| 供应商类型 | 使用的子路径 | 示例安装行 |
|---|---|---|
| 酒商(完全合规+多铁路) | /identity/*, (中文(简体) ), /payment, (中文(简体) ), /discovery, (中文(简体) ), /challenge, (中文(简体) ), /stripe-multichain | npm install @agent-score/commerce stripe |
| API 供应商(按电话计费,不合规) | /payment, (中文(简体) ), /discovery | npm install @agent-score/commerce |
| 仅限时间的商人 | /payment | npm install @agent-score/commerce mppx |
| 加密本地, 无花纹 | /identity/*, (中文(简体) ), /payment, (中文(简体) ), /challenge | npm install @agent-score/commerce @x402/core |
SDK确实是一个工具包;销售商只负责他们所需要的东西。 帮助者不会将你支持的铁路或协议的假设捆绑起来,也不推荐一条铁路过另一条铁路.
稳定
全商SDK表面稳定. 帮助者是协议翻译+可配置的意见;大多数进化是添加剂(新可选参数,新帮助者,新网络/铁路). 给真正的协议映射错误预留了大出击.
文档
完全整合文件 docs.agentscore.com/整合/节点-商业。 。 。 .