后端引擎 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>
178 lines
7.4 KiB
Markdown
178 lines
7.4 KiB
Markdown
# 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 方法)
|
||
|
||
```go
|
||
// 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 扩展接口
|
||
|
||
```go
|
||
type DynamicRiskTool interface {
|
||
Tool
|
||
RiskLevelForArgs(args map[string]interface{}) RiskLevel
|
||
}
|
||
```
|
||
|
||
部分工具的「静态风险」无法反映真实风险(如 `ssh_execute` 静态是 High,但 `df -h` 是 Safe、`rm -rf /` 是 Critical)。这些工具额外实现 `DynamicRiskTool`,安全控制器 `Check` 时优先调用动态评估。
|
||
|
||
### Result 结构
|
||
|
||
```go
|
||
type Result struct {
|
||
Success bool `json:"success"`
|
||
Output string `json:"output"`
|
||
Error string `json:"error,omitempty"`
|
||
}
|
||
```
|
||
|
||
## Registry 注册中心
|
||
|
||
```go
|
||
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 版)
|
||
|
||
### 放入内置工具集的条件(需同时满足)
|
||
|
||
1. 属于运维 Agent 高频需要的能力
|
||
2. 无法用现有工具简单组合完成(如 `analyze_output` 不能用 `ssh_execute` 替代 —— 它操作的是已有文本而非远程命令)
|
||
3. 实现简洁(单文件 < 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 会根据任务自主决定执行什么命令,无需为每类命令提供独立工具。
|
||
|
||
## 混合架构的好处
|
||
|
||
1. **职责单一**:每个工具只做一件事,`ssh_execute` 执行、`analyze_output` 分析
|
||
2. **协议简单**:LLM 只需理解 2 个 function,决策快、错误少
|
||
3. **风险可控**:所有远程操作统一走 `ssh_execute` 的风险评估(`AssessBashRisk`),不会因为工具增多而出现安全盲区
|
||
4. **扩展灵活**:未来若需要新工具(如 `kubectl_apply`),实现 Tool 接口注册即可
|
||
|
||
## 扩展指南
|
||
|
||
### 添加新工具
|
||
|
||
1. 实现 `Tool` 接口(必要时实现 `DynamicRiskTool`):
|
||
|
||
```go
|
||
// 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
|
||
}
|
||
```
|
||
|
||
2. 在 `agentcli.NewEngine` 中注册:
|
||
|
||
```go
|
||
registry.Register(tools.NewSSHExecuteTool(cfg.SSH, coreCfg.ToolTimeout))
|
||
registry.Register(tools.NewAnalyzeOutputTool())
|
||
registry.Register(tools.NewKubectlGetTool(cfg.SSH)) // 新增
|
||
```
|
||
|
||
3. 工具自动出现在 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 内置工具](05-Builtin内置命令.md)。
|
||
|
||
> 作者:Logan.Li
|