Trae-Agent中的设计模式应用

Trae Agent 设计模式分析

概述

Trae Agent 项目广泛运用了多种经典设计模式,使代码具有良好的扩展性、可维护性和灵活性。本文档详细分析项目中使用的主要设计模式。


一、工厂模式 (Factory Pattern)

1.1 LLMClient 工厂

文件 : trae_agent/utils/llm_clients/llm_client.py

python 复制代码
class LLMClient:
    """LLM 客户端工厂类"""
    
    @staticmethod
    def create(model_config: ModelConfig) -> BaseLLMClient:
        """根据配置创建对应的 LLM 客户端"""
        provider = model_config.model_provider.provider
        
        match provider:
            case "anthropic":
                return AnthropicClient(
                    api_key=model_config.model_provider.api_key,
                    base_url=model_config.model_provider.base_url,
                )
            case "openai":
                return OpenAIClient(
                    api_key=model_config.model_provider.api_key,
                    base_url=model_config.model_provider.base_url,
                )
            case "azure":
                return AzureOpenAIClient(
                    api_key=model_config.model_provider.api_key,
                    base_url=model_config.model_provider.base_url,
                    api_version=model_config.model_provider.api_version,
                )
            case "google":
                return GoogleClient(
                    api_key=model_config.model_provider.api_key,
                )
            case "ollama":
                return OllamaClient(
                    base_url=model_config.model_provider.base_url,
                )
            case _:
                raise ValueError(f"Unknown provider: {provider}")

优点:

  • 客户端代码无需知道具体类名
  • 新增提供商只需添加 case 分支
  • 集中管理对象创建逻辑

1.2 CLIConsole 工厂

文件 : trae_agent/utils/cli/console_factory.py

python 复制代码
class ConsoleFactory:
    """CLI 控制台工厂"""
    
    @staticmethod
    def create_console(
        console_type: ConsoleType,
        mode: ConsoleMode = ConsoleMode.RUN,
        lakeview_config: LakeviewConfig | None = None,
    ) -> CLIConsole:
        """创建对应类型的控制台"""
        match console_type:
            case ConsoleType.SIMPLE:
                return SimpleConsole(mode=mode, lakeview_config=lakeview_config)
            case ConsoleType.RICH:
                return RichConsole(mode=mode, lakeview_config=lakeview_config)
            case _:
                raise ValueError(f"Unknown console type: {console_type}")

二、抽象工厂模式 (Abstract Factory)

2.1 BaseLLMClient 抽象接口

文件 : trae_agent/utils/llm_clients/base.py

python 复制代码
class BaseLLMClient(ABC):
    """LLM 客户端抽象基类"""
    
    @abstractmethod
    def chat(
        self,
        messages: list[LLMMessage],
        model_config: ModelConfig,
        tools: list[Tool] | None,
    ) -> LLMResponse:
        """与 LLM 进行对话"""
        pass
    
    @abstractmethod
    def convert_messages(
        self, messages: list[LLMMessage]
    ) -> list[dict[str, object]]:
        """转换消息格式"""
        pass
    
    @abstractmethod
    def convert_tools(self, tools: list[Tool]) -> list[dict[str, object]]:
        """转换工具定义格式"""
        pass

具体实现:

  • AnthropicClient - Anthropic API 实现
  • OpenAIClient - OpenAI API 实现
  • AzureOpenAIClient - Azure OpenAI 实现
  • GoogleClient - Google Gemini 实现
  • OllamaClient - Ollama 本地模型实现

优点:

  • 统一接口,不同实现
  • 客户端代码与具体实现解耦
  • 易于扩展新的 LLM 提供商

三、策略模式 (Strategy Pattern)

3.1 工具执行策略

文件 : trae_agent/tools/base.py

python 复制代码
class ToolExecutor:
    """工具执行器,支持并行和串行策略"""
    
    async def parallel_tool_call(
        self, tool_calls: list[ToolCall]
    ) -> list[ToolResult]:
        """并行执行策略"""
        return await asyncio.gather(*[
            self.execute_tool_call(call) for call in tool_calls
        ])
    
    async def sequential_tool_call(
        self, tool_calls: list[ToolCall]
    ) -> list[ToolResult]:
        """串行执行策略"""
        return [await self.execute_tool_call(call) for call in tool_calls]

使用:

python 复制代码
# 根据配置选择策略
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)

3.2 Docker 执行策略

文件 : trae_agent/tools/docker_tool_executor.py

python 复制代码
class DockerToolExecutor:
    """Docker 执行策略包装器"""
    
    def __init__(self, original_executor: ToolExecutor, ...):
        self._original_executor = original_executor
    
    async def execute_tool_call(self, tool_call: ToolCall) -> ToolResult:
        """选择在 Docker 或宿主机执行"""
        if tool_call.name in self._docker_tools:
            # Docker 执行策略
            return await self._execute_in_docker(tool_call)
        else:
            # 宿主机执行策略(委托给原始执行器)
            return await self._original_executor.execute_tool_call(tool_call)

