我的 Agent 调用一次查询工具就把上万行结果原样塞回上下文,从此推理越来越笨、还越来越贵,我对着工具返回结果的治理排查了大半天的复盘

我做了个数据分析 Agent,能调用"查数据库"工具,根据用户问题查数据再总结。小数据量测试惊艳,接上生产库就抽风:有时答到一半报上下文超限崩了,有时答得驴唇不对马嘴像"忘了"用户问什么,token 账单还高得吓人。以为模型不行、prompt 不好,改半天没用,直到把 Agent 每步上下文 dump 出来,看到一条工具返回里塞着上万行查询结果、几十万字符,才恍然大悟:我从没处理过工具返回,而是原样塞回了上下文。根因是把"工具能返回的全部原始数据"等同于了"Agent 需要放进上下文思考的信息"——这俩根本不是一回事:查库返回 1 万行,Agent 也许只需要总数/前 5 条/汇总。后果是三重:撑爆窗口崩、关键信息被淹没推理变笨(迷失在中间)、多轮重复发送成本爆炸。这篇从工具返回"原始数据≠Agent需要的信息"、工具内聚合/大文本摘要/分页/硬截断存外部留引用的正解、Agent 上下文治理全景(Context Engineering)、返回治理策略速查、上下文膨胀三重伤害、决策图与铁律,到附上一个通用的工具返回治理装饰器(超长自动截断+存外部+留引用+按需读片段)。核心领悟:构建 Agent 的核心挑战之一不是给它能力,而是管理它的注意力和上下文;工具不是数据管道而是信息加工厂;把横切关注点抽象成统一基础设施,让正确成为默认。

我的 Agent 调用一次查询工具就把上万行结果原样塞回上下文,从此推理越来越笨、还越来越贵,我对着工具返回结果的治理排查了大半天的复盘

那是我做的一个数据分析 Agent。它能调用一个"查数据库"的工具,根据用户问题查数据、再总结成答案。小数据量测试时表现惊艳,我信心满满。可真接上生产库后,它就开始"抽风":有时一个问题答到一半就报上下文超限崩了;有时答得驴唇不对马嘴、好像"忘了"用户最初问的是什么;而且 token 账单高得吓人。我一开始以为是模型不行、prompt 不好,改了半天没用。直到我把 Agent 每一步实际的上下文 dump 出来,看到其中一条工具返回里塞着整整上万行的查询结果、几十万字符时,才恍然大悟:我从来没有处理过"工具返回的结果",而是把它原原本本地塞回了 Agent 的上下文。这篇就把这场"工具返回结果撑爆 Agent"的事故,从头复盘一遍。

故障现场:一次工具调用,塞回几十万字符

先看现场。问题就藏在我那个"把工具结果直接返回"的天真实现里:

# 我的 Agent 工具: 查数据库, 然后...把结果原样返回
def query_database(sql: str) -> str:
    rows = db.execute(sql)            # 可能返回上万行!
    return str(rows)                  # ✗ 直接把全部结果转成字符串返回给 Agent

# Agent 的主循环(简化):
def agent_loop(user_question):
    messages = [{"role": "system", "content": SYSTEM},
                {"role": "user", "content": user_question}]
    while True:
        resp = llm.chat(messages, tools=TOOLS)
        if resp.tool_calls:
            for call in resp.tool_calls:
                result = run_tool(call)            # ← 工具返回的海量结果
                messages.append({"role": "tool",
                                 "content": result})  # ✗ 原样塞回上下文!
            continue
        return resp.content

# 实际发生了什么(一次用户提问):
# 第1步: Agent 决定调用 query_database("SELECT * FROM orders WHERE ...")
# 第2步: 工具返回了 12000 行数据, str() 后约 380000 字符 (≈ 15万 token!)
# 第3步: 这 38万字符被原样 append 进 messages, 塞回给模型
#        → 单这一条 tool 消息, 就几乎占满甚至超过了上下文窗口!

# 现象拼图:
#   - 后果1(崩): 工具结果太大, messages 总 token 超上下文窗口 → 报错崩溃。
#   - 后果2(变笨): 就算没崩, 上下文被海量原始数据"淹没", 真正重要的信息
#     (用户问题、系统指令)被稀释, 模型注意力被无关细节分散 → 推理质量暴跌,
#     "忘了"用户问的是什么(迷失在中间, lost in the middle)。
#   - 后果3(变贵): 这几十万 token 要计费; 且 Agent 多轮, 这坨数据会
#     在后续每一轮都被重复发送 → 成本爆炸。
#   - 根因: 我把"工具能返回的全部原始数据", 不加任何处理地等同于
#     "Agent 需要放进上下文思考的信息" —— 这俩根本不是一回事!

