从零设计 Agent 框架(7 个核心模块的优先实现顺序)

从零设计一个 Agent 框架,最常犯的错是一上来就堆功能——记忆、规划、工具、监控、调试面板一齐上,结果是 6 个月后还跑不通一个真实任务。在做内部 Agent 框架”AgentKit”的第一个版本时,我把模块按”必需 → 加分 → 锦上添花”分了三档,先实现最底层的 7 个模块,6 周就交付了一个能跑生产任务的 MVP。下文把这 7 个模块的依赖关系、实现顺序和最小可用版本都讲清,重点是工程团队最关心的”先做哪个能最快打通闭环”。

一、模块依赖全景

一个 Agent 框架的核心模块,大致分三层:

  • 基础层(必须先有,无它整个框架跑不起来):LLM 客户端、工具注册与执行、对话循环;
  • 核心层(决定框架能跑多复杂的任务):记忆管理、规划与任务分解、可观测性;
  • 增值层(让框架好用,延后实现影响也不大):调试 UI、评估体系、多 Agent 协作。

按依赖关系,前 7 个模块的优先级如下:

  1. LLM 客户端(必需)
  2. 工具注册与执行(必需)
  3. 对话循环(必需)
  4. 记忆管理(核心)
  5. 规划与任务分解(核心)
  6. 可观测性(核心)
  7. 错误处理与重试(核心)

二、模块 1:LLM 客户端

最底层,所有其它模块都依赖它。最小可用版本只需要支持:同步调用、流式输出、function calling、错误重试。

class LLMClient:
    def __init__(self, model="gpt-4o", api_key=None):
        self.model = model
        self.client = OpenAI(api_key=api_key)
    
    def chat(self, messages, tools=None, stream=False):
        kwargs = {"model": self.model, "messages": messages}
        if tools: kwargs["tools"] = tools
        if stream: kwargs["stream"] = True
        return self.client.chat.completions.create(**kwargs)

实现要点:用统一的 ChatCompletion 接口封装 OpenAI、Anthropic、本地模型,让上层不关心模型细节。

三、模块 2:工具注册与执行

工具是 Agent 与外部世界交互的桥梁。最小可用版本需要:工具描述 schema、参数校验、调用超时、调用日志。

class ToolRegistry:
    def __init__(self):
        self.tools = {}
    
    def register(self, name, func, description, parameters):
        self.tools[name] = {
            "func": func,
            "schema": {
                "type": "function",
                "function": {
                    "name": name,
                    "description": description,
                    "parameters": parameters
                }
            }
        }
    
    def execute(self, name, arguments, timeout=30):
        if name not in self.tools:
            raise ValueError(f"Tool {name} not found")
        # 参数校验(JSON Schema)
        # jsonschema.validate(arguments, self.tools[name]["schema"]["function"]["parameters"])
        return self.tools[name]["func"](**arguments)

实现要点:工具描述必须严格遵循 OpenAI function calling 格式,这样 LLM 能直接消费。

四、模块 3:对话循环

Agent 的”心脏”:接收用户输入、调 LLM 决策、执行工具、把结果再喂回 LLM,直到任务完成或放弃。

class AgentLoop:
    def __init__(self, llm, tools, max_iterations=10):
        self.llm = llm
        self.tools = tools
        self.max_iterations = max_iterations
    
    def run(self, user_input, system_prompt=""):
        messages = [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_input}
        ]
        for i in range(self.max_iterations):
            resp = self.llm.chat(messages, tools=[t["schema"] for t in self.tools.tools.values()])
            msg = resp.choices[0].message
            messages.append(msg)
            
            if not msg.tool_calls:
                return msg.content
            
            for tc in msg.tool_calls:
                args = json.loads(tc.function.arguments)
                try:
                    result = self.tools.execute(tc.function.name, args)
                except Exception as e:
                    result = f"Error: {str(e)}"
                messages.append({
                    "role": "tool",
                    "tool_call_id": tc.id,
                    "content": str(result)
                })
        
        return "任务超时,请简化后重试"

实现要点:max_iterations 必须设上限,防止死循环;每次循环要记录 trace,便于调试。

五、模块 4:记忆管理

让 Agent 跨任务/跨会话有记忆,是处理复杂任务的必备能力。最小可用版本支持:短期消息列表(上下文窗口)+ 长期向量库(按需检索)。

class Memory:
    def __init__(self, collection_name="agent_memory"):
        import chromadb
        self.client = chromadb.PersistentClient(path="./memory")
        self.collection = self.client.get_or_create_collection(collection_name)
    
    def store(self, text, metadata=None):
        import uuid
        self.collection.add(documents=[text], ids=[str(uuid.uuid4())], metadatas=[metadata] or [{}])
    
    def retrieve(self, query, top_k=3):
        results = self.collection.query(query_texts=[query], n_results=top_k)
        return "\n".join(results["documents"][0]) if results["documents"] else ""

