一只用 AI Agent 搭副业产线的程序员给你看一段对话用户帮我分析这个 Go 项目里有几个 SQL 注入风险 AI好的我来看看……额我没法看你的代码。你把代码贴给我。 用户贴代码 AI发现 3 处风险。第 12 行、第 47 行、第 89 行。 用户能帮我自动修复吗 AI我做不到我只能给你建议。这是聊天机器人。你问一句它答一句。像个实习生——聪明但不主动。Agent 不是这样的。Agent 是这样的用户帮我检查 project-a 里的 SQL 注入风险自动修好然后跑一下测试确保没挂。 Agent收到。 → 读取 project-a 下所有 .go 文件 → 逐个分析 SQL 拼接 → 发现 3 处风险 → 改成参数化查询 → 执行 go test ./... → 测试通过 ✓ → 输出修改报告Agent 和聊天机器人的区别就一个词自主行动。这篇我们用 100 行 Go 代码写一个最小的 Agent让你看到它的核心骨架。Agent 的骨架感知-决策-执行循环所有 Agent不管多复杂拆开就是三个步骤的循环┌─────────────────────────────────────────────┐ │ │ │ ① 感知Perception │ │ 读取环境信息——文件、API 返回、用户输入 │ │ ↓ │ │ ② 决策Decision │ │ 用 LLM 分析当前状态决定下一步做什么 │ │ ↓ │ │ ③ 执行Execution │ │ 调用工具、操作文件、发送请求产生实际效果 │ │ ↓ │ │ 回到 ①直到任务完成 │ │ │ └─────────────────────────────────────────────┘这跟你每天上班一模一样看 Jira → 决定做什么 → 写代码 → 看结果 → 决定下一步。Agent 只是把这个过程自动化了。100 行 Go 实现不废话直接上代码。packagemainimport(bytesencoding/jsonfmtionet/httposstrings)// Message 对话消息typeMessagestruct{Rolestringjson:roleContentstringjson:content}// ToolCall 工具调用请求typeToolCallstruct{Namestringjson:nameArgumentsstringjson:arguments}// LLMResponse LLM 返回typeLLMResponsestruct{Contentstringjson:contentToolCalls[]ToolCalljson:tool_calls,omitempty}// Agent 最小 Agent 实现typeAgentstruct{apiKeystringmessages[]Message toolsmap[string]func(string)string// 工具名 → 执行函数maxStepsint}funcNewAgent(apiKeystring)*Agent{returnAgent{apiKey:apiKey,maxSteps:10,tools:make(map[string]func(string)string),}}// RegisterTool 注册一个工具func(a*Agent)RegisterTool(namestring,fnfunc(string)string){a.tools[name]fn}// Run 启动 Agent 循环func(a*Agent)Run(taskstring)string{// 初始化只告诉 Agent 任务a.messages[]Message{{Role:system,Content:a.buildSystemPrompt()},{Role:user,Content:task},}// 主循环感知 → 决策 → 执行forstep:0;stepa.maxSteps;step{fmt.Printf(--- Step %d ---\n,step1)// ① 决策调用 LLM让它决定下一步resp:a.callLLM()// ② 如果 LLM 决定调用工具 → 执行iflen(resp.ToolCalls)0{for_,tc:rangeresp.ToolCalls{fmt.Printf( 调用工具: %s(%s)\n,tc.Name,tc.Arguments)result:a.executeTool(tc)// ③ 把执行结果反馈给 LLM感知 → 下一轮决策a.messagesappend(a.messages,Message{Role:user,Content:fmt.Sprintf(工具 %s 的执行结果%s,tc.Name,result),})}continue}// ④ 没有工具调用 → 任务完成返回最终答案returnresp.Content}return达到最大步数限制}func(a*Agent)buildSystemPrompt()string{vartoolDescs[]stringforname:rangea.tools{toolDescsappend(toolDescs,name)}returnfmt.Sprintf(你是一个自主 Agent。完成任务时如果需要使用工具 在回复中以 JSON 格式指定工具调用 {tool_calls: [{name: 工具名, arguments: 参数}]} 可用工具%s 当你不再需要工具时直接输出最终答案。,strings.Join(toolDescs,, ))}func(a*Agent)callLLM()LLMResponse{body,_:json.Marshal(map[string]interface{}{model:deepseek-v4-pro,messages:a.messages,})req,_:http.NewRequest(POST,https://api.deepseek.com/anthropic/v1/messages,bytes.NewReader(body))req.Header.Set(Authorization,Bearer a.apiKey)req.Header.Set(Content-Type,application/json)resp,_:http.DefaultClient.Do(req)deferresp.Body.Close()data,_:io.ReadAll(resp.Body)varllmResp LLMResponse json.Unmarshal(data,llmResp)// 记录 LLM 的回复到历史a.messagesappend(a.messages,Message{Role:assistant,Content:llmResp.Content,})returnllmResp}func(a*Agent)executeTool(tc ToolCall)string{fn,ok:a.tools[tc.Name]if!ok{returnfmt.Sprintf(错误未知工具 %s,tc.Name)}returnfn(tc.Arguments)}// ──────────── 示例工具 ────────────funcmain(){agent:NewAgent(os.Getenv(DEEPSEEK_API_KEY))// 注册工具读取文件agent.RegisterTool(read_file,func(pathstring)string{content,err:os.ReadFile(strings.TrimSpace(path))iferr!nil{returnfmt.Sprintf(读取失败%v,err)}returnstring(content)})// 注册工具运行命令agent.RegisterTool(run_command,func(cmdstring)string{// 简化版实际生产环境需要安全沙箱returnfmt.Sprintf(命令 %s 执行成功模拟,cmd)})result:agent.Run(读取 main.go 文件检查里面有没有 TODO 注释)fmt.Println(\n✅ 最终结果,result)}拆解这个循环核心就 30 行——Run方法里的for循环forstep:0;stepa.maxSteps;step{resp:a.callLLM()// 决策AI 想下一步做什么iflen(resp.ToolCalls)0{result:a.executeTool()// 执行AI 想用工具就执行a.messagesappend(...)// 感知把结果告诉 AIcontinue// 回到决策}returnresp.Content// 完成AI 不想用工具了输出答案}这就是 Agent 的全部秘密。不是什么黑科技就是一个for循环包着一个 LLM 调用。为什么这个模式这么强普通聊天用户 → AI → 用户 → AI单向一步一问。Agent用户 → AI → 工具 → AI → 工具 → AI → 答案AI 能自己驱动流程。AI 从一个「回答问题的人」变成了「完成任务的人」。这个转变的威力有多大想象一下——以前你让 AI 帮你修 Bug你得把代码贴给 AIAI 告诉你哪里有问题你手动改把改完的代码贴给 AI 确认重复 2-4Agent 模式下你一句话它全干了。一个真实的坑死循环我第一次写 Agent 的时候忘了加maxSteps。结果 AI 陷入了一个循环读文件 → 觉得没读对 → 又读了一次 → 又觉得没读对……10 秒钟烧了 15 次 API 调用全在重复同一件事。maxSteps 是 Agent 的安全带。永远都要设。建议值简单任务 5中等任务 10复杂任务 20。超过 20 步的任务建议拆成多个子任务单独跑。本篇核心收获概念一句话Agent 本质感知-决策-执行 的循环核心代码for callLLM executeTool与聊天机器人区别Agent 能自主调用工具驱动任务完成必须的安全措施maxSteps 防止死循环100 行 Go 代码一个for循环你就有了一个能自主完成任务的 Agent。下一篇我们深入 Agent 最核心的能力——Function CallingAI 是怎么知道该调用哪个函数的JSON Schema 怎么定义函数执行出错了怎么办完整实现一行不跳。关注我别错过。 一只用 AI Agent 搭副业产线的程序员全平台同名虾哥不加班需要定制 AI 工具来聊聊 → lob_ai源码GitHub - lobster-bujiaban
Agent 到底是什么:感知-决策-执行的循环
发布时间:2026/6/10 1:02:58
一只用 AI Agent 搭副业产线的程序员给你看一段对话用户帮我分析这个 Go 项目里有几个 SQL 注入风险 AI好的我来看看……额我没法看你的代码。你把代码贴给我。 用户贴代码 AI发现 3 处风险。第 12 行、第 47 行、第 89 行。 用户能帮我自动修复吗 AI我做不到我只能给你建议。这是聊天机器人。你问一句它答一句。像个实习生——聪明但不主动。Agent 不是这样的。Agent 是这样的用户帮我检查 project-a 里的 SQL 注入风险自动修好然后跑一下测试确保没挂。 Agent收到。 → 读取 project-a 下所有 .go 文件 → 逐个分析 SQL 拼接 → 发现 3 处风险 → 改成参数化查询 → 执行 go test ./... → 测试通过 ✓ → 输出修改报告Agent 和聊天机器人的区别就一个词自主行动。这篇我们用 100 行 Go 代码写一个最小的 Agent让你看到它的核心骨架。Agent 的骨架感知-决策-执行循环所有 Agent不管多复杂拆开就是三个步骤的循环┌─────────────────────────────────────────────┐ │ │ │ ① 感知Perception │ │ 读取环境信息——文件、API 返回、用户输入 │ │ ↓ │ │ ② 决策Decision │ │ 用 LLM 分析当前状态决定下一步做什么 │ │ ↓ │ │ ③ 执行Execution │ │ 调用工具、操作文件、发送请求产生实际效果 │ │ ↓ │ │ 回到 ①直到任务完成 │ │ │ └─────────────────────────────────────────────┘这跟你每天上班一模一样看 Jira → 决定做什么 → 写代码 → 看结果 → 决定下一步。Agent 只是把这个过程自动化了。100 行 Go 实现不废话直接上代码。packagemainimport(bytesencoding/jsonfmtionet/httposstrings)// Message 对话消息typeMessagestruct{Rolestringjson:roleContentstringjson:content}// ToolCall 工具调用请求typeToolCallstruct{Namestringjson:nameArgumentsstringjson:arguments}// LLMResponse LLM 返回typeLLMResponsestruct{Contentstringjson:contentToolCalls[]ToolCalljson:tool_calls,omitempty}// Agent 最小 Agent 实现typeAgentstruct{apiKeystringmessages[]Message toolsmap[string]func(string)string// 工具名 → 执行函数maxStepsint}funcNewAgent(apiKeystring)*Agent{returnAgent{apiKey:apiKey,maxSteps:10,tools:make(map[string]func(string)string),}}// RegisterTool 注册一个工具func(a*Agent)RegisterTool(namestring,fnfunc(string)string){a.tools[name]fn}// Run 启动 Agent 循环func(a*Agent)Run(taskstring)string{// 初始化只告诉 Agent 任务a.messages[]Message{{Role:system,Content:a.buildSystemPrompt()},{Role:user,Content:task},}// 主循环感知 → 决策 → 执行forstep:0;stepa.maxSteps;step{fmt.Printf(--- Step %d ---\n,step1)// ① 决策调用 LLM让它决定下一步resp:a.callLLM()// ② 如果 LLM 决定调用工具 → 执行iflen(resp.ToolCalls)0{for_,tc:rangeresp.ToolCalls{fmt.Printf( 调用工具: %s(%s)\n,tc.Name,tc.Arguments)result:a.executeTool(tc)// ③ 把执行结果反馈给 LLM感知 → 下一轮决策a.messagesappend(a.messages,Message{Role:user,Content:fmt.Sprintf(工具 %s 的执行结果%s,tc.Name,result),})}continue}// ④ 没有工具调用 → 任务完成返回最终答案returnresp.Content}return达到最大步数限制}func(a*Agent)buildSystemPrompt()string{vartoolDescs[]stringforname:rangea.tools{toolDescsappend(toolDescs,name)}returnfmt.Sprintf(你是一个自主 Agent。完成任务时如果需要使用工具 在回复中以 JSON 格式指定工具调用 {tool_calls: [{name: 工具名, arguments: 参数}]} 可用工具%s 当你不再需要工具时直接输出最终答案。,strings.Join(toolDescs,, ))}func(a*Agent)callLLM()LLMResponse{body,_:json.Marshal(map[string]interface{}{model:deepseek-v4-pro,messages:a.messages,})req,_:http.NewRequest(POST,https://api.deepseek.com/anthropic/v1/messages,bytes.NewReader(body))req.Header.Set(Authorization,Bearer a.apiKey)req.Header.Set(Content-Type,application/json)resp,_:http.DefaultClient.Do(req)deferresp.Body.Close()data,_:io.ReadAll(resp.Body)varllmResp LLMResponse json.Unmarshal(data,llmResp)// 记录 LLM 的回复到历史a.messagesappend(a.messages,Message{Role:assistant,Content:llmResp.Content,})returnllmResp}func(a*Agent)executeTool(tc ToolCall)string{fn,ok:a.tools[tc.Name]if!ok{returnfmt.Sprintf(错误未知工具 %s,tc.Name)}returnfn(tc.Arguments)}// ──────────── 示例工具 ────────────funcmain(){agent:NewAgent(os.Getenv(DEEPSEEK_API_KEY))// 注册工具读取文件agent.RegisterTool(read_file,func(pathstring)string{content,err:os.ReadFile(strings.TrimSpace(path))iferr!nil{returnfmt.Sprintf(读取失败%v,err)}returnstring(content)})// 注册工具运行命令agent.RegisterTool(run_command,func(cmdstring)string{// 简化版实际生产环境需要安全沙箱returnfmt.Sprintf(命令 %s 执行成功模拟,cmd)})result:agent.Run(读取 main.go 文件检查里面有没有 TODO 注释)fmt.Println(\n✅ 最终结果,result)}拆解这个循环核心就 30 行——Run方法里的for循环forstep:0;stepa.maxSteps;step{resp:a.callLLM()// 决策AI 想下一步做什么iflen(resp.ToolCalls)0{result:a.executeTool()// 执行AI 想用工具就执行a.messagesappend(...)// 感知把结果告诉 AIcontinue// 回到决策}returnresp.Content// 完成AI 不想用工具了输出答案}这就是 Agent 的全部秘密。不是什么黑科技就是一个for循环包着一个 LLM 调用。为什么这个模式这么强普通聊天用户 → AI → 用户 → AI单向一步一问。Agent用户 → AI → 工具 → AI → 工具 → AI → 答案AI 能自己驱动流程。AI 从一个「回答问题的人」变成了「完成任务的人」。这个转变的威力有多大想象一下——以前你让 AI 帮你修 Bug你得把代码贴给 AIAI 告诉你哪里有问题你手动改把改完的代码贴给 AI 确认重复 2-4Agent 模式下你一句话它全干了。一个真实的坑死循环我第一次写 Agent 的时候忘了加maxSteps。结果 AI 陷入了一个循环读文件 → 觉得没读对 → 又读了一次 → 又觉得没读对……10 秒钟烧了 15 次 API 调用全在重复同一件事。maxSteps 是 Agent 的安全带。永远都要设。建议值简单任务 5中等任务 10复杂任务 20。超过 20 步的任务建议拆成多个子任务单独跑。本篇核心收获概念一句话Agent 本质感知-决策-执行 的循环核心代码for callLLM executeTool与聊天机器人区别Agent 能自主调用工具驱动任务完成必须的安全措施maxSteps 防止死循环100 行 Go 代码一个for循环你就有了一个能自主完成任务的 Agent。下一篇我们深入 Agent 最核心的能力——Function CallingAI 是怎么知道该调用哪个函数的JSON Schema 怎么定义函数执行出错了怎么办完整实现一行不跳。关注我别错过。 一只用 AI Agent 搭副业产线的程序员全平台同名虾哥不加班需要定制 AI 工具来聊聊 → lob_ai源码GitHub - lobster-bujiaban