Trae-Agent中的轨迹记录逻辑分析

3 阅读5分钟

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,
        }
数据结构
字段类型说明
taskstr任务描述
start_timestr开始时间 (ISO 格式)
end_timestr结束时间 (ISO 格式)
providerstrLLM 提供商
modelstr模型名称
max_stepsint最大步数限制
llm_interactionslistLLM 交互记录列表
agent_stepslistAgent 执行步骤列表
successbool是否成功完成
final_resultstr最终结果
execution_timefloat执行时间(秒)

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 格式,便于分析和可视化
时间戳每个事件都有精确的时间戳

八、应用场景

  1. 调试分析 - 查看 Agent 执行过程中的决策路径
  2. 性能优化 - 分析 token 使用和执行时间
  3. 审计追踪 - 记录完整的执行历史
  4. 回放复现 - 基于轨迹重现执行过程
  5. 数据收集 - 用于训练和优化模型

最后更新: 2026-03-16