mcpField
B
bnbagent

bnbagent

github.com/starchild-ai-agentAgent 工作流3060 次安装6 天前更新
代码仓库

关于 bnbagent

用于在 BNB Chain 构建链上 AI Agent 的 Python SDK,分别提供 ERC-8004 Agent 身份和 ERC-8183 托管任务能力,并支持多种钱包与存储选项。

主要功能

  1. 01注册 ERC-8004 Agent 身份
  2. 02创建和管理 ERC-8183 任务
  3. 03监控已托管任务并提交结果
  4. 04支持争议投票和退款
  5. 05提供 EVM 与 TWAK 钱包后端

适用场景

  1. 01在 BSC 注册 Agent 身份
  2. 02接单并交付已托管任务
  3. 03为服务提供方创建并资助任务
  4. 04对有争议的任务投票

MCP 相关

SDK 将服务接口(包括 MCP)留给实现者选择。示例包含 Agent 服务端,并将 MCP 列为一种可选接口。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/starchild-ai-agent/official-skills --skill bnbagent

安装后在 Claude Code 中输入/bnbagent确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/
auto_settle.py
README.md
examples/a2a-agent/
.env.example
pyproject.toml
README.md
examples/a2a-agent/scripts/
buyer.py
register.py
examples/a2a-agent/src/
server.py
examples/agent-server/
.env.example
pyproject.toml
README.md
examples/agent-server/scripts/
register.py
run_agent_mount.py
run_agent.py
settle.py
examples/agent-server/src/
erc8183_server.py
service_mount.py
service.py
examples/client/
_helpers.py
.env.example
cancel_open.py
create_and_verify.py
dispute_reject.py
gen_job_report.py
happy.py
never_submit.py
README.md
stalemate_expire.py
examples/security/
e2e.py
examples/twak/
.env.example

详细介绍

BNBAgent SDK

用于 BNB Chain 上链上 AI Agent 的 Python SDK(pip install bnbagent,Python 3.10+)。两项独立能力:

  • ERC-8004(身份) — 将 Agent 作为 ERC-721 身份代币注册到链上,并带有可发现的 profile URI。在 BSC Testnet 上通过 MegaFuel paymaster 免 Gas。
  • ERC-8183(Agent 商务) — 客户端(付款)与提供方(交付)之间的免信任任务托管。乐观结算:超过争议窗口后保持沉默 = 批准;客户端提出争议会触发白名单投票人法定人数的拒绝。

二者相互独立:你可以在没有 ERC-8004 注册的情况下运行 ERC-8183 任务(注册仅为便于发现而推荐)。

正在积极开发中 — 可能引入破坏性变更。已使用 bnbagent==0.4.0 测试;用 python -c "import bnbagent; print(bnbagent.__version__)" 验证安装。可选附加项:pip install "bnbagent[ipfs]" 用于 IPFS/Pinata 交付物存储。

⚠️ 主网经济模型 — 进行任何主网商务之前必读

  • 支付代币是 U(United Stables) 0xcE24439F2D9C6a2289F741120FE202248B666666 — 不是 BNB,不是 USDT/USDC。它没有水龙头:在 PancakeSwap 上获取 U(存在 WBNB–U 交易对)。客户端必须在调用 fund() 之前持有 U。在运行时通过 erc8183.token_decimals() 获取小数位数 — 不要假设。
  • 主网上的 ERC-8183 写入永远不会获得 Gas 赞助。 客户端和提供方都需要 BNB 支付 Gas(仅 ERC-8004 身份注册在主网上获得赞助)。
  • 主网争议窗口为 604800s(7 天)。 顺利路径无法在单次会话中达到 COMPLETED — 沉默批准仅在窗口结束后才生效。请规划部分 E2E(推进到 SUBMITTED),之后通过 cron/运维脚本(examples/auto_settle.py)结算。在这一周内 settle 因 policy pending 而回滚是预期行为,不是错误。
预检余额清单(主网)
参与方需要原因
客户端BNBcreateJob/registerJob/setBudget/approve/fund 的 Gas(+ 可选兑换 Gas)
客户端Ufund 托管的任务预算(+ 少量余量用于重试)
提供方BNBsubmit 的 Gas — 在主网上不获赞助
结算者(任何人)BNB窗口结束后 settle 的 Gas

确定你要做什么

目标使用参考
在链上注册 Agent 身份ERC8004Agent下方快速开始
赚取:接受并交付已资助的任务ERC8183JobOps + funded_job_watcher下方快速开始,examples/agent-server/,examples/a2a-agent/
付款:创建/资助/结算任务ERC8183Client下方快速开始,examples/client/
对争议投票(白名单投票人)PolicyClient.vote_rejectexamples/voter/
支付 HTTP 402 挑战(x402)X402Signer / twak 委托付款方examples/x402/,references/twak.md
理解内部机制/扩展—references/architecture.md
钱包后端(EVM keystore 与 twak)EVMWalletProvider / TWAKProviderreferences/wallets.md,references/twak.md

