
Python製CTI向けエージェントメモリ — STIXナレッジグラフ、脅威アクターのエイリアス解決、オフラインファーストRAG、Claude CodeおよびLangChainエージェント向けMCPサーバー
サイバー脅威インテリジェンスのために構築された唯一のエージェンティックメモリシステム。
上級アナリストが去ると、2~3年分のコンテキスト(顧客環境、過去の調査、攻撃者のTTP、誤検知パターン、苦労して得た「あれ、前に見た」という知識)も一緒に去っていきます。ZettelForgeは、そのコンテキストをチーム内に留めておくために構築されたエージェンティックメモリシステムです。
アナリストのメモや脅威レポートからCVE、脅威アクター、IOC、ATT&CKテクニックを抽出し、エイリアスを解決し(APT28 = Fancy Bear = STRONTIUM = Sofacy)、STIX 2.1ナレッジグラフを構築し、過去のすべての調査を自然言語でアナリストや(MCP経由の)Claude Codeに返します。すべてインプロセスで動作。APIキー不要。クラウド不要。データがホストから出ることはありません。
Star · pip install zettelforge · Docs · ThreatRecall (hosted) · Changelog
v2.6.2 (2026-04-27): 設定Webエディタに、すべてのenumフィールド(LLM/埋め込みプロバイダ、ログレベル、PIIアクション、合成フォーマット)で動作するドロップダウンと、動作するApplyボタンが含まれました。新しい
[crewai]エクストラにより、ZettelForgeをCrewAIツールとして公開します --pip install zettelforge[crewai]。フルチェンジログ
ZettelForgeがあなたの実行するCTIワークフローに適合するなら、スターを付けることがこのカテゴリーに投資を続ける価値があることを示す最も迅速なシグナルです。
すべてのSOCはアナリストを失います。彼らが去ると、調査のコンテキスト、攻撃者の属性、環境固有の誤検知パターンが一緒に去っていきます。後任者は同じチケットを再オープンし、同じレポートを再読み込みし、同じメンタルモデルをゼロから再構築します。
汎用AIメモリシステムはセキュリティチームにとってこれを解決しません。APT28とFancy Bearを区別できず、CVE-2024-3094がXZ Utilsバックドアであることを知らず、SigmaやYARAを解析できず、MITRE ATT&CKテクニックIDの概念がありません。CTIアナリストが1年分のインテルレポートを与えても、返ってくるのはチャット履歴に対するあいまいなセマンティック検索だけです。
ZettelForgeは脅威グラフで考えるアナリストのために構築されました。CVE、脅威アクター、IOC、ATT&CKテクニックを自動的に抽出し、命名規則間のエイリアスを解決し、因果関係を持つナレッジグラフを構築し、意図認識型ブレンド検索を使用してメモリを取得します。すべてインプロセスで、外部API依存はありません。
メモリ拡張は、CTIタスクにおいて小規模モデルと大規模モデルのギャップの33%を埋めます(CTI-REALM, Microsoft 2026、GPT-4を大規模モデルのベースラインとして使用)。方法論と比較については完全なベンチマークレポートを参照してください。
エンティティ抽出 -- CVE、脅威アクター、IOC(IP、ドメイン、ハッシュ、URL、メール)、MITRE ATT&CKテクニック、キャンペーン、侵入セット、ツール、人物、場所、組織を自動的に識別します。全体を通して正規表現 + LLM NERとSTIX 2.1タイプを使用。
ナレッジグラフ -- エンティティはノードに、共起はエッジになります。LLMが因果トリプル(「APT28 が Cobalt Strike を使用する」)を推論します。時間的エッジと後続関係により、インテリジェンスの進化を追跡します。
エイリアス解決 -- APT28、Fancy Bear、Sofacy、STRONTIUMはすべて同じアクターノードとして解決されます。保存時と検索時に自動的に機能します。
ブレンド検索 -- ベクトル類似度(768次元 fastembed、ONNX)+ グラフトラバーサル(ナレッジグラフエッジ上のBFS)、意図分類で重み付け。5つの意図タイプ:事実、時間、関係、探索、因果。
メモリ進化 -- evolve=True を指定すると、新しいインテルが既存のメモリと比較されます。LLMがADD、UPDATE、DELETE、NOOPを決定します。古いインテルは後続としてマークされます。矛盾は解決され、重複はスキップされます。
RAG合成 -- direct_answer フォーマットを使用して、保存されたすべてのメモリを横断して回答を合成します。
アーキテクチャによるインプロセス -- 埋め込みにfastembed(ONNX)、オプションのローカルLLM推論にllama-cpp-python、ストレージにSQLite + LanceDB、デフォルトでlocalhost上のOllamaを使用。外部APIキーは不要。初回実行時に埋め込み/LLMモデルがダウンロードされる際に発信ネットワークアクセスが発生する可能性があります。モデルを事前ロードした後は、完全にオフライン(隔離ホストを含む)で実行できます。
OCSFスキーマの監査ログ -- すべての操作は、Open Cybersecurity Schema Framework形式の構造化イベントを出力します。ログストリームをどうするか(SIEM、WORMストレージ、何もしない)はユーザー次第です。
pip install zettelforge
from zettelforge import MemoryManager
mm = MemoryManager()
# CTIを保存 -- エンティティ(CVE、アクター、ATT&CK ID、IOC)は正規表現で抽出されます
mm.remember("APT28 uses Cobalt Strike for lateral movement via T1021")
mm.remember("APT28 (Fancy Bear) targets NATO defense contractors with spear-phishing")
mm.remember("CVE-2024-3094 is the XZ Utils backdoor (CVSS 10.0) affecting sshd")
# 検索はベクトル検索とグラフ検索をブレンド。エイリアス解決が機能します(Fancy Bear -> APT28)
for note in mm.recall("What tools does Fancy Bear use?", 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("Summarize known APT28 TTPs")
print(answer["synthesis"]["answer"])
# バックグラウンドのLLM NERはまた、保存されたメモリに追加のエンティティをエンリッチします
ZettelForgeはOllamaを自動検出します。別のプロバイダ(local llama-cpp、100以上のプロバイダ向けlitellm、テスト用mock)を使用するには、設定を参照してください。LLMがない場合、synthesize() は構造化されたレスポンスを返しますが、answer フィールドはフォールバックのプレースホルダになります。pipのみのモードでは remember と recall だけが有用な結果を生成します。
# 新しいインテルが到着 -- evolve=Trueでメモリ進化を有効化:
# LLMがファクトを抽出し、既存のメモリと比較し、ADD/UPDATE/DELETE/NOOPを決定
mm.remember(
"APT28 has shifted tactics. They dropped DROPBEAR and now exploit edge devices.",
domain="cti",
evolve=True, # 既存のAPT28メモは重複せず、後続としてマークされます
)
remember() が呼ばれるたびに、次のパイプラインが起動します:
recall() が呼ばれるたびに、2つの検索戦略をブレンドします:
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
# セッション内で次のように尋ねます:"What tools do you have available from zettelforge?"
7つのツールが公開されています:zettelforge_remember、zettelforge_recall、zettelforge_synthesize、zettelforge_entity、zettelforge_graph、zettelforge_stats、zettelforge_sync(エンタープライズパッケージが必要)。完全なスキーマ、JSON-RPCリクエスト/レスポンスの例、エラーコード、遅延シングルトンのライフサイクルについては、MCPプロトコルリファレンスを参照してください。トラブルシューティング、virtualenvパス、手動ツールテストについては、set-up-mcp-serverを参照してください。
公開された学術ベンチマークに対して評価:
スコア列は、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 hunts parsed
# Ingested 12/12 hunts into 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) | Yes | No | No | No |
| STIX 2.1オントロジー | Yes | No | No | No |
| 脅威アクターのエイリアス解決 | Yes (APT28 = Fancy Bear) | No | No | No |
| 因果トリプルを持つナレッジグラフ | Yes | No | Yes | Yes |
| 意図分類型検索(5種類) | Yes | No | No | No |
| インプロセス / 外部API不要 | Yes | No | No | No |
| OCSFスキーマの監査ログ | Yes | No | No | No |
| MCPサーバー (Claude Code) | Yes | No | No | No |
| ベンチマーク | 測定内容 | スコア |
|---|
| 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 |