> ## Documentation Index
> Fetch the complete documentation index at: https://qitor.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 第 4 课：代码安全审计智能体

> 把 QitOS 内核专门化成一个可复现的防御式审计智能体，具备领域工具、排序发现与审查级追踪记录。

最后一课会回答整条课程里最难的问题：

**同一个执行内核，能不能支撑一个真正严肃的领域智能体，而不坍缩成定制编排？**

QitOS 给出的答案是：可以，但前提是你把领域逻辑放对地方。

本课对应的示例是 `examples/real/code_security_audit_agent.py`。

## 相比第 3 课的变化

| 设计分支    | Claude Code 风格课 | 安全审计课                |
| ------- | --------------- | -------------------- |
| 目标      | 修改代码并验证补丁       | 检查仓库、收集证据并排序发现       |
| 工具界面    | 通用编码预设          | 安全审计工具 + 代码库工具 + 任务板 |
| 提示词策略   | 编码工作流纪律         | 审计协议与证据纪律            |
| 状态      | 待办事项与模式         | 临时记录与排序发现            |
| 成功条件    | 验证命令通过          | 高信号最终审计报告            |
| qita 作用 | 调试长时运行行为        | 产出可供审阅的审查产物          |

## 系统提示词现在在教一种审计协议

这一课使用 `SECURITY_AUDIT_SYSTEM_PROMPT`，其中通常会明确写出：

```text theme={null}
Primary objective:
- Audit the repository for meaningful security risk, not just keyword matches.
- Use tools to collect evidence before making strong claims.

Judgment rules:
- Treat tool output as evidence, not proof.
- Separate results into:
  1. confirmed issue
  2. high-value lead
  3. human review needed
- Prefer a small number of high-signal findings over a long noisy list.
```

这也是整条课程里提示词设计梯子的最后一级：

* 第 1 课：解析器契约
* 第 2 课：规划器与执行器契约
* 第 3 课：工作流纪律
* 第 4 课：领域判断协议

而运行时仍然没有变。

## 解析器与适配层仍然保持稳定

这个审计智能体仍然使用：

```python theme={null}
model_parser=ReActTextParser()
```

并继续走文本优先的 OpenAI 兼容适配层。

这很重要，因为它证明了一件事：

**领域专门化默认不需要更换协议。**

只有当领域真正受益于新协议时，才值得升级，例如：

* 你需要更严格机器可读输出时，改用 JSON 或 XML
* 供应商原生结构化工具调用更可靠时，使用原生工具调用解析器
* 智能体驱动的是交互式终端而不是仓库工具时，使用 Terminus 风格协议

QitOS 支持这些路径，但默认研究路径依然是与供应商无关的文本 ReAct。