快速开始:注册 Agent(ERC-8004)

一次性设置。需要私钥(如省略则自动生成)和 WALLET_PASSWORD。

import os
from bnbagent import ERC8004Agent, AgentEndpoint, EVMWalletProvider

wallet = EVMWalletProvider(
    password=os.getenv("WALLET_PASSWORD"),
    private_key=os.getenv("PRIVATE_KEY"),  # only needed on first run; keystore persists to ~/.bnbagent/wallets/
)
sdk = ERC8004Agent(network="bsc-testnet", wallet_provider=wallet)

agent_uri = sdk.generate_agent_uri(
    name="my-ai-agent",
    description="AI agent for document processing",
    endpoints=[
        AgentEndpoint.a2a("https://my-agent.example.com"),                      # A2A first (discovery doc URL)
        AgentEndpoint.mcp("https://my-agent.example.com/mcp", version="2025-06-18"),  # MCP second, if served
    ],
)
result = sdk.register_agent(agent_uri=agent_uri)
# result["agentId"], result["transactionHash"]

快速开始:提供方(赚取循环,无头模式)

无需服务器。监听已注资的任务,完成工作,提交:

import asyncio
from bnbagent import EVMWalletProvider
from bnbagent.erc8183 import ERC8183JobOps, funded_job_watcher
from bnbagent.storage import LocalStorageProvider

wallet = EVMWalletProvider(password="...", private_key="0x...")
ops = ERC8183JobOps(
    wallet,
    network="bsc-testnet",
    storage_provider=LocalStorageProvider(),
    service_price=1_000_000_000_000_000_000,      # min acceptable budget, raw units (18 decimals here)
    agent_url="http://localhost:8003/erc8183",    # public URL; required for file:// deliverable rewriting
)

async def on_funded(job: dict) -> None:
    deliverable = f"Processed: {job['description']}"   # your business logic
    await ops.submit_result(job["jobId"], deliverable)

asyncio.run(funded_job_watcher(ops, on_funded, interval=30))
  • submit_result 负责处理验证(FUNDED 状态、分配、过期、预算 ≥ service_price)、可交付物上传、清单哈希以及 submit 交易。
  • 监听器自身从不提交或结算。结算是单独的步骤 —— 在争议窗口结束后,运行调用 ERC8183Client.settle(job_id) 的操作员脚本(examples/auto_settle.py、examples/agent-server/scripts/settle.py)。
  • job 字典字段:jobId、description、budget、client、provider、evaluator、status(始终为 FUNDED)、expiredAt、hook。
  • 服务接口(A2A/MCP/HTTP)由你选择 —— 复制并自行掌控 examples/a2a-agent/(推荐)和 examples/agent-server/(FastAPI)中的参考实现。
  • 可交付物存储:像 https://example.invalid/manifest.json(如 examples/client/happy.py 中所示)这样的占位 URL 是仅上链的演示 —— 投票者无法验证可交付物。对于任何客户端可能提出争议的内容,请使用真实存储(公开 ERC8183_AGENT_URL 背后的 LocalStorageProvider,或 IPFSStorageProvider)。

快速开始:客户端(创建任务并付款)

import time
from bnbagent.erc8183 import ERC8183Client, JobStatus
from bnbagent.wallets import EVMWalletProvider

wallet = EVMWalletProvider(password="...", private_key="0x...")
erc8183 = ERC8183Client(wallet, network="bsc-testnet")

budget = 1 * (10 ** erc8183.token_decimals())   # DEMO-SCALE (1 full token). On MAINNET use tiny
                                                # budgets, e.g. (10 ** dec) // 100 for 0.01 U.
expired_at = int(time.time()) + 65 * 60

job_id = erc8183.create_job(provider=provider_addr, expired_at=expired_at, description="task")["jobId"]
erc8183.register_job(job_id)          # bind default policy (OptimisticPolicy)
erc8183.set_budget(job_id, budget)
erc8183.fund(job_id, budget)          # escrows; auto-approves payment token with 100-token floor

# ... provider submits ... dispute window elapses ...
erc8183.settle(job_id)                # permissionless — anyone can call
assert erc8183.get_job_status(job_id) == JobStatus.COMPLETED

争议与逃生通道:

erc8183.dispute(job_id)        # client only, within dispute window after submit
erc8183.vote_reject(job_id)    # whitelisted voters only, after dispute; quorum flips verdict to REJECT
erc8183.claim_refund(job_id)   # anyone, after expiredAt if never settled — non-pausable escape hatch

fund(job_id, amount, approve_floor=None):默认授权 max(amount, 100 * 10**decimals),以避免跨任务流重复授权;approve_floor=0 则精确授权 amount;若授权额度已足够则不再发送授权。

