当你给它一个目标 URL,它真的会在 Docker 里跑 nmap、起 Caido 代理、用 agent-browser 操控 Chromium、构造 payload、真正发出 HTTP 请求拿到 5xx/2xx 响应,然后才会告诉你:“这是一个 SQL 注入。”
如果没有 PoC,它甚至不会把这条记录写进报告。
这就是 usestrix/strix ↗ 在做的事:把”AI 渗透测试”这个听起来很玄学的命题,变成一支有规划、有执行、有验证、有报告的多 Agent 协作队伍——而每一步都被强制带上真实证据。
这篇文章会带你从顶层设计、Hierarchical Agent 编排、agents_graph 工具、27 个内置工具、技能系统、Docker 沙箱、Caido 代理、SARIF 输出、可借鉴与短板,把这个 ~25K 行 Python 的项目拆透。

Strix v0.x,基于 OpenAI Agents SDK + LiteLLM,~25K 行 Python
一、定位与四层架构#
1.1 一句话#
Strix = 一支由 LLM Agent 协作组成的自主渗透测试队伍。
每个 Agent 跑在一个 Kali Linux Docker 沙箱里,能调用真实工具(nmap / nuclei / sqlmap / httpx / Caido 拦截代理 / agent-browser),并通过工具调用链产出带 PoC、可直接合入的修复 patch、可上 GitHub 的 SARIF 报告 的安全测试结果。
1.2 技术栈#
| 层 | 选型 | 证据 |
|---|---|---|
| 语言 | Python ≥ 3.13 | strix.spec:36-40 python_requires=">=3.13" |
| Agent 框架 | OpenAI Agents SDK 0.14.6 | strix/runtime/docker_client.py:13 注释 |
| LLM 统一层 | LiteLLM + MultiProvider | strix/config/models.py:22、strix/llm/compaction.py:9 |
| 沙箱运行时 | Docker(可插拔 backend) | strix/runtime/backends.py:19-44 |
| 浏览器自动化 | agent-browser Node CLI | containers/Dockerfile:91 agent-browser@0.26.0 |
| 拦截代理 | Caido(开源 Burp 替代品)容器内 sidecar | strix/runtime/caido_bootstrap.py:24-99 |
| CLI | Typer + Rich + Textual TUI | strix/interface/cli.py、strix/interface/tui/ |
| SARIF 输出 | 自写 schema 校验 | strix/report/sarif.py、strix/report/writer.py |
| 可观测性 | PostHog + Scarf + 结构化 logging | strix/telemetry/ |
1.3 四层架构#
┌────────────────────────────────────────────────────────────────┐
│ L4 CLI / TUI strix/interface/ (cli.py, interactive.py) │
│ │ │
│ ▼ │
│ L3 Orchestration strix/core/runner.py (执行入口) │
│ │ core/agents.py (StrixCoordinator) │
│ │ core/sessions.py (会话持久化) │
│ ▼ │
│ L2 Agent Runtime strix/agents/factory.py (build_strix_agent) │
│ │ agents/prompts/system_prompt.jinja (单源 prompt) │
│ ▼ │
│ L1 Tools + Skills strix/tools/* (27 个内置 tool) │
│ │ strix/skills/<cat>/*.md (Markdown + YAML) │
│ ▼ │
│ L0 LLM/Sandbox/Proxy │
│ strix/config/models.py (MultiProvider) │
│ strix/runtime/ (Docker sandbox) │
│ strix/tools/proxy/ (Caido SDK) │
│ strix/llm/compaction.py (上下文压缩) │
└────────────────────────────────────────────────────────────────┘plaintext关键事实:Strix 不自己实现 LLM Agent 循环,而是基于 OpenAI Agents SDK 的 SandboxAgent(strix/agents/factory.py:27),并通过 _with_bounded_result + _with_coerced_arguments 两个 wrapper(factory.py:620-628)做输出限流和参数归一化。
整个 prompt 是单源 jinja 模板(strix/agents/prompts/system_prompt.jinja,507 行),通过 render_system_prompt 配合 is_root / scan_mode / is_whitebox / interactive 四个开关渲染。这也是 Strix 把”root agent 不准自己跑扫描器”这种硬约束写进 prompt 的关键机制(system_prompt.jinja:6-15)。
1.4 与传统扫描器和 ReAct 的本质差异#
| 维度 | 传统扫描器(Nuclei / Burp) | 经典 ReAct Agent | Strix |
|---|---|---|---|
| 工作单元 | 一条规则 / 一个 payload | 单 LLM 在循环里 Think→Act→Observe | 多 Agent 分层,每 Agent 一个 SandboxAgent |
| 决策范式 | 静态 if/else | 线性链 | 分层图(root planner → specialist → 各自 ReAct) |
| 工具调用 | 死规则、签名匹配 | function-calling | SDK function_tool + 自写 sandbox exec |
| 上下文 | 无状态 | 会话内累积,但会爆 | 显式 compaction(strix/llm/compaction.py)+ per-agent 持久化 |
| 报告 | raw output | 无 | CVSS + SARIF + PR body + code_locations |
| 误报控制 | 规则匹配即报告 | 自我陈述”找到了” | 强制 PoC:没有 PoC 报告直接被 dedupe 拒绝 |
| 沙箱 | 通常无 | 视实现 | 真 Docker 容器 + 容器内 Caido sidecar |
| 验证/可观测 | 取决于产品 | 完全黑盒 | PostHog + Scarf + 自建 session 落盘 |
二、Hierarchical Agent:Master 与 Specialist 的契约#

Strix 采用严格分层 Agent 范式——不是 Graph-of-Thoughts,也不是纯 Plan-and-Execute,而是 Plan-and-Execute + 子任务独立反馈的混合:
┌───────────────────────┐
│ Root Agent (1) │ is_root=True
│ - 永不执行扫描 │ finish_scan 收尾
│ - 维护 todo/notes │ spawn 子 agent
└──────────┬────────────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Recon Agent │ │ SQLi Agent │ │ XSS Agent │
│ - 子 agent #1 │ │ - 子 agent #N │ │ - 子 agent #M │
│ agent_finish │ │ agent_finish │ │ agent_finish │
└────────────────┘ └────────────────┘ └────────────────┘
│ │ │
└───────────────┴───────────────┘
▼
进一步分层(按需):
Validation Agent → Reporting-with-fix Agentplaintext证据:
_BASE_TOOLS(factory.py:485-519)列出 27 个基础工具,finish_scan仅 root,agent_finish仅 child;- Root 在 prompt 里被强制只做编排:“Your job is ORCHESTRATION, not hands-on testing.”(
system_prompt.jinja:6-8); - 子 Agent 三段式:“Discovery → Validation → Reporting-with-fix (3 agents per vulnerability)“(
system_prompt.jinja:316-318)。
2.1 agents_graph 工具——最值得借鉴的设计#
完整定义在 strix/tools/agents_graph/tools.py(740 行)。这是 Strix 最值得借鉴的设计之一,暴露给 LLM 的工具:
| 工具 | 用途 | 行号 |
|---|---|---|
create_agent | 递归生成子 agent(可以再生成子 agent 的子 agent) | :245-340 |
send_message_to_agent | 点对点消息 | :347-405 |
wait_for_agents | 块式等待,阻塞直到指定 agent 完成 | :573-625 |
view_agent_graph | 让自己看到整张 agent 树 | :535-572 |
stop_agent | 砍掉某个 agent(防止失控蔓延) | :627-693 |
关键设计:
create_agent不仅能传name/instructions/skills,还能传预加载的 skills、模型设置和子 agent 自己要用的工具(:255-300),让父 agent 能精准调度子任务;- 子 agent 的
instructions是一段完整可独立运行的指令体,root 通过system_prompt_context注入 scope / authorization 信息(factory.py:550-560); wait_for_agents是 SDK 级function_tool,调用一次就 block,禁止轮询——这一点在 prompt 里被反复强调:“wait_for_agents blocks and resumes you automatically, so it is never a poll you repeat”(system_prompt.jinja:36-38)。
2.2 状态共享:共享文件系统 + 共享容器#
/workspace是所有 agent 共享目录(system_prompt.jinja:240-243“All agents share the same /workspace directory and proxy history”);- Caido proxy 流量全 agent 可见——这就是为什么要在容器内启动 sidecar;
- per-agent todo / notes 通过
{state_dir}/todos.json/notes.json落盘(strix/tools/todo/tools.py:48-60、strix/tools/notes/tools.py:46-50); - reports 通过
ReportState(strix/report/state.py)做进程级共享。
三、工具系统:27 个内置工具 + 严格的契约#

strix/agents/factory.py:485-519 是权威清单。我按用途归类:
| 类目 | 工具 | 文件 |
|---|---|---|
| 思考 | think | strix/tools/thinking/tool.py |
| 技能注入 | load_skill | strix/tools/load_skill/tool.py |
| 元任务 | create_todo / list / update、create_note / list / get_note | strix/tools/{todo,notes}/tools.py |
| 网络 | web_search(Perplexity Sonar-Reasoning-Pro)、list_requests / view_request / repeat_request / list_sitemap / view_sitemap_entry / scope_rules | strix/tools/{web_search,proxy}/tool.py |
| 报告 | create_vulnerability_report(强制 PoC + CVSS)、create_dependency_report(仅 CVE 已知)、list_reports / get_report | strix/tools/reporting/tool.py |
| 多 Agent | view_agent_graph / send_message_to_agent / wait_for_agents / create_agent / stop_agent | strix/tools/agents_graph/tools.py |
| 生命周期 | finish_scan(root only)、agent_finish(child only)、respond_to_user(interactive) | strix/tools/{finish,respond}/tool.py |
| 来自 SDK | exec_command(容器内 TTY shell)、apply_patch、agent_browser、view_image | OpenAI Agents SDK 内置 |
3.1 create_vulnerability_report:最复杂的工具#
strix/tools/reporting/tool.py:347-373 的签名极有教益:
@function_tool(timeout=180, strict_mode=False)
async def create_vulnerability_report(
ctx: RunContextWrapper,
title: str,
description: str,
impact: str,
target: str,
technical_analysis: str,
poc_description: str,
poc_script_code: str, # ← 强制 PoC
remediation_steps: str,
evidence: str,
assumptions: str,
fix_effort: str,
cvss_breakdown: dict[str, str], # ← CVSS vector
endpoint: str | None = None,
method: str | None = None,
cve: str | None = None,
cwe: str | None = None,
code_locations: list[dict[str, Any]] | None = None, # ← 含 fix_before / fix_after
fix_pr_body: str | None = None,
) -> strpython强制项 + 安全护栏:
- 强制 PoC:没有
poc_script_code / poc_description直接拒收; - CVSS 校验:
_CVSS_VALID字典(reporting/tool.py:24-33)列出每项合法值(attack_vector 必须是 N/A/L/P),不在合法集内直接拒绝; - 路径安全:
_validate_file_path(reporting/tool.py:36-44)禁止绝对路径、禁止..穿越。
3.2 工具注册契约#
所有工具必须满足以下契约:
- 用
agents.function_tool(timeout=..., strict_mode=False)装饰,自动从签名生成 JSON Schema 给 LLM; - 注册表是
_BASE_TOOLS(root/child 共有)和_EXTRA_TOOLS(register_agent_tools(*tools)注入,factory.py:533-551); - 在
build_strix_agent里用_ensure_unique_tool_names强校验名称唯一(factory.py:514-525); - 所有
FunctionTool都被两层 wrapper 包:_with_coerced_arguments(参数归一化)+_with_bounded_result(输出限流),factory.py:620-628。
3.3 错误处理:契约性错误写在 docstring 里教给 LLM#
返回是 JSON 字符串,约定有 success 字段。tool.py:42 这段非常典型:
“If you get a
duplicate_ofresponse, do NOT retry”
——契约性错误被显式写在 docstring 里教给 LLM,让模型知道重复报告应该停止而不是再发一次。
web_search 的错误粒度也很细:Query cannot be empty / Web search is not configured / timed out / HTTPError,每种都有特定 hint(web_search/tool.py:45-72),让 LLM 拿到错误后能自我修正。
四、技能系统:Markdown 即知识库#

strix/skills/ 按类目组织(strix/skills/__init__.py 枚举):
skills/
├── scan_modes/ quick / standard / deep.md 顶层扫描策略
├── coordination/ root_agent / source_aware_white_box 等
├── reconnaissance/ asset_discovery / subdomain_enum / port_scan / tech_fingerprint / dir_fuzz
├── technologies/ cms / framework / language / dev_tool / ai_ml / supply_chain
├── frameworks/ FastAPI / Django / Express / Next.js / React / Vue ...
├── vulnerabilities/ sqli / xss / ssrf / idor / rce / auth_bypass / file_upload ...
├── protocols/ http / graphql / websocket / grpc / oauth / jwt
├── cloud/ aws / gcp / azure / kubernetes / docker
├── tooling/ nuclei / burp / sqlmap / nmap / ffuf
├── custom/
└── README.mdplaintext一个 skill 文件长什么样(strix/skills/reconnaissance/asset_discovery.md,节选):
---
name: asset-discovery
description: Passive asset and attack-surface discovery via certificate
transparency, TLS SAN pivoting, passive DNS, and ASN/IP enumeration
---
# Asset Discovery
Most engagements start from a small seed (one domain, one org name)...
## Attack Surface
- Hosts discoverable via issued certificates (CT logs)...
- Internal/staging/pre-prod hostnames leaked in certificate SAN lists...
## High-Value Sources
### Certificate Transparency (CT)
...markdown格式:YAML frontmatter + 详细自然语言指导,完全可代码完全解耦。
4.1 load_skill 工具:动态注入到 LLM 上下文#
async def load_skill(ctx, skills: list[str]) -> str:
"""Return the markdown body of one or more skills as reference material."""python把 skill Markdown 拼成 ## Skill: <name>\n\n<body> 直接塞回 LLM 上下文。这意味着:
- 技能是 lazy load:root agent 只在确认要做某类攻击时才调
load_skill,避免一开始就吞掉全部 ~10K 行的 skill 文本撑爆上下文; - 技能是版本无关:纯 Markdown 文件,可以用 git 管理,与代码库解耦;
- 技能可热更新:新增一种漏洞类型只要写一份 Markdown + 在
skills/__init__.py注册。
五、运行时:Docker 沙箱 + Caido 容器内 sidecar#

5.1 沙箱抽象:strix/runtime/#
| 文件 | 职责 |
|---|---|
docker_client.py | Docker SDK 封装 |
backends.py:19-44 | 可插拔 backend 接口 |
session_manager.py | 会话生命周期 |
status.py | 状态推送 |
caido_bootstrap.py:24-99 | Caido sidecar 启动 + GraphQL guest token 探活 |
backends.py 抽象出”沙箱后端”接口,理论上可以替换成 Firejail / E2B / Fly machines / 自建 K8s,而不仅限于本地 Docker。
5.2 Caido:容器内的 Burp#
Caido 是一个开源的 HTTP 拦截代理(“Burp Suite 的现代化替代品”),Strix 在每个 agent 容器内启一个 Caido sidecar:
- 所有 HTTP 请求自动经过 Caido;
- Agent 通过
list_requests / view_request / repeat_request / list_sitemap工具读流量; scope_rules工具动态增删 in-scope URL;- 所有 agent 共享同一份 proxy history——这就是为什么要在容器内启动 sidecar,而不是在 host 端。
Caido 启动探活用 caido_bootstrap.py:42-72 的 GraphQL “最多 10 次 backoff 拿 guest token”,这是真实的 readiness probe,不是写死 sleep。
5.3 agent-browser:容器内浏览器自动化#
containers/Dockerfile:91 安装 agent-browser@0.26.0,让 agent 能用自然语言操控 Chromium:
“打开
https://target.com/login,填用户名admin密码admin,点击登录”
→ 工具调用 → 浏览器执行 → 拿到响应 → 写回 proxy history。
六、报告与 SARIF:从 PoC 到 PR#

6.1 三种报告类型#
strix/tools/reporting/tool.py 暴露三种报告工具:
create_vulnerability_report(:347):业务漏洞,强制 PoC + CVSS + fix patch + PR body;create_dependency_report(:1111):依赖漏洞(CVE 已知),无 PoC 强制;list_reports / get_report(:1508 / :1573):只读查询。
6.2 去重:strix/report/dedupe.py#
避免同一漏洞被多个 agent 重复报告。dedupe.py:1-50 实现了基于 (target + vulnerability_type + endpoint) 三元组的去重——重复时返回 duplicate_of,前面提到过,这个错误码被显式写在 docstring 里教给 LLM:不要重试。
6.3 SARIF 2.1.0 输出#
strix/report/sarif.py 把报告转成 SARIF 2.1.0——这是 GitHub Code Scanning 的标准格式,扫描结果可以直接出现在 PR 页面:
{
"runs": [{
"tool": { "driver": { "name": "Strix", "version": "..." } },
"results": [{
"ruleId": "sqli",
"level": "error",
"message": { "text": "..." },
"locations": [{ "physicalLocation": { ... } }]
}]
}]
}json加上 fix_pr_body 字段后,Strix 的报告可以直接走 GitHub Actions → 自动开 PR with patch。
七、上下文压缩:让长任务跑得动#

strix/llm/compaction.py 处理一个现实问题:一次渗透测试可能要几十分钟到几小时,LLM 上下文会爆。
策略(推测结合文件):
- 分段摘要:保留最近 N 轮对话 + 对早期对话生成摘要;
- 证据保留:所有
list_requests/view_request/create_vulnerability_report的结果完整保留; - TODO/Notes 优先级提升:per-agent 持久化的 todo / notes 被压进 system prompt,类似 LangGraph 的 long-term memory;
- 显式触发:在 token 用量达到某个阈值时由 SDK 触发,而不是每次都压缩(避免过早丢失细节)。
这与 MoneyPrinterTurbo 的 “提交瞬间配置快照” 是完全不同的设计哲学——MPT 是”任务开始锁定配置”,Strix 是”任务过程中持续整理上下文”。两个项目都体现了 AI 长任务的工程复杂度。
八、可借鉴 & 局限#
8.1 值得借鉴#
- 单源 jinja prompt 模板:通过
is_root / scan_mode / is_whitebox / interactive四个开关切换,避免 prompt 爆炸; agents_graph工具的递归 spawn:把”多 Agent 编排”暴露给 LLM 自己——LLM 决定 spawn 几个子 agent、各自做什么、什么时候等、什么时候停,这是 Hierarchical Agent 的工程化范本;- 契约性错误写在 docstring 里:让 LLM 拿到错误后能自我修正(如 “If you get a
duplicate_ofresponse, do NOT retry”); - 强制 PoC + CVSS 校验 + 路径安全护栏:LLM 写报告时必须带证据,避免幻觉漏洞;
- Markdown 即知识库:技能是纯 Markdown 文件,与代码完全解耦,可热更新、可 git 版本管理;
- 共享文件系统 + 共享容器:多 Agent 通过
/workspace和 Caido history 自然共享状态,不需要复杂的消息总线; - 容器内 sidecar 模式:Caido / agent-browser 都跑在同一容器内,避免跨网络延迟和安全边界问题。
8.2 局限#
- 依赖 OpenAI Agents SDK:版本被 pin 到
0.14.6,生态绑定较深。如果想换成 LangGraph / CrewAI,需要重写factory.py; - LLM 成本:一次 deep 扫描可能要烧几美元到十几美元的 token,对个人用户不友好(这也是为什么有
app.strix.ai托管服务); - Docker 强依赖:沙箱完全绑定 Docker,
backends.py的可插拔设计有了,但还没实现 Firejail/E2B 后端; - 强制 PoC 是双刃剑:挡住了幻觉,但也可能漏报某些”无法在 sandbox 内复现”的漏洞(如需要特定网络环境、需要真实用户凭据);
- 没有内置 Sora/AI 视频源(不是本项目问题,提一下对比 MoneyPrinterTurbo);
- 可观测性 PostHog + Scarf 偏外部:自建的部分只在 session 落盘,缺少 Prometheus / OpenTelemetry 标准接入。
九、写在最后#
Strix 给我最大的启发是:AI Agent 项目的工程难度,不在 Agent 本身,而在”如何让 Agent 之间、Agent 与真实世界之间安全可控地交互”。
Agent 循环可以用 SDK;但
- 工具的 schema 设计 + 错误契约,
- 多 Agent 的 共享状态 + 递归 spawn,
- 沙箱的 sidecar 模式 + 可插拔后端,
- 技能的 Markdown 化 + lazy load,
- 报告的 强制证据 + 去重 + SARIF,
这些都是只有真在生产化跑过渗透测试才会知道要面对的细节。
这也是为什么我在做完 MoneyPrinterTurbo ↗ 之后会被这个项目吸引:它把”AI 调用传统多媒体管线”换成了”AI 调用真实安全工具链”,复杂度又上了一个台阶。
如果你也在做 AI Agent 工具链,强烈建议读两遍 strix/agents/factory.py 和 strix/tools/agents_graph/tools.py——你会在 1500 行内看到 Hierarchical Agent 的工程化范本:递归 spawn、阻塞等待、契约性错误、单源 prompt、可插拔 backend。
附录:关键源码定位速查#
| 模块 | 关键文件 / 行号 |
|---|---|
| Agent 工厂 | strix/agents/factory.py:27 (SandboxAgent)、:485-519 (_BASE_TOOLS)、:620-628 (wrappers) |
| 单源 prompt | strix/agents/prompts/system_prompt.jinja(507 行) |
| 多 Agent 编排 | strix/tools/agents_graph/tools.py:245-693 |
| 工具注册 | strix/agents/factory.py:533-551 (register_agent_tools)、:514-525 (_ensure_unique_tool_names) |
| 漏洞报告 | strix/tools/reporting/tool.py:347-373 (signature)、:24-44 (CVSS / path validation) |
| 去重 | strix/report/dedupe.py |
| SARIF | strix/report/sarif.py |
| 沙箱 | strix/runtime/{docker_client,backends,session_manager}.py |
| Caido 集成 | strix/runtime/caido_bootstrap.py:24-99 |
| 技能系统 | strix/skills/{reconnaissance,vulnerabilities,protocols,cloud,...}/*.md |
| 浏览器自动化 | containers/Dockerfile:91 |
| LLM 统一 | strix/config/models.py:22 (MultiProvider) |
| 上下文压缩 | strix/llm/compaction.py |
📘 项目信息
- 仓库:usestrix/strix ↗
- 作者:usestrix 团队
- License:Apache 2.0
- 配套服务:app.strix.ai ↗(托管版,无需 Docker/LLM key)
- 文档:docs.strix.ai ↗