看到那条塞了 38 万字符的工具返回消息时,三个症状一下子都有了解释。工具一次返回上万行、十几万 token,被我原样塞回上下文,直接导致:要么撑爆窗口崩溃,要么把真正重要的信息(用户问题、系统指令)淹没在海量原始数据里、让模型"迷失在中间"而推理变笨,要么这坨数据在 Agent 的后续每一轮里被重复发送、token 成本爆炸而这一切的根因,是我犯了一个根本性的认知错误:我把"工具能返回的全部原始数据",不加任何处理地,等同于了"Agent 需要放进上下文去思考的信息"——可这两者,根本不是一回事

第一件事:搞懂工具返回的"数据"与 Agent 需要的"信息"之别

要解决它,得先想明白一个根本问题:Agent 调用工具,到底想从返回里得到什么?

工具返回: "原始数据" ≠ "Agent 需要的信息"

# Agent 调工具的本质:
#   - Agent 是靠"上下文(它能看到的所有文字)"来思考和决策的。
#   - 上下文是【有限且宝贵】的资源(窗口有限、每个token都计费、
#     且信息越多越容易分散注意力)。
#   - 工具的作用, 是帮 Agent "获取它需要的信息" 来完成任务。

# 关键区分:
#   "工具能产出的全部原始数据"  ≠  "Agent 完成任务真正需要的信息"
#   - 查数据库可能返回1万行, 但 Agent 也许只需要"总数"或"前5条"或"汇总"。
#   - 读文件可能是10万字, 但 Agent 也许只需要"其中关于X的那一段"。
#   - 调API可能返回巨大JSON, 但 Agent 也许只关心其中3个字段。

# 所以工具的返回, 必须经过"治理"(中间处理), 而不是原样透传:
#   原始数据 → [筛选/聚合/摘要/截断/分页] → Agent 真正需要的精炼信息

# 类比: 你让助理去查资料, 你要的是他"整理后的要点", 不是
#   把整个图书馆搬到你桌上。Agent 的工具也该如此 —— 返回"要点", 不是"全集"。

# 一个心智模型: 把 Agent 的上下文当成"工作台", 台面就那么大。
#   - 该往台面上放的, 是"当前思考真正用得上的精华信息"。
#   - 不该把"工具能拿到的所有原材料"全堆上去 —— 台面会被淹没。

# 核心: 工具的原始输出 ≠ Agent 需要的信息; 上下文是有限宝贵资源,
#   工具返回必须经筛选/聚合/摘要/分页治理成"精炼信息", 而非原样透传海量数据。

想透这一层,我才明白自己错在哪。Agent 是靠"上下文"来思考的,而上下文是有限且宝贵的资源(窗口有限、每个 token 都计费、信息越多越容易分散注意力)。工具的作用,是帮 Agent 获取它需要的信息这里有一个我之前完全忽略的关键区分:"工具能产出的全部原始数据" ≠ "Agent 完成任务真正需要的信息"——查数据库可能返回 1 万行,但 Agent 也许只需要"总数"或"前 5 条";读文件可能 10 万字,但 Agent 也许只需要"关于 X 的那一段";调 API 可能返回巨大 JSON,但 Agent 也许只关心 3 个字段。所以,工具的返回必须经过"治理"(筛选/聚合/摘要/截断/分页),而不是原样透传:原始数据 → 治理 → Agent 真正需要的精炼信息。这就像你让助理去查资料,你要的是他整理后的要点,而不是把整个图书馆搬到你桌上。把 Agent 的上下文想象成一张大小有限的"工作台":该往上放的是"当前思考真正用得上的精华",而不是"工具能拿到的所有原材料"——否则台面会被瞬间淹没

第二件事:正解——治理工具返回,只给 Agent 精炼信息

搞懂了原理,正解就清晰了:在工具内部就对结果做治理——聚合/截断/摘要/分页,只把 Agent 真正需要的精炼信息返回

# ====== 正解一: 工具内部就聚合/筛选, 别返回明细全集 ======
def query_database(sql: str, intent: str = "") -> str:
    rows = db.execute(sql)
    # ✓ 如果 Agent 只需要"有多少", 就只返回数量, 别返回全部行
    if len(rows) > 100:
        # 返回"摘要 + 样本", 而不是全部
        return (f"查询共返回 {len(rows)} 行。"
                f"前5行样本:\n{format_rows(rows[:5])}\n"
                f"(结果过多, 已省略 {len(rows)-5} 行。"
                f"如需进一步分析, 请用更精确的条件/聚合查询)")
    return format_rows(rows)