任务生命周期

OPEN ──► FUNDED ──► SUBMITTED ──┬─ silence past window ──► COMPLETED (provider paid, minus platform fee)
  │         │                   ├─ dispute + quorum reject ──► REJECTED (client refunded)
  │         │                   └─ no verdict + past expiredAt ──► EXPIRED (client claimRefund)
  │         └─ past expiredAt ──► EXPIRED (claimRefund)
  └─ client reject() before funding ──► REJECTED

Gas 赞助矩阵

协议 / 写入BSC 测试网BSC 主网
ERC-8004 register_agent✅ 已赞助(MegaFuel)✅ 已赞助(MegaFuel)—— 可在零 BNB 钱包上使用
ERC-8183 create/fund/submit/settle🟡 逐次调用:由 MegaFuel 决定(目前 fund/settle 已赞助);被拒绝的调用自行付费❌ 从不赞助 —— 所有写入自行支付 BNB
支付代币的 ERC-20 approve(额度不足时在 fund 内部发送)❌ 始终自行付费 —— 全新的测试网买家需要少量 tBNB❌ 自行付费
twak 钱包操作❌ twak 自行付费(twak 内部,SDK 无法控制)✅ twak 自动赞助 —— 参见 references/twak.md

网络与合约

BSC 测试网(链 97) —— 水龙头:tBNB、U 代币

合约地址
Identity Registry (ERC-8004)0x8004A818BFB912233c491871b3d84c89A494BD9e
AgenticCommerce0xa206c0517b6371c6638cd9e4a42cc9f02a33b0de
EvaluatorRouter0xd7d36d66d2f1b608a0f943f722d27e3744f66f25
OptimisticPolicy0x4f4678d4439fec812ac7674bb3efb4c8f5fb78a6

BSC 主网(链 56)

合约地址
Identity Registry (ERC-8004)0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
AgenticCommerce0xea4daa3100a767e86fded867729ae7446476eba6
EvaluatorRouter0x51895229e12f9876011789b04f8698af06ccd6da
OptimisticPolicy0x9c01845705b3078aa2e8cff7520a6376fd766de5

支付代币地址不可配置 —— 它在运行时从 Commerce 内核读取(ERC8183Client.payment_token)。在主网上它解析为 U (United Stables) 0xcE24…6666(参见顶部的主网经济部分)。

