{"id":48835154,"url":"https://github.com/rolandpg/zettelforge","last_synced_at":"2026-04-14T23:02:22.994Z","repository":{"id":350904021,"uuid":"1203202149","full_name":"rolandpg/zettelforge","owner":"rolandpg","description":"ZettelForge -  Agentic Memory System for Cyber Threat Intelligence","archived":false,"fork":false,"pushed_at":"2026-04-12T18:31:11.000Z","size":10490,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-12T19:05:26.828Z","etag":null,"topics":["claude-code","claude-code-plugin","cti","hermes-agent","llm","memory-management","openclaw","rag","threat-hunting","threat-intelligence"],"latest_commit_sha":null,"homepage":"https://threatengram.ai","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rolandpg.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-06T20:26:58.000Z","updated_at":"2026-04-12T18:31:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rolandpg/zettelforge","commit_stats":null,"previous_names":["rolandpg/zettelforge"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/rolandpg/zettelforge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rolandpg%2Fzettelforge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rolandpg%2Fzettelforge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rolandpg%2Fzettelforge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rolandpg%2Fzettelforge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rolandpg","download_url":"https://codeload.github.com/rolandpg/zettelforge/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rolandpg%2Fzettelforge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31818840,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T18:05:02.291Z","status":"ssl_error","status_checked_at":"2026-04-14T18:05:01.765Z","response_time":153,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude-code","claude-code-plugin","cti","hermes-agent","llm","memory-management","openclaw","rag","threat-hunting","threat-intelligence"],"created_at":"2026-04-14T23:02:17.493Z","updated_at":"2026-04-14T23:02:22.982Z","avatar_url":"https://github.com/rolandpg.png","language":"Python","readme":"# ZettelForge\n\n**Give your AI agents memory that persists, connects, and reasons.**\n\n[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![CI](https://github.com/rolandpg/zettelforge/actions/workflows/ci.yml/badge.svg)](https://github.com/rolandpg/zettelforge/actions)\n[![Version](https://img.shields.io/badge/version-2.1.0-green.svg)](https://github.com/rolandpg/zettelforge/releases)\n\n## The Problem\n\nYour AI agent starts from zero every session. Context from yesterday's threat hunt, last week's incident, or the report you read an hour ago -- gone. The agent has no memory, no entity relationships, no sense of what changed since the last time it ran.\n\nYou've tried RAG over documents. You get semantic search but no structure -- no \"APT28 uses Cobalt Strike which exploits CVE-2024-1111\" chain of reasoning. No deduplication. No contradiction detection. No way to ask \"what changed since Tuesday?\"\n\nZettelForge fixes this.\n\n## What It Does\n\nZettelForge is an **agentic memory system** -- a structured, persistent knowledge store that AI agents can write to, read from, and reason over. Purpose-built for cyber threat intelligence, but works for any domain.\n\n```python\nfrom zettelforge import MemoryManager\n\nmm = MemoryManager()\n\n# Store intelligence -- entities are auto-extracted, graph edges are built\nmm.remember(\"APT28 uses Cobalt Strike for lateral movement via CVE-2024-1111\", domain=\"cti\")\n\n# New intel arrives -- LLM decides: is this new, an update, or a contradiction?\nmm.remember_with_extraction(\n    \"APT28 has shifted tactics. They dropped DROPBEAR and now exploit edge devices.\"\n)\n\n# Retrieve -- blends vector similarity + knowledge graph traversal\nresults = mm.recall(\"What tools does APT28 use?\")\n# Returns Cobalt Strike note (high confidence), DROPBEAR note (superseded)\n\n# Alias resolution works automatically\nmm.recall_actor(\"Fancy Bear\")  # resolves to APT28\n\n# Synthesize answers from memory\nmm.synthesize(\"Summarize APT28 activity\")\n```\n\nNo cloud. No API keys. Runs entirely on your laptop.\n\n## How It Works\n\nEvery `remember()` call triggers a pipeline:\n\n1. **Entity Extraction** -- regex + LLM NER identifies CVEs, actors, tools, campaigns, people, locations, orgs (10 types)\n2. **Knowledge Graph Update** -- entities become nodes, co-occurrence becomes edges, LLM infers causal triples (\"APT28 *uses* Cobalt Strike\")\n3. **Vector Embedding** -- 768-dim fastembed (ONNX, in-process, 7ms/embed) stored in LanceDB\n\nEvery `recall()` call blends two retrieval strategies:\n\n1. **Vector similarity** -- semantic search over embeddings\n2. **Graph traversal** -- BFS over knowledge graph edges, scored by hop distance\n3. **Intent routing** -- query classified as factual/temporal/relational/causal/exploratory, weights adjusted per type\n4. **Cross-encoder reranking** -- ms-marco-MiniLM reorders final results by relevance\n\nThe **two-phase extraction** pipeline (`remember_with_extraction`) goes further:\n- **Phase 1**: LLM extracts salient facts with importance scores\n- **Phase 2**: Each fact is compared to existing memory -- LLM decides ADD, UPDATE, DELETE, or NOOP\n\nThis means your agent's memory self-corrects. Stale intel gets superseded. Contradictions get resolved. Duplicates get skipped.\n\n## Benchmarks\n\nEvaluated against published academic benchmarks:\n\n| Benchmark | What it measures | Score |\n|-----------|-----------------|-------|\n| **CTI Retrieval** | Attribution, CVE linkage, multi-hop | **75.0%** |\n| **RAGAS** | Retrieval quality (keyword presence) | **78.1%** |\n| **LOCOMO** (ACL 2024) | Conversational memory recall | **18.0%** |\n\nSee the [full benchmark report](benchmarks/BENCHMARK_REPORT.md) for methodology and analysis.\n\n## Quick Start\n\n```bash\ngit clone https://github.com/rolandpg/zettelforge.git\ncd zettelforge\npip install -e .\n```\n\n```python\nfrom zettelforge import MemoryManager\nmm = MemoryManager()\nnote, _ = mm.remember(\"APT28 uses Cobalt Strike for lateral movement\", domain=\"cti\")\nresults = mm.recall(\"What tools does APT28 use?\")\nprint(results[0].content.raw)\n```\n\nNo TypeDB, no Ollama, no Docker -- just `pip install`. Embeddings run in-process via fastembed. LLM features (extraction, synthesis) activate when Ollama is available.\n\n### With Ollama (enables LLM features)\n\n```bash\nollama pull qwen2.5:3b \u0026\u0026 ollama serve\n# ZettelForge auto-detects Ollama for extraction and synthesis\n```\n\n### MCP Server (Claude Code / AI agent integration)\n\n```bash\npython web/mcp_server.py\n# Exposes: remember, recall, synthesize, entity, graph, stats\n```\n\nAdd to `.claude.json`:\n```json\n{\n  \"mcpServers\": {\n    \"threatrecall\": {\n      \"command\": \"python3\",\n      \"args\": [\"web/mcp_server.py\"]\n    }\n  }\n}\n```\n\n## Integrations\n\n### ATHF (Agentic Threat Hunting Framework)\n\nIngest completed [ATHF](https://github.com/Nebulock-Inc/agentic-threat-hunting-framework) hunts into ZettelForge memory. MITRE techniques and IOCs are extracted and linked in the knowledge graph.\n\n```bash\npython examples/athf_bridge.py /path/to/hunts/\n# 12 hunt(s) parsed\n# Ingested 12/12 hunts into ZettelForge\n```\n\nSee [examples/athf_bridge.py](examples/athf_bridge.py).\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────────────────┐\n│                           MemoryManager                              │\n│  remember()  remember_with_extraction()  recall()  synthesize()      │\n├──────────┬───────────┬──────────────┬───────────┬────────────────────┤\n│  Note    │  Fact     │   Memory     │  Blended  │   Synthesis        │\n│Constructor│ Extractor │  Updater     │ Retriever │   Generator        │\n│(enrich)  │(Phase 1)  │(Phase 2)     │(vec+graph)│   (RAG)            │\n├──────────┴───────────┴──────────────┼───────────┴────────────────────┤\n│       Entity Indexer + Alias        │  Intent Classifier             │\n│       Resolver                      │  (factual/temporal/causal)     │\n├─────────────────────────────────────┼────────────────────────────────┤\n│   Knowledge Graph (JSONL)           │  LanceDB (Vectors)             │\n│   Entity nodes + edges              │  768-dim fastembed (ONNX)      │\n│   Causal triple inference           │  Zettelkasten notes            │\n│   [Enterprise: TypeDB STIX 2.1]    │  IVF_PQ index                  │\n└─────────────────────────────────────┴────────────────────────────────┘\n```\n\n## Community vs Enterprise\n\n**ZettelForge Community** (MIT) is everything above -- a complete, production-ready agentic memory system. Free, open-source, local-first.\n\n**[ThreatRecall Enterprise](https://threatengram.com/enterprise)** (BSL-1.1) adds what teams need in production:\n\n| Feature | What it adds |\n|---------|-------------|\n| TypeDB STIX 2.1 ontology | Replaces JSONL graph at scale -- inference rules, 9 entity types, 8 relation types, 36 CTI aliases |\n| Temporal KG queries | \"What changed since Tuesday?\" -- `get_changes_since()`, `get_entity_timeline()` |\n| Multi-hop graph traversal | `traverse_graph()` with BFS across relationship chains |\n| Advanced synthesis | `synthesized_brief`, `timeline_analysis`, `relationship_map` |\n| Report ingestion | `remember_report()` with auto-chunking for long threat reports |\n| OpenCTI integration | Bi-directional sync with OpenCTI platform |\n| Sigma rule generation | Sigma YAML detection rules from IOCs |\n| Multi-tenant auth | OAuth/JWT with per-tenant data isolation |\n| Context injection | Auto-load relevant context before agent tasks |\n\n```bash\npip install zettelforge-enterprise\nexport THREATENGRAM_LICENSE_KEY=\"TG-xxxx-xxxx-xxxx-xxxx\"\n```\n\n## Configuration\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `AMEM_DATA_DIR` | `~/.amem` | Data directory |\n| `ZETTELFORGE_BACKEND` | `jsonl` | `jsonl` or `typedb` [Enterprise] |\n| `ZETTELFORGE_LLM_PROVIDER` | `local` | `local` (llama-cpp) or `ollama` |\n| `THREATENGRAM_LICENSE_KEY` | | Enterprise license key |\n\nSee [config.default.yaml](config.default.yaml) for all options.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and the Community/Enterprise boundary.\n\n## License\n\n- **Community**: [MIT](LICENSE)\n- **Enterprise**: [BSL-1.1](LICENSE-ENTERPRISE) (converts to Apache-2.0 after 4 years)\n\nBuilt by [Threatengram](https://threatengram.com).\n\n## Acknowledgments\n\n- Inspired by [Zettelkasten](https://en.wikipedia.org/wiki/Zettelkasten) and [A-Mem](https://arxiv.org/abs/2602.10715) (NeurIPS 2025)\n- Two-phase pipeline inspired by [Mem0](https://mem0.ai/research)\n- STIX 2.1 schema informed by [typedb-cti](https://github.com/typedb-osi/typedb-cti)\n- Benchmarked against [LOCOMO](https://snap-research.github.io/locomo/) (ACL 2024) and [CTIBench](https://arxiv.org/abs/2406.07599) (NeurIPS 2024)\n- [LanceDB](https://lancedb.com) | [fastembed](https://github.com/qdrant/fastembed) | [Pydantic](https://pydantic.dev) | [TypeDB](https://typedb.com)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frolandpg%2Fzettelforge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frolandpg%2Fzettelforge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frolandpg%2Fzettelforge/lists"}