# ====== 正解二: 提供"聚合型"工具, 而非只有"取明细"工具 ======
# 与其让 Agent 取全部行自己数, 不如直接给它聚合能力:
def query_count(table: str, where: str) -> str:
    n = db.execute(f"SELECT COUNT(*) FROM {table} WHERE {where}")[0][0]
    return f"符合条件的记录数: {n}"          # 只返回一个数字, 极省上下文
def query_aggregate(table: str, group_by: str, agg: str) -> str:
    ...   # 返回汇总后的少量结果, 而非明细

# ====== 正解三: 大文本结果, 先摘要再返回 ======
def read_document(path: str, question: str) -> str:
    content = open(path).read()             # 可能很长
    if len(content) > 4000:
        # 用便宜模型把"与question相关的部分"摘出来, 别返回全文
        return summarize_relevant(content, question)
    return content

# ====== 正解四: 分页/游标, 让 Agent 按需翻页, 而不是一次全要 ======
def query_paged(sql: str, page: int = 1, size: int = 20) -> str:
    rows = db.execute(f"{sql} LIMIT {size} OFFSET {(page-1)*size}")
    total = db.execute(f"SELECT COUNT(*) FROM (...)")[0][0]
    return (f"第{page}页/共{(total+size-1)//size}页 (总{total}条):\n"
            f"{format_rows(rows)}\n如需下一页, 用 page={page+1} 再次调用")

# ====== 正解五: 硬性截断兜底 + 把"原始数据"存到外部, 上下文只放引用 ======
MAX_TOOL_RESULT = 2000   # 工具返回的硬上限(字符)
def safe_tool_result(result: str) -> str:
    if len(result) > MAX_TOOL_RESULT:
        ref = save_to_store(result)         # 全量存外部(文件/对象存储)
        return (result[:MAX_TOOL_RESULT] +
                f"\n...[已截断, 完整结果见引用 {ref}, 可用工具按需读取片段]")
    return result

# 核心: 在工具内部治理返回 —— 能聚合就返回聚合(COUNT/汇总)、大文本先摘要、
#   多结果分页、再加硬截断兜底; 只给 Agent "精炼信息", 全量数据存外部留引用。

修复的核心,是"在工具内部就把返回治理好,只给 Agent 精炼信息"正解一:工具内部就聚合/筛选——结果太多时返回"摘要 + 样本"(共多少行、前 5 行样本、提示用更精确的条件),而不是全部明细。正解二:提供"聚合型"工具——与其让 Agent 取全部行自己数,不如直接给它 query_countquery_aggregate 这样的聚合能力,只返回一个数字或少量汇总。正解三:大文本先摘要再返回——读文件/文档时,用便宜模型把"与问题相关的部分"摘出来,别返回全文。正解四:分页/游标——让 Agent 按需翻页,而不是一次全要。正解五:硬性截断兜底 + 全量存外部、上下文只放引用——超过阈值就截断,把完整结果存到外部存储、上下文里只留一个引用(Agent 需要时再按需读片段)。归根结底:在工具内部治理返回——能聚合就聚合、大文本先摘要、多结果分页、再加硬截断兜底;只给 Agent 精炼信息,全量数据存外部留引用。

第三件事:Agent 上下文治理的全景

修这个问题时我意识到,工具返回只是"Agent 上下文治理"的一环。我把整个上下文治理梳理了一遍。

Agent 上下文治理全景(Context Engineering)

# Agent 的上下文里, 都有什么会"膨胀"?
#   1. 对话历史(用户/Agent 多轮往来)—— 越聊越长。
#   2. 工具返回结果(本文重灾区)—— 单次就可能爆炸。
#   3. 系统提示 + 工具定义 —— 固定但每轮都发。
#   4. 检索注入的知识(RAG)—— 塞太多文档也会膨胀。

# 治理手段(把上下文当稀缺资源来"经营"):
#   - 工具返回治理(本文): 聚合/摘要/分页/截断, 只放精炼信息。
#   - 历史治理: 滑动窗口 + 旧对话摘要(保要点)。
#   - 外部记忆: 大块信息存外部(向量库/文件), 上下文只放"引用/索引",
#     需要时再按需取回(把上下文当"缓存", 外部存储当"主存")。
#   - 子任务隔离: 复杂任务拆给子 Agent, 每个子 Agent 只带它需要的上下文,
#     主 Agent 只收子 Agent 的"结论", 不收它的全过程。
#   - 结构化压缩: 把冗长信息转成紧凑结构(表格/要点), 同样信息更少 token。

