Agent 到底是什么:感知-决策-执行的循环
2026/6/10 1:02:57 网站建设 项目流程

🦞 一只用 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("bytes""encoding/json""fmt""io""net/http""os""strings")// Message 对话消息typeMessagestruct{Rolestring`json:"role"`Contentstring`json:"content"`}// ToolCall 工具调用请求typeToolCallstruct{Namestring`json:"name"`Argumentsstring`json:"arguments"`}// LLMResponse LLM 返回typeLLMResponsestruct{Contentstring`json:"content"`ToolCalls[]ToolCall`json:"tool_calls,omitempty"`}// Agent 最小 Agent 实现typeAgentstruct{apiKeystringmessages[]Message toolsmap[string]func(string)string// 工具名 → 执行函数maxStepsint}funcNewAgent(apiKeystring)*Agent{return&Agent{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;step<a.maxSteps;step++{fmt.Printf("--- Step %d ---\n",step+1)// ① 决策:调用 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.messages=append(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{toolDescs=append(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.messages=append(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;step<a.maxSteps;step++{resp:=a.callLLM()// 决策:AI 想下一步做什么?iflen(resp.ToolCalls)>0{result:=a.executeTool()// 执行:AI 想用工具,就执行a.messages=append(...)// 感知:把结果告诉 AIcontinue// 回到决策}returnresp.Content// 完成:AI 不想用工具了,输出答案}

这就是 Agent 的全部秘密。不是什么黑科技,就是一个for循环包着一个 LLM 调用。


为什么这个模式这么强

普通聊天:用户 → AI → 用户 → AI,单向,一步一问。

Agent:用户 → AI → 工具 → AI → 工具 → AI → 答案,AI 能自己驱动流程。

AI 从一个「回答问题的人」变成了「完成任务的人」。

这个转变的威力有多大?想象一下——以前你让 AI 帮你修 Bug,你得:

  1. 把代码贴给 AI
  2. AI 告诉你哪里有问题
  3. 你手动改
  4. 把改完的代码贴给 AI 确认
  5. 重复 2-4

Agent 模式下:你一句话,它全干了。


一个真实的坑:死循环

我第一次写 Agent 的时候,忘了加maxSteps。结果 AI 陷入了一个循环:读文件 → 觉得没读对 → 又读了一次 → 又觉得没读对……

10 秒钟烧了 15 次 API 调用,全在重复同一件事。

maxSteps 是 Agent 的安全带。永远都要设。

建议值:简单任务 5,中等任务 10,复杂任务 20。超过 20 步的任务建议拆成多个子任务单独跑。


本篇核心收获

概念一句话
Agent 本质感知-决策-执行 的循环
核心代码for + callLLM + executeTool
与聊天机器人区别Agent 能自主调用工具,驱动任务完成
必须的安全措施maxSteps 防止死循环

100 行 Go 代码,一个for循环,你就有了一个能自主完成任务的 Agent。

下一篇我们深入 Agent 最核心的能力——Function Calling:AI 是怎么知道该调用哪个函数的?JSON Schema 怎么定义?函数执行出错了怎么办?完整实现,一行不跳。

关注我,别错过。


🦞 一只用 AI Agent 搭副业产线的程序员

全平台同名:虾哥不加班
需要定制 AI 工具?来聊聊 → lob_ai

源码:GitHub - lobster-bujiaban

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询