1. INMS 论文里的 Memory Sharing 到底在解决什么问题
如果你最近在折腾 LLM Agents,大概率会遇到一个很别扭的场景:你写了三个 Agent,一个负责查资料,一个负责写代码,一个负责跑测试。它们各自维护自己的上下文,互相之间完全不知道对方刚才干了什么。查资料的 Agent 好不容易从一堆文档里定位到关键接口,写代码的 Agent 却要从零开始重新理解需求;跑测试的 Agent 发现某个依赖版本不对,这个信息也传不回给写代码的那个。结果就是每个 Agent 都在重复劳动,token 烧得飞快,任务还经常卡在信息断层上。
INMS 这篇论文的核心切入点就在这里。它讨论的是 Memory Sharing,也就是让多个 LLM Agents 之间能够共享和复用记忆,而不是各自为战。论文里把记忆分成几个层次来管理:有短期的工作记忆,记录当前这一轮任务里发生了什么;有长期的语义记忆,沉淀跨任务的经验;还有共享记忆池,让不同 Agent 可以按需读取别人产生的中间结果。这个思路其实很符合工程直觉——你不需要让每个 Agent 都变成全知全能,而是让它们能像团队一样交换笔记。
我自己的理解是,Memory Sharing 要落地,绕不开三个工程问题。第一是记忆的写入格式要统一,否则 A Agent 写的东西 B Agent 读不懂;第二是读取权限和范围要可控,不能让一个负责闲聊的 Agent 读到生产环境的敏感配置;第三是调用通道要稳定,多个 Agent 频繁读写共享记忆,底层 API 的并发和鉴权必须扛得住。前两个问题偏架构设计,第三个问题则直接落到 API 接入层。
这也是为什么我把这篇论文笔记和 TaoToken 的接入实践放在一起写。论文给的是机制层面的思路,但真要跑起来,你得有一个统一的 Key 和 Base URL 来支撑多 Agent 的并发调用。否则每个 Agent 配一套密钥,光是管理就够头疼的。下面我会先讲清楚 INMS 里 Memory Sharing 的机制拆解,然后给出可复制的配置片段,最后演示一次多 Agent 记忆共享请求的验证动作。目标很明确:把论文里的思路变成你本地能跑通的工程配置。
2. TaoToken 统一 Key 接入:多 Agent 共享记忆的前置准备
在动手配置之前,先把 TaoToken 这边的准备工作说清楚。你可以把它理解成一个统一的 API 通道,多个 Agent 共用同一个 Base URL 和 Key,不需要每个 Agent 单独申请一套凭证。对于 Memory Sharing 这种需要频繁跨 Agent 读写的场景,统一通道的好处很明显:鉴权逻辑只维护一份,调用配额集中管理,出问题的时候排查路径也短。
先访问官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 了解整体能力,然后进入控制台创建你的 API Key。控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,在这里你可以生成和管理 Key。生成之后,API Keys 管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,建议你在这里给不同的 Agent 打上标签,方便后续区分调用来源。
这里有个细节值得注意:Memory Sharing 场景下,多个 Agent 会并发读写共享记忆,所以 Key 的权限范围要提前想好。如果你只是本地实验,一个 Key 给所有 Agent 用完全没问题;如果是要跑长期任务,建议按 Agent 角色拆分 Key,比如「检索 Agent 专用」「编码 Agent 专用」,这样某个 Agent 出问题的时候不会影响其他 Agent 的调用配额。
Base URL 统一用 https://taotoken.net/api ,注意这个地址后面不加任何 UTM 参数,直接作为 API 请求的根地址。模型 ID 方面,你可以根据任务复杂度选择,轻量的记忆摘要任务用较小的模型,复杂的推理任务用大模型。具体支持哪些模型,可以在模型对话页面 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 查看当前可用的列表。
接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有针对不同语言和框架的调用示例。如果你用的是 Claude Code 这类工具,可以参考 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude-code-anthropic&utm_campaign=rewrite 里的配置说明。长期跑编码类 Agent 的话,Coding Plan 页面 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 有更详细的套餐说明。
准备工作做完之后,你手里应该有三样东西:一个 Base URL(https://taotoken.net/api)、一个 API Key、一个选定的 Model ID。这三件套是后面所有配置的基础,缺一不可。接下来我会给出具体的配置文件片段,你可以直接复制到自己的项目里。
3. 可复制的多 Agent 记忆共享配置片段
这一节给出实际可用的配置片段。我会用 JSON 和 TOML 两种格式分别演示,你可以根据自己的技术栈选择。核心思路是:所有 Agent 共用同一个 Base URL 和 Key,但通过不同的 system prompt 和记忆读写策略来区分角色。
先看 JSON 格式的配置,适合 Node.js 或 Python 项目直接读取:
{ "taotoken": { "base_url": "https://taotoken.net/api", "api_key": "sk-your-taotoken-key-here", "default_model": "claude-sonnet-4-20250514", "timeout": 60 }, "agents": { "retriever": { "role": "retrieval", "model": "claude-haiku-3-5-20241022", "memory_scope": "shared_read_write", "system_prompt": "你负责从共享记忆池中检索相关信息,并将新发现的资料写入记忆池。" }, "coder": { "role": "coding", "model": "claude-sonnet-4-20250514", "memory_scope": "shared_read_write", "system_prompt": "你负责根据共享记忆中的需求编写代码,并将代码变更记录写入记忆池。" }, "tester": { "role": "testing", "model": "claude-haiku-3-5-20241022", "memory_scope": "shared_read_only", "system_prompt": "你负责运行测试并读取共享记忆中的代码变更,将测试结果写入记忆池。" } }, "memory": { "storage": "local_file", "path": "./shared_memory.json", "max_entries": 500, "ttl_seconds": 86400 } }如果你用的是 TOML 格式,比如 Rust 项目或者某些 Python 工具的配置,可以这样写:
[taotoken] base_url = "https://taotoken.net/api" api_key = "sk-your-taotoken-key-here" default_model = "claude-sonnet-4-20250514" timeout = 60 [agents.retriever] role = "retrieval" model = "claude-haiku-3-5-20241022" memory_scope = "shared_read_write" system_prompt = "你负责从共享记忆池中检索相关信息,并将新发现的资料写入记忆池。" [agents.coder] role = "coding" model = "claude-sonnet-4-20250514" memory_scope = "shared_read_write" system_prompt = "你负责根据共享记忆中的需求编写代码,并将代码变更记录写入记忆池。" [agents.tester] role = "testing" model = "claude-haiku-3-5-20241022" memory_scope = "shared_read_only" system_prompt = "你负责运行测试并读取共享记忆中的代码变更,将测试结果写入记忆池。" [memory] storage = "local_file" path = "./shared_memory.json" max_entries = 500 ttl_seconds = 86400这里有几个参数需要解释一下。memory_scope控制每个 Agent 对共享记忆的读写权限,shared_read_write表示可读可写,shared_read_only表示只读。这个设计对应了 INMS 论文里提到的权限分层思路——不是所有 Agent 都需要写入权限,测试 Agent 只需要读取代码变更并写入测试结果,不需要修改需求描述。
max_entries和ttl_seconds是记忆池的容量控制。Memory Sharing 最大的坑就是记忆无限膨胀,最后每个 Agent 的 prompt 里塞了几万条历史记录,token 直接爆炸。所以一定要设置上限和过期时间,让旧记忆自动淘汰。
如果你用的是 Claude Code 或者类似的工具,配置方式会略有不同。以 Claude Code 为例,你需要在 settings 文件里指定 Base URL 和 Key:
{ "anthropic": { "base_url": "https://taotoken.net/api", "api_key": "sk-your-taotoken-key-here" }, "model": "claude-sonnet-4-20250514" }注意这里的 Base URL 同样是 https://taotoken.net/api ,不要加多余的路径。Model ID 要和你实际使用的模型对应,写错了会直接报 404。
配置写完之后,建议先跑一个最简单的连通性测试,确认 Key 和 Base URL 没问题,再开始多 Agent 的记忆共享逻辑。下一节我会给出具体的验证请求代码。
4. 验证请求:跑通一次多 Agent 记忆共享
配置写好了,接下来要验证它真的能跑通。我会用一个最小化的 Python 示例,演示两个 Agent 如何通过共享记忆池协作完成一个任务。这个示例不依赖任何复杂的框架,只用标准的 requests 库,你可以直接复制运行。
先安装依赖:
pip install requests然后创建一个memory_sharing_demo.py文件:
import json import os import requests from datetime import datetime TAOTOKEN_BASE_URL = "https://taotoken.net/api" TAOTOKEN_API_KEY = os.environ.get("TAOTOKEN_API_KEY", "sk-your-taotoken-key-here") MEMORY_FILE = "./shared_memory.json" def load_memory(): if os.path.exists(MEMORY_FILE): with open(MEMORY_FILE, "r", encoding="utf-8") as f: return json.load(f) return {"entries": []} def save_memory(memory): with open(MEMORY_FILE, "w", encoding="utf-8") as f: json.dump(memory, f, ensure_ascii=False, indent=2) def write_memory(agent_name, content): memory = load_memory() memory["entries"].append({ "agent": agent_name, "content": content, "timestamp": datetime.now().isoformat() }) if len(memory["entries"]) > 500: memory["entries"] = memory["entries"][-500:] save_memory(memory) def read_memory(agent_name, limit=10): memory = load_memory() entries = memory["entries"][-limit:] return "\n".join([f"[{e['agent']}] {e['content']}" for e in entries]) def call_agent(agent_name, system_prompt, user_input, model="claude-haiku-3-5-20241022"): headers = { "Authorization": f"Bearer {TAOTOKEN_API_KEY}", "Content-Type": "application/json" } payload = { "model": model, "max_tokens": 1024, "system": system_prompt, "messages": [ {"role": "user", "content": user_input} ] } response = requests.post( f"{TAOTOKEN_BASE_URL}/v1/messages", headers=headers, json=payload, timeout=60 ) response.raise_for_status() return response.json()["content"][0]["text"] if __name__ == "__main__": # Agent A:检索 Agent,负责收集信息并写入共享记忆 retriever_prompt = "你是一个检索 Agent。请根据用户需求,列出需要查证的关键信息点,每条不超过 50 字。" retriever_result = call_agent( "retriever", retriever_prompt, "我要给一个 Python 项目添加单元测试,需要了解哪些信息?" ) write_memory("retriever", retriever_result) print("检索 Agent 写入完成:") print(retriever_result) # Agent B:编码 Agent,读取共享记忆后继续工作 coder_prompt = "你是一个编码 Agent。请根据共享记忆中的信息,给出下一步的具体操作建议。" shared_context = read_memory("coder") coder_result = call_agent( "coder", coder_prompt, f"当前共享记忆内容:\n{shared_context}\n\n请给出下一步操作建议。" ) write_memory("coder", coder_result) print("\n编码 Agent 读取并写入完成:") print(coder_result)运行之前,先把你的 Key 设置到环境变量里:
export TAOTOKEN_API_KEY="sk-your-taotoken-key-here" python memory_sharing_demo.py如果一切正常,你会看到类似这样的输出:
检索 Agent 写入完成: 1. 项目使用的测试框架(pytest/unittest) 2. 现有代码的模块划分 3. 需要覆盖的核心函数列表 4. 是否已有 CI 配置 编码 Agent 读取并写入完成: 根据共享记忆,建议先确认测试框架,然后为每个核心函数编写测试用例。这个示例虽然简单,但它完整演示了 Memory Sharing 的核心流程:Agent A 产生记忆并写入共享池,Agent B 读取共享池后继续工作。你可以把call_agent函数替换成任何你需要的 Agent 逻辑,共享记忆的读写机制保持不变。
实测下来,这个模式在多个 Agent 协作的场景里非常实用。比如你有一个负责爬取文档的 Agent,一个负责总结的 Agent,一个负责生成代码的 Agent,它们通过共享记忆池传递中间结果,比每个 Agent 单独维护上下文要高效得多。
5. 常见报错排查:401、local proxy failed、reading choices
多 Agent 接入的过程中,有几个报错出现的频率特别高。我把自己踩过的坑整理出来,你可以对照着排查。
401 Unauthorized
这是最常见的鉴权错误。原因通常是 Key 写错了、Key 过期了、或者请求头格式不对。检查你的请求头,确保是Authorization: Bearer sk-xxx的格式,注意 Bearer 和 Key 之间有一个空格。如果你用的是环境变量,确认环境变量真的被读取到了,可以在代码里打印一下os.environ.get("TAOTOKEN_API_KEY")看看是不是 None。
还有一种情况是 Base URL 写错了。正确的地址是 https://taotoken.net/api ,如果你写成了https://taotoken.net/api/v1或者少了/api,都会导致鉴权失败。记住这个地址后面不加任何多余路径。
local proxy failed
这个报错通常出现在你本地配置了某些网络工具的情况下。TaoToken 的 API 通道是直连的,不需要额外的网络配置。如果你看到这个报错,先检查你的环境变量里有没有HTTP_PROXY或HTTPS_PROXY的设置,有的话先取消掉。另外检查一下你的 hosts 文件,确认没有把taotoken.net指向错误的地址。
reading choices 相关报错
如果你用的是 OpenAI 兼容的调用方式,可能会遇到reading 'choices'这样的报错。这通常是因为响应格式和你的解析代码不匹配。TaoToken 的 API 返回格式是标准的,但如果你用的是 Anthropic 风格的接口,返回的是content字段而不是choices。检查你的解析代码,确认它和实际返回的 JSON 结构对应。可以在请求之后先打印完整的 response.json() 看看结构。
OAuth 相关报错
如果你用的是 Claude Code 或者其他需要 OAuth 的工具,可能会遇到 OAuth 相关的报错。这种情况下,检查你的 settings 文件里是否正确配置了 Base URL 和 Key。以 Claude Code 为例,配置里需要同时指定base_url和api_key,缺一不可。如果你用的是 CC Switch 或者 Cline MCP 这类工具,配置里要写全三件套:Base URL、Key、Model ID。少写任何一个都会导致连接失败。
模型 ID 写错导致的 404
这个报错信息通常比较模糊,可能只显示model not found。解决办法是去模型对话页面确认当前可用的模型 ID,不要凭记忆写。模型 ID 是区分大小写的,claude-sonnet-4-20250514和Claude-Sonnet-4-20250514是两个不同的字符串。
并发请求导致的限流
多 Agent 场景下,多个 Agent 同时调用 API 是很常见的。如果你看到 429 或者 rate limit 相关的报错,说明触发了限流。解决办法有两个:一是降低并发数,给每个 Agent 加一个简单的请求间隔;二是检查你的套餐配额,确认当前配额是否足够支撑多 Agent 并发。Coding Plan 页面有更详细的配额说明。
排查问题的通用思路是:先确认 Base URL 和 Key 没问题,再确认 Model ID 正确,最后检查请求格式和解析逻辑。大部分报错都出在前两步。
6. 从论文到工程:多 Agent 记忆共享的落地建议
把 INMS 论文里的 Memory Sharing 机制落到工程上,我最大的体会是:不要一上来就追求完美的记忆管理架构。先跑通一个最小的共享记忆池,让两个 Agent 能通过它交换信息,然后再逐步增加权限控制、容量管理、过期淘汰这些机制。
共享记忆的格式尽量用纯文本或者简单的 JSON,不要搞太复杂的嵌套结构。因为最终这些记忆是要塞进 prompt 里的,结构越简单,模型理解起来越容易。我试过用嵌套很深的 JSON 存记忆,结果模型经常解析错字段,后来改成扁平的文本记录,问题就少了很多。
权限控制方面,建议从最小权限开始。默认所有 Agent 都是只读,只有明确需要写入的 Agent 才给写权限。这样即使某个 Agent 出问题,也不会污染整个共享记忆池。
容量管理一定要做。我见过太多项目因为记忆池无限增长,最后每个请求的 prompt 都超过模型上下文限制。设置一个合理的max_entries和ttl_seconds,让旧记忆自动淘汰,比手动清理靠谱得多。
最后,多 Agent 的调用通道尽量统一。用 TaoToken 这样的统一 Key 和 Base URL,比每个 Agent 单独配一套凭证要省心得多。出问题的时候,你只需要检查一个地方,而不是在多个配置之间来回切换。接入文档里有更详细的配置示例,模型对话页面可以快速验证你的 Key 是否可用。长期跑编码类 Agent 的话,Coding Plan 的配额方案值得看一下。