# 一个核心原则: 上下文不是"垃圾桶"(什么都往里扔),
#   而是"工作台"(只放当前思考必需的精华)。
#   → Context Engineering(上下文工程): 主动地、有策略地决定
#     "什么该进上下文、什么不该、什么该压缩、什么该外置"。

# 核心: 工具返回只是上下文膨胀的一环; 完整治理还需历史摘要、外部记忆引用、
#   子任务隔离、结构化压缩 —— 把上下文当稀缺工作台来经营, 而非垃圾桶。

修这个问题让我接触到了一个更大的概念:上下文工程(Context Engineering)。原来 Agent 上下文里会"膨胀"的不止工具返回,还有对话历史、系统提示 + 工具定义、RAG 注入的知识对应的治理手段是一整套:工具返回治理(本文:聚合/摘要/分页/截断)、历史治理(滑动窗口 + 旧对话摘要)、外部记忆(大块信息存外部,上下文只放引用,把上下文当"缓存"、外部存储当"主存")、子任务隔离(复杂任务拆给子 Agent,主 Agent 只收"结论"不收全过程)、结构化压缩(冗长信息转成紧凑表格/要点)它们共同指向一个核心原则:上下文不是"垃圾桶"(什么都往里扔),而是"工作台"(只放当前思考必需的精华);所谓上下文工程,就是主动地、有策略地决定"什么该进上下文、什么不该、什么该压缩、什么该外置"归根结底:工具返回只是上下文膨胀的一环;把上下文当稀缺工作台来经营,而非垃圾桶。下面这张图,是这次工具返回撑爆 Agent 的成因与解法:

第四件事:工具返回治理策略速查

这次踩坑后,我把"工具返回该怎么治理"按数据类型整理成一张表,设计 Agent 工具时对照着选。

工具返回类型 裸返回的问题 治理策略
大量行(查库/列表) 上万行撑爆上下文 聚合/COUNT/前N行样本/分页
长文本(文件/网页) 全文几十万字符 按问题摘要相关段落
大JSON(API响应) 嵌套巨大,大量无关字段 只提取需要的字段
二进制/图片 没法放进文本上下文 存外部,上下文放引用/描述
报错堆栈 超长堆栈刷屏 提取关键错误行
任意超长结果 不可预测的爆炸 硬截断+存外部留引用兜底

这张表,把"不同类型的工具返回该怎么处理"讲清了。核心思路始终如一:不管工具拿到的原始数据有多大,返回给 Agent 的,都必须是"经过裁剪、与任务相关、体积可控"的精炼版本它给我的启发是:设计 Agent 的工具时,"工具返回什么、返回多少"和"工具能做什么"同等重要,甚至更重要很多人(包括之前的我)设计工具,只关心"它能不能拿到数据",却忽略了"它该怎么把数据交给 Agent";而后者,恰恰直接决定了 Agent 的上下文健康、推理质量和成本。更深一层,这让我意识到:Agent 的工具,不是简单的"数据管道"(把数据从源头原样导给模型),而应该是智能的"信息加工厂"(把原始数据加工成 Agent 好用的精炼信息)一个好的工具,替 Agent 把"信息的预处理"做好了,Agent 才能把宝贵的上下文和注意力,用在真正的"思考和决策"上,而不是淹没在原始数据的汪洋里。

第五件事:上下文膨胀对 Agent 的三重伤害

这次事故让我看清,上下文膨胀的危害是多方面的。我把它对 Agent 的三重伤害梳理了一下。

伤害维度 表现 根源
可用性(崩) 超上下文窗口直接报错 总token超模型上限
质量(变笨) 忘记目标、答非所问、遗漏 关键信息被淹没、注意力分散(迷失在中间)
成本(变贵) token账单飙升 海量数据多轮重复发送
延迟(变慢) 每轮响应变慢 输入token越多处理越慢

