低调学安全

CyberStrikeAI 新增四项长跑能力

解决跨小时授权测试中的状态丢失问题 · 任务板 · 断点续跑 · 单次模型重试 · 结论锚点

Image

凌晨两点,nmap 扫完、httpx 跑完、子代理把 SQL 注入面也摸了一遍。消息列表滚了三百条,进度条还在走——你关页面去睡。

早上回来,后端昨晚滚动发布了一轮。对话还在,但 Agent 重新列了一份测试计划,从「信息收集」第一步开始。昨晚已经确认的开放端口、已经派出去还没收口的子任务,全当没发生过。

这不是模型变笨了。是把「给人看的聊天记录」当成了「给机器用的执行状态」。

CyberStrikeAI 面向的是跨小时、甚至跨天的授权渗透与业务逻辑审计。一轮 Deep 编排里,主代理派 task、子代理连打十几轮 MCP、扫描结果动辄几十 KB 灌进 context——流程状态、进程状态、调用状态、语义状态是四件不同的事,混在一份 SSE 流里迟早要崩。

这一版把四项长跑能力写进默认配置(config.yaml → multi_agent.eino_middleware),不新增 MCP、不改聊天 UI,改的是底层假设:上下文会满、进程会死、网关会抖、流式 token 不等于可机器读取的最终交付。


一、结构化任务板:计划不能和 nmap 输出抢 token

问题背景

Deep 的真实节奏:

主代理拆计划 → task 派子代理 → 子代理 10+ 轮工具 → 结果回灌主代理历史 → 下一步

测试步骤若只写在 assistant 回复里,就和 nmap、dirsearch、Burp 插件输出挤在同一份 context。max_total_tokens 到八成,summarization 一触发——摘要擅长记住「发现了什么 SQL 注入点」,对「第 7 项越权测试还没做、第 3 项子代理结果待汇总」却容易糊成一句「继续推进中」。

发现可以压缩,待办不能丢。

实现说明

任务板把计划从聊天正文里拆出去,存成按会话隔离的 JSON 文件:

skills/.eino/plantask/<会话ID>/

主代理通过 TaskCreate / TaskGet / TaskUpdate / TaskList 维护结构化待办——状态、优先级、依赖关系写在文件里,不占用对话 token。

只挂在主编排(Deep / Supervisor 主代理、单代理、plan_execute Executor),不挂子代理。全局待办只能有一个记账的;子代理专心打穿一个攻击面,回来交差,不各自维护一份互相打架的计划。

中间件链里有两处实现细节,影响长跑场景下的稳定性:

  1. reduction 清超大 tool 输出时,刻意排除 Task* 四个工具。 nmap 全端口扫描结果可以截断落盘,任务状态不能被当垃圾清掉。
  2. plantask 排在 summarization 前面,不进 token 计数。 压缩历史时,任务板读的是磁盘,不是被摘要过的二手描述。

删对话会同步清该目录,不留孤儿任务文件。

plantask_enable: true# 需 eino_skills + 可写 skills_dir

二、Runner 断点续跑:救的是调度栈,不是聊天记录

与「中断并继续」的区别

中断并继续
Runner 断点续跑
触发
你主动暂停、改工具白名单后再发
进程 OOM、滚动发布、机器重启
存什么last_react_*
:上一轮送进模型的消息快照
checkpoint:Runner 图执行到哪一步
接什么
从上次模型入参接着聊
从挂起的子代理 / 未完成的节点接着跑

名称相近,机制不同:前者是「对话续写」,后者是「执行续跑」。

问题背景

进程崩溃后,内存里的调度栈没了。聊天记录能告诉你「之前聊过什么」,但接不回:

  • 子代理挂起在哪个 tool call
  • 主代理的 ReAct 循环停在第几轮
  • plan_execute 的 execute 节点是否已返回

同会话再进来,如果只能 Run 不能 Resume,等于把已经跑过的 nmap、已经入库的 tool_result 全部作废,从头再来。

实现说明

checkpoint 落盘路径:

data/eino-checkpoints/<会话ID>/runner-<编排模式>.ckpt

同会话进来,Runner 先 Resume,失败才全新 Run。前端会明确提示「断点恢复失败,已回退为全新执行」——不静默重头跑,便于判断状态是否丢失。

  • Deep 和 Supervisor 各用各的 ckpt,不能混。
  • 写入走 .tmp 再 rename,防半写损坏;正常结束删文件,异常才留。