四、注册表模式 (Registry Pattern)

4.1 工具注册表

文件 : trae_agent/tools/__init__.py

python 复制代码
# 工具注册表:名称 -> 工具类
tools_registry: dict[str, type[Tool]] = {
    "bash": BashTool,
    "str_replace_based_edit_tool": TextEditorTool,
    "json_edit_tool": JSONEditTool,
    "sequentialthinking": SequentialThinkingTool,
    "task_done": TaskDoneTool,
    "ckg": CKGTool,
}

# 使用
from trae_agent.tools import tools_registry
tool_class = tools_registry["bash"]
tool_instance = tool_class(model_provider="anthropic")

优点:

  • 运行时动态查找
  • 解耦工具定义和使用
  • 便于扩展新工具

4.2 Agent 类型注册

文件 : trae_agent/agent/agent.py

python 复制代码
# Agent 类型注册表
AGENT_TYPES: dict[str, type[BaseAgent]] = {
    "trae": TraeAgent,
    "code_review": CodeReviewAgent,
    # ...
}

def create_agent(agent_type: str, config: Config) -> BaseAgent:
    """根据类型创建 Agent"""
    if agent_type not in AGENT_TYPES:
        raise ValueError(f"Unknown agent type: {agent_type}")
    return AGENT_TYPES[agent_type](config)

五、模板方法模式 (Template Method Pattern)

5.1 BaseAgent 执行模板

文件 : trae_agent/agent/base_agent.py

python 复制代码
class BaseAgent(ABC):
    """Agent 抽象基类,定义执行模板"""
    
    async def execute_task(self) -> AgentExecution:
        """模板方法:定义执行流程"""
        # 1. 初始化(固定步骤)
        execution = AgentExecution(task=self._task, steps=[])
        
        # 2. 主循环(固定流程)
        while step_number <= self._max_steps:
            # 3. 执行单步(可定制)
            messages = await self._run_llm_step(step, messages, execution)
            
            # 4. 步骤收尾(固定步骤)
            await self._finalize_step(step, messages, execution)
            
            # 5. 检查完成(可定制)
            if execution.agent_state == AgentState.COMPLETED:
                break
        
        # 6. 清理(固定步骤)
        await self._close_tools()
        return execution
    
    @abstractmethod
    async def cleanup_mcp_clients(self) -> None:
        """抽象方法:子类必须实现"""
        pass
    
    def reflect_on_result(self, tool_results: list[ToolResult]) -> str | None:
        """钩子方法:子类可重写"""
        # 默认实现
        ...

具体实现:

python 复制代码
class TraeAgent(BaseAgent):
    async def cleanup_mcp_clients(self) -> None:
        """实现抽象方法"""
        for client in self._mcp_clients.values():
            await client.cleanup()
    
    def reflect_on_result(self, tool_results: list[ToolResult]) -> str | None:
        """重写钩子方法"""
        # 自定义反思逻辑
        ...

六、装饰器模式 (Decorator Pattern)

6.1 重试装饰器

文件 : trae_agent/utils/llm_clients/retry_decorator.py

python 复制代码
def retry_with(max_retries: int = 3, exceptions: tuple = (Exception,)):
    """重试装饰器工厂"""
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return await func(*args, **kwargs)
                except exceptions as e:
                    if attempt == max_retries - 1:
                        raise
                    await asyncio.sleep(2 ** attempt)  # 指数退避
            return None
        return wrapper
    return decorator

# 使用
@retry_with(max_retries=10, exceptions=(APIError,))
async def chat_with_llm(self, messages, tools):
    ...

6.2 属性缓存装饰器

文件 : trae_agent/tools/base.py

python 复制代码
class Tool(ABC):
    """工具基类,使用 @cached_property 缓存属性"""
    
    @cached_property
    def name(self) -> str:
        """缓存工具名称,避免重复计算"""
        return self.get_name()
    
    @cached_property
    def description(self) -> str:
        """缓存工具描述"""
        return self.get_description()
    
    @cached_property
    def parameters(self) -> list[ToolParameter]:
        """缓存工具参数"""
        return self.get_parameters()

七、代理模式 (Proxy Pattern)

7.1 DockerToolExecutor 代理

文件 : trae_agent/tools/docker_tool_executor.py

