DuckDB CLI 加了 agent 模式,AI 读结果 token 省 59%
你让 Claude Code 或者 Cursor 去查数据,它十有八九是起个 shell 跑 duckdb -c "...",把 stdout 整个吞回去当上下文。DuckDB 官方留意到了这件事:现在 CLI 里跑的命令,相当一部分根本不是人敲的,是 AI 敲的。读者变了,输出格式却还是给坐终端的人看的。
10 月 9 日官方博客发了新特性:agent 模式,随 v2.0 CLI 发布。一句话说清它干了什么:agent 模式最大的价值不是省 token,是让 AI 不再把半截结果当完整答案。
写稿时 v2.0 还没正式发(正式版最新是 9 月 28 日的 v1.5.6),我拉了 main 分支的 nightly(v2.0.0-alpha46057,10 月 9 日构建)把每个特性都跑了一遍,下面的输出全是我本机实测。
● ● ●
DuckDB 默认给人看的输出长这样:框线、对齐填充、列名下面一行类型。
对人是好事,对模型是坏事。博客里算过一笔账:对齐用的空格没有任何信息量,但模型要按 token 付钱。更坑的是大结果的显示方式——默认只显示前 20 行和后 20 行,中间一行省略号。人看见 (40 shown) 就知道有埋伏,模型很容易扫过去,拿着 40 行数据当全量数据下结论。
还有一种死法:查询要跑很久,agent 干等着,超时或者烧钱。以及报错——给人看的错误信息是排版好的文本,模型只能拿正则去猜。
● ● ●
agent 模式改了什么
先说触发方式。CLI 启动时检查三件事:环境变量里有没有 agent 痕迹(Claude Code 会设 CLAUDECODE,Codex 设 CODEX_CI,Cursor 设 CURSOR_AGENT,Gemini CLI、Copilot 都有自己的变量)、stdout 是不是管道、命令行有没有指定输出格式。三条全中,agent 模式自动开。也可以用 -agent / -no-agent 强制开关。
我在测试机上装好 nightly 之后跑 --version,输出前面多了一行——这个 cron 环境里恰好设着 CLAUDECODE,agent 模式自己醒了:
duckdb agent mode on: CLAUDECODE is set and stdout is not a terminal;
-no-agent turns it off, .help agent explains the output
开了之后,同一个查询的输出从框线表格变成紧凑 Markdown 表,类型直接写进表头:
| name:VARCHAR | n:INTEGER | total:INTEGER |
|---|---|---|
| customer_0 | 3 | 777 |
拿 10 行 4 列的结果实测,老格式 1080 字节,agent 模式 452 字节,省 58%。换成 8 列的宽表,2122 字节降到 625 字节,省 71%。列越宽省得越多。
box 输出 vs agent 输出对比
● ● ●
截断会明说,结果带指纹
agent 模式下,1000 行以内、10000 字节以内的结果全量打印;超了的,前 20 行加后 20 行,中间插一行显式标记,页脚写清楚发生了什么:
| … 4960 rows omitted … |
first 20 and last 20 of 5000 rows (.maxbytes 0 for all), hash 6a1df30bfd3851e3
页脚那个 hash 是整个结果集的指纹,跟行序无关。我验证过:同一份数据正序和倒序各查一遍,hash 完全相同(都是 142834df7ce17104)。AI 想确认改了查询之后结果有没有变,比一次 hash 就行,不用把结果打两遍。
更狠的是提前停。FROM range(1_000_000_000) 这种查询,agent 模式下 30 毫秒就返回(我实测 0.030s)——打印满额之后剩下的行只计数不打印,再多数 10 万行就直接停掉查询,页脚明说"至少 102400 行,查询提前停了"。博客原文那句设计意图很直白:agent 不能要求"再给我看更多",所以要么给它看全,要么明确告诉它没看全。
错误也换了形态,从 stderr 的排版文本变成结构化 JSON,模型不用再正则猜:
{"exception_type":"Catalog","exception_message":"Table with name nosuchtable does not exist!\nDid you mean \"duckdb_tables\"?","error_subtype":"MISSING_ENTRY","position":"14"}长查询还有两道保险:预估要读 100 万行以上的,执行前 stderr 先报一行预估量(estimate: ~2000000 rows read),agent 可以掂量一下要不要跑;跑的过程中每 5 秒报一次进度,不再是无尽的沉默。另外 EXPLAIN 换成一行一个算子的紧凑格式,.tables 一张表一行连列定义一起给全。
● ● ●
官方让 Claude 自己测了自己
博客里最有意思的实验是让 Claude 当被试:TPC-H 22 道题,SF100 数据量,自然语言出题不带 SQL,agent 模式和 -no-agent 各跑三遍。132 次运行全部答对,模型读回来的输出从 123.6k token 降到 50.8k,省 59%。
但博客没有把丑话藏起来:总成本几乎没降,因为每轮对话都要重读 agent 的系统提示词,那玩意比查询输出大得多,省下的 token 只占总输入的 0.5% 左右;轮次反而多了几轮(237 对 224)。所以这个特性的卖点确实不是省钱,是把 AI 从"看着半截数据自信作答"的坑里捞出来——省 token 是顺带的。
● ● ●
什么时候能用
等 v2.0 正式发布,你什么都不用配。Claude Code、Codex、Cursor、Gemini CLI、Copilot 本来就会设那些环境变量,命令也是走管道执行的,两个条件天然满足。唯一的例外:如果你在命令里显式传了 -csv、-json 这类格式参数,CLI 认为你是故意选的格式,agent 模式就不掺和。
现在就想试的话,装个 nightly(curl https://install.duckdb.org | bash 会装 alpha 版),跑一句 duckdb -agent -c "SELECT 1" | cat 就能看到 AI 视角的输出。
第一版行为官方自己也说是尝试,agent 识别不全或者输出看不懂的,欢迎去仓库提 issue——尤其欢迎附上"AI 被搞糊涂的对话记录"。
回到开头那个场景:以后你让 AI 查库,它拿到的不再是画着框线的半截表格,而是带截断声明、带结果指纹、错误能直接解析的输出。数据库厂商开始把 AI 当一等公民设计 CLI,这一步比省那点 token 重要得多——工具适配读它的人,从来都是效率提升的开始。
你平时让 AI 帮你查数据吗?投个票:A. 天天用,早离不开;B. 偶尔用,总觉得它答得心虚;C. 不敢用,就怕它看漏数据瞎说。评论区聊聊你的用法。
● ● ●
参考来源
- 01
Agent Mode in the DuckDB CLI(官方博客,2026-10-09)https://duckdb.org/2026/10/09/agent-mode.html - 02
PR #26167: Shell: agent mode https://github.com/duckdb/duckdb/pull/26167 - 03
DuckDB v2.0 alpha 安装入口 https://install.duckdb.org