这张表,把"上下文膨胀到底坏在哪"彻底讲透了。它对 Agent 的伤害是全方位的:可用性上会直接撑爆窗口崩溃;质量上会因关键信息被淹没、注意力被分散("迷失在中间")而变笨、答非所问、忘记目标;成本上会因海量数据多轮重复发送而账单飙升;延迟上会因输入 token 太多而每轮变慢而其中最隐蔽、也最该警惕的,是"质量变笨"这一重——崩溃和变贵你能立刻发现,但"推理质量悄悄下降",却很容易被误判成"模型不行"或"prompt 不好"(我一开始就是这么误判的)。它给我的最大启发是:对 Agent 来说,"上下文里塞了什么",和"用了多强的模型"同等重要,甚至更重要一个再强的模型,如果上下文里塞满了垃圾和无关信息,它的表现也会大打折扣——这就像让一个天才,在一个堆满杂物、找不到重点的桌面上工作所以,"为 Agent 精心组织上下文"(上下文工程),是和"选好模型""写好 prompt"并列的、决定 Agent 成败的核心工程能力

第六件事:设计 Agent 工具时,我现在的决策习惯

现在再给 Agent 设计工具,我不再"拿到数据就 return",而是按这张图先想清楚"该返回什么、返回多少":

这张图的精髓,是"设计工具时,从'Agent 真正需要什么'倒推'该返回什么'"第一问是 "这个返回可能有多大":可能很大或不可控的,一律必须治理。然后从 Agent 的真实需求倒推返回形态:只要数量/汇总就提供聚合工具、要明细但量大就分页或给样本、要长文里的信息就按问题摘要、要特定字段就只提取必要字段无论哪种,都加一个硬截断上限兜底,超限的全量数据存外部、上下文只留引用最后一步是我现在的硬习惯:把 Agent 的上下文 dump 出来,亲眼确认单条工具返回的体积是可控的(就像我这次,正是 dump 上下文才发现问题)。这套习惯,让我设计工具时,从"能拿到数据就行"变成了"该怎么把数据精炼好交给 Agent"——核心始终是:工具是 Agent 的信息加工厂,要主动设计它的返回,而不是把原始数据一股脑倒给 Agent。

我立下的几条规矩

这场"工具返回撑爆 Agent"的事故,换来了我做 Agent 时,刻进骨子里的几条铁律:

  1. 工具返回必须治理,绝不裸透传。原始数据 ≠ Agent 需要的信息,要聚合/摘要/分页/截断。
  2. 能聚合就别返明细。提供 COUNT/SUM/汇总型工具,别让 Agent 取全部行自己数。
  3. 大文本先摘要、按需取。读文件/网页只返回与任务相关的部分。
  4. 给工具返回设硬上限兜底。超限就截断 + 全量存外部、上下文留引用。
  5. 把上下文当工作台,不是垃圾桶。只放当前思考必需的精华信息。
  6. 警惕"悄悄变笨"。推理质量下降常被误判为模型差,先查上下文是不是被垃圾淹没了。
  7. 定期 dump 上下文检查。亲眼看 Agent 每步上下文里到底装了什么、多大。

附:一个通用的工具返回治理装饰器

口说无凭。下面把"工具返回治理"封装成一个装饰器,套在任何工具上,自动截断超长返回、全量存外部、上下文只留引用:

import functools, hashlib, json, os

EXTERNAL_STORE = "/tmp/agent_tool_results"   # 全量结果的外部存储
MAX_RESULT_CHARS = 2000                       # 返回给Agent的硬上限

def govern_tool_result(max_chars=MAX_RESULT_CHARS):
    """工具返回治理装饰器: 超长则截断+存外部+留引用, 保护Agent上下文。"""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            text = result if isinstance(result, str) else json.dumps(
                result, ensure_ascii=False, default=str)

            if len(text) <= max_chars:
                return text                   # 体积可控, 直接返回

            # 超长: 1) 全量存外部
            os.makedirs(EXTERNAL_STORE, exist_ok=True)
            ref = hashlib.md5(text.encode()).hexdigest()[:12]
            with open(f"{EXTERNAL_STORE}/{ref}.txt", "w", encoding="utf-8") as f:
                f.write(text)
            # 2) 上下文只放: 预览 + 体积说明 + 引用(可用别的工具按需读)
            return (
                f"[结果较大, 共 {len(text)} 字符, 已存外部]\n"
                f"预览(前{max_chars}字符):\n{text[:max_chars]}\n"
                f"...[完整结果引用ID: {ref}。"
                f"如需查看更多, 调用 read_result(ref='{ref}', start=..., length=...)]"
            )
        return wrapper
    return decorator