python 复制代码
class DockerToolExecutor:
    """Docker 执行代理,控制对真实执行器的访问"""
    
    def __init__(self, original_executor: ToolExecutor, ...):
        self._original_executor = original_executor  # 真实执行器
        self._docker_manager = docker_manager
    
    async def execute_tool_call(self, tool_call: ToolCall) -> ToolResult:
        """代理方法:决定在哪里执行"""
        if self._should_execute_in_docker(tool_call):
            # 代理到 Docker
            return await self._execute_in_docker(tool_call)
        else:
            # 委托给真实执行器
            return await self._original_executor.execute_tool_call(tool_call)
    
    async def sequential_tool_call(self, tool_calls: list[ToolCall]) -> list[ToolResult]:
        """代理批量执行"""
        results = []
        for tool_call in tool_calls:
            result = await self.execute_tool_call(tool_call)
            results.append(result)
        return results

优点:

  • 透明地添加 Docker 执行层
  • 无需修改原有 ToolExecutor 代码
  • 灵活控制执行环境

八、观察者模式 (Observer Pattern)

8.1 CLIConsole 状态更新

文件 : trae_agent/agent/base_agent.py

python 复制代码
class BaseAgent:
    def __init__(self, ...):
        self._cli_console: CLIConsole | None = None
    
    def set_cli_console(self, cli_console: CLIConsole | None) -> None:
        """注册观察者"""
        self._cli_console = cli_console
    
    def _update_cli_console(
        self, 
        step: AgentStep | None = None, 
        agent_execution: AgentExecution | None = None
    ) -> None:
        """通知观察者状态变化"""
        if self._cli_console:
            self._cli_console.update_status(step, agent_execution)

观察者实现:

python 复制代码
class SimpleConsole(CLIConsole):
    def update_status(
        self, 
        agent_step: AgentStep | None = None, 
        agent_execution: AgentExecution | None = None
    ):
        """响应状态更新"""
        if agent_step:
            self._print_step(agent_step)
        if agent_execution:
            self._print_execution_summary(agent_execution)

8.2 TrajectoryRecorder 轨迹记录

python 复制代码
class BaseAgent:
    def set_trajectory_recorder(self, recorder: TrajectoryRecorder | None) -> None:
        """注册轨迹记录观察者"""
        self._trajectory_recorder = recorder
    
    def _record_handler(self, step: AgentStep, messages: list[LLMMessage]) -> None:
        """通知轨迹记录器"""
        if self._trajectory_recorder:
            self._trajectory_recorder.record_agent_step(...)

九、建造者模式 (Builder Pattern)

9.1 配置构建

文件 : trae_agent/utils/config.py

python 复制代码
class Config:
    """配置建造者"""
    
    @classmethod
    def create(cls, config_file: str | None = None) -> "Config":
        """建造方法:从文件构建配置对象"""
        config = cls()
        
        # 1. 构建 model_providers
        config.model_providers = cls._build_model_providers(yaml_config)
        
        # 2. 构建 models
        config.models = cls._build_models(yaml_config, config.model_providers)
        
        # 3. 构建 agents
        config.trae_agent = cls._build_agent(yaml_config, config.models)
        
        return config
    
    @classmethod
    def create_from_legacy_config(cls, config_file: str) -> "Config":
        """另一种建造方法:从旧版配置构建"""
        legacy_config = LegacyConfig(config_file)
        
        config = cls()
        config.model_providers = {...}
        config.models = {...}
        config.trae_agent = {...}
        
        return config

十、单例模式 (Singleton Pattern)

10.1 BashSession 管理

文件 : trae_agent/tools/bash_tool.py

python 复制代码
class BashTool(Tool):
    """Bash 工具,维护单一会话"""
    
    def __init__(self, ...):
        self._session: _BashSession | None = None
    
    @property
    def session(self) -> _BashSession:
        """懒加载单例会话"""
        if self._session is None:
            self._session = _BashSession()
            asyncio.create_task(self._session.start())
        return self._session

十一、适配器模式 (Adapter Pattern)

11.1 MCP 工具适配

文件 : trae_agent/tools/mcp_tool.py

python 复制代码
class MCPTool(Tool):
    """MCP 工具适配器,将 MCP 工具适配为内部 Tool 接口"""
    
    def __init__(self, client, tool: mcp.types.Tool, ...):
        self.client = client
        self.tool = tool  # MCP 工具定义
    
    def get_name(self) -> str:
        """适配:MCP name -> 内部 name"""
        return self.tool.name
    
    def get_parameters(self) -> list[ToolParameter]:
        """适配:MCP inputSchema -> 内部 ToolParameter"""
        parameters = []
        input_schema = self.tool.inputSchema
        for name, prop in input_schema.get("properties", {}).items():
            parameters.append(ToolParameter(
                name=name,
                type=prop["type"],
                description=prop["description"],
                required=name in input_schema.get("required", []),
            ))
        return parameters
    
    async def execute(self, arguments: ToolCallArguments) -> ToolExecResult:
        """适配:内部 execute -> MCP call_tool"""
        output = await self.client.call_tool(self.get_name(), arguments)
        return ToolExecResult(output=output.content[0].text)

