You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**Entity retrieval**: `mm.recall_actor()`, `mm.recall_tool()`, `mm.recall_cve()` provide O(1) indexed lookups for targeted enrichment.
229
229
230
+
**LLM provider options**: Configure via `config.yaml``llm:` section. The default is `provider: ollama` with `model: qwen3.5:9b`. Optional extras: `pip install zettelforge[local]` for in-process GGUF inference, `pip install zettelforge[local-onnx]` for ONNX inference, `pip install zettelforge[litellm]` for LiteLLM routing to 100+ cloud providers.
231
+
230
232
**Performance**: `remember()` is fast (no LLM). `remember_with_extraction()` is slow (LLM per fact). `get_context()` is fast (vector search). Tune `min_importance` and `max_facts` for throughput.
No data migration required. The following new features are available as optional extras:
30
+
31
+
### Local LLM backend selection (RFC-011)
32
+
33
+
`provider: local` now supports two in-process inference engines via `local_backend`:
34
+
35
+
-**`llama-cpp-python`** (default) -- GGUF models. No config change needed if you already use `provider: local`.
36
+
-**`onnxruntime-genai`** -- ONNX models with AMD ROCm, Intel OpenVINO, Apple CoreML support. Requires `pip install zettelforge[local-onnx]` and `local_backend: onnxruntime-genai` in config.
37
+
38
+
The `LlamaCppBackend` code was extracted from `LocalProvider` into its own class. Behavior is identical for existing users. See the [Configuration Reference](reference/configuration.md#llm) for example configs.
39
+
40
+
### LiteLLM unified provider (RFC-012)
41
+
42
+
A new `provider: litellm` option routes to 100+ LLM providers through a single interface, replacing the need for separate `openai_compat`, `anthropic`, `bedrock`, and `vertex` providers.
43
+
44
+
To use: `pip install zettelforge[litellm]`, then configure:
45
+
46
+
```yaml
47
+
llm:
48
+
provider: litellm
49
+
model: gpt-4o
50
+
api_key: ${OPENAI_API_KEY}
51
+
```
52
+
53
+
Model name prefix routing determines the backend automatically: `gpt-4o` -> OpenAI, `claude-sonnet-4-20250514` -> Anthropic, `groq/llama-3.3-70b-versatile` -> Groq, etc.
54
+
55
+
### Steps
56
+
57
+
1. `pip install -U 'zettelforge>=2.5.0'`
58
+
2. (Optional) Install optional extras:
59
+
```bash
60
+
pip install zettelforge[local-onnx] # ONNX local inference
Copy file name to clipboardExpand all lines: docs/index.md
+32-10Lines changed: 32 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,23 +4,23 @@ description: ZettelForge documentation — tutorials, API reference, and archite
4
4
diataxis_type: "navigation"
5
5
audience: "all"
6
6
tags: [overview, navigation]
7
-
last_updated: "2026-04-18"
8
-
version: "2.3.0"
7
+
last_updated: "2026-04-25"
8
+
version: "2.5.0"
9
9
---
10
10
11
11
# ZettelForge Documentation
12
12
13
13
**Your SOC's most expensive asset walks out the door every day.**
14
14
15
-
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.
15
+
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.
16
16
17
-
It extracts CVEs, threat actors, IOCs, and ATT&CK techniques from analyst notes and threat reports, resolves aliases (APT28 = Fancy Bear = STRONTIUM = Sofacy), and indexes vector-embedded Zettelkasten notes in LanceDB for retrieval in natural language by analysts and Claude Code via MCP. Community defaults use SQLite + LanceDB, while TypeDB-backed STIX 2.1 graph storage is optional. No external API keys are required. Default LLM traffic stays on localhost (Ollama), and fully offline operation is possible after required models are preloaded.
17
+
It extracts CVEs, threat actors, IOCs, and ATT&CK techniques from analyst notes and threat reports, resolves aliases (APT28 = Fancy Bear = STRONTIUM = Sofacy), and indexes vector-embedded Zettelkasten notes in LanceDB for retrieval in natural language by analysts and Claude Code via MCP. Community defaults use SQLite + LanceDB, while TypeDB-backed STIX 2.1 graph storage is optional. No external API keys are required by default. Fully offline operation is possible with the `local` provider after preloading models. For cloud-connected deployments, the `litellm` provider routes to OpenAI, Anthropic, Google, Groq, and 100+ other backends through a single interface.
18
18
19
19
**New here?** Start with the [5-minute Quickstart](tutorials/01-quickstart.md), or `pip install zettelforge`.
20
20
21
21
## Architecture Overview
22
22
23
-
ZettelForge uses a hybrid storage architecture with in-process AI. TypeDB stores structured CTI entities and their relationships using the STIX 2.1 ontology. LanceDB stores unstructured notes as 768-dimensional vectors with IVF_PQ indexing. Embeddings are generated in-process by fastembed (nomic-embed-text-v1.5-Q, ONNX runtime, ~7ms/embed) and LLM inference runs in-process via llama-cpp-python (Qwen2.5-3B-Instruct Q4_K_M GGUF). No external AI services are required by default. The BlendedRetriever fuses results from both stores at query time, weighting vector similarity against graph traversal based on the classified intent of the query.
23
+
ZettelForge uses a hybrid storage architecture with in-process AI. TypeDB stores structured CTI entities and their relationships using the STIX 2.1 ontology. LanceDB stores unstructured notes as 768-dimensional vectors with IVF_PQ indexing. Embeddings are generated in-process by fastembed (nomic-embed-text-v1.5-Q, ONNX runtime, ~7ms/embed). LLM inference runs through one of four backends selected by `llm.provider`: in-process GGUF via `llama-cpp-python`, in-process ONNX via `onnxruntime-genai`, Ollama HTTP, or LiteLLM routing to 100+ cloud providers. No external AI services are required by default. The BlendedRetriever fuses results from both stores at query time, weighting vector similarity against graph traversal based on the classified intent of the query.
24
24
25
25
Ingestion follows a two-phase pipeline. The **FactExtractor** distills raw text into scored candidate facts using an LLM. The **MemoryUpdater** compares each fact against existing notes and decides whether to ADD, UPDATE, DELETE, or NOOP -- preventing duplicates and keeping the knowledge base current.
26
26
@@ -62,6 +62,19 @@ graph TB
62
62
end
63
63
```
64
64
65
+
## LLM Provider Options
66
+
67
+
ZettelForge offers four LLM provider options, configured via `llm.provider` in `config.yaml`:
68
+
69
+
| Provider | Installation | Use Case | Configuration |
See the [Configuration Reference](reference/configuration.md) for full details on all provider options, API key management, and example configurations.
77
+
65
78
## Documentation Map
66
79
67
80
This documentation follows the [Diataxis framework](https://diataxis.fr/), organized into four quadrants.
@@ -89,17 +102,17 @@ Practical recipes for specific tasks you need to accomplish.
89
102
|[Configure TypeDB](how-to/configure-typedb.md)| Docker setup, schema deployment, and troubleshooting. |
|[Integrate with Your LLM Agent](how-to/integrate-llm-agent.md)| Use `get_context()` and `ProactiveAgentMixin` in agent loops. |
92
-
|[Configure OpenCTI Integration](how-to/configure-opencti.md)| Bi-directional sync with OpenCTI via pycti — pull threat intelligence, push notes as STIX reports. (requires zettelforge-enterprise) |
105
+
|[Configure OpenCTI Integration](how-to/configure-opencti.md)| Bi-directional sync with OpenCTI via pycti. (requires zettelforge-enterprise) |
93
106
94
107
### Reference (Information-Oriented)
95
108
96
109
Exact specifications for every public class, method, and configuration option.
97
110
98
111
| Reference | Description |
99
112
|-----------|-------------|
100
-
|[Memory Manager API](reference/memory-manager-api.md)|`MemoryManager`— all 19 public methods with full type signatures. |
113
+
|[Memory Manager API](reference/memory-manager-api.md)|`MemoryManager`-- all 19 public methods with full type signatures. |
101
114
|[STIX 2.1 Schema](reference/stix-schema.md)| 9 entity types, 8 relation types, TypeDB functions, and type mappings. |
102
-
|[Configuration](reference/configuration.md)| All `config.yaml` keys, types, defaults, and environment variable overrides. |
115
+
|[Configuration](reference/configuration.md)| All `config.yaml` keys, types, defaults, environment variable overrides, provider quick-reference, and example configs by use case. |
@@ -129,9 +142,18 @@ Background context and design rationale for the system's architecture.
129
142
-**Governance enforcement** -- GOV-003 (data classification), GOV-007 (retention), GOV-011 (access control), GOV-012 (audit) validated on every operation.
130
143
-**Sigma rule generation** -- Produce detection rules from actor TTPs and indicators stored in memory.
131
144
-**Proactive context injection** -- `ContextInjector` pushes relevant memories into agent prompts before the agent asks.
145
+
-**Multi-backend LLM** -- Four provider options: in-process GGUF (llama-cpp-python), in-process ONNX (onnxruntime-genai), Ollama HTTP, and LiteLLM unified routing to 100+ cloud providers.
132
146
133
147
## LLM Quick Reference
134
148
135
-
ZettelForge (v2.3.0, MIT license) is an agentic memory system for cyber threat intelligence. It requires Python 3.10+. By default, storage uses SQLite for the primary backend together with LanceDB for vector-indexed notes; TypeDB 3.x via Docker on port 1729 is an optional graph backend/integration rather than a requirement. Embeddings run in-process via fastembed (nomic-embed-text-v1.5-Q, 768-dim, ONNX). The default LLM provider is Ollama. Local in-process inference via llama-cpp-python (for example, with a Qwen2.5-3B-Instruct Q4_K_M GGUF) is an optional configuration, and the implicit provider fallback is local to Ollama rather than Ollama to local. Storage therefore defaults to SQLite + LanceDB, while optional TypeDB-backed deployments can hold a STIX 2.1 knowledge graph with 9 entity types (threat-actor, malware, tool, attack-pattern, vulnerability, campaign, indicator, infrastructure, zettel-note) and 8 relation types (uses, targets, attributed-to, indicates, mitigates, mentioned-in, supersedes, alias-of). When TypeDB is enabled, graph-oriented functions include get_aliases, get_tools_used, and get_entity_notes. The system seeds 36 CTI aliases at startup (APT28/Fancy Bear/Strontium, APT29/Cozy Bear/Midnight Blizzard, Lazarus/Hidden Cobra/Diamond Sleet, Sandworm/Seashell Blizzard, Volt Typhoon/Bronze Silhouette, Kimsuky/Emerald Sleet, Turla/Secret Blizzard, MuddyWater/Mango Sandstorm, plus tool aliases for Cobalt Strike and Mimikatz).
149
+
ZettelForge (v2.5.0, MIT license) is an agentic memory system for cyber threat intelligence. It requires Python 3.10+. By default, storage uses SQLite together with LanceDB for vector-indexed notes; TypeDB 3.x via Docker on port 1729 is an optional graph backend. Embeddings run in-process via fastembed (nomic-embed-text-v1.5-Q, 768-dim, ONNX). The default LLM provider is Ollama (`provider: ollama`, `model: qwen3.5:9b`).
150
+
151
+
Three additional LLM providers are available as optional extras:
152
+
153
+
-**`provider: local`** with `pip install zettelforge[local]` for in-process GGUF inference via llama-cpp-python (fully offline, Qwen2.5-3B-Instruct Q4_K_M default).
154
+
-**`provider: local` with `local_backend: onnxruntime-genai`** and `pip install zettelforge[local-onnx]` for in-process ONNX inference (AMD ROCm, Intel OpenVINO, Apple CoreML support).
155
+
-**`provider: litellm`** with `pip install zettelforge[litellm]` for unified routing to 100+ providers (OpenAI, Anthropic, Google, Groq, Together AI, AWS Bedrock, OpenRouter, and more) via model name prefix matching. API keys via config or standard environment variables.
156
+
157
+
Storage defaults to SQLite + LanceDB, while optional TypeDB-backed deployments can hold a STIX 2.1 knowledge graph with 9 entity types (threat-actor, malware, tool, attack-pattern, vulnerability, campaign, indicator, infrastructure, zettel-note) and 8 relation types (uses, targets, attributed-to, indicates, mitigates, mentioned-in, supersedes, alias-of). When TypeDB is enabled, graph-oriented functions include get_aliases, get_tools_used, and get_entity_notes. The system seeds 36 CTI aliases at startup (APT28/Fancy Bear/Strontium, APT29/Cozy Bear/Midnight Blizzard, Lazarus/Hidden Cobra/Diamond Sleet, Sandworm/Seashell Blizzard, Volt Typhoon/Bronze Silhouette, Kimsuky/Emerald Sleet, Turla/Secret Blizzard, MuddyWater/Mango Sandstorm, plus tool aliases for Cobalt Strike and Mimikatz).
136
158
137
-
The primary interface is `MemoryManager`. `remember(content)` stores a note with entity extraction, alias resolution, knowledge graph update, supersession check, and causal triple extraction. `remember_with_extraction(content)` runs the two-phase pipeline: FactExtractor distills scored facts, MemoryUpdater compares each against existing notes and applies ADD/UPDATE/DELETE/NOOP. `remember_report(content)` chunks long text and runs two-phase extraction per chunk. `recall(query)` classifies intent (factual/temporal/relational/causal/exploratory), runs BlendedRetriever with policy-weighted vector + graph scores, and returns ranked MemoryNote objects. `recall_actor(name)`, `recall_cve(id)`, `recall_tool(name)` perform fast entity-indexed lookups. `synthesize(query, format)` retrieves notes and produces an LLM-synthesized answer in one of four formats: direct_answer, synthesized_brief, timeline_analysis, or relationship_map. `get_entity_relationships(type, value)` and `traverse_graph(type, value, depth)` expose raw graph queries. Governance policies GOV-003 (data classification), GOV-007 (retention), GOV-011 (access control), and GOV-012 (audit) are enforced automatically on every operation via GovernanceValidator. Configuration lives in config.yaml with sections for storage, typedb, embedding, llm, extraction, retrieval, synthesis, cache, governance, and logging. The BlendedRetriever weights vector vs. graph results using the IntentClassifier's traversal policy: factual queries favor entity lookup, relational queries favor graph BFS, exploratory queries balance both. Notes support supersession (old note marked superseded_by, excluded from recall) and temporal edges for timeline queries.
159
+
The primary interface is `MemoryManager`. `remember(content)` stores a note with entity extraction, alias resolution, knowledge graph update, supersession check, and causal triple extraction. `remember_with_extraction(content)` runs the two-phase pipeline: FactExtractor distills scored facts, MemoryUpdater compares each against existing notes and applies ADD/UPDATE/DELETE/NOOP. `remember_report(content)` chunks long text and runs two-phase extraction per chunk. `recall(query)` classifies intent (factual/temporal/relational/causal/exploratory), runs BlendedRetriever with policy-weighted vector + graph scores, and returns ranked MemoryNote objects. `recall_actor(name)`, `recall_cve(id)`, `recall_tool(name)` perform fast entity-indexed lookups. `synthesize(query, format)` retrieves notes and produces an LLM-synthesized answer in one of four formats: direct_answer, synthesized_brief, timeline_analysis, or relationship_map. `get_entity_relationships(type, value)` and `traverse_graph(type, value, depth)` expose raw graph queries. Governance policies GOV-003 (data classification), GOV-007 (retention), GOV-011 (access control), and GOV-012 (audit) are enforced automatically on every operation via GovernanceValidator. Configuration lives in config.yaml with sections for storage, typedb, embedding, llm, extraction, retrieval, synthesis, cache, governance, logging, lance, and opencti. The BlendedRetriever weights vector vs. graph results using the IntentClassifier's traversal policy: factual queries favor entity lookup, relational queries favor graph BFS, exploratory queries balance both. Notes support supersession (old note marked superseded_by, excluded from recall) and temporal edges for timeline queries.
0 commit comments