🦞 一只用 AI Agent 搭副业产线的程序员
前 9 篇文章,我们拆解了 Agent 的每个零件:感知-决策循环、Function Calling、Tool 接口、ReAct、Plan-and-Execute、多 Agent 协作、记忆系统、自我反思、人机协作。
现在把这些零件组装成一个完整的框架。你可以直接拿这个架构去写自己的 Agent,不用从零搭。
模块四知识地图
┌──────────────────────┐ │ Agent 核心循环 │ │ 感知 → 决策 → 执行 │ ← 第 31 篇 └──────────┬───────────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ ┌────────────────┐ ┌──────────────┐ ┌─────────────────┐ │ Function │ │ Tool 接口 │ │ 推理模式 │ │ Calling │ │ 统一设计 │ │ ReAct / P&E │ │ 第 32 篇 │ │ 第 33 篇 │ │ 第 34/35 篇 │ └────────────────┘ └──────────────┘ └─────────────────┘ │ │ │ └──────────────────┼──────────────────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ ┌────────────────┐ ┌──────────────┐ ┌─────────────────┐ │ 多 Agent 协作 │ │ 记忆系统 │ │ 自我反思 │ │ 第 36 篇 │ │ 第 37 篇 │ │ 第 38 篇 │ └────────────────┘ └──────────────┘ └─────────────────┘ │ ▼ ┌──────────────────────┐ │ Human-in-the-Loop │ │ 安全阀门 │ ← 第 39 篇 └──────────────────────┘通用 Agent 框架设计
packageframeworkimport("context""time")// ───────── 核心接口 ─────────// Agent 所有 Agent 的统一接口typeAgentinterface{// Run 执行任务,返回最终输出Run(ctx context.Context,taskstring)(string,error)// Name Agent 名称Name()string// Describe 描述 Agent 的能力Describe()string}// Tool 工具接口(来自第 33 篇)typeToolinterface{Name()stringDescription()stringParameters()SchemaExecute(ctx context.Context,argsstring)Result}// Memory 记忆接口(来自第 37 篇)typeMemoryinterface{Remember(msg Message)Recall(querystring)stringConsolidate()// 巩固短期记忆到长期}// Planner 规划器接口(来自第 35 篇)typePlannerinterface{CreatePlan(goalstring,contextstring)(Plan,error)RevisePlan(plan Plan,feedbackstring)(Plan,error)}// Critic 反思接口(来自第 38 篇)typeCriticinterface{Review(outputstring,criteriastring)ReviewResult}// HumanGate 人机协作接口(来自第 39 篇)typeHumanGateinterface{RequestApproval(req ConfirmationRequest)ConfirmationResponse}// ───────── 基础类型 ─────────typeMessagestruct{Rolestring`json:"role"`Contentstring`json:"content"`Timestamp time.Time`json:"timestamp"`}typeSchemastruct{Typestring`json:"type"`Propertiesmap[string]Property`json:"properties"`Required[]string`json:"required"`}typePropertystruct{Typestring`json:"type"`Descriptionstring`json:"description"`Enum[]string`json:"enum,omitempty"`}typeResultstruct{Successbool`json:"success"`Datastring`json:"data"`Errorstring`json:"error,omitempty"`}typePlanstruct{Goalstring`json:"goal"`Tasks[]Task`json:"tasks"`}typeTaskstruct{IDstring`json:"id"`Namestring`json:"name"`Descriptionstring`json:"description"`DependsOn[]string`json:"depends_on"`Actionstring`json:"action"`}typeReviewResultstruct{HasIssuesboolIssues[]string}typeConfirmationRequeststruct{StepIDstringActionstringDetailsstringRisk RiskLevel}typeConfirmationResponsestruct{ApprovedboolCommentstring}typeRiskLevelintconst(RiskLow RiskLevel=iotaRiskMedium RiskHigh RiskCritical)// ───────── Agent 配置 ─────────typeAgentConfigstruct{Namestring`json:"name"`SystemPromptstring`json:"system_prompt"`Modelstring`json:"model"`Temperaturefloat64`json:"temperature"`MaxStepsint`json:"max_steps"`MaxTokensint`json:"max_tokens"`StepTimeout time.Duration`json:"step_timeout"`EnableReActbool`json:"enable_react"`EnableReflectbool`json:"enable_reflect"`MaxReflectionsint`json:"max_reflections"`AutoApproveRisk RiskLevel`json:"auto_approve_risk"`}funcDefaultConfig()AgentConfig{returnAgentConfig{Model:"deepseek-v4-pro",Temperature:0.2,MaxSteps:15,MaxTokens:8000,StepTimeout:30*time.Second,EnableReAct:true,EnableReflect:true,MaxReflections:3,AutoApproveRisk:RiskLow,}}// ───────── 通用 Agent 实现 ─────────typeGenericAgentstruct{config AgentConfig tools*ToolRegistry memory Memory planner Planner critic Critic humanGate HumanGate llmCallfunc([]Message,[]Tool)(string,[]ToolCall,error)messages[]Message}funcNewGenericAgent(config AgentConfig)*GenericAgent{return&GenericAgent{config:config,tools:NewToolRegistry(),memory:NewNoopMemory(),// 默认无记忆planner:nil,// nil 表示使用 ReAct 模式critic:nil,// nil 表示不审查humanGate:NewNoopHumanGate(),// nil 表示不等待确认}}// WithTools 注入工具集func(a*GenericAgent)WithTools(tools...Tool)*GenericAgent{for_,t:=rangetools{a.tools.Register(t)}returna}// WithMemory 注入记忆系统func(a*GenericAgent)WithMemory(m Memory)*GenericAgent{a.memory=mreturna}// WithPlanner 注入规划器(启用 Plan-and-Execute 模式)func(a*GenericAgent)WithPlanner(p Planner)*GenericAgent{a.planner=preturna}// WithCritic 注入反思器func(a*GenericAgent)WithCritic(c Critic)*GenericAgent{a.critic=creturna}// WithHumanGate 注入人机协作func(a*GenericAgent)WithHumanGate(h HumanGate)*GenericAgent{a.humanGate=hreturna}// WithLLM 注入 LLM 调用函数func(a*GenericAgent)WithLLM(fnfunc([]Message,[]Tool)(string,[]ToolCall,error))*GenericAgent{a.llmCall=fnreturna}// Run 执行任务func(a*GenericAgent)Run(ctx context.Context,taskstring)(string,error){// 初始化a.messages=[]Message{{Role:"system",Content:a.config.SystemPrompt},}// 如果有记忆,先检索相关内容ifa.memory!=nil{context:=a.memory.Recall(task)ifcontext!=""{a.messages=append(a.messages,Message{Role:"user",Content:"[相关记忆]\n"+context,})}}a.messages=append(a.messages,Message{Role:"user",Content:task,})// 选择执行模式ifa.planner!=nil{returna.runPlanAndExecute(ctx)}returna.runReAct(ctx)}// runReAct ReAct 模式(第 34 篇)func(a*GenericAgent)runReAct(ctx context.Context)(string,error){forstep:=0;step<a.config.MaxSteps;step++{select{case<-ctx.Done():return"",ctx.Err()default:}// 决策:调用 LLMcontent,toolCalls,err:=a.llmCall(a.messages,a.tools.ListTools())iferr!=nil{return"",fmt.Errorf("LLM 调用失败 (step %d): %w",step,err)}// 有工具调用 → 执行iflen(toolCalls)>0{for_,tc:=rangetoolCalls{// 人机协作检查ifa.humanGate!=nil{risk:=assessRisk(tc.Name,tc.Args)ifrisk>a.config.AutoApproveRisk{resp:=a.humanGate.RequestApproval(ConfirmationRequest{StepID:fmt.Sprintf("step_%d",step),Action:tc.Name,Details:tc.Args,Risk:risk,})if!resp.Approved{return"",fmt.Errorf("步骤被用户拒绝")}}}// 执行工具result:=a.tools.Execute(ctx,tc.Name,tc.Args)a.messages=append(a.messages,Message{Role:"user",Content:fmt.Sprintf("工具 %s 结果: %s",tc.Name,result.Data),})}continue}// 没有工具调用 → 最终答案output:=content// 自我反思(第 38 篇)ifa.critic!=nil{reviewResult:=a.critic.Review(output,"检查正确性和完整性")ifreviewResult.HasIssues{// 注入反思结果,让 LLM 修正a.messages=append(a.messages,Message{Role:"user",Content:fmt.Sprintf("反思发现问题:\n%s\n请修正。",strings.Join(reviewResult.Issues,"\n")),})continue}}// 记忆巩固(第 37 篇)ifa.memory!=nil{a.memory.Remember(Message{Role:"assistant",Content:output,Timestamp:time.Now(),})a.memory.Consolidate()}returnoutput,nil}return"",fmt.Errorf("达到最大步数限制 (%d)",a.config.MaxSteps)}// runPlanAndExecute Plan-and-Execute 模式(第 35 篇)func(a*GenericAgent)runPlanAndExecute(ctx context.Context)(string,error){// 先获取当前上下文contextStr:=""ifa.memory!=nil{contextStr=a.memory.Recall(a.messages[len(a.messages)-1].Content)}plan,err:=a.planner.CreatePlan(a.messages[len(a.messages)-1].Content,contextStr,)iferr!=nil{return"",fmt.Errorf("规划失败: %w",err)}// 执行 DAGresults:=make(map[string]string)for_,task:=rangetopologicalSort(plan.Tasks){// 收集依赖结果vardepResults[]stringfor_,depID:=rangetask.DependsOn{depResults=append(depResults,results[depID])}// 执行单个任务(这里可以用 ReAct 做子任务执行)taskInput:=fmt.Sprintf("任务: %s\n上下文: %s",task.Action,strings.Join(depResults,"\n"))subAgent:=NewGenericAgent(a.config)subAgent.WithTools(a.tools.ListTools()...)subAgent.WithLLM(a.llmCall)// 子任务不需要规划器(用 ReAct)subAgent.planner=nilresult,err:=subAgent.Run(ctx,taskInput)iferr!=nil{return"",fmt.Errorf("任务 %s 失败: %w",task.ID,err)}results[task.ID]=result}// 汇总所有结果varallResults[]stringfor_,t:=rangeplan.Tasks{allResults=append(allResults,fmt.Sprintf("[%s] %s: %s",t.ID,t.Name,results[t.ID]))}returnstrings.Join(allResults,"\n"),nil}// ───────── 辅助函数 ─────────functopologicalSort(tasks[]Task)[]Task{// 实现拓扑排序(见第 35 篇)// ...returntasks}funcassessRisk(toolName,argsstring)RiskLevel{// 根据工具名称和参数评估风险destructive:=[]string{"deploy","drop","delete","force_push","publish"}for_,d:=rangedestructive{ifstrings.Contains(strings.ToLower(toolName),d){returnRiskCritical}}returnRiskLow}// ───────── 空实现(默认值) ─────────typeNoopMemorystruct{}funcNewNoopMemory()*NoopMemory{return&NoopMemory{}}func(n*NoopMemory)Remember(msg Message){}func(n*NoopMemory)Recall(querystring)string{return""}func(n*NoopMemory)Consolidate(){}typeNoopHumanGatestruct{}funcNewNoopHumanGate()*NoopHumanGate{return&NoopHumanGate{}}func(n*NoopHumanGate)RequestApproval(req ConfirmationRequest)ConfirmationResponse{returnConfirmationResponse{Approved:true}}// ───────── Tool 注册中心(来自第 33 篇) ─────────typeToolRegistrystruct{toolsmap[string]Tool}funcNewToolRegistry()*ToolRegistry{return&ToolRegistry{tools:make(map[string]Tool)}}func(r*ToolRegistry)Register(t Tool){r.tools[t.Name()]=t}func(r*ToolRegistry)Execute(ctx context.Context,namestring,argsstring)Result{t,ok:=r.tools[name]if!ok{returnResult{Success:false,Error:fmt.Sprintf("未知工具: %s",name)}}returnt.Execute(ctx,args)}func(r*ToolRegistry)ListTools()[]Tool{vartools[]Toolfor_,t:=ranger.tools{tools=append(tools,t)}returntools}使用示例:5 分钟组装一个代码审查 Agent
funcmain(){// 1. 创建 Agentagent:=framework.NewGenericAgent(framework.AgentConfig{Name:"CodeReviewBot",SystemPrompt:coderPrompt,Model:"deepseek-v4-pro",MaxSteps:10,EnableReAct:true,EnableReflect:true,})// 2. 注册工具agent.WithTools(&FileReader{BasePath:"./project"},&CodeRunner{Timeout:5*time.Second},)// 3. 添加记忆(记住项目上下文)agent.WithMemory(framework.NewShortTermMemory(8000))// 4. 添加自我反思agent.WithCritic(&GoCodeCritic{})// 5. 添加人机协作(危险操作需要确认)agent.WithHumanGate(&framework.ConsoleGate{})// 6. 注入 LLMagent.WithLLM(func(msgs[]framework.Message,tools[]framework.Tool)(string,[]framework.ToolCall,error){returncallDeepSeekAPI(msgs,tools)})// 7. 运行result,err:=agent.Run(context.Background(),"审查 pkg/handler/ 目录下所有 Go 文件的安全漏洞,输出报告")iferr!=nil{log.Fatal(err)}fmt.Println(result)}框架的核心哲学是插件式组装:你需要什么能力就装什么组件。
- 简单任务 → 只装 Tools
- 复杂推理 → 加 ReAct + Memory
- 质量控制 → 加 Critic
- 生产环境 → 加 HumanGate
- 批处理 → 加 Planner
模块四总结地图
| 文章 | 核心能力 | 关键代码量 | 一句话 |
|---|---|---|---|
| 31 | Agent 循环 | ~100 行 | for + LLM + Tool = Agent |
| 32 | Function Calling | ~150 行 | Schema 定义 → LLM 决策 → 你执行 |
| 33 | Tool 接口 | ~200 行 | 统一接口,注册即用 |
| 34 | ReAct | ~180 行 | 推理 → 行动 → 观察 → 再推理 |
| 35 | Plan-and-Execute | ~200 行 | DAG 拓扑排序,先规划再执行 |
| 36 | 多 Agent 协作 | ~180 行 | 一个生成一个审查,互相制约 |
| 37 | 记忆系统 | ~250 行 | 短期窗口 + 长期向量存储 |
| 38 | 自我反思 | ~180 行 | 生成 → 审查 → 修正循环 |
| 39 | Human-in-the-Loop | ~200 行 | 高风险节点拉手刹 |
| 40 | 通用框架 | ~300 行 | 插件式组装,5 分钟搭一个新 Agent |
模块四总计约 1940 行 Go 代码,覆盖了从零到一搭建一个生产级 Agent 的所有核心组件。
下一步
模块四到此结束。你已经掌握了从底层原理到完整框架的 Agent 设计能力。
模块五我们将进入Agent 的实战案例——用这个框架解决真实世界的三个问题:自动化代码审查、智能数据分析、24 小时运维助手。每个案例都是完整可运行的。
关注我,别错过。
🦞 一只用 AI Agent 搭副业产线的程序员
全平台同名:虾哥不加班
需要定制 AI 工具?来聊聊 → lob_ai源码:GitHub - lobster-bujiaban