使用边界: 断点续跑恢复的是 Runner 进度,不恢复 summarization 已压缩的历史正文。三者分工如下——任务板管「还要做什么」,checkpoint 管「执行器卡在哪」,summarization 管「旧对话怎么变短」。

checkpoint_dir: data/eino-checkpoints

三、单次模型重试:502 不该让 nmap 再扫一遍

问题背景

一轮 user 消息,Deep 里常常对应 十几次 ChatModel.Generate,中间夹着真工具调用。网关某次 502、读超时,多半打在其中某一次——前面的 nmap 已经跑完,tool_result 也在库里了。

若在整轮 user 消息上重试,等于扫描再扫一遍。授权测试里,重复发包可能触发 WAF 封禁、污染测试窗口、浪费配额。

实现说明

deep_model_retry_max_retries: 3 挂在单次 Generate:同一套 messages,重试 HTTP,不重放整轮 ReAct。

三层重试,各管各的粒度:

层级
配置
作用
单次 API 调用
deep_model_retry_max_retries: 3
某次 Generate 502/超时,同 messages 重打
整轮 Run
run_retry_max_attempts
(默认 10)
429/5xx 时段性故障,指数退避续跑
用户主动停止
context.Canceled任何重试都不触发

子代理未配置单次重试。 若子代理静默重试成功,主代理会误判任务已完成,授权测试场景下可能造成漏报。子代理失败后由主编排决定重派或上报。

deep_model_retry_max_retries: 3

四、结论锚点:流式输出 ≠ 框架里的交付字段

问题背景

界面上是 SSE 流式 token,逐段输出。框架里还有 Session——summarization 压历史、子代理结果回传、轨迹写库,都需要明确:

本轮最终结论,写在哪个键上?

不设锚点,只能从一长串 assistant 里猜。多代理下很容易:

  • 把中间分析(「疑似存在越权,待进一步验证」)当成最终结论
  • 把没收束的推理(「接下来应该测试…」)当成交付
  • 后面十几轮 tool call 在错误前提下继续跑,报告和实际执行分叉

实现说明

deep_output_key: final_answer 把 Deep / Supervisor 主代理和单代理的最终结论钉在 session 的 final_answer。

  • 前端不因此多一个框——这是编排层内部约定,给 summarization、子代理回传、后续轮次一个唯一可信的语义锚点。
  • plan_execute 走自己的 ExecutedStepSessionKey,和 Deep 的 task 子代理不是一套状态机,不硬共用。
deep_output_key: final_answer

能力对照

长跑 Agent 的状态可以拆成四块,以前混在聊天记录里,现在各有归宿:

┌─────────────────────────────────────────────────────────┐
│  流程状态:待办执行到哪        →  结构化任务板(磁盘 JSON) │
│  进程状态:Runner 卡在哪一步     →  checkpoint(.ckpt)    │
│  调用状态:某次 API 是否可重试   →  单次模型重试(Generate)│
│  语义状态:哪句话算最终交付      →  结论锚点(final_answer)│
└─────────────────────────────────────────────────────────┘
问题场景
能力
配置项
计划在压缩后变模糊
结构化任务板
plantask_enable
重启后 Runner 接不上
Runner 断点续跑
checkpoint_dir
一次 API 失败拖垮整轮
单次模型重试
deep_model_retry_max_retries
压缩时不知道哪句算交付
结论锚点
deep_output_key

默认配置

四项能力在仓库 config.yaml 的 multi_agent.eino_middleware 下默认已启用,升级或使用默认配置时无需额外操作:

配置项
默认值
plantask_enabletrue
checkpoint_dirdata/eino-checkpoints
deep_model_retry_max_retries3
deep_output_keyfinal_answer

仅在你曾手动关闭上述项,或沿用较旧配置文件时,需要对照检查。任务板另需 eino_skills 可用且 skills_dir 可写,否则 plantask_enable 会被跳过。

跨会话的目标、端口、凭据等信息由项目黑板维护;本文四项针对同一条对话内的计划、进程、调用与结论状态。对跨小时授权测试而言,这四项比单纯扩大上下文窗口,更能缓解「计划变粗、进程中断接不上、502 导致重扫、结论字段不准」等结构性问题。


CyberStrikeAI · 仅用于授权安全测试与研究

地址:https://github.com/Ed1s0nZ/CyberStrikeAI