编码代理可以读取代码、执行命令、修改文件,甚至持续参与一个跨多天的开发任务。但如果每次会话结束后,代理都忘记项目约定、失败原因和关键决策,它就很难从一次性工具变成稳定的工程伙伴。
“给编码代理一份你拥有的记忆”,核心不是简单地把更多文本塞进上下文,而是把记忆从临时会话中抽离出来,存放在开发者能够查看、修改、备份和删除的位置。这样,代理的行为才不会完全依赖某个产品的隐藏状态或不可见策略。
记忆应该记录什么
编码代理的记忆最好围绕可复用的工程事实,而不是完整保存每次对话。可以优先记录以下内容:
- 项目约定:代码格式、目录边界、测试命令、提交规范。
- 重要决策:为什么选择某个数据库、接口风格或依赖版本。
- 已知陷阱:某个测试必须按特定顺序执行,或者某个脚本不能在生产环境运行。
- 当前状态:正在处理的任务、已验证的方案和仍然存在的风险。
- 用户偏好:例如希望代理先修改测试,再实现功能。
不建议把密码、访问令牌、个人隐私或未经筛选的完整聊天记录写入长期记忆。记忆越长并不代表越有用,过期信息还可能诱导代理做出错误决定。
一种实用的目录结构可以这样设计:
.agent-memory/
├── project.md # 稳定的项目规则
├── decisions.md # 架构和技术决策
├── pitfalls.md # 已知问题与失败经验
└── session.md # 当前任务的短期状态
把记忆放进可审查的工作流
记忆应当像代码和配置一样接受审查。代理可以提出记忆更新建议,但是否写入长期文件,最好由开发者或自动化检查决定。
可以把每条记忆写成结构清晰的记录:
## 2025-03-08: API 错误响应格式
- 决策:所有公开 API 使用 `{ "error": { "code": "...", "message": "..." } }`。
- 原因:客户端需要稳定的机器可读错误码。
- 验证:`pytest tests/api/test_errors.py`
- 状态:有效
这里的日期、验证命令和状态字段很重要。它们帮助人和代理判断一条记忆是否仍然可靠,而不是把历史结论误当成永恒规则。
在每次代理任务开始时,可以将这些文件作为明确的上下文输入。下面是一个可运行、可改造的 Python 示例。它不依赖特定代理产品,假设你已经有一个兼容 OpenAI 风格接口的模型服务,并通过环境变量提供地址和密钥。
运行前安装依赖并设置环境变量:
python -m pip install openai
export OPENAI_API_KEY="replace-me"
export OPENAI_BASE_URL="https://your-model-endpoint.example/v1"
将以下内容保存为 run_agent_with_memory.py:
from pathlib import Path
import os
from openai import OpenAI
MEMORY_DIR = Path(".agent-memory")
MEMORY_FILES = ["project.md", "decisions.md", "pitfalls.md", "session.md"]
def load_memory() -> str:
sections = []
for name in MEMORY_FILES:
path = MEMORY_DIR / name
if path.exists():
sections.append(f"## {name}\n{path.read_text(encoding='utf-8')}")
return "\n\n".join(sections) or "No project memory is available yet."
def main() -> None:
task = input("Task for the coding agent: ").strip()
if not task:
raise SystemExit("A task is required.")
memory = load_memory()
prompt = f"""
You are a coding agent working in the current repository.
Use the project memory as guidance, but treat the repository and tests as the
source of truth. Do not invent a memory entry. At the end, propose only concise
updates that are directly supported by evidence from this task.
PROJECT MEMORY:
{memory}
CURRENT TASK:
{task}
"""
client = OpenAI(
api_key=os.environ["OPENAI_API_KEY"],
base_url=os.getenv("OPENAI_BASE_URL"),
)
response = client.chat.completions.create(
model=os.getenv("MODEL_NAME", "coding-model"),
messages=[{"role": "user", "content": prompt}],
temperature=0,
)
print(response.choices[0].message.content)
if __name__ == "__main__":
main()
这个示例只负责读取记忆并注入提示词,没有自动改写长期文件。实际项目中,可以让代理输出一个单独的 MEMORY_UPDATE 区块,再由脚本检查格式、去除敏感信息并生成补丁,交给开发者审核后合并。
记忆所有权带来的边界
把记忆放在自己的仓库或私有存储中,能够带来更好的可见性和迁移能力,但也会增加维护责任。
一方面,代理需要知道哪些文件可以读取,避免把整个主目录或无关仓库内容作为上下文。另一方面,记忆文件本身可能包含内部架构信息,因此应当遵循仓库的访问控制和密钥扫描规则。可以在提交前运行:
rg -n -i "api[_-]?key|secret|token|password|private key" .agent-memory
这不是完整的安全扫描,只适合作为低成本检查;生产环境仍应使用组织已有的 secret scanning 工具。
还要处理记忆衰减问题。可以给记录增加 状态、适用范围 和 复查日期,并定期删除已经被代码或测试推翻的内容。代理不应拥有无限期保留历史错误的权力。
一份可执行的采用清单
可以从一个小范围项目开始:
- 只建立
project.md和session.md,先验证记忆是否真的减少重复说明。 - 要求代理引用测试、代码或文档作为记忆更新的依据。
- 对长期记忆采用人工审核或 Pull Request 流程。
- 明确禁止写入密钥、个人数据和未经确认的推测。
- 为过期记录设置状态和复查时间。
- 记录代理读取了哪些记忆,便于排查错误行为。
真正有价值的记忆不是代理替你保存的一切,而是团队愿意持续维护的一小组工程事实。让记忆进入自己的文件、版本控制和审查流程,编码代理才能在保持灵活性的同时,拥有可解释、可迁移、可纠正的长期上下文。