别让 Data Agent 只会“给答案”:从 !assert 到 save,把分析变成可验证的生产数据资产

发布时间:2026/7/29 23:22:37
别让 Data Agent 只会“给答案”:从 !assert 到 save,把分析变成可验证的生产数据资产 大多数 Data Agent 的演示都停在同一个漂亮瞬间用户问了一个问题Agent 连上数据库写出 SQL返回一张表和几句结论。这当然有价值。但如果结果只存在于聊天记录里它还不是生产数据资产。下一次 BI 报表要用调度任务要用另一个 Agent 要接着分析团队往往还得把聊天里的逻辑重新翻译成 ETL、表结构和验证脚本。真正困难的从来不是“让模型给出一个答案”而是让这个答案满足四个条件可验证脏数据或错误口径不能悄悄越过边界可落地结果能写入明确的数据目标而不是只显示在对话框里可回读写入后的真实状态能被再次读取和核对可复用BI、调度任务和后续 Agent 能把它当成普通数据资产继续消费。过去几天我们在 Infinity SQL 测试环境里分别验证了两个关键环节!assert确定性质量门会在发现脏数据时抛错并停止后续语句save分析结果可以写入 MySQL 生产表形态再通过load回读验证。把它们放进同一套生产思路Data Agent 才从“回答问题的聊天工具”迈向“交付可验证数据资产的执行系统”。一条可信分析链路至少要闭环四次可以把理想的执行链路压缩成下面六个动作load → select → !assert → save → reload → verify 读取 计算 放行 写入 回读 核验其中有两条边界尤其重要!assert决定结果能不能影响外部世界reload verify决定外部世界是否真的变成了预期状态。模型负责提出计算步骤运行时负责执行确定性规则负责放行目标系统的回读结果负责验收。概率能力和确定性约束各司其职才是可审计的 Agent 工作流。第一关不要让概率系统用概率审计概率假设 Agent 收到四行订单事件其中一行user_id是空值setevents {id:1,user_id:u1,amount:120} {id:2,user_id:u2,amount:80} {id:3,user_id:null,amount:56} {id:4,user_id:u4,amount:230} ;loadjsonStr.eventsasevents_table;selectcount(*)asnull_usersfromevents_tablewhereuser_idisnullasnull_check;!assert null_check :null_users 0 user_id 存在空值阻断下游写入;selectquality gate passedasmessageasoutput;在测试环境中引擎返回java.lang.RuntimeException: user_id 存在空值阻断下游写入更重要的是后面的quality gate passed没有执行。这和让模型“再检查一次结果是否合理”有本质区别。后者仍然是一次概率判断!assert则把业务规则变成了运行时必须满足的确定条件。条件不成立管道就停止。!assert的设计还有一个很实用的特点它断言的是一张表。想验证什么先用select把证据算成一张小表再对表中字段做判断。Agent 不需要学习另一套测试语言它已经会的查询能力可以直接变成质量门行数必须大于零主键不能为空唯一键不能重复新旧口径必须对账金额波动不能超过业务阈值写回前的目标分区必须符合预期。因此质量验证不再是分析完成后的人工附注而是管道本身的一部分。第二关把质量门放在不可逆动作之前质量门最有价值的位置不是在所有探索之前而是在每个不可逆动作之前自由探索区 外部影响区 load → 清洗 → 聚合 → 口径对账 → !assert → save / 发报告 / 触发下游在自由探索区里Agent 可以尝试不同查询、修正语法、比较多种解释。错误的成本很低。一旦要写库、发报告或触发下游任务风险就完全不同。此时应该由确定性规则决定能否跨过边界而不是由模型用一句“看起来没问题”自我批准。这和软件工程中的 CI 很像开发者可以自由修改代码测试不通过代码不能合并Data Agent 可以自由探索质量门不通过结果不能写入生产目标。关键不在于让 Agent 永远不犯错而在于让错误无法悄悄扩大影响范围。第三关save让探索结果直接成为表质量门通过之后分析结果还需要一个明确的生产出口。我们在另一个独立测试中让同一条 InfiniSQL 管道读取 MySQL 订单、计算区域报表、写回region_report_daily再回读验证loadjdbc.biz_mysql.ordersasorders;selectregion,count(*)asorder_cnt,sum(amount)asgmvfromorderswherestatuspaidgroupbyregionasregion_report;saveoverwrite region_reportasjdbc.biz_mysql.region_report_daily;loadjdbc.biz_mysql.region_report_dailyasverify_report;select*fromverify_reportorderbygmvdescasoutput;测试环境的真实回读结果是区域已支付订单数GMV华东8274,600华北214,000华南112,000西南27,200这里最值得关注的不是少写了一段 ETL而是分析与交付没有发生语言切换读取数据用load计算口径用select ... as写入目标用save验收结果仍然用load和select。探索阶段确认过的逻辑不需要再被另一套框架、另一种语言或另一个团队手工翻译。少一次翻译就少一类口径漂移。第四关为什么写完还必须回读很多自动化流程把“写入命令没有报错”当成成功但对生产系统来说这个证据还不够。写入动作返回成功只能说明请求完成回读才能回答更关键的问题目标表是否真的存在字段和值是否符合预期行数是否正确覆盖写是否只影响了预定目标下一个消费者能否用标准读取方式获得结果因此reload不是多余的重复而是一次状态确认。一个更稳妥的生产模板应该是计算候选结果 ↓ 写前断言数据质量、口径、目标范围 ↓ save执行明确写入语义 ↓ load从目标系统重新读取 ↓ 写后断言行数、关键指标、幂等键、分区范围 ↓ 交付给 BI、调度任务或后续 Agent写前断言约束“准备写什么”写后断言验证“实际写成了什么”。两者解决的是不同问题。save的四种语义其实是四种风险选择save支持四种明确模式模式语义适合场景主要风险overwrite覆盖目标全量刷新报表错误目标会造成覆盖append追加数据增量流水、事件日志重跑可能重复ignore目标存在时跳过幂等初始化可能保留旧状态errorIfExists目标存在时报错防止误覆盖需要显式处理冲突这张表说明save不是一个模糊的“帮我存一下”。每次写入都必须声明语义也就是主动选择风险模型。对 Agent 来说默认策略应该更保守未确认目标时优先errorIfExists使用overwrite前先断言目标名称、分区和关键指标使用append时必须设计业务唯一键或幂等规则写入完成后必须回读并核验高风险目标还需要权限、审计和人工审批。语言可以提供确定性原语但不能替团队替代所有生产治理。从一次回答到一个可持续消费的资产当链路闭合之后同一份结果会获得完全不同的生命周期。如果它只在聊天记录里用户离开页面后很难复用口径与来源不容易追踪下一个 Agent 需要重新理解上下文BI 和调度系统无法直接消费失败后很难判断执行到了哪一步。如果它通过质量门写入表并完成回读验证表名成为稳定引用口径可以和管道一起审计BI 可以直接读取调度任务可以按周期刷新后续 Agent 可以从这张表继续分析失败可以定位在读取、计算、放行、写入或回读中的具体阶段。这才是“分析结果成为资产”的准确含义不是把答案存成一段文本而是把它变成一个有名字、有结构、有验证证据、能被其他系统继续消费的数据对象。InfiniSynapse 真正需要提供的不只是聊天体验用户仍然可以用自然语言提问。自然语言入口没有问题问题在于底层执行不能只依赖自然语言。一个可信的产品层应该把用户意图逐步落到可检查的执行对象用户目标 → Agent 生成 InfiniSQL 管道 → 运行时执行并保留中间结果 → 确定性质量门决定是否放行 → 明确写入语义落到目标系统 → 回读与断言生成验收证据 → 结果进入 BI、调度或下一轮 Agent在这个结构里大模型负责理解模糊目标、生成候选步骤和解释结果InfiniSQL 负责把数据操作、状态、验证与交付收束到同一套执行语言中。这比单纯追求“Agent 一次回答得更聪明”更接近企业真实需求。企业需要的不是一句自信的回答而是一条能够追溯、复跑、阻断和验收的链路。必须讲清楚的事实边界这篇文章组合了两个分别完成的测试不应把它们夸大成一次端到端生产验收!assert测试验证的是带空值的数据会触发运行时错误后续语句停止该脚本没有连接真实目标库执行写入。save测试验证的是区域报表写入 MySQLregion_report_daily后可以被load回读并返回上述四个区域的结果。当前证据没有证明生产 SLA、并发吞吐、事务回滚、权限模型或故障恢复时间。在真实生产环境中还需要补充访问控制、凭据隔离、审计日志、目标白名单、幂等策略、事务边界、监控告警和人工审批。诚实地保留这些边界不会削弱方案反而说明这是一套可以继续工程化验证的架构而不是一段营销魔法。结语不要只问 Agent“答案是什么”更好的问题是这个答案基于哪份数据哪些规则决定它可以被交付它写到了哪里写入后是否被重新读取和核验下一个系统或 Agent 如何继续消费如果失败我们能否知道停在了哪一步当load → select → !assert → save → reload → verify成为一条完整链路Data Agent 才不只是会给答案。它开始具备交付数据资产的能力。本文中的!assert拦截与save写回/回读数据均来自 Infinity SQL 测试环境的真实执行结果。InfiniSQL 是 InfiniSynapse 数据分析 Agent 的底座引擎。