Agent 人机协作闭环:AI 做事,人做决策,别把 Loop 写成死循环

📅 2026/7/9 6:18:49 👁️ 阅读次数 📝 编程学习
Agent 人机协作闭环:AI 做事,人做决策,别把 Loop 写成死循环

Agent 人机协作闭环:AI 做事,人做决策,别把 Loop 写成死循环

一、Agent 替你写完了代码,然后直接 git push 到了 master

自动化的诱惑让工程师不断给 Agent 开放权限。
先是读取文件,然后是修改文件。
接着是执行命令,最后是 git push。
每一步都合理,直到某天 Agent 执行了rm -rf /tmp/*而路径变量恰好为空。

这不是虚构场景。
AutoGPT 和 BabyAGI 等自主 Agent 的早期用户,都经历过类似事故。
Agent 的 Loop 机制让模型可以不断调用工具、获取反馈、再调用工具。
这个循环里缺少一个关键环节——人的决策。

自主 Agent 和辅助 Agent 有本质区别。
前者追求闭环,后者追求人机协作。
工程落地中,辅助 Agent 远比自主 Agent 有价值。

二、人机协作 Loop 的设计模式

Agent 的标准 Loop 是"思考-行动-观察-再思考"。
人机协作模式在关键节点插入人工确认。

flowchart TB A[用户输入任务] --> B[LLM 分析并生成计划] B --> C{计划是否需要人工确认?} C -->|高风险操作| D[展示计划给用户] D --> E{用户批准?} E -->|是| F[执行工具调用] E -->|否| G[重新规划] G --> B C -->|低风险操作| F F --> H[获取工具结果] H --> I[LLM 分析结果] I --> J{任务完成?} J -->|是| K[汇总输出给用户] J -->|否| L{是否超过最大轮次?} L -->|是| M[请求用户干预] L -->|否| C

三个关键的人机协作点:
第一,高风险操作前的人工确认。
第二,超过 N 轮推理后的人工介入。
第三,置信度低于阈值时的降级处理。

三、带人工确认的 Agent Loop 实现

package agent import ( "context" "fmt" "log" "time" ) // RiskLevel 操作风险等级 type RiskLevel int const ( RiskRead RiskLevel = 0 // 只读操作 RiskWrite RiskLevel = 1 // 数据写入 RiskExec RiskLevel = 2 // 命令执行 RiskDeploy RiskLevel = 3 // 部署操作 ) // Action 单步操作 type Action struct { Tool string `json:"tool"` Params map[string]any `json:"params"` RiskLevel RiskLevel `json:"risk_level"` Reason string `json:"reason"` } // HumanConfirmCallback 人工确认回调 type HumanConfirmCallback func(action Action) (bool, error) // AgentLoop Agent 执行循环 type AgentLoop struct { llmClient LLMClient toolRegistry *ToolRegistry maxSteps int confirmThreshold RiskLevel // 超过此等级需要人工确认 humanConfirm HumanConfirmCallback stepTimeout time.Duration } // Config Agent 配置 type Config struct { MaxSteps int ConfirmThreshold RiskLevel StepTimeout time.Duration } // DefaultConfig 默认配置:10 步限制,写入以上需确认 func DefaultConfig() Config { return Config{ MaxSteps: 10, ConfirmThreshold: RiskWrite, StepTimeout: 30 * time.Second, } } // NewAgentLoop 创建 Agent 循环 func NewAgentLoop( llm LLMClient, registry *ToolRegistry, confirm HumanConfirmCallback, cfg Config, ) *AgentLoop { return &AgentLoop{ llmClient: llm, toolRegistry: registry, maxSteps: cfg.MaxSteps, confirmThreshold: cfg.ConfirmThreshold, humanConfirm: confirm, stepTimeout: cfg.StepTimeout, } } // Run 执行 Agent 任务 func (a *AgentLoop) Run(ctx context.Context, task string) (string, error) { messages := []Message{ {Role: "system", Content: systemPrompt()}, {Role: "user", Content: task}, } for step := 0; step < a.maxSteps; step++ { // 超时保护 stepCtx, cancel := context.WithTimeout(ctx, a.stepTimeout) defer cancel() resp, err := a.llmClient.Chat(stepCtx, messages) if err != nil { return "", fmt.Errorf("第 %d 步 LLM 调用失败: %w", step+1, err) } // 模型决定不再调用工具,输出最终结果 if resp.ToolCall == nil { log.Printf("[Step %d] 任务完成,输出最终结果", step+1) return resp.Content, nil } action := Action{ Tool: resp.ToolCall.Name, Params: resp.ToolCall.Args, RiskLevel: a.assessRisk(resp.ToolCall), Reason: resp.Content, } log.Printf("[Step %d] 计划执行: %s (风险: %d)", step+1, action.Tool, action.RiskLevel) // 🔑 高风险操作需要人工确认 if action.RiskLevel >= a.confirmThreshold { log.Printf("[Step %d] 需要人工确认: %s", step+1, action.Tool) approved, err := a.humanConfirm(action) if err != nil { return "", fmt.Errorf("人工确认异常: %w", err) } if !approved { messages = append(messages, Message{ Role: "user", Content: fmt.Sprintf("操作被拒绝。请换一种方式完成任务。被拒原因:用户不同意执行 %s。", action.Tool), }) continue } log.Printf("[Step %d] 人工已批准", step+1) } // 执行工具调用 result, toolErr := a.toolRegistry.Execute(ctx, resp.ToolCall) if toolErr != nil { // 工具执行失败,告知模型 messages = append(messages, Message{ Role: "tool", Content: fmt.Sprintf("工具 %s 执行失败: %v", action.Tool, toolErr), }) continue } // 将工具结果注入对话 messages = append(messages, Message{Role: "assistant", Content: resp.Content, ToolCall: resp.ToolCall}, Message{Role: "tool", Content: result}, ) } return "", fmt.Errorf("超过最大执行步骤 (%d),任务未完成", a.maxSteps) } // assessRisk 评估操作风险 func (a *AgentLoop) assessRisk(tc *ToolCall) RiskLevel { switch tc.Name { case "read_file", "search", "list_directory": return RiskRead case "write_file", "update_database", "send_email": return RiskWrite case "run_command", "execute_sql": return RiskExec case "git_push", "deploy", "restart_service": return RiskDeploy default: return RiskRead } } func systemPrompt() string { return `你是一个 AI 助手。请逐步完成任务。 每一步你可以调用一个工具。 高风险操作会需要人工确认。` }

四、人机协作的代价与适用边界

人工确认引入等待延迟。
用户可能不在电脑前,任务会卡住。
建议在确认机制中加入超时策略。
超时后降级为只读模式或暂停任务。

确认频率过高会导致"弹窗疲劳"。
用户最终会机械地点击"同意"。
需要根据历史行为动态调整确认阈值。
用户一贯批准的操作,可以降低确认等级。

不适合人机协作的场景:
批量处理成千上万条数据的任务(每步确认不可行);
用户提供明确授权脚本的自动化运维;
非交互式的后台定时任务。

五、总结

Agent 的 Loop 必须有退出机制,不能无限循环。
人机协作闭环在高风险操作前插入人工确认。
风险分级机制让确认策略可配置。
确认超时和频率控制防止弹窗疲劳。
目标是让 AI 有效率地做事,关键决策保留在人手里。