实现要点:短期记忆(对话历史)和长期记忆(向量库)双轨,Agent 每次循环把”相关长期记忆”注入上下文。

六、模块 5:规划与任务分解

复杂任务不能”一杆子捅到底”,需要拆成子任务。最小可用版本支持:Plan-and-Execute 模式(先生成完整计划,再逐步执行,执行中可重规划)。

class Planner:
    def plan(self, goal, available_tools):
        # 调 LLM 生成步骤列表
        prompt = f"""把目标拆成 2-7 个步骤,每步用 available_tools 里的工具或子任务。
目标: {goal}
可用工具: {json.dumps(available_tools, ensure_ascii=False)}
返回 JSON 列表,每项: {{"step": 1, "action": "...", "tool": "...", "input": "..."}}"""
        resp = self.llm.chat([{"role": "user", "content": prompt}])
        return json.loads(resp.choices[0].message.content)

实现要点:规划器本身也是一个 LLM 调用,通常用更便宜的模型(如 gpt-4o-mini)即可。

七、模块 6:可观测性

Agent 调试之所以难,是因为”决策”和”行动”分散在多步循环里。最小可用版本需要:trace_id 贯穿、每步记录 span、span 间能查因果。

import uuid
from datetime import datetime

class Tracer:
    def __init__(self):
        self.spans = []
    
    def start(self, name, parent_id=None):
        span = {
            "id": str(uuid.uuid4()),
            "parent_id": parent_id,
            "name": name,
            "start": datetime.now().isoformat()
        }
        self.spans.append(span)
        return span["id"]
    
    def end(self, span_id, output=None):
        for s in self.spans:
            if s["id"] == span_id:
                s["end"] = datetime.now().isoformat()
                s["output"] = output
                break
    
    def export(self):
        return self.spans

实现要点:span 设计要带 traceid(贯穿整个 Agent 任务)+ parentid(父子关系),便于画调用树。

八、模块 7:错误处理与重试

工具调用失败、LLM 速率限制、网络抖动……Agent 必须能优雅恢复。最小可用版本需要:工具调用失败重试(指数退避)+ LLM 速率限制处理 + 整体降级(工具调不通时改用 LLM 推理兜底)。

import time

class RetryPolicy:
    def __init__(self, max_retries=3, base_delay=1):
        self.max_retries = max_retries
        self.base_delay = base_delay
    
    def execute(self, func, *args, **kwargs):
        for attempt in range(self.max_retries):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                if attempt == self.max_retries - 1:
                    raise
                delay = self.base_delay * (2 ** attempt)
                time.sleep(delay)
        return None

实现要点:可重试错误(网络、超时)自动重试,不可重试错误(参数错、权限拒绝)直接失败转人工。

7 个模块的依赖关系可总结为下面这张表:

序号 模块 依赖 必需 估时(人天)
1 LLM 客户端 无 是 1-2
2 工具注册与执行 1 是 2-3
3 对话循环 1、2 是 2-3
4 记忆管理 1 推荐 2-3
5 规划与任务分解 1、2 推荐 3-5
6 可观测性 1、2、3 推荐 2-3
7 错误处理与重试 1、2 推荐 1-2

九、实施路线图

按下面 8 周时间表推进,可在 6 周交付 MVP:

  • 第 1-2 周:模块 1-3(LLM 客户端 + 工具注册 + 对话循环),打通”用户问 → Agent 调工具 → 返回结果”闭环
  • 第 3-4 周:模块 4-5(记忆 + 规划),让 Agent 能处理多步任务
  • 第 5-6 周:模块 6-7(可观测性 + 错误处理),上生产前的最后一道门
  • 第 7-8 周:接真实业务、收集问题、修 bug、加评估

十、不要先做的模块

几个常见的”过早优化”,应该延后:

  1. 多 Agent 协作:等单 Agent 跑稳再上,否则复杂度爆炸;
  2. 调试 UI:用 trace 日志先凑合,UI 后期再做;
  3. 评估体系:先靠人工事后抽审,有真实流量后再上自动化评估;
  4. 可视化流程编排:大多数任务用代码定义 Agent 就够,可视化是后期优化项。

常见问题(FAQ)

Q1:为什么不用 LangGraph / CrewAI / AutoGen 这些现成框架?

业务有特殊需求(比如必须走内部审批流)时自研更合适;否则先用现成框架,等真碰到瓶颈再考虑自研。

Q2:7 个模块必须按这个顺序吗?

基本是,前 3 个有强依赖(没 LLM 客户端就没对话循环),后 4 个可并行。

Q3:小项目也要做这 7 个吗?

不必。前 3 个必需,后 4 个按需——单 Agent 短任务可能不需要规划也不需要长期记忆。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
其AI的头像其AI普通用户

相关推荐

返回顶部