安全运营Agent实践:从”求它别乱来”到”它想乱也乱不了”

admin 2026-03-09 01:57:54 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文分享安全运营Agent实践经验,作者从ClaudeCodeAgentSDK转向自建轻量级框架NanoBot,解决原方案结果不收敛、约束不住、黑盒不可控等问题。通过代码层面约束(工具白名单、执行限制、轮次控制、参数校验)实现可控性,Skill机制承载领域知识。核心结论:能用代码管住的事别指望Prompt,可控性比强大黑盒更重要。 综合评分: 89 文章分类: 安全运营,AI安全,安全建设,实战经验,安全工具


cover_image

安全运营 Agent 实践:从”求它别乱来”到”它想乱也乱不了”

原创

Purpleroc Purpleroc

Purpleroc的札记

2026年3月8日 09:04 广东

#

上一篇文章《安全运营 Agent 落地:让 LLM 亲手把自己「炼」成规则》里,我基于 claude-code-agent-sdk 借助skill实现了 secops-analyzer,不过结果不收敛、约束不住。这篇主要受OpenClaw的启发,最后用 NanoBot 替换了 Claude Code Agent。


先回顾一下坑在哪

简单说下背景。我在做安全告警的自动化分析——业务上报的报错日志,经规则引擎筛选后被标记为”疑似 Web 攻击”。这些日志需要进一步分析:是真入侵导致还是扫描器瞎探测?是暴力破解还是正常用户输错密码?风险多高,要不要转人工?

之前用 claude-code-agent-sdk 做这个事。上篇文章里提了两个核心问题:

  1. 1. 结果不收敛。日志数据明明够判定了,它还要去查威胁情报、查历史告警,越查越散,结论反而更模糊。
  2. 2. 约束不住它。Skills 里写了「不许创建脚本」,加粗了、加 emoji 了,它还是自己创建脚本来”辅助分析”。

那之后我也不是直接放弃的,还挣扎过。

换掉之前,我试过优化

我想的是,Claude Code 处理起来慢,那我能不能减少它需要处理的量?

于是加了一层预处理逻辑:先用普通的 LLM 调用(不走 Agent,就是单轮对话)做一次快速分类——把日志丢给模型,让它判断是否有 Web 攻击。只有判定为”有攻击”的,才交给 Claude Code Agent 做深度分析。

逻辑上没问题,也确实过滤掉了一批。但剩下的丢给 Claude Code,还是慢。一个事件分析几分钟甚至十几分钟,中间不知道它在想什么、调了什么。偶尔还会卡在某个工具调用上半天不动。

而且加了预处理之后,整个系统变成了两层——先一次 LLM 分类,再一次 Agent 深度分析。代码复杂度上去了,但体验并没有本质改善。

慢不是唯一的问题。更本质的问题是不可控。

放弃的真正原因

翻来覆去想了想,不只是”慢”的问题,而是一连串的不舒服:

创建文件不可控。 它动不动就在工作目录下创建 Python 脚本、Shell 脚本、临时文件来辅助分析。跑一个事件还好,批量跑几百个之后,工作目录一片狼藉。关键是这些脚本跑了什么你也不太确定,副作用不可控。

完全黑盒,没法优化。 你看不到它每一步在想什么、为什么选择调这个工具。想优化某类事件的分析效果,得先搞清楚它在哪一步判断错了——但在黑盒模式下,你只能看到最终结果,中间过程全靠翻日志猜。日志量一大,这件事本身就变成了另一个需要”分析”的工作。

结果不稳定。 同一个事件跑两次,有时候给出不同结论。批量处理场景下不太能接受。

容易卡住。 不知道是工具调用卡住,还是LLM卡住,还是我没设置最大轮次,它什么时候结束全看心情。偶尔进入某种重试循环出不来,你只能等着或者手动 kill。

环境依赖重。 Node.js、Claude CLI、权限配置……对一个本质上”读数据 → 分析 → 写结论”的场景来说,太重了。

模型依赖。 不方便快速配置、使用可用的LLM API。

这就是上篇文章为啥写:能用代码管住的事,别指望 Prompt。 Claude Code 的工具调用、文件操作、执行路径,全靠 Prompt 约束。说白了就是在自然语言层面”拜托”它别乱来,它有时候听有时候不听。

怎么换的

