Agent Memory机制详解
概述
Trae Agent的memory机制基于**消息列表(Message List)**实现,通过维护一个对话历史记录来保持上下文。这种设计简单高效,符合LLM的交互模式。
Memory架构
sql
┌─────────────────────────────────────────────────────────────────┐
│ Memory架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ _initial_messages (list[LLMMessage]) │ │
│ │ │ │
│ │ ┌─────────────┐ │ │
│ │ │ System Msg │ 系统提示词 │ │
│ │ └─────────────┘ │ │
│ │ ┌─────────────┐ │ │
│ │ │ User Msg │ 用户任务 │ │
│ │ └─────────────┘ │ │
│ │ ┌─────────────┐ │ │
│ │ │ Assistant │ LLM回复 │ │
│ │ └─────────────┘ │ │
│ │ ┌─────────────┐ │ │
│ │ │ Tool Result │ 工具执行结果 │ │
│ │ └─────────────┘ │ │
│ │ ┌─────────────┐ │ │
│ │ │ ... │ 更多消息... │ │
│ │ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ TrajectoryRecorder (轨迹记录器) │ │
│ │ - 持久化存储完整对话历史 │ │
│ │ - 用于调试和分析 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
核心数据结构
LLMMessage - 消息单元
文件 : trae_agent/utils/llm_clients/llm_basics.py
python
@dataclass
class LLMMessage:
"""标准消息格式"""
role: str # 角色: system, user, assistant
content: str | None = None # 消息内容
tool_call: ToolCall | None = None # 工具调用
tool_result: ToolResult | None = None # 工具执行结果
角色类型:
| 角色 | 说明 | 示例 |
|---|---|---|
system |
系统提示词 | "You are an expert AI software engineering agent." |
user |
用户输入 | "修复这个bug..." |
assistant |
LLM回复 | "我来分析这个问题..." |
Memory初始化流程
1. new_task方法 - 创建初始消息
文件 : trae_agent/agent/trae_agent.py (第108-150行)
python
def new_task(
self,
task: str,
extra_args: dict[str, str] | None = None,
tool_names: list[str] | None = None,
):
"""创建新任务,初始化memory"""
# 1. 清空并初始化消息列表
self._initial_messages: list[LLMMessage] = []
# 2. 添加系统提示词
self._initial_messages.append(
LLMMessage(role="system", content=self.get_system_prompt())
)
# 3. 构建用户消息
user_message = ""
user_message += f"[Project root path]:\n{self.project_path}\n\n"
user_message += f"[Problem statement]: {extra_args['issue']}"
# 4. 添加用户消息
self._initial_messages.append(
LLMMessage(role="user", content=user_message)
)
初始消息结构:
ini
_initial_messages = [
LLMMessage(
role="system",
content="You are an expert AI software engineering agent..."
),
LLMMessage(
role="user",
content="[Project root path]: /home/user/project\n\n[Problem statement]: 修复这个bug..."
)
]
Memory更新流程
2. execute_task - 主循环中的Memory更新
文件 : trae_agent/agent/base_agent.py (第159-180行)
python
async def execute_task(self) -> AgentExecution:
# 从初始消息开始
messages = self._initial_messages
step_number = 1
while step_number <= self._max_steps:
# 执行一步,更新messages
messages = await self._run_llm_step(step, messages, execution)
# 完成步骤
await self._finalize_step(step, messages, execution)
step_number += 1
3. _run_llm_step - LLM交互更新Memory
文件 : trae_agent/agent/base_agent.py (第210-236行)
python
async def _run_llm_step(
self,
step: AgentStep,
messages: list[LLMMessage],
execution: AgentExecution
) -> list[LLMMessage]:
# 1. 调用LLM,传入当前messages
llm_response = self._llm_client.chat(messages, self._model_config, self._tools)
# 2. 检查任务是否完成
if self.llm_indicates_task_completed(llm_response):
if self._is_task_completed(llm_response):
# 任务完成,返回当前messages
return messages
else:
# 任务未完成,添加提示消息
return [
LLMMessage(role="user", content=self.task_incomplete_message())
]
else:
# 3. 有工具调用,处理工具调用并更新messages
tool_calls = llm_response.tool_calls
return await self._tool_call_handler(tool_calls, step)
4. _tool_call_handler - 工具调用更新Memory
文件 : trae_agent/agent/base_agent.py (第316-352行)
python
async def _tool_call_handler(
self,
tool_calls: list[ToolCall] | None,
step: AgentStep
) -> list[LLMMessage]:
messages: list[LLMMessage] = []
# 1. 执行工具调用
if self._model_config.parallel_tool_calls:
tool_results = await self._tool_caller.parallel_tool_call(tool_calls)
else:
tool_results = await self._tool_caller.sequential_tool_call(tool_calls)
# 2. 将工具结果转换为消息并添加到列表
for tool_result in tool_results:
message = LLMMessage(role="user", tool_result=tool_result)
messages.append(message)
# 3. 反思结果(可选)
reflection = self.reflect_on_result(tool_results)
if reflection:
messages.append(LLMMessage(role="assistant", content=reflection))
return messages
Memory流转示例
完整对话流程
css
初始状态:
┌─────────────────────────────────────────────────────────────┐
│ _initial_messages │
│ [ │
│ {role: "system", content: "You are..."}, │
│ {role: "user", content: "修复这个bug..."} │
│ ] │
└─────────────────────────────────────────────────────────────┘
│
▼
第1步: LLM调用
┌─────────────────────────────────────────────────────────────┐
│ messages → LLM │
│ LLM返回: "我来查看代码..." + tool_calls │
│ │
│ _initial_messages (不变) │
│ 返回: tool_results_messages │
└─────────────────────────────────────────────────────────────┘
│
▼
第2步: 工具执行
┌─────────────────────────────────────────────────────────────┐
│ 执行工具: view, grep等 │
│ │
│ 返回新messages: [ │
│ {role: "user", tool_result: {...}}, │
│ ] │
└─────────────────────────────────────────────────────────────┘
│
▼
第3步: 合并messages
┌─────────────────────────────────────────────────────────────┐
│ messages = _initial_messages + 新messages │
│ │
│ [ │
│ {role: "system", ...}, │
│ {role: "user", ...}, │
│ {role: "user", tool_result: ...}, ← 新添加 │
│ ] │
└─────────────────────────────────────────────────────────────┘
│
▼
第4步: 再次调用LLM
┌─────────────────────────────────────────────────────────────┐
│ 传入合并后的messages │
│ LLM基于完整上下文回复 │
└─────────────────────────────────────────────────────────────┘
Memory特点
1. 基于消息列表
python
# 简单的列表结构
self._initial_messages: list[LLMMessage] = []
- 使用Python列表维护对话历史
- 每个元素是一个LLMMessage对象
- 按时间顺序排列
2. 无状态设计
python
# 每次调用都传入完整messages
llm_response = self._llm_client.chat(messages, ...)
- LLM本身是无状态的
- 每次调用都传入完整对话历史
- 由LLM维护上下文理解
3. 增量更新
python
# 每步只添加新消息
messages = await self._run_llm_step(step, messages, execution)
- 不删除历史消息
- 只追加新消息
- 保持完整对话上下文
4. 工具结果嵌入
python
message = LLMMessage(role="user", tool_result=tool_result)
messages.append(message)
- 工具执行结果作为user消息
- LLM可以看到工具输出
- 支持多轮工具调用
Memory与轨迹记录的区别
| 特性 | Memory (messages) | Trajectory (轨迹) |
|---|---|---|
| 用途 | 运行时LLM交互 | 持久化存储和调试 |
| 存储 | 内存中的列表 | 文件系统 |
| 内容 | 完整对话历史 | 结构化执行记录 |
| 生命周期 | 任务执行期间 | 长期保存 |
| 访问 | LLM使用 | 人类分析 |
TrajectoryRecorder
文件 : trae_agent/utils/trajectory_recorder.py
python
# 记录每个步骤的详细信息
self._trajectory_recorder.record_agent_step(
step_number=step.step_number,
state=step.state.value,
llm_messages=messages, # 记录当时的messages
llm_response=step.llm_response,
tool_calls=step.tool_calls,
tool_results=step.tool_results,
)
Memory限制
1. 上下文长度限制
python
# LLM有最大token限制
max_tokens: int = 4096 # 或更高
- 消息列表过长会超出LLM上下文窗口
- 可能导致早期信息丢失
- 需要截断或摘要处理
2. 当前实现无截断
python
# 当前代码没有实现自动截断
while step_number <= self._max_steps:
messages = await self._run_llm_step(step, messages, execution)
# messages会不断增长
- 依赖max_steps限制步数
- 不主动管理上下文长度
核心代码索引
| 文件 | 行数 | 职责 |
|---|---|---|
utils/llm_clients/llm_basics.py |
1-52 | LLMMessage定义 |
agent/trae_agent.py |
108-150 | new_task初始化memory |
agent/base_agent.py |
40 | _initial_messages定义 |
agent/base_agent.py |
159-180 | execute_task主循环 |
agent/base_agent.py |
210-236 | _run_llm_step更新memory |
agent/base_agent.py |
316-352 | _tool_call_handler更新memory |
总结
Trae Agent的memory机制设计简洁:
- 基于消息列表 - 使用
list[LLMMessage]维护对话历史 - 无状态LLM - 每次调用传入完整messages
- 增量更新 - 每步追加新消息,不删除历史
- 工具结果嵌入 - 工具输出作为user消息
- 轨迹分离 - Memory用于运行时,Trajectory用于持久化
这种设计简单高效,符合LLM的交互模式,但需要注意上下文长度限制。
最后更新: 2026-03-16