Trae Agent Trajectory 轨迹记录逻辑
概述
Trajectory(轨迹)记录是 Trae Agent 的重要功能,用于捕获 Agent 执行过程中的完整信息,包括 LLM 交互、工具调用、状态转换等。本文档详细分析轨迹记录的逻辑和实现。
一、整体架构
┌─────────────────────────────────────────────────────────────────────────────┐
│ Trajectory 记录系统 │
└─────────────────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────┼─────────────────────────┐
▼ ▼ ▼
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ TrajectoryRecorder │ │ BaseAgent │ │ LLM Clients │
│ (轨迹记录器) │ │ (Agent 基类) │ │ (模型客户端) │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
│ │ │
│ ┌────────────────────┘ │
│ │ │
▼ ▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ 记录 LLM 交互 │◄─────────────────────────────│ 各模型客户端实现 │
│ 记录 Agent 步骤 │ │ (Anthropic/OpenAI │
│ 保存 JSON 文件 │ │ /Google 等) │
└─────────────────────┘ └─────────────────────┘
二、核心组件
2.1 TrajectoryRecorder 类
文件: trae_agent/utils/trajectory_recorder.py
class TrajectoryRecorder:
"""记录 Agent 执行和 LLM 交互的轨迹数据"""
def __init__(self, trajectory_path: str | None = None):
"""初始化轨迹记录器
Args:
trajectory_path: 轨迹文件保存路径,None 则自动生成
"""
if trajectory_path is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
trajectory_path = f"trajectories/trajectory_{timestamp}.json"
self.trajectory_path: Path = Path(trajectory_path).resolve()
self.trajectory_data: dict[str, Any] = {
"task": "",
"start_time": "",
"end_time": "",
"provider": "",
"model": "",
"max_steps": 0,
"llm_interactions": [], # LLM 交互记录
"agent_steps": [], # Agent 执行步骤
"success": False,
"final_result": None,
"execution_time": 0.0,
}
数据结构
| 字段 | 类型 | 说明 |
|---|---|---|
task | str | 任务描述 |
start_time | str | 开始时间 (ISO 格式) |
end_time | str | 结束时间 (ISO 格式) |
provider | str | LLM 提供商 |
model | str | 模型名称 |
max_steps | int | 最大步数限制 |
llm_interactions | list | LLM 交互记录列表 |
agent_steps | list | Agent 执行步骤列表 |
success | bool | 是否成功完成 |
final_result | str | 最终结果 |
execution_time | float | 执行时间(秒) |
2.2 核心方法
start_recording() - 开始记录
def start_recording(
self,
task: str,
provider: str,
model: str,
max_steps: int
) -> None:
"""开始记录新的轨迹
Args:
task: 执行的任务
provider: 使用的 LLM 提供商
model: 使用的模型
max_steps: 最大步数
"""
self._start_time = datetime.now()
self.trajectory_data.update({
"task": task,
"start_time": self._start_time.isoformat(),
"provider": provider,
"model": model,
"max_steps": max_steps,
"llm_interactions": [],
"agent_steps": [],
})
self.save_trajectory() # 立即保存初始状态
record_llm_interaction() - 记录 LLM 交互
def record_llm_interaction(
self,
messages: list[LLMMessage],
response: LLMResponse,
provider: str,
model: str,
tools: list[Any] | None = None,
) -> None:
"""记录一次 LLM 交互"""
interaction = {
"timestamp": datetime.now().isoformat(),
"provider": provider,
"model": model,
"input_messages": [self._serialize_message(msg) for msg in messages],
"response": {
"content": response.content,
"model": response.model,
"finish_reason": response.finish_reason,
"usage": {
"input_tokens": response.usage.input_tokens if response.usage else 0,
"output_tokens": response.usage.output_tokens if response.usage else 0,
"cache_creation_input_tokens": ...,
"cache_read_input_tokens": ...,
"reasoning_tokens": ...,
},
"tool_calls": [self._serialize_tool_call(tc) for tc in response.tool_calls]
if response.tool_calls else None,
},
"tools_available": [tool.name for tool in tools] if tools else None,
}
self.trajectory_data["llm_interactions"].append(interaction)
self.save_trajectory() # 实时保存
record_agent_step() - 记录 Agent 步骤
def record_agent_step(
self,
step_number: int,
state: str,
llm_messages: list[LLMMessage] | None = None,
llm_response: LLMResponse | None = None,
tool_calls: list[ToolCall] | None = None,
tool_results: list[ToolResult] | None = None,
reflection: str | None = None,
error: str | None = None,
) -> None:
"""记录一个 Agent 执行步骤"""
step_data = {
"step_number": step_number,
"timestamp": datetime.now().isoformat(),
"state": state, # thinking/calling_tool/completed/error
"llm_messages": [...], # 序列化后的消息
"llm_response": {...}, # LLM 响应
"tool_calls": [...], # 工具调用
"tool_results": [...], # 工具执行结果
"reflection": reflection, # 反思内容
"error": error, # 错误信息
}
self.trajectory_data["agent_steps"].append(step_data)
self.save_trajectory()
finalize_recording() - 完成记录
def finalize_recording(
self,
success: bool,
final_result: str | None = None
) -> None:
"""完成轨迹记录"""
end_time = datetime.now()
self.trajectory_data.update({
"end_time": end_time.isoformat(),
"success": success,
"final_result": final_result,
"execution_time": (end_time - self._start_time).total_seconds()
if self._start_time else 0.0,
})
self.save_trajectory()
三、与 Agent 的集成
3.1 BaseAgent 中的轨迹记录
文件: trae_agent/agent/base_agent.py
class BaseAgent:
def __init__(self, ...):
# 初始化轨迹记录器(可选)
self._trajectory_recorder: TrajectoryRecorder | None = None
@property
def trajectory_recorder(self) -> TrajectoryRecorder | None:
"""获取轨迹记录器"""
return self._trajectory_recorder
def set_trajectory_recorder(
self,
recorder: TrajectoryRecorder | None
) -> None:
"""设置轨迹记录器"""
self._trajectory_recorder = recorder
# 同时设置到 LLM 客户端
self._llm_client.set_trajectory_recorder(recorder)
3.2 步骤记录触发点
def _finalize_step(
self,
step: AgentStep,
messages: list[LLMMessage],
execution: AgentExecution
) -> None:
"""步骤结束时记录轨迹"""
step.state = AgentStepState.COMPLETED
# 调用记录处理器
self._record_handler(step, messages)
self._update_cli_console(step, execution)
execution.steps.append(step)
def _record_handler(
self,
step: AgentStep,
messages: list[LLMMessage]
) -> None:
"""记录步骤到轨迹"""
if self.trajectory_recorder:
self.trajectory_recorder.record_agent_step(
step_number=step.step_number,
state=step.state.value,
llm_messages=messages,
llm_response=step.llm_response,
tool_calls=step.tool_calls,
tool_results=step.tool_results,
reflection=step.reflection,
error=step.error,
)
3.3 TraeAgent 中的初始化和完成
文件: trae_agent/agent/trae_agent.py
class TraeAgent(BaseAgent):
def new_task(self, task: str, ...):
"""创建新任务时开始记录"""
# ... 其他初始化 ...
# 如果设置了轨迹记录器,开始记录
if self._trajectory_recorder:
self._trajectory_recorder.start_recording(
task=task,
provider=self._llm_client.provider.value,
model=self._model_config.model,
max_steps=self._max_steps,
)
async def execute_task(self) -> AgentExecution:
"""执行任务并完成记录"""
execution = await super().execute_task()
# 完成轨迹记录
if self._trajectory_recorder:
self._trajectory_recorder.finalize_recording(
success=execution.success,
final_result=execution.final_result
)
# 保存 Patch
if self.patch_path is not None:
with open(self.patch_path, "w") as f:
f.write(self.get_git_diff())
return execution
四、与 LLM Clients 的集成
4.1 基类支持
文件: trae_agent/utils/llm_clients/base_client.py
class BaseLLMClient(ABC):
def __init__(self, ...):
self.trajectory_recorder: TrajectoryRecorder | None = None
def set_trajectory_recorder(
self,
recorder: TrajectoryRecorder | None
) -> None:
"""设置轨迹记录器"""
self.trajectory_recorder = recorder
4.2 各客户端实现
所有 LLM 客户端在 chat() 方法中记录交互:
# Anthropic Client 示例
def chat(self, messages, model_config, tools):
# ... 调用 API ...
# 记录轨迹
if self.trajectory_recorder:
self.trajectory_recorder.record_llm_interaction(
messages=messages,
response=llm_response,
provider="anthropic",
model=model_config.model,
tools=tools
)
return llm_response
支持的客户端:
- AnthropicClient
- OpenAIClient
- AzureOpenAIClient
- GoogleClient
- DoubaoClient
- OllamaClient
- OpenRouterClient
五、轨迹文件示例
{
"task": "Fix bug in calculate function",
"start_time": "2026-03-16T10:30:00",
"end_time": "2026-03-16T10:35:30",
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"max_steps": 100,
"llm_interactions": [
{
"timestamp": "2026-03-16T10:30:05",
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"input_messages": [
{"role": "system", "content": "You are an expert..."},
{"role": "user", "content": "Fix the bug..."}
],
"response": {
"content": "I'll analyze the issue...",
"model": "claude-sonnet-4-20250514",
"finish_reason": "stop",
"usage": {
"input_tokens": 1500,
"output_tokens": 800
},
"tool_calls": [
{
"call_id": "tool_001",
"name": "bash",
"arguments": {"command": "ls -la"}
}
]
},
"tools_available": ["bash", "str_replace_based_edit_tool"]
}
],
"agent_steps": [
{
"step_number": 1,
"timestamp": "2026-03-16T10:30:05",
"state": "completed",
"llm_messages": [...],
"llm_response": {...},
"tool_calls": [...],
"tool_results": [...],
"reflection": null,
"error": null
}
],
"success": true,
"final_result": "Bug fixed successfully",
"execution_time": 330.5
}
六、使用方式
6.1 命令行使用
# 自动启用轨迹记录
trae-cli run \
--file problem.txt \
--trajectory-file ./trajectory.json
6.2 编程方式使用
from trae_agent.agent import TraeAgent
from trae_agent.utils.trajectory_recorder import TrajectoryRecorder
# 创建轨迹记录器
recorder = TrajectoryRecorder(trajectory_path="./my_trajectory.json")
# 创建 Agent
agent = TraeAgent(config)
# 设置轨迹记录器
agent.set_trajectory_recorder(recorder)
# 执行任务(自动记录)
execution = await agent.execute_task()
6.3 Agent 包装器使用
文件: trae_agent/agent/agent.py
class Agent:
"""Agent 包装器,自动处理轨迹记录"""
def __init__(self, trajectory_file: str | None = None, ...):
if trajectory_file:
self.trajectory_recorder = TrajectoryRecorder(trajectory_file)
else:
self.trajectory_recorder = TrajectoryRecorder()
self.trajectory_file = self.trajectory_recorder.get_trajectory_path()
self.agent = TraeAgent(...)
self.agent.set_trajectory_recorder(self.trajectory_recorder)
七、设计特点
| 特点 | 说明 |
|---|---|
| 实时保存 | 每次记录后立即保存到文件,防止数据丢失 |
| 可选组件 | 不强制使用,不设置记录器则跳过记录 |
| 完整上下文 | 记录完整的对话历史和工具调用链 |
| 多客户端支持 | 所有 LLM 客户端统一记录格式 |
| 结构化数据 | JSON 格式,便于分析和可视化 |
| 时间戳 | 每个事件都有精确的时间戳 |
八、应用场景
- 调试分析 - 查看 Agent 执行过程中的决策路径
- 性能优化 - 分析 token 使用和执行时间
- 审计追踪 - 记录完整的执行历史
- 回放复现 - 基于轨迹重现执行过程
- 数据收集 - 用于训练和优化模型
最后更新: 2026-03-16