
ZettelForge
io.github.rolandpgPublished by GitHub account rolandpgv2.4.0Updated Oct 24, 2026
Agentic memory for cyber threat intelligence. STIX graphs, actor aliasing, offline RAG, Sigma/YARA.
Overview
Local agentic memory for cyber threat intelligence: stores analyst notes as a STIX knowledge graph and recalls them in natural language.
- What you can do
- Store and recall CTI notes, with automatic extraction of CVEs, threat actors, IOCs and ATT&CK techniques and alias resolution across actor names
- Query the knowledge graph of entities, co-occurrence and causal triples, and inspect memory statistics
- Synthesize answers across all stored memories and evolve existing notes by superseding stale or contradictory intel
- Ingest, validate and explain Sigma and YARA detection rules so their tags link into the same graph
- Sync with an enterprise backend (requires the enterprise package)
- When to use it
- Useful for security teams that want an assistant to keep and query investigation context — prior tickets, actor TTPs, false-positive patterns — instead of re-reading reports from scratch. Best suited to CTI and SOC workflows that think in threat graphs rather than generic chat memory.
- Requirements
- Runs as a local Python process installed from PyPI (pip install zettelforge) and launched via python -m zettelforge.mcp. No API keys or cloud account. Embeddings run in-process via fastembed; an optional local LLM (Ollama on localhost or llama-cpp) enables synthesis and richer extraction. Data is stored under ~/.amem by default, configurable via AMEM_DATA_DIR or ZETTELFORGE_DATA_DIR. First run may download models (~80MB).
Installation
In SourceWeft
- Open ZettelForge in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
ZettelForge
The only agentic memory system built for cyber threat intelligence.
When a senior analyst leaves, two or three years of context walks out with them — customer environments, prior investigations, actor TTPs, false-positive patterns, every hard-won "wait, we've seen this before." ZettelForge is an agentic memory system built so that context stays with the team.
It extracts CVEs, threat actors, IOCs, and ATT&CK techniques from analyst notes and threat reports, resolves aliases (APT28 = Fancy Bear = STRONTIUM = Sofacy), builds a STIX 2.1 knowledge graph, and serves every past investigation back to your analysts — and to Claude Code via MCP — in natural language. Runs entirely in-process. No API keys. No cloud. No data leaves the host.
[PyPI] [Downloads/month] [Star History] [Python 3.10+] [License: MIT] [CI] [Open Issues] [Ask DeepWiki]
Star · pip install zettelforge · Docs · ThreatRecall (hosted) · Changelog
v2.6.2 (2026-04-27): Config web editor ships with working dropdowns for all enum fields (LLM/embedding provider, log level, PII action, synthesis format) and a working Apply button. New
[crewai]extra exposes ZettelForge as CrewAI tools --pip install zettelforge[crewai]. Full changelog
[ZettelForge demo -- CTI agentic memory in action]
If ZettelForge fits a CTI workflow you run, a star is the fastest signal that this category is worth continuing to invest in.
The problem
Every SOC loses analysts. When they leave, investigation context, actor attribution, and environment-specific false-positive patterns go with them. Their replacements re-open the same tickets, re-read the same reports, and re-build the same mental models from scratch.
General-purpose AI memory systems don't fix this for security teams. They can't tell APT28 from Fancy Bear, don't know that CVE-2024-3094 is the XZ Utils backdoor, can't parse Sigma or YARA, and have no concept of MITRE ATT&CK technique IDs. When a CTI analyst gives them a year of intel reports, they get back fuzzy semantic search over chat history.
ZettelForge was built for analysts who think in threat graphs. It extracts CVEs, threat actors, IOCs, and ATT&CK techniques automatically, resolves aliases across naming conventions, builds a knowledge graph with causal relationships, and retrieves memories using intent-aware blended search -- all in-process, with no external API dependency.
Memory augmentation closes 33% of the gap between small and large models on CTI tasks (CTI-REALM, Microsoft 2026, using GPT-4 as the large-model baseline). See full benchmark report for methodology and comparisons.
Data Pipeline
Features
Entity Extraction -- Automatically identifies CVEs, threat actors, IOCs (IPs, domains, hashes, URLs, emails), MITRE ATT&CK techniques, campaigns, intrusion sets, tools, people, locations, and organizations. Regex + LLM NER with STIX 2.1 types throughout.
Knowledge Graph -- Entities become nodes, co-occurrence becomes edges. LLM infers causal triples ("APT28 uses Cobalt Strike"). Temporal edges and supersession track how intelligence evolves.
Alias Resolution -- APT28, Fancy Bear, Sofacy, STRONTIUM all resolve to the same actor node. Works automatically on store and recall.
Blended Retrieval -- Vector similarity (768-dim fastembed, ONNX) + graph traversal (BFS over knowledge graph edges), weighted by intent classification. Five intent types: factual, temporal, relational, exploratory, causal.
Memory Evolution -- With evolve=True, new intel is compared to existing memory. LLM decides ADD, UPDATE, DELETE, or NOOP. Stale intel gets superseded. Contradictions get resolved. Duplicates get skipped.
RAG Synthesis -- Synthesize answers across all stored memories with direct_answer format.
In-process by architecture -- fastembed (ONNX) for embeddings, llama-cpp-python for optional local LLM inference, SQLite + LanceDB for storage, and Ollama on localhost by default. No external API keys are required. Outbound network access may occur on first run when embedding/LLM models are downloaded; after models are preloaded, it can run fully offline (including on air-gapped hosts).
Audit logging in OCSF schema -- Every operation emits a structured event in the Open Cybersecurity Schema Framework format. What you do with the log stream (SIEM, WORM store, nothing) is up to you.
Quick Start
30-second hello world (no LLM required)
That works on a fresh pip install with no external services. Embeddings run in-process via fastembed (~80MB ONNX model downloaded on first call). MemoryManager() writes to ~/.amem/ by default; override with ZETTELFORGE_DATA_DIR or via config. A runnable copy lives at examples/quickstart.py.
Add an LLM for synthesis and richer extraction
ZettelForge auto-detects Ollama. To use a different provider (local llama-cpp, litellm for 100+ providers, mock for tests), see Configuration. Without an LLM, synthesize() still returns a structured response but the answer field is a fallback placeholder -- only remember and recall produce useful results in pip-only mode.
Memory Evolution
How It Works
Every remember() call triggers a pipeline:
- Entity Extraction -- regex + LLM NER identifies CVEs, intrusion sets, threat actors, tools, campaigns, ATT&CK techniques, IOCs (IPv4, domain, URL, MD5/SHA1/SHA256, email), people, locations, organizations, events, activities, and temporal references (19 types)
- Knowledge Graph Update -- entities become nodes, co-occurrence becomes edges, LLM infers causal triples
- Vector Embedding -- 768-dim fastembed (ONNX, in-process, 7ms/embed) stored in LanceDB
- Supersession Check -- entity overlap detection marks stale notes as superseded
- Dual-Stream Write -- fast path returns in ~45ms; causal enrichment is deferred to a background worker
Every recall() call blends two retrieval strategies:
- Vector similarity -- semantic search over embeddings
- Graph traversal -- BFS over knowledge graph edges, scored by hop distance
- Intent routing -- query classified as factual/temporal/relational/causal/exploratory, weights adjusted per type
- Cross-encoder reranking -- ms-marco-MiniLM reorders final results by relevance
Use ZettelForge in Claude Desktop in 60 seconds
Create or edit .claude.json in your project root (or ~/.claude/.claude.json for global access):
If ZettelForge is installed in a virtual environment, use the full path to that Python interpreter:
Start Claude Code and verify the tools are available:
Seven tools are exposed: zettelforge_remember, zettelforge_recall, zettelforge_synthesize, zettelforge_entity, zettelforge_graph, zettelforge_stats, and zettelforge_sync (requires enterprise package). See the MCP protocol reference for full schemas, JSON-RPC request/response examples, error codes, and the lazy-singleton lifecycle. For troubleshooting, virtualenv paths, and manual tool testing, see set-up-mcp-server.
Benchmarks
Evaluated against published academic benchmarks:
The Score column reports ZettelForge measurements run with Ollama-hosted models, with one exception: the LOCOMO row was re-measured at v2.1.1 using an Ollama cloud judge for evaluation grading (not local generation). See the full benchmark report for benchmark-specific methodology, version history, and per-suite judge configuration.
Detection Rules as Memory (Sigma + YARA)
Sigma and YARA rules are first-class memory primitives. Parse, validate, and ingest a rule and its tags become graph edges: MITRE ATT&CK techniques, CVEs, threat-actor aliases, tools, and malware families resolve against the same ontology as every other note. A shared DetectionRule supertype carries SigmaRule and YaraRule subtypes, so a single rule UUID is addressable across both formats.
Sigma rules are validated against the vendored SigmaHQ JSON schema. YARA rules are parsed with plyara and checked against the CCCS YARA metadata standard (tiers: strict, warn, non_cccs). Ingest is idempotent -- re-ingesting an unchanged rule returns the original note via a content-hashed source_ref.
An LLM rule explainer (zettelforge.detection.explainer.explain) produces a structured JSON summary -- intent, key fields, evasion notes, false-positive hypotheses -- for any DetectionRule. It runs synchronously on demand in v1; async enrichment-queue wiring is v1.1. Rate-limited via ZETTELFORGE_EXPLAIN_RPM (default 60 calls/minute).
References: Sigma spec, SigmaHQ rules, CCCS YARA, YARA docs.
Integrations
ATHF (Agentic Threat Hunting Framework)
Ingest completed ATHF hunts into ZettelForge memory. MITRE techniques and IOCs are extracted and linked in the knowledge graph.
ThreatRecall (Hosted)
ThreatRecall is the commercial distribution of ZettelForge with enterprise extensions enabled. It is offered as managed SaaS by default, with optional self-hosted on-prem and air-gapped deployments for classified environments. Enterprise add-ons:
- TypeDB STIX 2.1 backend -- schema-enforced ontology with inference rules
- OpenCTI sync -- bi-directional sync with your OpenCTI instance
- Multi-tenant auth -- OAuth/JWT with per-tenant data isolation
- Sigma rule generation -- detection rules from extracted IOCs (upcoming)
SaaS deploys in minutes with no infrastructure to maintain. Self-hosted ships as a deployable bundle for environments where outbound network egress is restricted or prohibited.
Join the waitlist -- currently onboarding design partners.
Configuration
See config.default.yaml for all options.
Contributing
See CONTRIBUTING.md for development setup.
License
MIT -- See LICENSE.
Built by Patrick Roland -- LinkedIn | Director of SOC Services, Summit 7 Systems | Navy nuclear veteran | CISSP, CCP (CMMC 2.0 Professional)
Support the Project
ZettelForge is MIT-licensed. Star the repo, open issues, and submit PRs — all contributions are welcome.
Acknowledgments
- Inspired by Zettelkasten and A-Mem (NeurIPS 2025)
- Two-phase pipeline inspired by Mem0
- STIX 2.1 schema informed by typedb-cti
- Benchmarked against LOCOMO (ACL 2024) and CTIBench (NeurIPS 2024)
- LanceDB | fastembed | Pydantic | TypeDB
Source: README.md at commit d1484ea
Tools
0Version history
1- v2.4.0LatestSep 16, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts