Web3 AI Agent 框架对比:Eliza、Rig 与 LangChain 的 DApp 集成适配性分析
Web3 AI Agent 框架对比:Eliza、Rig 与 LangChain 的 DApp 集成适配性分析
一、Agent 框架的选型困境:通用框架无法理解链上语义
2025-2026 年 AI Agent 框架出现了明显的两条岔路。一条是以 LangChain/LlamaIndex 为代表的 Web2 通用 Agent 框架,链式调用、工具绑定、记忆管理都做得成熟。另一条是以 Eliza(ai16z)和 Rig(Arc)为代表的 Web3 原生 Agent 框架,在 Agent 的认知模型里内置了链上账户、交易签名、合约交互等 Web3 基础设施。
两者的核心差异不在于 LLM 调用方式,而在于框架的"世界观"。LangChain 的 Agent 默认理解"文件系统"、"HTTP API"、"数据库"这些工具。但在 DApp 场景中,Agent 需要理解的是"连接钱包"、"签署交易"、"查询链上状态"、"等待区块确认"。Eliza 在设计上把链上 Actor(Provider)作为一等公民,Agent 启动时自动注入钱包 Provider 和链上状态监听器。LangChain 也能通过自定义 Tool 实现这些功能,但每次调用都要手动管理钱包实例的上下文传递,状态一致性容易在对轮对话中丢失。
在动手之前,先明确三个框架在技术架构上的根本差异。
flowchart TD subgraph Eliza["Eliza (Web3 Native)"] E1[Actor 角色系统] E2[Wallet Provider 内置] E3[链上状态监听] E4[Character 配置文件] E1 --> E2 E2 --> E3 E4 --> E1 end subgraph Rig["Rig (Arc)"] R1[Rust 原生异步] R2[Solana 深度集成] R3[零拷贝内存模型] R4[嵌入式 Agent 推理] R1 --> R2 R2 --> R3 R4 --> R1 end subgraph LangChain["LangChain (通用)"] L1[Chain / Agent 模型] L2[自定义 Tool 绑定] L3[Memory 管理] L4[RAG 检索链] L1 --> L2 L1 --> L3 L4 --> L1 end Eliza --> DApp[DApp 前端直接调用] Rig --> SVM[SVM / Solana DApp] LangChain --> Backend[后端 API 调用]二、三个框架的技术架构对比
Eliza
Eliza 的核心设计理念是"Agent as Actor"。每个 Agent 实例拥有独立的角色定义(Character)、钱包、记忆和动作(Action)集合。框架启动时,Agent 会基于 Character 配置初始化所有 Provider(钱包 Provider、链上状态 Provider、社交媒体 Provider)。动作系统采用注册表模式,新增链上操作只需在 Action 注册表中追加一条入口。
适合场景:需要 Agent 主动监控链上事件并触发交易(如 MEV 保护机器人、链上套利 Agent、DAO 提案自动投票)。Eliza 的 Actor 模型天然适合这类"监听→决策→执行"的循环。
核心限制:Eliza 的插件生态快速增长但质量参差不齐。同一个功能的多个插件(如 Solana 钱包管理)可能存在依赖冲突,插件之间的状态共享机制不够规范。
Rig
Rig 的设计哲学是"高性能 + 嵌入式"。用 Rust 写的异步引擎,Agent 推理流程受益于 Rust 的零成本抽象。在 Solana 生态中,Rig 的优势尤为突出:Agent 可以直接调用 Solana 的 Rust SDK,不需要通过 FFI 或 WebSocket 桥接。Rig 的 Agent 可以被编译为 WASM,在浏览器的 Service Worker 或 Web Worker 中运行。
适合场景:需要 Agent 在客户端本地运行以保护用户私钥的场景(如钱包内的智能交易助手)、对延迟敏感的高频链上操作、以及需要嵌入 Web Worker 运行的 DApp 内 AI 功能。
核心限制:Rust 的 Agent 开发门槛明显高于 TypeScript/Python。团队如果全部是 JS/TS 技术栈,Rig 的学习曲线会显著拉长交付周期。Solana 深度集成也意味着 Ethereum/EVM 生态的支持力度不如 Eliza。
LangChain
LangChain 的优势在于"生态厚度"。LLM Provider 支持最全、记忆管理最成熟、RAG 工具链最完善。如果 Agent 的核心能力是"理解链上文档 + 回答用户问题 + 偶尔发起交易",LangChain 比另外两个框架更合适。
适合场景:DApp 的智能客服、链上数据问答、文档 RAG 检索等"分析重于执行"的场景。
核心限制:每次链上交互都需要自定义 Tool + 手动管理钱包状态。在多轮对话中保持钱包上下文的一致性需要额外开发,而这在 Eliza 中是开箱即用的。
sequenceDiagram participant User as 用户 participant Agent as AI Agent participant Wallet as 钱包 Provider participant Chain as 链上 RPC participant Contract as 智能合约 User->>Agent: "用 0.1 ETH 兑换 USDC" Agent->>Agent: 意图解析 + 参数提取 alt Eliza / Rig (内置钱包) Agent->>Wallet: 获取签名器 (已注入) Wallet-->>Agent: signer 实例 else LangChain (自定义 Tool) Agent->>Tool: 调用 wallet_tool Tool->>Wallet: 手动获取 signer Wallet-->>Tool: signer Tool-->>Agent: signer 上下文 end Agent->>Chain: 查询最优兑换路径 Chain-->>Agent: 路径 + 报价 Agent->>Agent: 验证滑点 / 确认风险 Agent->>User: "预计得到 2500 USDC,滑点 0.3%,确认?" User->>Agent: 确认 Agent->>Wallet: 签署交易 Wallet->>Chain: 广播交易 Chain-->>Agent: Tx Hash Agent->>User: "交易已提交: 0x..."三、代码实践:三个框架的 DApp 集成示例
3.1 Eliza Agent 配置与链上动作
// eliza-agent/character/dex-trader.character.ts import { Character, ModelProviderName, Clients } from "@elizaos/core"; /** * Eliza DEX Agent 角色配置 * 设计考量: * - plugins 按功能域分组:@elizaos/plugin-evm 提供链上交互基础能力 * - settings.secrets 引用 .env 变量:私钥绝不硬编码在配置文件中 * - bio 和 lore 描述 Agent 的行为模式:LLM 将遵循这些角色指引生成回复 */ export const dexTraderCharacter: Character = { name: "SwapAgent", modelProvider: ModelProviderName.OPENAI, clients: [Clients.TELEGRAM, Clients.TWITTER], plugins: [ "@elizaos/plugin-evm", "@elizaos/plugin-uniswap", "@elizaos/plugin-chainlink", ], settings: { secrets: { EVM_PRIVATE_KEY: process.env.AGENT_PRIVATE_KEY || "", EVM_RPC_URL: process.env.MAINNET_RPC_URL || "", }, voice: { model: "en_US-hfc_female-medium", }, }, // Agent 人设:描述 Agent 的行为边界 bio: [ "DEX 交易助手,专注于代币兑换操作", "仅当用户明确确认后才执行链上交易", "每次交易前计算并展示滑点和燃气费估算", ], lore: [ "需要用户明确说出'确认交易'才会执行", "交易金额超过 0.5 ETH 时要求二次确认", ], // 内置动作注册 actions: [ // 这里的 action 名称对应 @elizaos/plugin-uniswap 的已注册动作 ], messageExamples: [ { user: "{{user1}}", content: { text: "把 0.1 ETH 换成 USDC" }, }, { user: "SwapAgent", content: { text: "收到。当前报价:0.1 ETH ≈ 312.45 USDC,滑点 0.25%,燃气费约 0.002 ETH。确认执行吗?", }, }, ], };// eliza-agent/src/custom-actions/swap.ts import { Action, IAgentRuntime, Memory, State, composeContext, generateObject, ModelClass, } from "@elizaos/core"; import { parseEther } from "viem"; /** * 自定义 Swap Action * 设计考量: * - validate 方法提前检查用户消息的意图:不是所有消息都触发交易,避免不必要的 LLM 推理 * - handler 使用 composeContext + generateObject:让 LLM 提取参数而非正则解析, * 因为用户的自然语言可能有多种表达方式 * - 交易签名不暴露私钥:使用 WalletProvider 的内置签名方法 */ export const customSwapAction: Action = { name: "SWAP_TOKENS", similes: ["SWAP", "EXCHANGE", "TRADE", "兑换", "交易", "交换"], description: "执行代币兑换操作", validate: async (runtime: IAgentRuntime, message: Memory): Promise<boolean> => { const text = message.content?.text?.toLowerCase() || ""; // 仅当消息中同时出现"兑换/swap"和数量信息时才触发 const hasSwapIntent = ["swap", "兑换", "exchange"].some((kw) => text.includes(kw)); const hasAmount = /\d+(\.\d+)?\s*(eth|usdc|usdt)/i.test(text); return hasSwapIntent && hasAmount; }, handler: async ( runtime: IAgentRuntime, message: Memory, state?: State, ): Promise<boolean> => { if (!state) { state = (await runtime.composeState(message)) as State; } else { state = await runtime.updateRecentMessageState(state); } // 使用 LLM 结构化提取兑换参数 const swapContext = composeContext({ state, template: `提取兑换参数: - tokenIn: 输入代币符号 - tokenOut: 输出代币符号 - amount: 数量(ETH 单位) 用户消息: {{recentMessages}}`, }); const extracted = await generateObject({ runtime, context: swapContext, modelClass: ModelClass.SMALL, schema: { type: "object", properties: { tokenIn: { type: "string" }, tokenOut: { type: "string" }, amount: { type: "string" }, }, required: ["tokenIn", "tokenOut", "amount"], }, }); if (!extracted?.object) { await runtime.messageManager.createMemory({ userId: message.userId, agentId: runtime.agentId, content: { text: "未能识别兑换参数,请提供:代币A、代币B、数量。" }, roomId: message.roomId, }); return false; } const { tokenIn, tokenOut, amount } = extracted.object; // 实际链上交互由 plugin-evm 的 WalletProvider 处理 // 此处调用 walletProvider 发送交易 ... return true; }, examples: [ [ { user: "{{user1}}", content: { text: "把 0.1 ETH 换成 USDC" }, }, { user: "SwapAgent", content: { text: "确认兑换:0.1 ETH → USDC,开始执行...", action: "SWAP_TOKENS", }, }, ], ], };3.2 Rig Agent 示例(Rust)
// rig-agent/src/agent.rs use rig::{ agent::Agent, completion::{Chat, CompletionModel}, providers::openai, tool::{Tool, ToolSet}, }; use solana_client::rpc_client::RpcClient; use solana_sdk::{ signature::{Keypair, Signer}, transaction::Transaction, pubkey::Pubkey, }; use std::sync::Arc; use tokio::sync::Mutex; /// Rig + Solana Agent /// 设计考量: /// - Agent 持有 Solana 的 RpcClient 和 Keypair:无需外部 Tool 桥接 /// - 使用 Arc<Mutex<>> 保护 signer:Rig 的多步推理可能并发,签名器必须线程安全 /// - Tool 实现 trait Tool:Rig 的工具绑定是编译期类型检查,误用会在编译阶段暴露 struct SwapParams { input_mint: Pubkey, output_mint: Pubkey, amount: u64, } struct SolanaSwapTool { client: Arc<RpcClient>, signer: Arc<Mutex<Keypair>>, } #[async_trait::async_trait] impl Tool for SolanaSwapTool { const NAME: &'static str = "solana_swap"; type Error = Box<dyn std::error::Error + Send + Sync>; type Args = SwapParams; type Output = String; async fn definition(&self, _prompt: String) -> rig::completion::ToolDefinition { rig::completion::ToolDefinition { name: Self::NAME.to_string(), description: "在 Solana DEX 上执行代币兑换".to_string(), parameters: serde_json::json!({ "type": "object", "properties": { "input_mint": {"type": "string", "description": "输入代币的 Mint 地址"}, "output_mint": {"type": "string", "description": "输出代币的 Mint 地址"}, "amount": {"type": "integer", "description": "兑换数量(最小单位)"}, }, "required": ["input_mint", "output_mint", "amount"] }), } } async fn call(&self, args: Self::Args) -> Result<Self::Output, Self::Error> { // 1. 构建兑换指令 let signer = self.signer.lock().await; // 2. 获取最新区块哈希 let recent_blockhash = self.client.get_latest_blockhash()?; // 3. 构建交易 // 实际生产中应使用 Jupiter API 或 Orca SDK 构建完整的 swap 指令 let tx = Transaction::new_signed_with_payer( &[], // instructions 由 DEX SDK 构建 Some(&signer.pubkey()), &[&*signer], recent_blockhash, ); // 4. 发送交易 let signature = self.client.send_and_confirm_transaction(&tx)?; Ok(format!("交易已确认: {}", signature)) } } /// 构建 Rig Agent pub async fn create_solana_agent( rpc_url: &str, keypair: Keypair, ) -> Result<Agent<openai::Client>, Box<dyn std::error::Error + Send + Sync>> { // 初始化 OpenAI 客户端 let llm_client = openai::Client::from_env(); // 初始化 Solana RPC let rpc_client = Arc::new(RpcClient::new(rpc_url.to_string())); // 构建工具集 let swap_tool = SolanaSwapTool { client: rpc_client, signer: Arc::new(Mutex::new(keypair)), }; let tools = ToolSet::new() .dynamic_tool(swap_tool); // 构建 Agent let agent = Agent::builder(llm_client) .tools(tools) .preamble( "你是一个 Solana 交易助手。在用户确认价格和滑点后再执行交易。\ 交易金额超过 5 SOL 时要求用户二次确认。" ) .temperature(0.3) .build(); Ok(agent) }3.3 LangChain Agent 对比实现
""" langchain_agent.py — LangChain DApp Agent 设计考量: - 钱包状态使用 ContextVar 传递:LangChain 的 Tool 调用是函数级作用域, 需要跨调用保持的钱包上下文必须通过 ContextVar 或自定义 Callback 传递 - 所有链上操作包装为 Tool:LangChain 不自带链上交互能力,每个链上操作都是自定义 Tool - 二次确认通过 agent_scratchpad 实现:让 Agent 在调用交易 Tool 前先输出确认信息 """ from contextvars import ContextVar from typing import Optional from langchain_openai import ChatOpenAI from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.tools import tool from web3 import Web3 # ContextVar 用于在多轮对话中保持钱包上下文 # LangChain 的 Tool 函数之间没有直接的状态共享机制,ContextVar 是 Python 的原生解决方案 wallet_var: ContextVar[Optional[dict]] = ContextVar("dapp_wallet", default=None) w3 = Web3(Web3.HTTPProvider("https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY")) @tool def connect_wallet() -> str: """连接用户钱包,获取地址和余额信息""" # 实际生产中用 WalletConnect 或 wagmi wallet_var.set({ "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0", "chain_id": 1, }) wallet = wallet_var.get() balance = w3.eth.get_balance(wallet["address"]) return f"已连接: {wallet['address']}, 余额: {w3.from_wei(balance, 'ether')} ETH" @tool def get_swap_quote(token_in: str, token_out: str, amount: float) -> str: """获取代币兑换报价(模拟 0x API)""" # 生产环境调用 0x API 或 1inch API return f"报价: {amount} {token_in} → {amount * 2500} {token_out},滑点 0.3%" @tool def execute_swap(token_in: str, token_out: str, amount: float, confirm: bool) -> str: """执行代币兑换。confirm 必须为 True 才会实际执行。""" if not confirm: return "未确认,取消交易。" wallet = wallet_var.get() if not wallet: return "错误: 未连接钱包。请先调用 connect_wallet。" # 构建交易(简化示例) # 生产环境:构建 ERC20 approve + swap 交易,估算 Gas,展示给用户 return f"交易已提交: 0x{Web3.keccak(text='mock_tx').hex()[:16]}..." # 构建 Agent prompt = ChatPromptTemplate.from_messages([ ("system", """你是 DApp 交易助手。规则: 1. 每次交易前先调用 get_swap_quote 查询报价 2. 将报价展示给用户后再调用 execute_swap 3. execute_swap 的 confirm 参数:用户明确说"确认"或"执行"时传 True"""), MessagesPlaceholder(variable_name="chat_history"), ("human", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]) llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.3) tools = [connect_wallet, get_swap_quote, execute_swap] agent = create_tool_calling_agent(llm, tools, prompt) executor = AgentExecutor( agent=agent, tools=tools, verbose=True, max_iterations=5, # 防止 Agent 在错误循环中无限重试 handle_parsing_errors=True, # LLM 输出解析失败时自动重试 ) # 使用示例 # result = executor.invoke({"input": "帮我用 0.1 ETH 换 USDC", "chat_history": []})四、边界分析与选型建议
Eliza 的适用边界:如果你的 Agent 需要频繁与链上合约交互(触发交易、订阅事件、管理多钱包),且团队主要是 TypeScript 开发者,Eliza 是综合投入产出比最高的选择。它的插件注册表模式让新增链上功能像安装 npm 包一样简单。但需要注意的是,Eliza 的插件质量认证体系尚不完善,引入第三方插件前需要审计其代码。
Rig 的适用边界:如果 Agent 只服务于 Solana 生态、对推理延迟有极端要求(毫秒级)、或者需要编译为 WASM 嵌入 Web Worker,Rig 是不二选择。Rust 的类型系统在编译期就消除了大部分运行时错误,这对资金敏感的 DApp Agent 来说是重要保障。但 Rust 团队组建和开发效率是现实成本。
LangChain 的适用边界:如果 Agent 的核心任务是自然语言理解和知识检索,链上交互只是偶尔为之,LangChain 的快速原型能力和丰富的 LLM 集成生态是优势。但长期维护中,钱包上下文管理的定制代码会成为技术债。
不适用场景:
- 需要 Agent 在用户离线时自主运行的场景:三个框架都需要运行 Agent 进程
- 100% 链上部署的 Agent:当前没有任何框架支持纯链上 Agent 推理(受限于 EVM/SVM 的计算模型)
- 需要跨多条链原子化操作的 Agent:三个框架都依赖外部桥接或中继器处理跨链操作
五、总结
| 维度 | Eliza (ai16z) | Rig (Arc) | LangChain |
|---|---|---|---|
| 语言 | TypeScript | Rust | Python / JS |
| 链上原生 | EVM + Solana (插件) | Solana 深度集成 | 无原生支持 (Tool 桥接) |
| 钱包管理 | 内置 Provider | 直接持有 Keypair | 手动 ContextVar |
| 插件生态 | 快速增长、质量参差 | 较新、相对精准 | 庞大、通用 |
| 适合场景 | 链上交互密集型 Agent | Solana 生态高性能 Agent | 分析/问答型 Agent |
| 开发门槛 | 中等 | 较高 | 较低 |
| 性能上限 | Node.js 运行时 | Rust 原生,接近硬件 | Python/JS 运行时 |
| 核心权衡 | 功能丰富 vs 稳定性 | 性能 vs 开发效率 | 原型速度 vs 链上深度 |