决定换掉之后,需要一个替代品。我的要求其实不多:

  1. 1. 可控——可执行的命令列表我能定,每一步做了什么我能看到,
  2. 最大思考轮次我能设
  3. 2. 轻量——纯 Python,不依赖外部运行时
  4. 3. 支持 Skill——能加载领域知识来引导分析
  5. 4. 够用就好——不需要它能写代码、能上网

一细想,嗯,我是不是只要找个能支持 skill 的 Agent 就好了,比如 OpenClaw。恰好那天刷视频,作者吐槽 OpenClaw 太臃肿,夸 NanoBot 只用了几百行核心代码就实现了类似效果。出于好奇去看了它的实现,发现核心循环真的很简单,原理上来说:

LLM 调用 → 有 tool_calls?→ 执行工具 → 结果追加到上下文 → 继续调 LLM
没有 tool_calls → 返回最终结果

于是,让 Cursor直接帮我完成了整个 agent 的替换,顺带,我还给 tools 加上了urldecode、base64decode 等,方便做一些简单的编解码。从 NanoBot 抽离后,整个 agent 模块长这样:

agent/
├── loop.py          # 核心循环,114 行
├── context.py       # 上下文管理,53 行
├── provider.py      # LLM 适配,68 行
├── skill_loader.py  # Skill 加载,72 行
└── tools/
    ├── base.py      # 工具基类 + 参数校验,94 行
    ├── registry.py  # 工具注册表,60 行
    ├── filesystem.py# 文件读取,236 行
    ├── shell.py     # 脚本执行(受限),155 行
    └── decoders.py  # 编解码工具,225 行

总共不到1000行。

代码层面的约束:上篇文章的教训

上篇文章里我说”约束不住 Claude Code”,这次吸取教训了。所有约束都在代码层面做,不靠 Prompt。

工具白名单。 Agent 能用的工具只有我显式注册的这几个:读文件(只能读 Skill 目录下的参考资料)、执行脚本(只能跑预先写好的 .py 脚本)、编解码(URL/Base64/HTML/Hex/Unicode)。它没有”写文件”的工具,没有”执行任意 Shell 命令”的工具。想创建辅助脚本?对不起,没这个能力。

脚本执行受限。exec 工具做了严格的路径校验——只允许运行 scripts/ 目录下的 .py 文件,用 subprocess_exec 而不是 shell 模式执行,路径解析后还会检查是否真的在允许目录内,防止 ../../ 之类的绕过。超时也有硬限制,120 秒到了直接 kill。

最大轮次。max_turns=15,15 轮之内必须给结论。不管你分析得怎么样,到了就停。不会再出现”跑了十几分钟还没完”的情况。

参数校验。 每个工具调用前都会验证参数格式,类型不对、缺必填字段直接报错返回,不会带着错误的参数去执行。

这些约束 LLM 绕不过去,因为它接触不到约束逻辑本身——它只能在我给的工具范围内行动。

这就是上篇文章说的”能用代码管住的事,别指望 Prompt”的具体落地。

切换后的效果

不会卡住了。 这是最直观的感受。以前偶尔一个事件分析十几分钟最后还没结果,现在有 max_turns 兜底,顶多打满。

每一步都清楚。 日志里打得明明白白——第几轮、调了什么工具、传了什么参数、拿到什么结果。想优化某个场景的分析效果,直接定位到具体的某一轮某个判断就行,不用在一大堆黑盒日志里翻来翻去。

[Agent Turn 1/15]
[Agent] 工具调用: read_file({"path": "references/web_attacks.md"})
[Agent Turn 2/15]
[Agent] 工具调用: exec({"command": "python scripts/query_waf_logs.py --mode attacker --ips 1.2.3.4 ..."})
[Agent Turn 3/15]
[Agent] 完成,最终响应 1842 字符

三轮结束,干净利落。

LLM 换了,成本降了。 先前想要切换,得找内部二开claude code的小伙伴,还不太好实现。现在随意切换,换到 DeepSeek,单次分析的 token 消耗也降了不少——没有那些自创脚本的上下文膨胀了。分析质量也没明显下降,因为真正驱动分析质量的是 Skill 里的领域知识,不是模型的通用能力。

