Python中的CTI智能体记忆 — STIX知识图谱、威胁行为者别名解析、离线优先的RAG、适用于Claude Code和LangChain智能体的MCP服务器
专为网络威胁情报打造的智能体记忆系统。
当资深分析师离职时,两三年的语境也随之消失——客户环境、过往调查、攻击者TTP、误报模式,以及每一个来之不易的“等等,我们之前见过这个”。ZettelForge 是一个智能体记忆系统,旨在让语境始终留在团队中。
它能够从分析师笔记和威胁报告中提取 CVE、威胁行为者、IOC 以及 ATT&CK 技术,解析别名(APT28 = Fancy Bear = STRONTIUM = Sofacy),构建 STIX 2.1 知识图谱,并以自然语言将过往的每一项调查回馈给分析师——以及通过 MCP 回馈给 Claude Code。完全在进程内运行。无需 API 密钥。无需云端。数据不离开主机。
点赞 · pip install zettelforge · 文档 · ThreatRecall(托管版) · 更新日志
v2.6.2(2026-04-27):配置 Web 编辑器现在附带针对所有枚举字段(LLM/嵌入提供者、日志级别、PII 操作、合成格式)的工作下拉菜单,以及一个可用的“应用”按钮。新增
[crewai]附加组件,可将 ZettelForge 作为 CrewAI 工具公开——pip install zettelforge[crewai]。完整更新日志
如果 ZettelForge 适合您运行的 CTI 工作流,点个星是表明这一类别值得继续投入的最快信号。
每个 SOC 都会流失分析师。当他们离开时,调查语境、行为者归因以及特定环境的误报模式也随之消失。他们的接替者会重新打开相同的工单,重新阅读相同的报告,并从零开始重建相同的思维模型。
通用 AI 记忆系统无法解决安全团队的问题。它们无法区分 APT28 和 Fancy Bear,不知道 CVE-2024-3094 是 XZ 工具包后门,无法解析 Sigma 或 YARA,也不理解 MITRE ATT&CK 技术 ID。当 CTI 分析师向它们提供一年的情报报告时,它们只能返回基于聊天历史的模糊语义搜索。
ZettelForge 专为使用威胁图谱思考的分析师而打造。它能自动提取 CVE、威胁行为者、IOC 和 ATT&CK 技术,解析跨命名约定的别名,构建具有因果关系的知识图谱,并使用意图感知的混合搜索检索记忆——所有这些都在进程内完成,无需依赖外部 API。
记忆增强填补了小型模型与大型模型在 CTI 任务上 33% 的差距(CTI-REALM,Microsoft 2026,以 GPT-4 作为大型模型基线)。参见完整基准报告了解方法和对比。
实体提取 —— 自动识别 CVE、威胁行为者、IOC(IP、域名、哈希、URL、电子邮件)、MITRE ATT&CK 技术、战役、入侵集、工具、人员、地点和组织。全程使用正则表达式 + LLM 命名实体识别,并采用 STIX 2.1 类型。
知识图谱 —— 实体成为节点,共现成为边。LLM 推断因果三元组(“APT28 使用 Cobalt Strike”)。时间边和替代关系追踪情报的演变。
别名解析 —— APT28、Fancy Bear、Sofacy、STRONTIUM 都解析到同一个行为者节点。在存储和召回时自动生效。
混合检索 —— 向量相似性(768维 fastembed,ONNX)+ 图遍历(知识图谱边上的广度优先搜索),通过意图分类加权。五种意图类型:事实性、时间性、关系性、探索性、因果性。
记忆演化 —— 使用 evolve=True 时,将新情报与现有记忆进行比较。LLM 决定添加、更新、删除或不做操作。过时情报被替代,矛盾被解决,重复项被跳过。
RAG 合成 —— 以 direct_answer 格式跨所有存储记忆合成答案。
架构上的进程内运行 —— fastembed(ONNX)用于嵌入,llama-cpp-python 用于可选的本地 LLM 推理,SQLite + LanceDB 用于存储,默认使用 localhost 上的 Ollama。无需外部 API 密钥。首次运行时可能需要进行出站网络访问以下载嵌入/LLM 模型;模型预加载后,可以完全离线运行(包括在气隙主机上)。
OCSF 模式审计日志 —— 每次操作都会发出一个符合开放网络安全架构框架格式的结构化事件。如何处理日志流(SIEM、WORM 存储、不处理)由您决定。
pip install zettelforge
from zettelforge import MemoryManager
mm = MemoryManager()
# 存储 CTI——通过正则表达式提取实体(CVE、行为者、ATT&CK ID、IOC)
mm.remember("APT28 使用 Cobalt Strike 通过 T1021 进行横向移动")
mm.remember("APT28(Fancy Bear)针对北约国防承包商进行鱼叉式钓鱼攻击")
mm.remember("CVE-2024-3094 是 XZ 工具包后门(CVSS 10.0),影响 sshd")
# 召回结合向量 + 图谱搜索;别名解析生效(Fancy Bear -> APT28)
for note in mm.recall("Fancy Bear 使用什么工具?", k=3):
print(f"[{note.metadata.tier}] {note.content.raw}")
这可以在全新的 pip install 上运行,无需任何外部服务。嵌入通过 fastembed 在进程内运行(首次调用时下载约 80MB ONNX 模型)。MemoryManager() 默认写入 ~/.amem/;可通过 ZETTELFORGE_DATA_DIR 或配置文件覆盖。可运行的副本位于 examples/quickstart.py。
ollama pull qwen3.5:9b && ollama serve
# 运行 Ollama 后,synthesize() 会跨存储笔记返回真正的摘要
answer = mm.synthesize("总结已知的 APT28 TTP")
print(answer["synthesis"]["answer"])
# 后台 LLM 命名实体识别还会用额外实体丰富存储的笔记
ZettelForge 自动检测 Ollama。要使用不同的提供者(local llama-cpp、litellm 用于 100+ 提供者、mock 用于测试),请参见配置。没有 LLM 时,synthesize() 仍然返回结构化响应,但 answer 字段是回退占位符——只有 remember 和 recall 在纯 pip 模式下产生有用结果。
# 新情报到达——evolve=True 启用记忆演化:
# LLM 提取事实,与现有笔记比较,决定添加/更新/删除/不做操作
mm.remember(
"APT28 已经改变了战术。他们放弃了 DROPBEAR,现在利用边缘设备。",
domain="cti",
evolve=True, # 现有的 APT28 笔记被替代,而不是重复
)
每次 remember() 调用都会触发一个流水线:
每次 recall() 调用结合两种检索策略:
pip install zettelforge
在项目根目录(或全局访问的 ~/.claude/.claude.json)创建或编辑 .claude.json:
{
"mcpServers": {
"zettelforge": {
"command": "python3",
"args": ["-m", "zettelforge.mcp"]
}
}
}
如果 ZettelForge 安装在虚拟环境中,请使用该 Python 解释器的完整路径:
{
"mcpServers": {
"zettelforge": {
"command": "/home/user/.venvs/zettelforge/bin/python",
"args": ["-m", "zettelforge.mcp"]
}
}
}
启动 Claude Code 并验证工具是否可用:
claude
# 在会话中询问:“你有哪些来自 zettelforge 的工具可用?”
公开了七个工具:zettelforge_remember、zettelforge_recall、zettelforge_synthesize、zettelforge_entity、zettelforge_graph、zettelforge_stats 和 zettelforge_sync(需要企业版包)。参见 MCP 协议参考了解完整模式、JSON-RPC 请求/响应示例、错误代码以及惰性单例生命周期。有关故障排除、虚拟环境路径和手动工具测试,请参见 设置 MCP 服务器。
对照已发表的学术基准进行评估:
得分列报告了使用 Ollama 托管模型运行的 ZettelForge 测量值,但有一个例外:LOCOMO 行在 v2.1.1 时使用 Ollama 云端评判器进行评估评分(非本地生成)。参见完整基准报告了解基准特定的方法、版本历史和每个套件的评判器配置。
Sigma 和 YARA 规则是一等记忆原语。解析、验证并摄入一条规则后,其标签变成图谱边:MITRE ATT&CK 技术、CVE、威胁行为者别名、工具和恶意软件家族与所有其他笔记解析到同一本体。一个共享的 DetectionRule 超类型携带 SigmaRule 和 YaraRule 子类型,因此单个规则 UUID 可跨两种格式寻址。
Sigma 规则根据供应商提供的 SigmaHQ JSON 模式进行验证。YARA 规则使用 plyara 解析,并根据 CCCS YARA 元数据标准(层级:strict、warn、non_cccs)进行检查。摄入是幂等的——重新摄入未更改的规则会通过内容哈希的 source_ref 返回原始笔记。
from zettelforge import MemoryManager
from zettelforge.sigma import ingest_rule as ingest_sigma
from zettelforge.yara import ingest_rule as ingest_yara
mm = MemoryManager()
ingest_sigma("rules/proc_creation_win_office_macro.yml", mm)
ingest_yara("rules/webshell_china_chopper.yar", mm, tier="warn")
# 从 SigmaHQ 或私有规则仓库批量摄入
python -m zettelforge.sigma.ingest /path/to/sigma/rules/
python -m zettelforge.yara.ingest /path/to/yara/rules/ --tier warn
# CI 夹具检查——解析 + 验证,不写入
python -m zettelforge.sigma.ingest rules/ --dry-run
LLM 规则解释器(zettelforge.detection.explainer.explain)为任何 DetectionRule 生成结构化 JSON 摘要——意图、关键字段、规避说明、误报假设。在 v1 中按需同步运行;异步丰富队列接线是 v1.1 的内容。通过 ZETTELFORGE_EXPLAIN_RPM 进行速率限制(默认 60 次/分钟)。
参考资料:Sigma 规范、SigmaHQ 规则、CCCS YARA、YARA 文档。
将已完成的 ATHF 狩猎摄入 ZettelForge 记忆。MITRE 技术和 IOC 被提取并链接到知识图谱中。
python examples/athf_bridge.py /path/to/hunts/
# 解析了 12 个狩猎
# 已摄入 12/12 个狩猎到 ZettelForge
ThreatRecall 是 ZettelForge 的商业发行版,包含企业扩展功能。默认作为托管 SaaS 提供,同时可为机密环境选择自托管本地部署和气隙部署。企业附加功能:
SaaS 可在几分钟内部署,无需维护基础设施。自托管版作为可部署捆绑包提供,适用于限制或禁止出站网络流出的环境。
加入等候列表 —— 目前正在招募设计合作伙伴。
参见 config.default.yaml 了解所有选项。
参见 CONTRIBUTING.md 了解开发设置。
MIT —— 参见 LICENSE。
由 Patrick Roland 构建 —— LinkedIn | Summit 7 Systems SOC 服务总监 | 海军核退役老兵 | CISSP, CCP (CMMC 2.0 专业)
ZettelForge 采用 MIT 许可证。给仓库点星、提 issue 以及提交 PR——所有贡献都受欢迎。
| 能力 | ZettelForge | Mem0 | Graphiti | Cognee |
|---|
| CTI 实体提取(CVE、行为者、IOC) | 是 | 否 | 否 | 否 |
| STIX 2.1 本体 | 是 | 否 | 否 | 否 |
| 威胁行为者别名解析 | 是(APT28 = Fancy Bear) | 否 | 否 | 否 |
| 带因果三元组的知识图谱 | 是 | 否 | 是 | 是 |
| 意图分类检索(5 种类型) | 是 | 否 | 否 | 否 |
| 进程内/无需外部 API | 是 | 否 | 否 | 否 |
| OCSF 模式的审计日志 | 是 | 否 | 否 | 否 |
| MCP 服务器(Claude Code) | 是 | 否 | 否 | 否 |
| 基准测试 | 测量内容 | 得分 |
|---|
| CTI 检索(CTIBench 子集) | 归因、CVE 关联、多跳 | 75.0% |
| RAGAS | 检索质量(关键词存在) | 78.1% |
| LOCOMO(ACL 2024) | 对话记忆召回 | 22.0% |
| 变量 | 默认值 | 描述 |
|---|
AMEM_DATA_DIR | ~/.amem | 数据目录 |
ZETTELFORGE_BACKEND | sqlite | SQLite 社区后端。TypeDB 可通过扩展使用。 |
ZETTELFORGE_LLM_PROVIDER | local | local(llama-cpp)或 ollama |