11.2 消息格式适配

文件 : trae_agent/utils/llm_clients/anthropic_client.py

python 复制代码
class AnthropicClient(BaseLLMClient):
    """将内部消息格式适配为 Anthropic 格式"""
    
    def convert_messages(self, messages: list[LLMMessage]) -> list[MessageParam]:
        """适配消息格式"""
        anthropic_messages = []
        for msg in messages:
            if msg.role == "system":
                anthropic_messages.append({
                    "role": "system",
                    "content": msg.content
                })
            elif msg.role == "user":
                if msg.tool_result:
                    # 适配工具结果格式
                    anthropic_messages.append({
                        "role": "user",
                        "content": [{"type": "tool_result", ...}]
                    })
                else:
                    anthropic_messages.append({
                        "role": "user",
                        "content": msg.content
                    })
        return anthropic_messages

十二、命令模式 (Command Pattern)

12.1 工具调用命令

文件 : trae_agent/tools/base.py

python 复制代码
@dataclass
class ToolCall:
    """命令对象:封装工具调用请求"""
    name: str           # 命令类型
    call_id: str       # 命令唯一标识
    arguments: dict    # 命令参数

class ToolExecutor:
    """命令执行器"""
    
    async def execute_tool_call(self, tool_call: ToolCall) -> ToolResult:
        """执行命令"""
        tool = self.tools[tool_call.name]
        return await tool.execute(tool_call.arguments)

十三、责任链模式 (Chain of Responsibility)

13.1 配置解析链

文件 : trae_agent/utils/config.py

python 复制代码
class Config:
    """配置解析责任链"""
    
    @classmethod
    def create(cls, config_file: str) -> "Config":
        """按顺序解析配置各部分"""
        yaml_config = yaml.safe_load(open(config_file))
        
        # 责任链:必须按顺序解析
        # 1. 先解析 providers(基础)
        model_providers = cls._parse_providers(yaml_config)
        
        # 2. 再解析 models(依赖 providers)
        models = cls._parse_models(yaml_config, model_providers)
        
        # 3. 最后解析 agents(依赖 models)
        agents = cls._parse_agents(yaml_config, models)
        
        return Config(
            model_providers=model_providers,
            models=models,
            agents=agents
        )

设计模式总结表

设计模式 应用场景 关键文件 优点
工厂模式 LLMClient、CLIConsole 创建 llm_client.py, console_factory.py 解耦创建逻辑
抽象工厂 BaseLLMClient 接口 base.py 统一接口,多实现
策略模式 并行/串行工具执行 base.py 运行时切换策略
注册表模式 工具、Agent 类型管理 __init__.py 动态查找扩展
模板方法 BaseAgent 执行流程 base_agent.py 复用流程,定制细节
装饰器模式 重试、缓存 retry_decorator.py 透明添加功能
代理模式 Docker 执行代理 docker_tool_executor.py 控制访问
观察者模式 CLI 更新、轨迹记录 base_agent.py 松耦合通信
建造者模式 配置构建 config.py 分步构建复杂对象
单例模式 BashSession bash_tool.py 全局唯一实例
适配器模式 MCP 工具、消息格式 mcp_tool.py 接口兼容
命令模式 ToolCall 封装 base.py 解耦请求和执行
责任链模式 配置解析顺序 config.py 按序处理

学习建议

  1. 从简单模式开始 - 先理解工厂、单例等基础模式
  2. 结合实际场景 - 理解为什么在这个场景使用这个模式
  3. 关注接口设计 - 模式的核心是良好的接口抽象
  4. 避免过度设计 - 不要为了用模式而用模式
  5. 阅读源码注释 - 很多设计意图都在注释中体现

最后更新: 2026-03-16

相关推荐
百慕大三角2 小时前
pi-mono sdk中文文档
人工智能·ai编程
const_qiu2 小时前
微服务测试策略:端到端质量保障
微服务·云原生·架构
码路高手2 小时前
Trae-Agent中的Evaluation架构分析
人工智能·架构
殷紫川2 小时前
别再乱用了!幂等处理与分布式锁,90% 开发者都踩过的坑与正确落地姿势
分布式·架构
lifallen2 小时前
从零推导 Plan-Execute (计划-执行) Agent
人工智能·语言模型
ALex_zry2 小时前
现代C++设计模式实战:从AIDC项目看工业级代码架构
c++·设计模式·架构
开开心心就好2 小时前
免费自媒体多功能工具箱,图片音视频处理
人工智能·pdf·ocr·excel·音视频·语音识别·媒体
昨夜见军贴06162 小时前
AI审核守护透析安全:IACheck助力透析微生物检测报告精准合规
大数据·人工智能·安全