注意事项:

  • SDK 构造函数默认 network="bsc-testnet" —— 主网工作务必显式传入 network="bsc-mainnet"(或 NETWORK=bsc-mainnet),并打印 bscscan.com(而非 testnet.bscscan.com)浏览器链接;部分示例脚本硬编码了测试网 URL。
  • 发现/索引器延迟:即使你的 URI 携带了真实名称,注册表索引也可能显示通用名称(例如 Agent #198565)。链上 URI 才是唯一可信来源;索引器名称可能滞后或保持通用。

环境变量

完整带注释的参考:references/env.example。要点如下:

变量是否必需说明
WALLET_PASSWORD是用于加密/解密位于 ~/.bnbagent/wallets/ 的密钥库。
PRIVATE_KEY仅首次运行导入并加密后可删除。若未提供则自动生成钱包。
WALLET_ADDRESS否当存在多个密钥库时,选择一个。
NETWORK否(bsc-testnet)或 bsc-mainnet。
RPC_URL否自定义 RPC 端点。
ERC8183_SERVICE_PRICE否(1e18)提供方最低预算,以原始单位计。
ERC8183_AGENT_URL若使用 LocalStorageProvider公开基础 URL,含 /erc8183;file:// 形式的交付物 URL 会被重写为该 URL。
STORAGE_API_KEY若使用 IPFSStorageProviderPinata 兼容的 JWT。
STORAGE_LOCAL_PATH否(.agent-data)本地交付物目录。

存储后端是在代码中选择的(传入 storage_provider=),而非通过环境变量。

安全规则(对 Agent 工作流很重要)

  • EIP-712 签名默认受策略门控。 EVMWalletProvider.sign_typed_data 仅接受针对 BSC 56/97 上 U-token 的 EIP-3009 TransferWithAuthorization/ReceiveWithAuthorization。EIP-2612 Permit 与 Permit2 PermitSingle/PermitBatch 被无条件列入拒绝名单(它们会授予无限额度——恶意 402 服务可能掏空钱包)。切勿在 Agent 可触达的代码中试图绕过这一限制;SigningPolicy.permissive() 和 _DANGEROUS_sign_typed_data_no_policy() 仅供测试使用。
  • 切勿将原始的 WalletProvider 交给工具函数。 应给它们一个受限的 X402Signer(wallet, max_value_per_call={token: ...}, session_budget={token: ...}),并且始终从配置/链上注册表传入 expected_to——绝不能来自 402 质询响应体。
  • 自定义代币/类型:SigningPolicy.strict_default().extend(domain_allowlist={(chain_id, contract)}, primary_type_allowlist={"MyType"})——Permit 拒绝名单仍然优先。
  • claimRefund 不可暂停、不可挂钩:超过 expiredAt 后资金始终可收回。
  • 一次性/演示密钥:使用 EVMWalletProvider(persist=False),让一次性密钥永不落盘,且切勿在生产环境复用演示密钥。切勿将生产私钥粘贴到聊天/日志中——优先使用密钥库 + WALLET_PASSWORD 流程。

完整理由、决策树与示例:references/sdk-readme.md(Security 一节)和 examples/security/e2e.py。

钱包后端

  • EVMWalletProvider(默认)——Keystore V3(兼容 MetaMask/Geth),持久化于 ~/.bnbagent/wallets/,或在 persist=False 时存于内存。
  • TWAKProvider(Trust Wallet Agent Kit)——自托管、自行广播;不支持原始交易或通用 EIP-712 签名;仅支持 BSC;通过委托付款方 make_x402_payer() 实现 x402。使用前请阅读 references/twak.md——不受支持的调用会抛出 UnsupportedWalletOperation。切换方式:TWAKProvider(chain="bsc") 或 WALLET_KIND=twak。
  • 自定义(HSM、MPC、KMS):继承 WalletProvider。详情:references/wallets.md。
AA / 自广播钱包(Privy、ZeroDev 等)——已知的集成成本

通过提交 Intents/UserOperations 而非原始签名交易来发送交易的账户抽象钱包在 SDK 中尚不是一等公民(已在 BSC 主网上使用 Privy AA 客户端、bnbagent==0.4.0 进行过实地测试)。以下是预期情况以及行之有效的变通方案:

  • ERC-20 approve 失败:approve_payment_token 会经过 _send_tx → 原始 sign_transaction,而 AA 钱包并未实现该方法(sign.transaction: wallet does not implement raw-transaction signing)。变通方案:通过你的 AA 技术栈手动对支付代币执行 approve(commerce, amount),然后以 fund_bundles_approval=True 调用 fund。create_job/set_budget/fund 本身可通过自定义 Intent 执行器正常工作(继承执行器 / WalletProvider 的子类)。
  • create_job 之后 jobId 返回 None:AA 钱包返回的是 user_operation_hash,而不是 tx hash,而 create_job 只会从收据日志中解析 jobId。变通方案:等待打包上链,然后反向扫描 jobCounter(或按 client + provider + description 索引最近的 job)来找到你的 job。
  • 对于有文档支持的自广播钱包,请使用 TWAKProvider(references/twak.md);Privy 风格的适配器目前需要自行构建。

故障排查

错误原因 → 修复
No PRIVATE_KEY and no keystore found已自动生成新钱包,或设置 PRIVATE_KEY 以导入。
Multiple wallets found设置 WALLET_ADDRESS=0x...。
403 Provider mismatchJob 分配给了其他 provider —— 检查 job.provider。
409 Not FUNDEDJob 已提交/已结算。
408 Job expired已超过 expiredAt;客户端可 claimRefund,并创建新 job。
402 Budget below service price客户端必须注资 ≥ ERC8183_SERVICE_PRICE。
settle 回滚 policy pending争议窗口尚未结束且无争议 —— 等待后重试。在主网上该窗口为 7 天。
voteReject 回滚 not voter/not disputed调用者不在白名单中或没有争议 —— 使用 examples/voter/vote_reject.py。
在 register_job 上回滚选择器 0xcdbc1d27Job 已绑定到某个 policy —— 重新注册按设计会回滚。如果 job_policy(job_id) 已设置,则视为成功。
sign.transaction: wallet does not implement raw-transaction signingAA/自广播钱包命中了原始交易 approve 路径 —— 参见上文 AA 钱包部分。
create_job 之后 jobId 为 NoneAA 钱包返回的是 user-op hash,没有可解析的收据 —— 反向扫描 jobCounter 找到你的 job。
尝试 fund 后 allowance 仍为 0捆绑的 approve 从未上链(钱包路径错误)—— 手动 approve(commerce, amount),然后 fund。

本 skill 中的文件

  • references/sdk-readme.md —— 完整的上游 SDK README(对以上所有内容的深入细节)
  • references/architecture.md —— 代码地图、分层、不变量
  • references/twak.md —— TWAK 钱包支持矩阵与边界
  • references/wallets.md —— 钱包 provider 深入剖析
  • references/env.example —— 带注释的环境变量参考
  • examples/ —— 可复制并自行掌控的脚本:client/(5 个典型 job 流程)、a2a-agent/、agent-server/、voter/、twak/、x402/、security/、auto_settle.py

评论

支持 Markdown