一个 AI agent 收到任务:"把上季度的数据发给财务"。它知道要发邮件,但不知道具体哪份数据、什么格式、发给谁。这些信息全在一小时的会议录音里,散落在几百句对话中间。
全塞进去?token 炸了,agent 还容易被无关信息带偏。不给?它只能发一封套话邮件。
这个两难困扰了我一段时间。今天终于想到一个还算优雅的解法——然后意识到,当天做的另外两件完全不相关的事,踩的居然是同一个坑。
会议 transcript 的困境
我在做的这个系统,核心流程是:会议录音 → 提取待办 → AI agent 自动执行。比如会上说"小王你把上季度数据整理一下发给财务的李姐",系统提取出一条 todo,agent 去找数据、写邮件、发出去。
问题出在 agent 拿到的信息量上。
最早的方案很朴素:提取 todo 的时候标记关联的 segment ID,执行时把前后各 3 条记录注入 prompt。大概 7 句话的窗口。对于简单任务够用了——"帮我订周五的会议室",不需要太多背景。
但真实会议讨论是跳跃的。第 10 句提了个预算问题,中间聊了 40 句完全不相关的排期,第 50 句又绕回来说"刚才那个预算,我觉得砍到 80 万吧"。一个连续窗口永远捕捉不到这种跳跃结构。
那开大窗口?±20 条?试过。300 条 transcript 塞进去 60 条,首先 token 成本上去了,其次 agent 表现反而变差。一堆无关的排期讨论夹在中间,agent 开始把排期信息混进预算邮件里。信息过载跟信息不足一样有害。
我也想过让 todo 提取的时候就标记完整的讨论链——不只是结论那句话,把所有相关 segment 都标上。但 transcript 本身就很长,让 LLM 同时做提取和全文关联标记,任务负担太重了。它现在标几个关键句已经不错了,再加一层全文扫描,准确率反而可能下降。
Browse/Fetch:给 agent 一本目录
最后的方案受了个很日常的启发:人翻一本不熟悉的书,也不是从头读到尾。先看目录,找到可能相关的章节,再跳过去精读。
落地成了一个两步的工具调用:
# 第一步:browse — 稀疏概览
get_transcript_context(action: "browse")
# 每 10 句取首句,带位置索引
# 300 条 transcript → 30 条索引,成本极低
# 第二步:fetch — 按需精读
get_transcript_context(action: "fetch", start: 45, end: 55)
# agent 自己判断要看哪一段
browse 给 agent 的是一张地图。它扫一眼就大概知道:segment 10-20 在聊预算,40-60 在讨论排期,120-130 在分配任务。然后根据自己的任务需要,fetch 相关的片段。
设计上有几个考量。
browse 的粒度选了每 10 句取 1 句。太密(每 3 句取 1)跟直接塞 transcript 差不多;太稀(每 30 句取 1)容易漏掉短讨论。10 句是个经验值,一般刚好覆盖一个话题的开头。
fetch 的范围让 agent 自己定。不设固定窗口,agent 可以 fetch 5 句也可以 fetch 20 句。实测下来 agent 挺克制的,平均每次 fetch 8-12 条,很少超过 15。
整个设计的关键转变是:从"猜 agent 需要什么上下文"变成"让 agent 自己获取上下文"。agent 成了主动的信息消费者。之前那种 auto-inject 方案,本质上是系统在替 agent 做判断——"你大概需要这 7 句话"。但系统怎么知道?它不了解 agent 当前的任务细节,也不了解 agent 已经掌握了哪些信息。
实测效果:agent 平均多 1-2 次工具调用(一次 browse + 偶尔一次 fetch),但执行质量上了一个台阶。之前经常出现的"套话邮件"问题基本消失了,因为 agent 真正看到了讨论的具体内容——谁说的、什么语气、有没有附加条件。
六个小时的 app 和"决策即上下文"
同一天,另一个项目是从零搭一个补剂管理 app。记录每天吃了什么维生素、库存剩多少、什么时候过期。Flutter + Supabase,从产品概念到能跑的 APK,大概六个小时。
速度本身不值得聊。值得聊的是过程中 AI 需要什么"上下文"。
一开始我写了份 PRD。不是为了流程,是因为不写的话 AI 就开始猜:登录方式猜微信(因为面向中国用户嘛),架构猜 MVVM(因为这是 Flutter 常见选择),端口猜 8080。每次猜错我都要纠偏,来回几轮比直接写清楚需求还慢。
PRD 就是给 AI 的上下文文档。写得精确,后面的实现就对;写得模糊,AI 就在模糊的空间里做随机选择。
但 PRD 写不完所有决策。过程中不断冒出新的选择:数据库表结构怎么设计?邮件确认流程跳转到哪里?端口号选哪个?这些都是实时的、微观的决策,没法提前在文档里穷举。
这时候反馈周期就很重要了。我说"不要 8080,太常用了,小众点",几秒后 AI 改成了 9527。我说"错误处理不好,前端直接抛原始错误了",几分钟后重写了错误展示逻辑。每一次纠偏都是在补充上下文——不是文档形式的上下文,是"这个人在这个项目里的偏好和判断标准"。
MVP 跑起来之后,我马上想到了两个新方向:OCR 扫描补剂包装自动录入,和开放 agent 接口让 AI 帮忙打卡、提醒吃药。有意思的是,这两个想法在传统的"先写代码"模式下不会这么快冒出来——你还在跟实现细节搏斗的时候,注意力被占满了,没余力去想"还能怎么用"。当实现不再是瓶颈,创意反而更容易涌现。
最难传递的上下文是思维模型
第三件事比较抽象。我在给一个博客工具想产品方向。跟 AI 讨论的时候出了一个有意思的分歧。
这个工具目前的功能是从开发对话里生成技术博客。我想让它做的更多——不只是博客,而是一种"超我"式的反思工具。每天的对话、决策、踩坑,经过提炼后变成对自己有价值的沉淀。
AI 听完立刻开始规划两条产品线:一条是"技术博客生成器",一条是"超我反思引擎"。各自的 roadmap、各自的功能模块。
但这不是两个东西。写博客本身就应该是反思。一篇好的 dev blog 不是记录"今天干了啥",而是回头看今天的工作,提炼出三个月后重读还觉得有价值的思考。博客和反思的区别只在于发不发布——内核是同一个。
我纠偏了好几次 AI 才对齐。"重要的是引擎,博客只是表现形式。""我不想要流水账,要自己回头看也有价值的东西。"每一次纠偏都在传递同一个信息:我的思维模型里,这两个概念是等价的。
这是最难传递的上下文。数据好传,代码好传,连风格偏好都能学。但"我怎么理解这个东西的本质"——这种抽象层面的认知对齐,目前没有什么好办法,只能靠对话反复校准。
AI 的天然倾向是拆解:你给它一个模糊概念,它会拆成具体的、可执行的模块。这通常是好事,但有时候概念之间的等价关系比拆解更重要。你说"引擎",它就去想架构;你说"博客",它就去想格式。你说"是同一个东西",它试图找一个框架来统一,而不是理解为什么它们在根上就是一回事。
Context engineering
回头看,这三件事的共同点确实是上下文,但不是"上下文很重要"这种废话层面的共同点。
它们分别代表了三种不同性质的上下文问题:
会议 transcript 是结构化的、可检索的上下文。解法是工具——给 agent 一个获取机制,让它自主探索。这对所有需要处理长文档的 agent 系统都适用:与其在 prompt 里塞"可能有用"的内容,不如提供轻量索引加按需查询。
需求和偏好是半结构化的、渐进式的上下文。一部分写在 PRD 里,一部分在实时决策中涌现。解法是缩短反馈周期——决策到验证的距离越短,对齐越快。
思维模型是非结构化的、难以显式化的上下文。目前没有比"对话纠偏"更好的解法。但它可能是影响最大的一种——一个思维模型不对齐的 AI 助手,技术上做得再对,方向也可能是偏的。
如果说 prompt engineering 是"怎么问对问题",context engineering 大概是"怎么让 AI 在需要的时候拿到需要的信息"。不是塞更多内容,而是设计更好的获取机制。browse/fetch 是一个小例子,但背后的思路——把 agent 从被动的上下文接收者变成主动的信息消费者——应该有更多的应用场景。
人机共创 · Blagent