AI Data Agent架构选型:Agent Runtime+Plugin与Framework的深度对比 1. 从一次真实的技术选型纠结说起去年下半年我接手了一个 AI Data Agent 项目目标很明确让业务同学用自然语言问数系统自动完成取数、清洗、分析、出图、写结论这一整条链路。听起来是个典型的“LLM 套壳 BI”活儿但真动手才发现第一个卡住我的不是模型效果而是架构选型——到底该走“通用 Agent Runtime Plugin”这条路还是直接上一个“Agent Framework”这个问题在社区里吵得很凶。有人觉得 Runtime Plugin 才是终局因为 Runtime 负责调度、状态、沙箱、工具协议Plugin 负责具体能力边界清晰、可插拔、可复用也有人觉得 Framework 更省事编排、记忆、工具调用、多智能体协作全都给你封装好了拿来就能跑。两边说的都对但都对得很笼统。真正落到 AI Data Agent 这种“重工具、重数据、重状态”的场景里选错的代价是实打实的要么被框架的抽象绑死改一个取数逻辑要翻三层源码要么自己造 Runtime 造到一半发现沙箱、并发、可观测性全是坑工期直接失控。所以这篇不打算给你一个“标准答案”而是把我踩过的路、算过的账、做过的对比摊开讲。核心关键词就几个Agent、Runtime、Plugin、Framework、AI Data Agent。如果你正在做 Agent 开发尤其是数据类、工具类、需要长期维护的 Agent 项目这篇应该能帮你少走至少两周弯路。我会先讲清楚这两条路线到底在争什么再拆解 AI Data Agent 的真实需求然后给出选型判断框架、实操落地细节、以及我踩过的坑和排查表。全程说人话能抄作业的地方直接给配置和代码。2. 先把概念掰开Runtime、Plugin、Framework 到底各管什么2.1 三个词被混用得最厉害的地方很多人一上来就争论“Runtime 好还是 Framework 好”其实这俩根本不在一个维度上。我用一个生活化的类比Runtime 像是操作系统Plugin 像是装在上面的 AppFramework 像是给你一套精装修的房子加物业管理。操作系统管进程调度、内存、权限、设备驱动App 只管自己的业务逻辑而精装修房子是开发商把水电、家具、物业都配好了你拎包入住但想砸墙改结构就得看合同。对应到 Agent 领域Agent Runtime负责 Agent 的“运行时环境”。它管的是执行循环loop、状态管理state、工具调用的分发与协议、沙箱隔离、并发控制、超时重试、日志与追踪。它不关心你具体是查数据库还是发邮件它只保证“你交给它的任务能被安全、可观测、可恢复地执行”。Plugin具体能力的封装单元。一个 Plugin 就是一个或一组工具tool有明确的输入输出 schema、权限声明、错误语义。比如sql_query、python_exec、chart_render各是一个 Plugin。Agent Framework一套更高层的开发框架通常自带编排引擎orchestration、记忆模块、多 Agent 协作、Prompt 管理、工具注册、甚至内置 Runtime。它试图把“从零到能跑”的路径缩到最短。关键区别在于Runtime Plugin 是“能力解耦”的思路Framework 是“能力打包”的思路。前者你拥有每一层的控制权后者你用控制权换开发速度。2.2 为什么这个区分对 AI Data Agent 特别重要AI Data Agent 和那种“聊天 查天气”的玩具 Agent 有本质区别。它的特点是工具重SQL 引擎、Python 沙箱、数据仓库连接器、图表库每一个都是重依赖启动慢、资源占用高。状态长一次分析任务可能跨十几轮工具调用中间结果DataFrame、临时表、中间图需要被保存和复用。数据敏感涉及真实业务数据权限、脱敏、审计是硬要求不能靠框架的“默认行为”。可复现要求高业务同学会问“这个数怎么算出来的”你得能回放整条执行链路。这四点决定了在 AI Data Agent 场景里Runtime 层的能力状态、沙箱、可观测、权限不是加分项而是及格线。Framework 如果把这些封装得太深你反而要花大力气去“撬开”它。2.3 一张表看清两条路线的能力归属能力维度Runtime Plugin 路线Framework 路线执行循环Runtime 提供可定制框架内置通常可配置但难改工具协议自定义或遵循开放协议框架私有协议为主状态管理自己设计灵活框架托管受抽象限制沙箱隔离自己接容器/子进程部分框架内置能力参差多 Agent 协作需自己实现或引入编排层多数框架原生支持上手速度慢前期投入大快demo 当天能跑长期维护可控边界清晰受框架版本与抽象影响可观测性自己埋点最贴合需求框架自带但可能不够细这张表不是让你选“好”的而是让你看清你愿意在哪一栏付出成本。选型本质是成本转移不是成本消除。3. AI Data Agent 的真实需求拆解别被 demo 骗了3.1 一个问数任务到底经历了什么我拿一个真实需求举例“帮我看看上个月华东区销售额环比下降的原因拆到品类和渠道。”这句话在 demo 里Agent 三步就出结果了。但在生产里它实际经历的是意图解析与任务规划拆成“取数 → 计算环比 → 维度下钻 → 归因 → 出图 → 写结论”。Schema 检索从几百张表里找到销售事实表、品类维表、渠道维表还要理解字段含义。SQL 生成与校验生成 SQL做语法校验、权限校验、成本预估防止全表扫描。执行与容错执行失败要能读懂报错、修正 SQL、重试。中间结果管理把结果存成 DataFrame 或临时表供后续步骤复用。计算与归因跑环比、做贡献度拆解这一步往往要写 Python。可视化与叙述出图、生成结论还要保证结论和数字一致。这七步里只有第 1 步和第 7 步是“LLM 原生”的中间五步全是工程问题。这就是为什么我说 AI Data Agent 的胜负手在 Runtime 层而不在 Prompt 层。3.2 需求优先级排序哪些是刚需哪些是锦上添花我把需求按“没有它项目就废”和“有了更好”分了两档刚需及格线工具调用的可靠分发与超时控制SQL 跑 30 秒没返回得能中断并降级。状态持久化任务中断后能恢复中间结果不丢。权限与审计谁能查哪些表每次查询留痕。可观测每一步的输入输出、耗时、token 消耗都能查。加分项决定体验上限多 Agent 协作比如一个负责取数、一个负责分析。自动重试与自我修正。记忆机制记住用户偏好、常用口径。可视化编排界面。看清这个排序选型就有了锚点Framework 通常在加分项上很强在刚需上“能用但不够细”Runtime Plugin 在刚需上可以做到极致但加分项要自己补。3.3 为什么“先用 Framework 快速验证”是个陷阱我见过太多团队的做法先用某个 Framework 两周搭出 demo老板很满意然后进入生产化阶段发现权限、审计、状态恢复全要改而框架的抽象层让每次改动都像在别人家承重墙上打洞。最后要么忍受框架的限制要么推倒重来。我的建议是验证阶段可以用 Framework但要在第一周就做一次“逃生演练”——试着把框架的编排层替换掉看你的业务逻辑是否和框架强耦合。如果发现业务代码里到处是框架特有的装饰器、状态对象、回调签名那就要警惕了。这个演练花不了两天但能帮你避免三个月的返工。4. 选型判断框架五个问题帮你定方向4.1 问题一你的工具是“标准件”还是“定制件”如果你的 Agent 主要调用的是标准 API搜索、天气、日历、通用数据库那 Framework 内置的工具生态能省你大量时间。但 AI Data Agent 的工具几乎全是定制件公司内部的数仓、特定的指标口径、自研的图表规范。定制件越多Framework 的通用抽象越帮不上忙反而增加理解成本。判断标准很简单数一数你的工具里有多少能直接用现成的有多少必须自己写。如果自研比例超过 60%Runtime Plugin 的边际收益会明显上升。4.2 问题二状态复杂度有多高单轮问答的 Agent状态就是对话历史Framework 托管完全够用。但 AI Data Agent 的状态是结构化、多类型、跨轮次的有对话历史、有中间 DataFrame、有临时表引用、有执行计划树。这种状态用框架的通用 memory 抽象去装要么装不下要么装得别扭。我实测过一个主流 Framework 的 memory 模块它默认把状态序列化成文本存进向量库。对于“记住用户喜欢看柱状图”这种偏好没问题但对于“记住上一步生成的临时表名和它的 schema”文本序列化会丢失结构恢复时还得重新解析。状态越结构化越应该自己管。4.3 问题三可观测性和审计要求有多硬金融、医疗、政企类项目审计是硬指标。你需要知道这次查询是谁发起的、用了哪个工具、传了什么参数、返回了什么、耗时多少、消耗多少 token。Framework 通常提供日志但日志的粒度和格式未必符合你的审计规范。Runtime Plugin 的优势在这里体现得最明显因为工具分发是你自己写的你可以在分发层统一埋点一次埋点覆盖所有工具。而 Framework 里不同工具的埋点方式可能不统一你得逐个适配。4.4 问题四团队的技术栈和运维能力这条最现实。Runtime Plugin 意味着你要自己维护执行引擎、沙箱、状态存储、并发控制。如果团队里没有熟悉容器、消息队列、分布式状态的工程师自己造 Runtime 会非常痛苦。反过来如果团队本来就是做平台工程的那自研 Runtime 反而是舒适区。我的经验是Runtime Plugin 适合“有平台工程能力、且业务长期演进”的团队Framework 适合“业务优先、快速迭代、团队偏应用层”的团队。没有对错只有匹配。4.5 问题五你打算维护这个项目多久这是个被严重低估的问题。Framework 的版本迭代很快今天好用的 API 明天可能就 deprecated。如果你的项目生命周期是半年跟着框架走没问题如果是三年以上框架升级带来的迁移成本会累积成一座山。Runtime Plugin 的接口是你自己定的只要协议稳定底层换实现比如从子进程沙箱换成容器沙箱不影响上层业务。长期项目接口的稳定性比实现的速度更重要。5. 实操落地Runtime Plugin 路线怎么搭5.1 整体架构分层我最终选的是 Runtime Plugin架构分四层接入层接收自然语言请求做鉴权和会话管理。编排层任务规划、步骤拆解、循环控制。这一层可以用轻量框架也可以自己写状态机。Runtime 层工具分发、沙箱执行、状态持久化、超时重试、埋点。Plugin 层SQL 查询、Python 执行、图表渲染、Schema 检索等具体能力。关键设计原则编排层不直接调用 Plugin必须经过 Runtime 层。这样所有工具调用都走统一通道埋点、权限、超时、重试都在一处实现。5.2 工具协议设计让 Plugin 可插拔Plugin 的核心是协议。我定义了一个简单的工具描述结构每个 Plugin 注册时提供{ name: sql_query, description: 在指定数据源上执行只读 SQL返回结果集, parameters: { type: object, properties: { datasource: {type: string}, sql: {type: string}, limit: {type: integer, default: 1000} }, required: [datasource, sql] }, permissions: [read:sales, read:dimension], timeout_seconds: 60, sandbox: readonly_db }这个结构有几个设计考量description 要写给 LLM 看措辞直接影响模型选工具的准确率我后面会讲怎么写。permissions 显式声明Runtime 在分发前校验不依赖 Plugin 自觉。timeout 和 sandbox 在协议层这样 Runtime 能统一执行Plugin 不用各自实现。提示工具协议一旦定下来尽量只增不改。改字段名会让所有已注册的 Plugin 失效迁移成本极高。5.3 Runtime 执行循环的关键实现Runtime 的核心是一个执行循环伪代码大致如下def run_agent_loop(task, max_steps20): state load_or_init_state(task.id) for step in range(max_steps): plan planner.next_action(state) if plan.is_final: return plan.answer tool registry.get(plan.tool_name) check_permission(tool, task.user) try: result execute_in_sandbox( tool, plan.args, timeouttool.timeout_seconds ) except TimeoutError: result handle_timeout(tool, plan, state) except ToolError as e: result handle_tool_error(e, state) state.append_step(plan, result) persist_state(state) return fallback_answer(state)这里面有几个容易忽略的点max_steps 必须有防止 Agent 陷入死循环烧 token。我设的是 20数据类任务一般 8 到 12 步就够。persist_state 每步都存不要等循环结束才存否则中断就全丢。错误处理要分类超时、工具报错、权限拒绝处理策略完全不同。超时可以降级工具报错可以让模型自我修正权限拒绝必须直接终止。5.4 沙箱选型子进程、容器还是远程执行沙箱是 Runtime 里最容易被低估的部分。我试过三种方案方案隔离性启动速度运维成本适用场景子进程弱快低内部可信代码容器强中中执行用户代码远程执行服务强慢高多租户、强隔离AI Data Agent 里SQL 查询走的是数据库自身的权限体系不需要额外沙箱但 Python 执行做计算和归因必须隔离因为模型生成的代码不可信。我最终选了容器方案每个 Python 执行任务起一个短生命周期容器挂载只读数据卷限制 CPU 和内存。注意容器启动有 1 到 3 秒开销如果一次任务要跑十几次 Python累积起来很可观。我的优化是维护一个预热容器池用完不销毁重置状态后复用。5.5 状态存储的 schema 设计状态存储我用了关系库加对象存储的组合结构化状态步骤、工具名、参数、状态码进关系库大对象DataFrame、图片进对象存储关系库里只存引用。CREATE TABLE agent_step ( task_id VARCHAR(64), step_index INT, tool_name VARCHAR(64), args_json TEXT, result_ref VARCHAR(256), status VARCHAR(16), duration_ms INT, token_used INT, created_at TIMESTAMP, PRIMARY KEY (task_id, step_index) );这样设计的好处是回放一条执行链路只需要按 task_id 查一次大对象按需加载不会把关系库撑爆。token_used 字段一定要留后面做成本分析全靠它。6. 实操落地Framework 路线怎么用才不翻车6.1 什么情况下我会推荐 Framework不是所有项目都值得自研 Runtime。如果满足以下条件我会直接推荐 Framework工具以标准 API 为主自研比例低于 30%。状态简单主要是对话历史。项目周期短三个月内要上线。团队没有平台工程背景。这种情况下自研 Runtime 是过度设计Framework 能让你把精力放在业务逻辑上。6.2 用 Framework 时的隔离设计即使用 Framework我也会做一层隔离在业务代码和 Framework 之间加一个适配层。业务逻辑只依赖自己定义的接口Framework 的调用被封装在适配层里。这样将来换框架只需要重写适配层。class AgentPort: def plan(self, task): ... def call_tool(self, name, args): ... def get_state(self, task_id): ... class FrameworkAdapter(AgentPort): def __init__(self, framework_agent): self._agent framework_agent def call_tool(self, name, args): return self._agent.invoke_tool(name, args)这层适配看起来多此一举但当你发现框架某个行为不符合预期、需要替换时你会感谢自己当初多写的这几十行。6.3 Framework 的常见坑与规避我用过的几个 Framework坑集中在几处隐式状态框架把状态藏在内部对象里你想导出做审计时发现拿不到。规避方法是定期主动 dump 状态。工具调用不可中断框架发起工具调用后超时控制不灵活。规避方法是在工具内部自己加超时。版本升级破坏兼容小版本升级改了回调签名。规避方法是锁死版本升级前先在测试环境跑全量回归。Prompt 被框架接管框架自动拼接 system prompt你想加业务约束时发现位置不对。规避方法是找到框架的 prompt 组装入口做后置注入。提示选 Framework 前先花半天读它的源码里“工具调用”和“状态管理”两个模块。如果这两个模块你看不懂或改不动就要慎重。7. 混合路线我最终的实际选择7.1 为什么纯路线都不完美纯 Runtime Plugin 的问题是编排层要自己写任务规划、循环控制、错误恢复这些逻辑重复造轮子。纯 Framework 的问题是 Runtime 层能力不够细审计和状态管理受制。所以我最终走的是混合路线编排层用轻量 FrameworkRuntime 层和 Plugin 层自研。Framework 只负责“下一步做什么”的决策一旦决策出要调用工具就交给自研 Runtime 执行。这样既省了编排的重复劳动又保住了 Runtime 层的控制权。7.2 混合路线的接口边界混合路线的关键是划清边界。我的划分是Framework 负责任务规划、步骤生成、结果汇总、最终叙述。自研 Runtime 负责工具分发、沙箱、状态持久化、权限、埋点、超时重试。Plugin 负责具体能力实现。Framework 和 Runtime 之间只通过一个窄接口通信Framework 输出“要调用哪个工具、传什么参数”Runtime 返回“执行结果或错误”。这个接口足够窄将来换 Framework 不影响 Runtime。7.3 混合路线的成本账我算过一笔账纯自研编排层大概要多花 3 到 4 周纯用 Framework 到生产级大概要多花 4 到 6 周去补 Runtime 能力。混合路线前期多花 1 周做接口设计但整体省下 2 到 3 周。这个账的前提是团队有 Runtime 开发能力否则混合路线会变成两头不讨好。8. 常见问题与排查技巧实录8.1 工具选错、参数传错怎么排查Agent 最常见的故障是“选错工具”或“参数格式不对”。我的排查顺序是看工具 description 是否清晰。模型选错工具八成是 description 写得含糊。看参数 schema 是否严格。如果 schema 里类型是 string 但实际要传对象模型会瞎猜。看上下文里是否有干扰信息。历史步骤里的旧参数可能被模型误用。我踩过最坑的一次两个工具 description 都写了“查询数据”模型随机选。后来把其中一个改成“查询实时指标毫秒级仅支持单指标”另一个改成“查询历史明细支持多维度聚合秒级返回”选错率立刻降下来。description 要写清楚“什么时候用我、什么时候别用我”。8.2 状态丢失与恢复失败状态恢复失败通常有三个原因持久化时机不对、序列化丢结构、引用失效。我的排查表现象可能原因排查方法恢复后步骤缺失持久化在循环末尾检查 persist 调用位置恢复后 DataFrame 为空对象存储引用过期检查引用 TTL 配置恢复后参数类型变了JSON 序列化丢类型检查序列化方案恢复后权限报错会话上下文未恢复检查用户上下文持久化注意状态里如果有时间戳、随机种子这类值恢复时要特别小心否则复现结果会不一致。8.3 超时与重试的边界超时处理最容易犯的错是“无脑重试”。SQL 超时重试可能让数据库压力翻倍。我的策略是分类幂等只读操作查询、检索可以重试最多 2 次指数退避。非幂等操作写入、发消息不自动重试转人工确认。模型调用超时可以重试但要换更短的 prompt 或降级模型。8.4 成本失控的排查Agent 烧钱主要烧在 token 和工具调用上。我见过一次任务跑了 40 步、消耗 20 万 token 的案例原因是模型在“SQL 报错 → 改 SQL → 再报错”里循环。排查方法是看步骤序列里是否有重复模式如果有说明缺少“连续失败 N 次就终止”的保护。我后来加了规则同一工具连续失败 3 次强制终止并返回中间结果。9. 我踩过的坑和几条硬经验第一条硬经验别在选型上追求“最优解”追求“可替换”。无论选哪条路线都要保证核心业务逻辑不依赖具体实现。我现在的项目里换掉编排框架只需要改一个适配类换掉沙箱方案只需要改一个执行器。这种可替换性比选对路线更重要因为需求会变路线也会变。第二条Runtime 层的埋点要第一天就做。我一开始觉得埋点可以后补结果上线后排查问题全靠猜。后来补埋点发现很多历史调用已经没法追溯了。埋点不是可观测性的锦上添花是排障的地基。第三条工具 description 是 Prompt 工程的一部分值得反复打磨。我花了整整两天专门优化工具描述把选错率从 15% 降到 3%。这两天比调模型参数值多了。第四条给 Agent 设“止损线”。max_steps、单任务 token 上限、单工具连续失败次数这三个阈值必须有。没有止损线的 Agent 在生产环境就是定时炸弹。最后分享一个我常用的小技巧在 Runtime 里加一个“干跑模式”只做规划和工具选择不真正执行工具。这样可以在不消耗资源的情况下快速验证 Agent 的决策质量特别适合在改 Prompt 或加新工具后做回归测试。这个模式帮我省了大量的调试时间也避免了在测试环境误操作真实数据。