预处理层也简化了。 之前在 orchestrator 里 hardcode 了大量分析逻辑——攻击模式检测、WAF 关联策略、响应安全信号检测——加起来好几百行。这些东西本质上是安全分析的领域知识,不应该写在数据预处理层。重构之后,orchestrator 只做数据搬运:取数据、精简格式、调 Agent、解析结果、存数据库。分析判断全部在 Skill 里,由 Agent 来做。

整个 orchestrator(analyzer.py)只有 250 行,干的事情一目了然。

Skill 才是灵魂

这个轻量 Agent 本身没什么技术含量,真的就是一个循环。它的”智慧”全在 Skill 里。

SKILL.md 大概 500 行,定义了分析的完整框架:

  • • 分类流程:先看 payload 有没有 Web 攻击特征,再看行为统计有没有业务攻击模式,都没有就是正常报错
  • • 判定标准:什么样的 payload 算通用探测(低危,AI 自动关闭)、什么算定向攻击(高危,转人工)
  • • 知识库:各类攻击的特征模式放在 references/ 目录下,Agent 可以 read_file 按需读取
  • • 工具使用指引:什么时候需要查 WAF 日志、怎么查、查完怎么判断
  • • 输出规范:严格的 JSON 格式,每个字段的取值范围和含义

以前那些写在代码里的分析逻辑,现在全在 Markdown 里。调整分析策略?改 Markdown。新增一种攻击类型的识别模式?改 Markdown。不用动代码,不用发版。

随便聊聊:从黑盒到可控的一点思考

换完之后,我回头想了想这件事,觉得还挺有意思的。

前两年开始就写过一些关于 LLM 赋能安全运营的思考,随着 LLM 的发展,现在回看,一路走来大家应该都或多或少经过这么些阶段:最开始的时候,用 LLM 做事件解读,就是单轮对话;然后 MCP 火了,大家开始写各种工具服务一股脑丢给 Agent 让它自主决策;接着发现太不可控了,又开始在代码里 hardcode 流程、引导性 Prompt,从通用往专用收;ReAct 也火过一阵,给个目标让 Agent 自己 Think-Act-Observe 循环,理论很优雅但实际受限于上下文和指令遵从性;到现在 Skill 的概念起来了,核心思路是「需要什么知识就加载什么,需要什么工具就注册什么」。

我不是说哪个方案一定比哪个好。但至少在我这个场景里,Skill 模式确实比较合适——比完全开放的 Agent 可控,比 hardcode 所有流程灵活。你不需要在代码里穷举所有分析分支,只需要把领域知识描述清楚,Agent 在这个框架内灵活应对。

还有一个有意思的点。传统安全运营里有个 SOAR 的概念(Security Orchestration, Automation and Response),走的是 Workflow 路线——提前定义好所有流程和分支。我之前觉得 n8n 那种拖拽式的工具挺适合做 SOAR 的,而且还能结合LLM来大量的处理日志数据,做分类、场景定义等。但后来逐渐意识到,安全事件千变万化,你没法穷举所有场景。这也是我在选型时纠结的一个点:用 ReAct 吧,我定义不完所有可能的状态;用 Workflow 吧,覆盖不了所有变体。

Skill 的模式好像提供了一个折中——你不需要穷举所有分支,只需要把领域知识描述清楚,让 Agent 在这个知识框架内灵活应对。遇到新场景?写一个新 Skill 就行。复杂场景?大 Skill 里嵌套小 Skill。

当然这还是很粗糙的想法,纯粹随想。但方向上我觉得值得继续试。

总结

回到最初的问题,为什么换掉 Claude Code SDK?上篇文章里我自己总结过一句话:

能用代码管住的事,别指望 Prompt。

这次做的事情,就是把这句话落地了。

不是 Claude Code 不好,而是在我的场景里,”够用且可控”比”强大但黑盒”更实际。一千来行的轻量 Agent + 500 行的 Skill,替代了一整套 Claude Code Agent SDK。效率没降,可控性大幅提升,成本也降了。

上篇留了个坑,这篇算是填上了。


这是《安全运营 Agent 落地:让 LLM 亲手把自己「炼」成规则》的续篇。如果你也在做类似的事情,欢迎交流。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:Purpleroc的札记 Purpleroc Purpleroc《安全运营 Agent 实践:从”求它别乱来”到”它想乱也乱不了”》

评论:0   参与:  0