<Steps>
  <Step title="按领域组合工具界面">
    这一课会组合三类工具：

    ```python theme={null}
    super().__init__(
        toolset=[
            SecurityAuditToolSet(
                workspace_root=workspace_root,
                include_external=False,
                max_matches=80,
            ),
            CodingToolSet(
                workspace_root=workspace_root,
                include_notebook=False,
                enable_lsp=False,
                enable_tasks=False,
                enable_web=False,
                expose_legacy_aliases=True,
                expose_modern_names=False,
                profile="codebase",
            ),
            TaskToolSet(workspace_root=workspace_root),
        ],
        llm=llm,
        model_parser=ReActTextParser(),
    )
    ```

    这是整条课程关于工具组合的收官。

    此时工具面开始呈现分层：

    * `SecurityAuditToolSet` 提供领域审计能力
    * `CodingToolSet(profile="codebase")` 提供低层代码库检查能力
    * `TaskToolSet` 提供显式进度跟踪

    这就是 QitOS 希望你用来专门化智能体的方式：

    **组合环境，而不是重写循环。**
  </Step>

  <Step title="让提示词与 prepare 共同编码审计方法">
    提示词负责定义全局审计纪律，而 `prepare()` 负责定义当前阶段的局部框架：

    ```python theme={null}
    lines = [
        f"Audit task: {state.task}",
        f"Workspace: {WORKSPACE}",
        f"Step: {state.current_step}/{state.max_steps}",
        "Suggested flow: inventory -> entrypoints -> sinks/secrets/config/dependencies -> hotspots -> final ranked findings.",
    ]
    ```

    这一模式很重要：

    * 系统提示词定义全局方法论
    * `prepare()` 定义本步上下文
  </Step>

  <Step title="把发现作为一等状态">
    审计状态反而应该保持精简：

    ```python theme={null}
    @dataclass
    class SecurityAuditState(StateSchema):
        scratchpad: list[str] = field(default_factory=list)
        findings: list[str] = field(default_factory=list)
    ```

    对这个领域来说，下一步模型并不需要：

    * 所有搜索结果
    * 所有文件列表
    * 所有中间工具负载

    它真正需要的是：

    * 最近的审计轨迹
    * 目前最值得保留的候选发现
  </Step>

  <Step title="让归约负责证据压缩与排名">
    示例里通常只会从工具输出中抽取最高信号的发现：

    ```python theme={null}
    if isinstance(first, dict):
        data = (
            first.get("data", {})
            if isinstance(first.get("data", {}), dict)
            else {}
        )
        for item in list(data.get("findings", []) or [])[:3]:
            title = str(item.get("title", "finding"))
            location = f"{item.get('file', '?')}:{item.get('line', '?')}"
            state.findings.append(f"{title} @ {location}")
        if decision.mode == "final":
            state.final_result = str(decision.final_answer or "")
    ```

    这仍然是在重复整个课程的一条主线：

    * 原始证据留在追踪记录
    * 压缩的工作记忆留在状态
  </Step>

  <Step title="使用有限历史，而不是无限累积">
    这一课的示例一般会使用：

    ```python theme={null}
    history_policy=HistoryPolicy(max_messages=14)
    ```

    这是一个很强的默认值，因为它既能保留最近的推理与证据，又不会让模型每步都重新阅读大量历史搜索结果。

    如果你准备把审计扩展成更大的工作流，下一个升级通常是 `CompactHistory`，而不是无上限历史。
  </Step>

  <Step title="只有当记忆真能改变结果时再加它">
    这一课默认仍然不挂载单独记忆适配器。

    对教程来说，这是正确的：

    * `findings` 已经承担了压缩型状态记忆的角色
    * `qita` 会保留完整追踪记录供后续审阅
    * 额外检索层只会让课程复杂化

    当你真的需要这些能力时，再引入记忆：

    * 跨运行的长期发现
    * 对历史审计结果的语义检索
    * 不适合放在即时提示词中的持久笔记
  </Step>

  <Step title="把 qita 当成审查产物，而不只是调试器">
    运行：

    ```bash theme={null}
    python examples/real/code_security_audit_agent.py
    ```

    查看：

    ```bash theme={null}
    qita board --logdir runs
    ```

    这一课里，`qita` 的角色已经超过调试器：

    * 它帮助你检查智能体是否先做盘点再下结论
    * 它帮助你看哪些发现被提升到了 `state.findings`
    * 它帮助你确认解析器诊断是否稳定
    * 它帮助你判断上下文压力是否影响了审计质量
    * 它帮助你把最终答案读成一份排序审查报告，而不是一堆原始搜索命中
  </Step>
</Steps>

## 这门课程的最终设计规则

到第 4 课结束时，有一条规则应该已经变得很自然：

**领域逻辑应该放在：**

* 状态设计
* 提示词策略
* 工具组合
* `reduce()` 语义

**而不应该藏在另一个隐式运行时里。**

## Whitzard 与模型原生脚手架

上面这条课程路线始终使用最可迁移的那条路径：

* 文本优先的提示词契约
* 提示词注入的工具模式
* `ReActTextParser`

这依然是最好的起点。但 QitOS 并不限于这一种组合。

如果你去看 [`examples/real/whitzard_agent.py`](https://github.com/Qitor/qitos/blob/main/examples/real/whitzard_agent.py)，你会看到课程之外的下一个设计点：

**有些时候，模型与脚手架应该一起设计。**

例如某些模型在原生 XML 风格工具调用上有更强先验，这时如果你强迫它始终走纯 JSON 契约，智能体也许还能工作，但贴合度会更差。

这也是为什么 QitOS 把这些选择当成协调后的协议决策，而不是彼此孤立的旋钮：

* 解析器
* 工具模式风格
* 输出契约
* 修复路径

Whitzard 的价值不只是它是一个更强的审计智能体，更在于它让一个更普遍的设计原则变得具体：

**当模型有很强的原生工具调用先验时，适配脚手架往往比强迫所有模型走同一协议更合理。**

## 完整示例

完整可运行代码位于：

* [`examples/real/code_security_audit_agent.py`](https://github.com/Qitor/qitos/blob/main/examples/real/code_security_audit_agent.py)
* [`examples/real/whitzard_agent.py`](https://github.com/Qitor/qitos/blob/main/examples/real/whitzard_agent.py)

## 后续阅读

<CardGroup cols={2}>
  <Card title="构建你自己的智能体" icon="sparkles" href="/zh/guides/build-your-first-agent">
    以整条课程里的设计工作表为模板，开始设计自己的 AgentModule
  </Card>

  <Card title="Kit 参考" icon="toolbox" href="/zh/reference/kit">
    查询课程中出现过的解析器、提示词、工具集、记忆与历史辅助工具
  </Card>

  <Card title="可观测性" icon="chart-line" href="/zh/guides/observability">
    深入掌握 qita 的回放、导出与研究级分享能力
  </Card>

  <Card title="基准测试" icon="trophy" href="/zh/benchmarks/overview">
    把同一个内核迁移到 GAIA、Tau-Bench 与 CyBench
  </Card>
</CardGroup>
