后端引擎 backend/pkg/agentcli/(纯引擎库,零业务依赖,剥离 CLI/TUI 外壳): - llm: OpenAI 兼容客户端,复用 model.LLMConfig - tools: ssh_execute(复用 pkg/remoteexec)+ analyze_output + 风险评估黑名单 - safety: 三级安全模式 + 五级风险 + WebSocket 异步确认 - prompt: 五层 System Prompt - core: ReAct 16 轮循环 + 自适应检查点 + 循环检测 - evolver: 四层记忆 + 进化循环,data/agentcli/ 文件存储 集成层: - controller/agent_cli.go: WebSocket 控制器(事件流推流 + 高危确认 + 会话持久化) - model/agent_cli.go: agent_cli_sessions/messages 表 + AutoMigrate - 路由 /ws/agent-cli + /api/v1/aiops/agent-cli/sessions - seed 权限 aiops:agent-cli / aiops:llm-config 前端: - AgentCLI.tsx: 对话流 + 工具块 + 高危确认 + 四模块 tips 面板 - LLMConfig.tsx: 大模型设置独立页 - api/agentCli.ts + Sidebar/App 菜单路由 文档: - docs/agent/ 11 篇(opsxcli 同名文档适配改写 + 00-README 映射总览) 其他: - CLAUDE.md 补充 agent-cli 模块说明 - 修正 .gitignore 根级二进制规则(前导 /,避免误伤 frontend/src/components/aiops/) Co-Authored-By: Claude <noreply@anthropic.com>
7.4 KiB
04 - 插件架构设计
本文由 opsxcli 同名设计文档适配改写,结合 aiops Agent CLI 的 Web 实现(
backend/pkg/agentcli/)。 opsxcli 的「plugins/」CLI 插件层(mysql/ssh/ping 等 46+ 命令)在 aiops 中不适用 —— Web 版聚焦远程运维,工具精简为 2 个并改由tools.Tool接口承载。
工具(Tool)= aiops 版的「插件」
opsxcli 有完整的 CLI 插件生态(46+ 命令插件);aiops Agent CLI 把「插件」概念收敛为更纯粹的 Tool 接口:
- 不再有 CLI 命令、参数解析、帮助文本
- 工具的唯一职责是:被 LLM 调用 → 在目标主机做事 → 返回结构化结果
- LLM 通过 function calling 协议感知工具的存在与用法
这是合理的精简:Web Agent 的能力边界由「Tool 接口 + LLM 推理」共同决定,不再需要 CLI 命令那一层。
Tool 接口(5 方法)
// backend/pkg/agentcli/tools/registry.go
type Tool interface {
Name() string // 工具名(LLM 调用时用)
Description() string // 给 LLM 看的描述
Parameters() map[string]interface{} // JSON Schema 参数定义
RiskLevel() RiskLevel // 静态风险等级
Execute(ctx context.Context, args map[string]interface{}) (*Result, error)
}
设计哲学:接口最小化 —— 5 个方法覆盖工具的完整生命周期。
DynamicRiskTool 扩展接口
type DynamicRiskTool interface {
Tool
RiskLevelForArgs(args map[string]interface{}) RiskLevel
}
部分工具的「静态风险」无法反映真实风险(如 ssh_execute 静态是 High,但 df -h 是 Safe、rm -rf / 是 Critical)。这些工具额外实现 DynamicRiskTool,安全控制器 Check 时优先调用动态评估。
Result 结构
type Result struct {
Success bool `json:"success"`
Output string `json:"output"`
Error string `json:"error,omitempty"`
}
Registry 注册中心
type Registry struct {
tools map[string]Tool
mu sync.RWMutex // 读写锁,支持并发注册和查询
}
核心方法:
| 方法 | 说明 |
|---|---|
NewRegistry() |
创建空注册中心 |
Register(tool) |
注册工具(线程安全) |
Get(name) |
按名获取工具(LLM 调用时按名查找) |
List() |
列出所有工具(构建 Prompt Layer 3 工具描述) |
ToLLMTools() |
转换为 OpenAI function calling 格式(自动注入到 LLM tools 参数) |
ToLLMTools() 是 Registry 与 LLM 协议的桥梁:注册的工具自动出现在 LLM 的 function 列表中,无需手动维护。
已注册工具一览
与 opsxcli 的关键差异:opsxcli 有 6 个工具(local_bash / ssh_execute / scp_transfer / file_read / file_search / analyze_output),aiops 精简为 2 个。
| 工具 | 风险等级 | 功能 | 来源 |
|---|---|---|---|
ssh_execute |
High(静态)/ Safe~Critical(动态) | 在目标主机远程执行 shell 命令 | aiops 既有 pkg/remoteexec |
analyze_output |
Safe | 对冗长输出做摘要/错误提取 | 内置 Go 实现 |
为什么精简?
| opsxcli 工具 | aiops 处理 | 原因 |
|---|---|---|
local_bash |
剥离 | Web 后端不应在服务器本地执行命令(安全风险 + 多用户隔离) |
scp_transfer |
剥离 | 文件传输走 aiops 既有的「文件管理」模块,不混入 Agent |
file_read |
剥离 | 远程读文件用 ssh_execute cat,无需独立工具 |
file_search |
剥离 | 远程搜文件用 ssh_execute grep/find |
ssh_execute |
保留 | 核心远程运维能力 |
analyze_output |
保留 | 防止长输出 token 爆炸,辅助 LLM 聚焦关键信息 |
工具越少,LLM 的决策空间越收敛(呼应 Ashby 定律),首次做对的概率越高。
工具分类标准(aiops 版)
放入内置工具集的条件(需同时满足)
- 属于运维 Agent 高频需要的能力
- 无法用现有工具简单组合完成(如
analyze_output不能用ssh_execute替代 —— 它操作的是已有文本而非远程命令) - 实现简洁(单文件 < 300 行)
通过 ssh_execute 间接覆盖的能力
opsxcli 用独立插件实现的能力,在 aiops 中全部由 ssh_execute 执行远程命令覆盖:
| opsxcli 插件能力 | aiops 等效 |
|---|---|
mysql -e "..." |
ssh_execute "mysql -e \"...\"" |
redis-cli ... |
ssh_execute "redis-cli ..." |
ping / traceroute |
ssh_execute "ping ..." |
cat / grep / find |
ssh_execute "cat ..." |
systemctl status nginx |
ssh_execute "systemctl status nginx" |
LLM 会根据任务自主决定执行什么命令,无需为每类命令提供独立工具。
混合架构的好处
- 职责单一:每个工具只做一件事,
ssh_execute执行、analyze_output分析 - 协议简单:LLM 只需理解 2 个 function,决策快、错误少
- 风险可控:所有远程操作统一走
ssh_execute的风险评估(AssessBashRisk),不会因为工具增多而出现安全盲区 - 扩展灵活:未来若需要新工具(如
kubectl_apply),实现 Tool 接口注册即可
扩展指南
添加新工具
- 实现
Tool接口(必要时实现DynamicRiskTool):
// pkg/agentcli/tools/kubectl_get.go
type KubectlGetTool struct{ cfg remoteexec.SSHConfig }
func (t *KubectlGetTool) Name() string { return "kubectl_get" }
func (t *KubectlGetTool) Description() string {
return "在目标主机执行 kubectl get 并返回结果"
}
func (t *KubectlGetTool) Parameters() map[string]interface{} {
return map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"resource": map[string]interface{}{"type": "string", "description": "如 pods/deployments"},
},
"required": []string{"resource"},
}
}
func (t *KubectlGetTool) RiskLevel() tools.RiskLevel { return tools.RiskSafe }
func (t *KubectlGetTool) Execute(ctx context.Context, args map[string]interface{}) (*tools.Result, error) {
// 复用 remoteexec 执行 kubectl get
}
- 在
agentcli.NewEngine中注册:
registry.Register(tools.NewSSHExecuteTool(cfg.SSH, coreCfg.ToolTimeout))
registry.Register(tools.NewAnalyzeOutputTool())
registry.Register(tools.NewKubectlGetTool(cfg.SSH)) // 新增
- 工具自动出现在 LLM 的 function 列表与 Prompt Layer 3 工具描述中。无需改 Prompt、controller、前端。
常见陷阱
| 陷阱 | 解决方案 |
|---|---|
忘记设置 RiskLevel 导致误判 |
默认按接口返回值,高危工具必须显式声明 |
高危工具未实现 DynamicRiskTool |
静态等级无法反映参数差异(如 ssh_execute 看 df 还是 rm -rf),必须实现动态评估 |
| 工具 Execute 无超时 | Config.ToolTimeout=120s 兜底(context.WithTimeout) |
| 工具输出过长导致 token 爆炸 | OutputMaxLength=10000 截断 + 引导 LLM 调用 analyze_output |
总结
aiops Agent CLI 的「插件架构」是 opsxcli 的精简版:从「46+ CLI 插件」收敛为「2 个 Tool 接口实现」。这不是能力的退化,而是收敛决策空间、聚焦远程运维、降低 LLM 误判概率的有意设计。详细工具实现见 05 - Builtin 内置工具。
作者:Logan.Li