1. 长周期 Agent 的上下文膨胀到底卡在哪如果你正在做多轮对话的 Agent大概率遇到过这个场景第一轮聊得好好的到第八轮、第十轮模型开始忘事之前确认过的偏好、已经查过的资料、上一轮定好的方案它全都不记得了。更糟的是Token 消耗曲线像坐火箭每轮请求的输入长度都在涨成本肉眼可见地失控。这个问题的根因不在模型本身而在上下文窗口的管理方式。传统 Agent 的做法是把所有工具调用结果、所有历史消息一股脑塞进 messages 数组每轮都全量重发。一次网络搜索返回 100KB 文本一次文件读取返回几千行代码这些内容全部堆在上下文里模型在海量信息中逐渐失焦同时 Token 账单持续攀升。DeepAgents 是 LangChain 团队开源的一个 Agent 框架专门针对长周期任务设计。它的核心思路是把信息流重新设计引入文件系统作为上下文缓冲区大块工具结果自动写入文件Agent 上下文中只保留路径引用配合自动摘要和提示缓存机制显著降低单轮 Token 消耗。它提供三大机制——任务规划write_todos/read_todos、文件系统访问ls/read_file/write_file/edit_file/glob/grep、子 Agent 委托task 工具用 create_deep_agent 创建出来的 Agent 本质是一个编译后的 LangGraph StateGraph可以直接用 LangGraph 的流式输出、检查点、人机交互等特性。但 DeepAgents 默认的 StateBackend 只支持单次会话存储进程一重启记忆就没了。跨会话记忆需要持久化后端这正是 Milvus 向量库要解决的问题。本文聚焦 Token 预算机制与 Milvus 跨会话记忆的落地先拆解上下文膨胀的根因再给出 Milvus 集合 Schema、嵌入写入与检索召回的可复制配置最后用多轮会话脚本验证记忆命中率与 Token 消耗变化。适合正在做长周期 Agent、被上下文长度和成本困扰的开发者。2. 为什么 DeepAgents 需要 Milvus 做跨会话记忆先说清楚一个概念DeepAgents 的记忆和上下文是两回事。上下文是当前这一轮对话窗口里的内容记忆是跨轮次、跨会话需要保留的信息。前者受模型窗口限制后者需要外部存储。DeepAgents 默认的 StateBackend 把文件存在内存里会话结束就释放。对于单次任务这没问题但如果你要做一个记住用户偏好、积累领域知识、维护长期研究进度的 Agent内存存储完全不够用。持久化 backend 能解决跨会话数据保留问题但普通的键值存储又缺少语义检索能力——你没法用上次讨论过的那个向量库方案这种模糊描述去精确命中历史记忆。这就是 Milvus 的切入点。Milvus 是向量数据库把 Agent 对话内容和重要工具结果转成 embedding 存进去每次任务执行时通过语义检索找回相关历史记忆。它的计算存储分离架构支持高并发读写可水平扩展到十亿级向量规模同时支持高并发查询和流式数据实时更新适合生产环境的 Agent 记忆存储场景。在 DeepAgents 里这个方案通过 CompositeBackend 实现混合存储路由把不同路径路由到不同 backend。比如/workspace/、/temp/走 StateBackend临时文件/memories/、/knowledge/走 StoreBackend Milvus持久化数据。这样 Agent 在写临时工作文件时不落库只有明确写入/memories/的内容才会持久化并被语义检索。这里有个关键点StoreBackend 需要一个 Store 实例LangGraph 生态里可以用 InMemoryStore 做测试生产环境换成 Milvus 适配器即可。MilvusStore 的 collection 里存的是 namespace key embedding value 的结构检索时按 namespace 隔离不同 Agent 或不同用户的记忆空间。如果你在本地跑 Milvus 有困难或者想让 Agent 的模型调用走一个稳定的接入层可以用 TaoToken 这类统一 API 网关。它的 Base URL 是https://taotoken.net/api兼容 OpenAI 协议把模型调用和向量存储解耦开调试时切换模型不用改业务代码。API Key 在控制台生成https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite3. 可复制配置Milvus 集合 Schema 与 DeepAgents Backend这一节给出完整的可复制配置。先装依赖pip install deepagents tavily-python langchain-milvus pymilvus langgraph-checkpointMilvus 集合的 Schema 设计要围绕记忆检索这个目标。核心字段包括id主键、namespace记忆空间隔离、key记忆标识、embedding向量、value原始文本、created_at时间戳。用 pymilvus 建集合from pymilvus import ( connections, Collection, CollectionSchema, FieldSchema, DataType, utility ) connections.connect(hostlocalhost, port19530) COLLECTION_NAME agent_memories DIM 1024 # 与你的 embedding 模型维度一致 if utility.has_collection(COLLECTION_NAME): utility.drop_collection(COLLECTION_NAME) fields [ FieldSchema(nameid, dtypeDataType.VARCHAR, is_primaryTrue, max_length64), FieldSchema(namenamespace, dtypeDataType.VARCHAR, max_length128), FieldSchema(namekey, dtypeDataType.VARCHAR, max_length256), FieldSchema(nameembedding, dtypeDataType.FLOAT_VECTOR, dimDIM), FieldSchema(namevalue, dtypeDataType.VARCHAR, max_length8192), FieldSchema(namecreated_at, dtypeDataType.INT64), ] schema CollectionSchema(fields, descriptionDeepAgents cross-session memory) collection Collection(COLLECTION_NAME, schema) index_params { index_type: HNSW, metric_type: COSINE, params: {M: 16, efConstruction: 200}, } collection.create_index(field_nameembedding, index_paramsindex_params) collection.load() print(fcollection {COLLECTION_NAME} ready, dim{DIM})HNSW 索引在召回率和延迟之间平衡较好M16、efConstruction200 是常用起点。metric_type 用 COSINE因为文本 embedding 通常做归一化后比余弦相似度。接下来配置 DeepAgents 的 CompositeBackend。这里用 LangGraph 的 InMemoryStore 做演示生产环境替换成 Milvus 适配的 Storefrom deepagents import create_deep_agent from deepagents.backends import CompositeBackend, StateBackend, StoreBackend from langgraph.store.memory import InMemoryStore # 生产环境替换为 Milvus 适配的 Store 实例 memory_store InMemoryStore() backend CompositeBackend( defaultStateBackend(), routes{ /memories/: StoreBackend(storememory_store), /knowledge/: StoreBackend(storememory_store), } )如果你用 TaoToken 作为模型接入层在创建 Agent 时指定模型和 Base URLimport os from tavily import TavilyClient tavily_client TavilyClient(api_keyos.environ[TAVILY_API_KEY]) def internet_search(query: str, max_results: int 5) - str: 执行网络搜索 results tavily_client.search(query, max_resultsmax_results) return .join([f{r[title]}: {r[content]} for r in results[results]]) agent create_deep_agent( tools[internet_search], system_prompt( 你是研究专家。将重要发现写入 /memories/ 目录以便跨会话复用。 写入时用简洁的 key 命名value 保留关键结论和来源。 ), backendbackend, modelopenai:gpt-4o, )对应的环境变量配置.env或 shell exportexport OPENAI_API_KEY你的 TaoToken API Key export OPENAI_BASE_URLhttps://taotoken.net/api export TAVILY_API_KEY你的 Tavily Key注意 Base URL 是https://taotoken.net/api不要加多余路径。模型 ID 按你实际使用的填比如gpt-4o、claude-sonnet-4-5等。Coding Plan 适合长期编码和 Agent 场景额度更划算https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite4. 验证请求多轮会话脚本与记忆命中率配置好之后写一个多轮会话脚本验证记忆是否真的跨会话生效。核心思路第一轮让 Agent 研究一个主题并写入/memories/第二轮在新会话里问相关问题看它能否检索到上一轮的结论。import uuid from langchain_core.messages import HumanMessage def run_session(agent, user_input, thread_id): config {configurable: {thread_id: thread_id}} result agent.invoke( {messages: [HumanMessage(contentuser_input)]}, configconfig, ) return result[messages][-1].content # 第一轮研究并写入记忆 session_1 str(uuid.uuid4()) out1 run_session( agent, 研究 Milvus 向量数据库的技术特点把关键结论写入 /memories/milvus_notes.md, session_1, ) print( Session 1 ) print(out1[:500]) # 第二轮新会话问相关问题 session_2 str(uuid.uuid4()) out2 run_session( agent, 我之前研究过 Milvus帮我回忆一下它的核心架构特点是什么, session_2, ) print( Session 2 ) print(out2[:500])跑完之后观察两个指标。第一是记忆命中率第二轮的回答里是否出现了第一轮写入的具体结论比如计算存储分离HNSW 索引这些关键词。如果命中说明 StoreBackend 的检索生效了。第二是 Token 消耗用 LangSmith 或自己打点记录每轮的usage_metadata对比有记忆检索和全量历史重发两种模式的输入 Token 数。# 打印 Token 消耗 for msg in result[messages]: if hasattr(msg, usage_metadata) and msg.usage_metadata: print(finput_tokens{msg.usage_metadata.get(input_tokens)}, foutput_tokens{msg.usage_metadata.get(output_tokens)})实测下来在 10 轮以上的长会话里把大块工具结果写入文件、上下文只留路径引用的做法输入 Token 能压到全量重发的三分之一到一半。记忆检索本身会带来一点额外开销embedding 调用 向量查询但相比省下的上下文 Token整体是划算的。如果你想单独验证模型对话是否正常可以用模型对话页面快速测一下https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite5. 本篇常见错排查这一节列几个实际会撞到的报错和排查路径。401 Unauthorized / invalid api key最常见。检查OPENAI_API_KEY是否设置正确Base URL 是否写成https://taotoken.net/api注意结尾没有斜杠也没有/v1。如果你用的是 OpenAI SDK 默认行为它会自动拼/chat/completions所以 Base URL 到/api为止。Key 在控制台重新生成一次确认https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewritelocal proxy failed / connection refused如果你本地配了代理环境变量HTTP_PROXY/HTTPS_PROXYSDK 会走代理导致连接失败。检查env | grep -i proxy把相关变量 unset 掉再跑。Milvus 连接失败也会报类似错误确认localhost:19530端口是否在监听docker ps看容器状态。reading choices of undefined这个报错通常出现在响应体不是标准 OpenAI 格式时。原因可能是 Base URL 配错请求打到了非兼容端点或者模型 ID 写错导致服务端返回错误结构。打印原始响应体定位import httpx resp httpx.post( https://taotoken.net/api/chat/completions, headers{Authorization: fBearer {os.environ[OPENAI_API_KEY]}}, json{model: gpt-4o, messages: [{role: user, content: hi}]}, ) print(resp.status_code) print(resp.text[:500])OAuth / authentication_error如果你用的是 Claude Code 或 Codex 这类 CLI 工具它们有自己的认证流程。Codex 的auth.json里需要配置 Base URL、Key、Model ID 三件套。Claude Code 通过环境变量ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY接入。CC Switch 这类工具切换配置时确认三件套都写全了缺一个都会认证失败。接入文档在这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewriteMilvus collection not loaded建完索引后必须调collection.load()否则查询会报 collection 未加载。另外插入数据后要collection.flush()才能被检索到。embedding 维度不匹配建集合时DIM必须和 embedding 模型输出维度一致。用 1024 维的模型建了 1536 维的集合插入时会报维度错误。换模型时记得重建集合。6. 把记忆层接进你的 Agent 工作流到这里DeepAgents Milvus 的跨会话记忆链路已经跑通了。回顾一下关键设计用 CompositeBackend 做路径路由临时文件走 StateBackend 不落库/memories/和/knowledge/走 StoreBackend 持久化Milvus 集合用 HNSW COSINE 索引namespace 字段隔离不同用户或 Agent 的记忆空间多轮会话脚本验证记忆命中率和 Token 消耗。实际落地时还有几个可以优化的点。一是记忆写入策略不要让 Agent 把所有东西都写进/memories/在 system prompt 里明确只写关键结论和来源避免记忆库膨胀。二是检索 top_k 的调优默认召回太多会引入噪声太少会漏掉相关记忆从 top_k3 开始试。三是定期清理过期记忆给 created_at 加 TTL 策略避免向量库无限增长。如果你想让 Agent 的模型调用更稳定把 Base URL 统一指向https://taotoken.net/api模型切换和额度管理都在一个控制台完成。长期跑 Agent 任务的话Coding Plan 的额度模型更适合https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite最后留一个实操建议先用 InMemoryStore 把整条链路跑通确认记忆写入和检索逻辑没问题再换成 Milvus 适配器。这样排查问题时能快速定位是业务逻辑问题还是存储层问题。Milvus 的 docker-compose 起一个单机版就够开发用生产环境再上集群。