# 配套: 让Agent能按需读取外部存储的片段(而不是一次全要回来)
def read_result(ref: str, start: int = 0, length: int = 1500) -> str:
    path = f"{EXTERNAL_STORE}/{ref}.txt"
    if not os.path.exists(path):
        return f"引用 {ref} 不存在或已过期"
    with open(path, encoding="utf-8") as f:
        f.seek(start)
        return f.read(length)                 # 只读这一段, 上下文友好

# ====== 用法: 任何工具套上装饰器, 自动获得返回治理 ======
@govern_tool_result(max_chars=1500)
def query_database(sql: str) -> str:
    rows = db.execute(sql)
    return str(rows)        # 哪怕这里返回上万行, 装饰器也会自动治理好
# → Agent 拿到的永远是"可控大小的预览+引用", 而非几十万字符的洪水。

# 核心: 用装饰器把"返回治理"统一兜底 —— 超长自动截断、全量存外部、
#   上下文只留预览+引用, 再配 read_result 让Agent按需取片段; 一处封装, 处处保护。

这个 govern_tool_result 装饰器,把这篇文章的核心解法,变成了一个可以套在任何工具上的统一兜底它的精妙,在于把"返回治理"这件事,从"每个工具自己记得做"变成了"套个装饰器就自动获得":任何工具一旦被它包裹,返回超过阈值就自动截断成"预览 + 体积说明 + 引用 ID",全量数据存到外部,Agent 想看更多就用配套的 read_result 按需读取片段这样,就算某个工具的实现里偷懒 return str(rows) 返回了上万行,装饰器也会在最后一道关口把它治理好,Agent 的上下文永远不会被一次工具调用淹没这,正是我想用这个装饰器,留给每个做 Agent 的人的最后一课:对于"每个工具都必须做、但又容易被忘记做"的横切关注点(返回治理、日志、限流、错误处理……),最好的办法是把它抽象成一层统一的、自动生效的基础设施(装饰器/中间件/网关)靠"每个工具的作者都自觉处理好返回"是不可靠的(人总会偷懒、会忘);而一个统一的治理层,把"正确"变成了"默认"、把"保护"变成了"无需操心"从"每个工具各自为政"到"一层基础设施统一兜底",这正是 Agent 工程走向成熟的标志之一:不依赖个体的自律,而依赖系统的设计,来保证整体的健壮把易错的事变成默认安全的事,让正确自然发生——无论是写 Agent,还是写任何系统,这都是对抗复杂度最可靠的智慧。

写在最后

回头看,这场由"工具返回不加治理"引发的、让 Agent 又崩又笨又贵的事故,真正教给我的,是关于"如何构建 Agent"的一次认知重塑。我一开始构建 Agent 的思路,是"给它接上尽可能多、尽可能强的工具"——以为工具越多越强,Agent 就越能干。可这次事故让我明白:Agent 的能力,不只取决于"它能调用什么工具",更取决于"这些工具如何与它的上下文协作"一个会"把整个数据库倒进上下文"的工具,不是在帮 Agent,而是在用信息的洪水淹没它。这让我领悟到一个 Agent 工程里至关重要、却常被新手忽略的道理:构建 Agent 的核心挑战之一,不是"让它获得能力",而是"管理它的注意力和上下文"——因为 Agent 的"智能",是在它那块有限的上下文工作台上发生的;而决定这块工作台上"放什么、不放什么"的,正是上下文工程(Context Engineering)这,或许是从"能跑的 Agent demo"走向"可靠的生产级 Agent"之间,最关键、也最容易被低估的一道门槛:我们不仅要赋予 Agent 行动的能力(工具),更要为它精心地、有节制地组织它思考所依赖的信息(上下文)真正强大的 Agent,背后一定有一套精心设计的上下文治理——让它在任何时候,面对的都是"恰到好处的信息",而不是"无穷无尽的数据"。这,是我用一次"又崩又笨又贵"的事故,换来的、关于 Agent、也关于"上下文工程"的、最朴素也最深刻的领悟。如果这篇复盘,能让你在给 Agent 写下一个工具时,多想一句"它该返回什么、返回多少给 Agent",那我对着那条 38 万字符的工具返回熬的这大半天,就值了。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

我用 as 把接口返回的数据断言成了想要的类型,编译器一声不吭全绿,上线后却在访问属性时疯狂报 undefined,我对着类型断言排查了大半天的复盘

2026-6-2 6:00:16

技术教程

我的 Python 函数返回的数据,第一次遍历好好的、第二次却空空如也,我对着生成器只能消费一次这个坑排查了大半天的复盘

2026-6-2 6:10:35

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索