Create Context Graph
Memory frameworkOfficial neo4j-labs project
Created by neo4j-labs
Published in neo4j-labs/create-context-graph. Publisher page
747 GitHub stars
What it is
AI agents with graph based reasoning memory, scaffolded in seconds
AutoGineer overview, from the brain’s own files
Create Context Graph is an interactive scaffolding tool designed to accelerate the development of AI agents that utilize graph-based memory. By walking developers through a wizard, it generates a complete, domain-specific application stack including a FastAPI backend, a Next.js frontend with interactive graph visualization, and a configured AI agent. The tool supports multiple agent frameworks and offers a choice between a hosted memory backend (NAMS) or a self-hosted Neo4j instance. It includes built-in support for importing data from various SaaS platforms, generating domain-specific ontologies, and creating MCP servers for integration with Claude Desktop.
How it works
Memory model: Hybrid
AutoGineer overview, from the brain’s own files
The tool operates as a CLI that uses Jinja2 templates to generate project code based on a selected industry domain and agent framework. It creates a FastAPI backend for agent logic and a Next.js frontend for visualization. Memory is managed either via the hosted NAMS service or a self-hosted Neo4j database. The system supports data ingestion from various connectors and can generate domain-specific ontologies, schemas, and agent tools automatically.
| Folder | Role | Files |
|---|---|---|
| .github | agent-config | 2 |
| docs | docs | 105 |
| scripts | scripts | 2 |
| src | source-code | 168 |
| tests | tests | 48 |
| .serena | folder | 1 |
| npm-wrapper | folder | 3 |
The agent reads
- get_entity_detail_nams evidence: CLAUDE.md
- list_traces evidence: CLAUDE.md
- list_documents_nams evidence: CLAUDE.md
- find_decisions evidence: CLAUDE.md
- search_sessions evidence: CLAUDE.md
- get_collector evidence: CLAUDE.md
The agent writes
- delete_entity evidence: CLAUDE.md
- add_relationship evidence: CLAUDE.md
- add_entity evidence: CLAUDE.md
Requirements
Runtimes: Python >=3.11
Databases: Neo4j
API keys (by name): ANTHROPIC_API_KEY, GOOGLE_API_KEY, LINEAR_API_KEY, MEMORY_API_KEY, OPENAI_API_KEY
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Google Antigravity, Kiro, OpenCode, Amp, Roo Code, Cline, JetBrains Junie, Devin (ex-Windsurf)
Set it up
This brain runs code automatically: 1 script. Review Makefile before opening the folder in Claude Code. No step below turns a hook on for you.
Makefile:uv venv && uv pip install -e ".[dev]"
- Not scanned by AutoGineerIts dependencies are installed by pip or uv when you run it and were not scanned by AutoGineer (7 declared). https://pypi.org/project/create-context-graph/
Created by neo4j-labs. Published in neo4j-labs/create-context-graph. Licence: Apache License 2.0.
Usage
AutoGineer overview, from the brain’s own files
- Scaffold a new project using the interactive CLI wizard.
- Generate a project with a specific domain and agent framework via CLI flags.
- Connect SaaS data sources like GitHub, Slack, or Notion to populate the graph.
- Configure the memory backend for either hosted NAMS or self-hosted Neo4j.
- Generate an MCP server configuration for Claude Desktop integration.
- Re-import data or seed the graph using generated make commands.
- “uvx create-context-graph my-app --domain healthcare --framework strands --nams-api-key sk-nams-...”
- Generates a healthcare-focused agent application using the Strands framework and hosted NAMS memory.
- “uvx create-context-graph my-app --domain personal-knowledge --framework pydanticai --self-hosted --connector github”
- Generates a personal knowledge application with self-hosted Neo4j, pre-populated with GitHub data.
Documentation by neo4j-labs
Create Context Graph
This is an experimental Neo4j Labs project and not part of Neo4j's supported product lineup. See the Neo4j Labs disclaimer.
Neo4j Labs Project — This project is part of Neo4j Labs. It is maintained by Neo4j staff and the community, but not officially supported. For help, use GitHub Issues or the Neo4j Community Forum.
Interactive CLI scaffolding tool that generates fully-functional, domain-specific context graph applications. Pick your industry domain, pick your agent framework, and get a complete full-stack app in under 5 minutes.
<p align="center"> <img src="docs/static/img/app-three-panel.png" alt="Generated app: chat interface, graph visualization, and document browser" width="800" /> </p>
# Python — NAMS-default (hosted memory)
uvx create-context-graph my-app --domain healthcare --framework strands --nams-api-key sk-nams-...
# Self-hosted Neo4j with full demo fixtures
uvx create-context-graph my-app --domain healthcare --framework pydanticai --self-hosted --demo
# Node.js / interactive wizard
npx create-context-graphWhat It Does
Create Context Graph walks you through an interactive wizard and generates a complete project:
FastAPI backend with an AI agent configured for your domain, powered by neo4j-agent-memory v0.4 for multi-turn conversations with automatic entity extraction. Memory backend is configurable: hosted NAMS (default) or self-hosted bolt Neo4j (
--self-hosted).LiteLLM provider injection for the memory layer — pick any LLM + embedding provider via
MEMORY_LLM/MEMORY_EMBEDDINGenv vars (Anthropic, OpenAI, Bedrock, Vertex AI, Ollama, Groq, Together, …). Native adapters resolve first; everything else routes through LiteLLM.Next.js + Chakra UI v3 frontend with streaming chat (Server-Sent Events), real-time tool call visualization (Timeline with live spinners), interactive graph visualization (schema view, double-click expand, drag/zoom, property panel), entity detail panel, document browser, and decision trace viewer
Neo4j schema with domain-specific constraints, indexes, and GDS projections (self-hosted mode)
Rich demo data — LLM-generated entities, relationships, professional documents (discharge summaries, trade confirmations, lab reports), and multi-step decision traces
SaaS data import — connect GitHub, Slack, Gmail, Jira, Notion, Google Calendar, Salesforce, Linear, Google Workspace, Claude Code, Claude AI, ChatGPT, or local files
Custom domains — describe your domain in plain English and the LLM generates a complete ontology
Domain-specific agent tools with Cypher queries tailored to your industry
MCP server for Claude Desktop — optionally generates an MCP server config so Claude Desktop can query the same knowledge graph (
--with-mcp)
Creating context graph application...
Domain: Wildlife Management
Framework: PydanticAI
Data: Demo (synthetic)
Neo4j: Docker (neo4j://localhost:7687)
[1/6] Generating domain ontology... ✓
[2/6] Creating project scaffold... ✓
[3/6] Configuring agent tools & system prompt... ✓
[4/6] Generating synthetic documents (25 docs)... ✓
[5/6] Writing fixture data... ✓
[6/6] Bundling project... ✓
Done! Your context graph app is ready.
cd my-app
make install && make startQuick Start
There are two flows depending on what you want:
NAMS (default) — hosted memory backend. No Neo4j to install or operate. Graph starts empty; the agent populates it as you chat.
Self-hosted (
--self-hosted) — bolt Neo4j you run yourself (Aura, Docker, neo4j-local). Full demo fixtures available viamake seed.
Prerequisites
Python 3.11+ (with uv recommended)
Node.js 18+ (for the frontend)
NAMS path: a NAMS API key from memory.neo4jlabs.com
Self-hosted path: Neo4j 5+ (Docker, Aura, or local install)
Either path:
ANTHROPIC_API_KEYfor the agent (orOPENAI_API_KEY/GOOGLE_API_KEYdepending on framework)
NAMS path (default, hosted memory)
uvx create-context-graph my-app \
--domain healthcare \
--framework strands \
--nams-api-key sk-nams-...
cd my-app
echo 'ANTHROPIC_API_KEY=sk-ant-...' >> .env # Strands needs Anthropic
make install
make startOpen http://localhost:3000. Graph starts empty — chat with the agent and entities populate via auto-extraction.
Self-hosted path (bolt Neo4j + full demo data)
uvx create-context-graph my-app \
--domain healthcare \
--framework pydanticai \
--self-hosted \
--demo
cd my-app
echo 'ANTHROPIC_API_KEY=sk-ant-...' >> .env
make install
make docker-up # or: make neo4j-start (for neo4j-local)
make seed
make startOpen http://localhost:3000. Pre-populated graph with ~85 entities, 180 relationships, 25 documents, and decision traces.
Other scaffold patterns
# Interactive wizard (asks 6 prompts, autocomplete domain picker)
uvx create-context-graph
# Custom domain from description
uvx create-context-graph my-app \
--custom-domain "veterinary clinic management" \
--framework pydanticai \
--self-hosted --demo \
--anthropic-api-key $ANTHROPIC_API_KEY
# Import real data from SaaS services
uvx create-context-graph my-app \
--domain personal-knowledge --framework pydanticai --self-hosted \
--connector github --connector slack
# With MCP server for Claude Desktop (works on either backend)
uvx create-context-graph my-app \
--domain healthcare --framework strands \
--nams-api-key sk-nams-... --with-mcp
# Pick a specific LiteLLM provider for memory entity extraction
uvx create-context-graph my-app \
--domain healthcare --framework strands --nams-api-key sk-nams-... \
--memory-llm bedrock/anthropic.claude-3-haiku-20240307-v1:0 \
--memory-embedding sentence-transformers/all-MiniLM-L6-v2Explore the running app
Frontend: http://localhost:3000 — Chat with the AI agent, explore the knowledge graph
Backend API: http://localhost:8000/docs — FastAPI auto-generated docs
Health endpoint: http://localhost:8000/health — reports the active memory backend
NAMS dashboard: memory.neo4jlabs.com (NAMS path only)
Neo4j Browser: http://localhost:7474 (self-hosted Docker / neo4j-local only)
NAMS write-path caveats (v0.4)
The NAMS REST API has a narrower write surface than bolt Cypher. The CLI and the generated import_data.py work around it with a hybrid write shape:
Relationships encoded as
ccg-edgesYAML blocks inside each source entity'sdescription. The frontend graph view parses them out and renders edges; a future migration replays them as native edges when NAMS addsadd_relationship.Entity properties collapse into
descriptionas a markdown block (NAMS REST accepts onlyname/type/description).Documents are dual-tracked —
long_term.add_entity(type=OBJECT)(queryable, matches bolt:Document) ANDshort_term.add_message(role="document")(extraction fuel).No preferences or facts via REST.
auto_preferencesforced off on NAMS.GDS endpoints and arbitrary Cypher writes return 501 on NAMS.
For native graph edges + GDS + arbitrary Cypher, use --self-hosted --demo.
Supported Domains
27 industry domains, each with a purpose-built ontology, sample data, agent tools, and demo scenarios:
| Domain | Key Entities | Domain | Key Entities |
|---|---|---|---|
| Financial Services | Account, Transaction, Decision, Policy | Real Estate | Property, Listing, Agent, Inspection |
| Healthcare | Patient, Provider, Diagnosis, Treatment | Vacation & Hospitality | Resort, Booking, Guest, Activity |
| Retail & E-Commerce | Customer, Product, Order, Review | Oil & Gas | Well, Reservoir, Equipment, Permit |
| Manufacturing | Machine, Part, WorkOrder, Supplier | Data Journalism | Source, Story, Claim, Investigation |
| Scientific Research | Researcher, Paper, Dataset, Grant | Trip Planning | Destination, Hotel, Activity, Itinerary |
| GenAI / LLM Ops | Model, Experiment, Prompt, Evaluation | GIS & Cartography | Feature, Layer, Survey, Boundary |
| Agent Memory | Agent, Conversation, Memory, ToolCall | Wildlife Management | Species, Sighting, Habitat, Camera |
| Gaming | Player, Character, Quest, Guild | Conservation | Site, Species, Program, Funding |
| Personal Knowledge | Note, Contact, Project, Topic | Golf & Sports Mgmt | Course, Player, Round, Tournament |
| Digital Twin | Asset, Sensor, Reading, Alert | Software Engineering | Repository, Issue, PR, Deployment |
| Product Management | Feature, Epic, UserPersona, Metric | Hospitality | Hotel, Room, Reservation, Service |
| Options Intelligence | Underlying, OptionsContract, Regime, KeyLevel | Legal | Case, Matter, Contract, Filing |
| Education | Student, Instructor, Course, Assessment | Cybersecurity | Asset, Vulnerability, Alert, Incident |
| Government | Agency, Program, Policy, Regulation |
# List all available domains
create-context-graph --list-domainsCustom domains: Don't see your industry? Select "Custom (describe your domain)" in the wizard or use --custom-domain "your description". The LLM generates a complete ontology with entity types, relationships, agent tools, and more.
SaaS Data Connectors
<p align="center"> <img src="docs/static/img/connector-data-flow.png" alt="SaaS connector data flow into Neo4j knowledge graph" width="700" /> </p>
Import real data from your existing tools instead of (or in addition to) synthetic demo data:
| Service | What's Imported | Auth |
|---|---|---|
| GitHub | Issues, PRs, commits, contributors | Personal access token |
| Notion | Pages, databases, users | Integration token |
| Jira | Issues, sprints, users | API token |
| Slack | Channel messages, threads, users | Bot OAuth token |
| Gmail | Emails (last 30 days) | Google Workspace CLI or OAuth2 |
| Google Calendar | Events, attendees (last 90 days) | Google Workspace CLI or OAuth2 |
| Salesforce | Accounts, contacts, opportunities | Username/password |
| Linear | Issues, projects, cycles, teams, users, labels, comments, milestones, initiatives, attachments + decision traces from history | Personal API key |
| Google Workspace | Drive files, comment threads (as decision traces), revisions, Drive Activity, Calendar events, Gmail metadata | Google OAuth 2.0 |
| Claude Code | Session history, messages, tool calls, files, decisions, preferences, errors | None (local files) |
| Claude AI | Conversations, messages, tool calls, thinking traces from Claude AI web/app export | None (local file) |
| ChatGPT | Conversations, messages, tool results from ChatGPT data export | None (local file) |
The Google Workspace connector extracts resolved comment threads from Google Docs as first-class decision traces — capturing the question, deliberation, resolution, and participants. Combined with Linear, it provides the full decision lifecycle: from meeting discussion to code execution.
The Claude Code connector reads your local session history from ~/.claude/projects/ — no API keys needed. It extracts decision traces from user corrections and error-resolution cycles, identifies developer preferences from explicit statements and behavioral patterns, and automatically redacts secrets before storage.
The Claude AI and ChatGPT connectors import your conversation exports directly from the official data export features. Export your data from Settings, pass the .zip file to the CLI with --import-type claude-ai or --import-type chatgpt, and get a fully populated context graph from your real conversations — no API keys needed.
Connectors run at scaffold time to populate initial data. They're also generated into your project so you can re-import with make import:
cd my-app
make import # Re-import from connected services
make import-and-seed # Import and seed into Neo4jAgent Frameworks
Select your preferred agent framework at project creation time:
| Framework | Description |
|---|---|
| PydanticAI | Structured tool definitions with Pydantic models and RunContext |
| Claude Agent SDK | Anthropic tool-use with agentic loop |
| OpenAI Agents SDK | @function_tool decorators with Runner.run() |
| LangGraph | Stateful graph-based agent workflow with create_react_agent() |
| CrewAI | Multi-agent crew with role-based tools |
| Strands | Tool-use agents with Anthropic model |
| Google ADK | Gemini agents with FunctionTool calling |
| Anthropic Tools | Modular tool registry with Anthropic API agentic loop |
All frameworks share the same FastAPI HTTP layer, Neo4j client, and frontend. Only the agent implementation differs. "Full streaming" means token-by-token text + real-time tool calls. "Tool streaming" means real-time tool calls with text delivered at the end.
Note on memory providers: Conversation memory uses local
sentence-transformers/all-MiniLM-L6-v2embeddings by default — no API key required. Override withMEMORY_EMBEDDING(LiteLLM provider string) for OpenAI, Vertex AI, Bedrock, or others. The entity-extraction LLM defaults toanthropic/claude-haiku-4-5whenANTHROPIC_API_KEYis set, oropenai/gpt-4o-miniif onlyOPENAI_API_KEYis set. Override withMEMORY_LLMfor full control. See Configure Memory Providers.
Generated Project Structure
<p align="center"> <img src="docs/static/img/ontology-pipeline.png" alt="From domain YAML through Jinja2 templates to generated code" width="750" /> </p>
A single domain YAML drives the entire generated application — schema, models, agent tools, and visualization — through the Jinja2 template engine.
my-app/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI application
│ │ ├── agent.py # AI agent (framework-specific)
│ │ ├── config.py # Settings from .env
│ │ ├── routes.py # REST API endpoints
│ │ ├── models.py # Pydantic models (from ontology)
│ │ ├── context_graph_client.py # Neo4j CRUD operations
│ │ ├── memory.py # Memory integration (MemoryIntegration)
│ │ ├── gds_client.py # Graph Data Science algorithms
│ │ ├── vector_client.py # Vector search
│ │ └── connectors/ # SaaS connectors (if selected)
│ ├── scripts/
│ │ ├── generate_data.py # Data seeding script
│ │ └── import_data.py # SaaS import script (if connectors selected)
│ └── pyproject.toml
├── frontend/
│ ├── app/ # Next.js pages
│ ├── components/
│ │ ├── ChatInterface.tsx # Streaming AI chat (SSE) with real-time tool calls + graph data flow
│ │ ├── ContextGraphView.tsx # Interactive NVL graph (schema view, expand, drag/zoom, properties)
│ │ ├── DecisionTracePanel.tsx # Reasoning trace viewer with step details
│ │ ├── DocumentBrowser.tsx # Document browser with template filtering
│ │ └── Provider.tsx # Chakra UI v3 provider
│ ├── lib/config.ts # Domain configuration
│ ├── theme/index.ts # Chakra theme with domain colors
│ └── package.json
├── cypher/
│ ├── schema.cypher # Constraints & indexes
│ └── gds_projections.cypher # GDS algorithm config
├── data/
│ ├── ontology.yaml # Domain ontology definition
│ └── fixtures.json # Pre-generated sample data
├── .env # Neo4j + API key configuration
├── .env.example # Configuration template (tracked in git)
├── .dockerignore # Docker build context exclusions
├── docker-compose.yml # Local Neo4j instance (Docker mode only)
├── Makefile # start, seed, reset, install, test, test-connection, lint
├── mcp/ # MCP server config (only if --with-mcp)
└── README.md # Domain-specific documentation (with framework docs + troubleshooting)CLI Reference
create-context-graph [PROJECT_NAME] [OPTIONS]
Arguments:
PROJECT_NAME Project name (optional — auto-generated from domain+framework if omitted)
Options:
--domain TEXT Domain ID (e.g., healthcare, gaming)
--framework TEXT Agent framework (strands [default], pydanticai, claude-agent-sdk, openai-agents, langgraph, crewai, google-adk, anthropic-tools)
--self-hosted Use self-hosted Neo4j (bolt) instead of NAMS hosted memory
--nams-api-key TEXT NAMS API key [env: MEMORY_API_KEY] — obtain at https://memory.neo4jlabs.com
--nams-endpoint TEXT Override NAMS endpoint URL (default: https://memory.neo4jlabs.com/v1)
--memory-llm TEXT LiteLLM provider string for memory entity extraction (e.g. anthropic/claude-haiku-4-5)
--memory-embedding TEXT LiteLLM provider string for memory embeddings (e.g. sentence-transformers/all-MiniLM-L6-v2)
--demo-data Generate synthetic demo data
--custom-domain TEXT Generate custom domain from description (requires --anthropic-api-key)
--connector TEXT SaaS connector to enable; repeatable (github, slack, jira, notion, gmail, gcal, salesforce, linear, google-workspace, claude-code, claude-ai, chatgpt)
--import-type TEXT Chat history import: claude-ai or chatgpt (requires --import-file)
--import-file PATH Path to chat export file (.zip, .json, .jsonl)
--import-depth TEXT Import extraction depth: fast (default) or deep
--import-filter-after TEXT Only import conversations after this date (ISO 8601)
--import-filter-before TEXT Only import conversations before this date (ISO 8601)
--import-filter-title TEXT Only import conversations matching title pattern (regex)
--import-max-conversations INT Max conversations to import, 0=all (default: 0)
--linear-api-key TEXT Linear API key (required for --connector linear) [env: LINEAR_API_KEY]
--linear-team TEXT Linear team key to filter import (e.g., ENG) [env: LINEAR_TEAM]
--gws-folder-id TEXT Google Drive folder ID to scope import [env: GWS_FOLDER_ID]
--gws-include-comments / --gws-no-comments Import comment threads (default: on)
--gws-include-revisions / --gws-no-revisions Import revision history (default: on)
--gws-include-activity / --gws-no-activity Import Drive Activity (default: on)
--gws-include-calendar Import Calendar events (default: off)
--gws-include-gmail Import Gmail thread metadata (default: off)
--gws-since TEXT Import data since date (ISO format, default: 90 days ago)
--gws-mime-types TEXT MIME types to include (default: docs,sheets,slides)
--gws-max-files INT Maximum files to import (default: 500)
--claude-code-scope TEXT Import current project or all (default: current)
--claude-code-project TEXT Explicit project path to import sessions for
--claude-code-since TEXT Import sessions since date (ISO format)
--claude-code-max-sessions INT Max sessions to import, 0=all (default: 0)
--claude-code-content TEXT Content mode: truncated, full, none (default: truncated)
--with-mcp Generate MCP server configuration for Claude Desktop
--mcp-profile TEXT MCP tool profile: core (6 tools) or extended (16 tools, default)
--session-strategy TEXT Memory session strategy: per_conversation (default), per_day, persistent
--auto-extract/--no-auto-extract Auto-extract entities from messages (default: on)
--auto-preferences/--no-auto-preferences Auto-detect user preferences (default: on)
--ingest Ingest data into Neo4j after generation
--neo4j-uri TEXT Neo4j connection URI [env: NEO4J_URI] (--self-hosted only)
--neo4j-username TEXT Neo4j username [env: NEO4J_USERNAME] (--self-hosted only)
--neo4j-password TEXT Neo4j password [env: NEO4J_PASSWORD] (--self-hosted only)
--neo4j-aura-env PATH Path to Neo4j Aura .env file with credentials (--self-hosted only)
--neo4j-local Use @johnymontana/neo4j-local for local Neo4j (--self-hosted only)
--anthropic-api-key TEXT Anthropic API key for LLM generation [env: ANTHROPIC_API_KEY]
--openai-api-key TEXT OpenAI API key for LLM generation [env: OPENAI_API_KEY]
--google-api-key TEXT Google/Gemini API key (required for google-adk) [env: GOOGLE_API_KEY]
--output-dir PATH Output directory (default: ./<project-name>)
--demo Shortcut for --reset-database --demo-data --ingest
--reset-database Clear all Neo4j data before ingesting
--dry-run Preview what would be generated without creating files
--verbose Enable verbose debug output
--list-domains List available domains and exit
--version Show version and exit
--help Show help and exitContext Graph Architecture
<p align="center"> <img src="docs/static/img/architecture-overview.png" alt="Architecture: generation pipeline and runtime components" width="800" /> </p>
Every generated app demonstrates the three-memory-type architecture from neo4j-agent-memory:
<p align="center"> <img src="docs/static/img/memory-architecture.png" alt="Three memory types: short-term, long-term, and reasoning memory in Neo4j" width="700" /> </p>
Short-term memory — Conversation history and document content stored as messages
Long-term memory — Entity knowledge graph built on the POLE+O model (Person, Organization, Location, Event, Object)
Reasoning memory — Decision traces with full provenance: thought chains, tool calls, causal relationships
This is what makes context graphs different from simple RAG — the agent doesn't just retrieve text, it reasons over a structured knowledge graph with full decision traceability.
With --with-mcp, the generated project also includes an MCP server configuration that connects Claude Desktop to the same knowledge graph. This dual-interface architecture means the web app and Claude Desktop share one context graph — entities, conversations, and reasoning traces are available everywhere.
Development
# Clone and install
git clone https://github.com/neo4j-labs/create-context-graph.git
cd create-context-graph
uv venv && uv pip install -e ".[dev]"
# Run tests (no Neo4j or API keys required)
source .venv/bin/activate
pytest tests/ -v # Fast: 1,177 tests
pytest tests/ -v --slow # Full: 1,398 tests (includes domain x framework matrix + perf + generated project tests)
pytest tests/ --integration # Integration tests (requires running Neo4j)
# Test a specific scaffold
create-context-graph /tmp/test-app --domain software-engineering --framework pydanticai --demo-dataMakefile Targets
| Target | Description | Requirements |
|---|---|---|
make test | Run fast unit tests (1,177 tests) | None |
make test-slow | Full suite including matrix + perf + generated project tests (1,398 tests) | None |
make test-matrix | Domain × framework matrix only (176 combos) | None |
make test-coverage | Tests with HTML coverage report | None |
make smoke-test | E2E smoke tests for 3 key frameworks | Neo4j + LLM API keys |
make lint | Run ruff linter | ruff |
make scaffold | Scaffold a test project to /tmp/test-scaffold | None |
make build | Build Python package (sdist + wheel) | None |
make docs | Start Docusaurus dev server | Node.js |
E2E Smoke Tests
The smoke tests scaffold a real project, install dependencies, start the backend, and send chat prompts to verify the full pipeline works end-to-end. Pass --backend nams to test the hosted-memory path (requires MEMORY_API_KEY env); the default bolt exercises self-hosted Neo4j with full demo fixtures:
# Run all 3 smoke tests (requires Neo4j + at least one LLM API key)
make smoke-test
# Or run individual framework tests directly (default: --backend bolt)
python scripts/e2e_smoke_test.py --domain financial-services --framework pydanticai --quick
python scripts/e2e_smoke_test.py --domain real-estate --framework google-adk --quick
python scripts/e2e_smoke_test.py --domain trip-planning --framework strands --quick
# Test against NAMS hosted backend (requires MEMORY_API_KEY env)
python scripts/e2e_smoke_test.py --domain healthcare --framework strands --backend nams --quick
# Test all 27 domains with one framework
python scripts/e2e_smoke_test.py --all-domains --framework pydanticai --quick
# Full mode (all prompts per scenario, not just first)
python scripts/e2e_smoke_test.py --domain healthcare --framework claude-agent-sdkRequired environment variables:
NEO4J_URI,NEO4J_USERNAME,NEO4J_PASSWORD— Neo4j connection (Aura, Docker, or local) for--backend boltMEMORY_API_KEY— NAMS API key for--backend namsANTHROPIC_API_KEY— for Claude-based frameworks (PydanticAI, Claude Agent SDK, Anthropic Tools, Strands, CrewAI)OPENAI_API_KEY— for OpenAI-based frameworks (OpenAI Agents, LangGraph)GOOGLE_API_KEY— for Google ADK (Gemini)
CI Pipeline
GitHub Actions (.github/workflows/ci.yml) runs automatically:
| Job | Trigger | Description |
|---|---|---|
| test | All pushes + PRs | Unit tests on Python 3.11 and 3.12 (1,177 tests including security, doc snippets, frontend logic, NAMS adapter, wizard, route integration) |
| lint | All pushes + PRs | Ruff linter on src/ and tests/ |
| matrix | Push to main only | Full suite + 176 domain × framework matrix + perf + generated project tests (1,398 tests) |
| smoke-test | Push to main only | Neo4j integration tests + E2E for all 8 frameworks (scaffold → install → start → chat) |
The smoke-test CI job is gated behind a SMOKE_TESTS_ENABLED repository variable. To enable it:
Go to Settings → Variables → Repository variables and add
SMOKE_TESTS_ENABLED=trueGo to Settings → Secrets → Repository secrets and add:
NEO4J_URI— e.g.,neo4j+s://xxxxx.databases.neo4j.ioNEO4J_USERNAMENEO4J_PASSWORDANTHROPIC_API_KEYOPENAI_API_KEYGOOGLE_API_KEY
The smoke-test job uses fail-fast: false so one framework failure doesn't block the others, and it only runs after the unit test job passes.
The npm package is a thin wrapper that delegates to the Python CLI via uvx, pipx, or python3 -m. It requires Python 3.11+ to be installed.
Automated Publishing (GitHub Actions)
Both packages are published automatically when you push a version tag:
# 1. Update version in pyproject.toml and npm-wrapper/package.json
# 2. Commit the version bump (and any CHANGELOG.md update)
# 3. Tag and push
git tag v0.13.0
git push origin v0.13.0This triggers a GitHub Actions workflow, release.yml with jobs:
publish-pypi — Builds and publishes to PyPI
publish-npm — Publishes the npm wrapper to npmjs.com Both use trusted publishing/OIDC.
Version Bumping
Both packages must use the same version. Update in two places:
pyproject.toml→version = "X.Y.Z"npm-wrapper/package.json→"version": "X.Y.Z"
Note: a job called validate-version-consistency in release.yml ensures that the correct versions exist in both places.
License
Apache-2.0
CHANGELOG.md
Changelog
v0.14.0 — community PR hardening: NEO4J_DATABASE, NAMS cypher runtime, --ontology-file (2026-09-04)
Integrates five community PRs merged since v0.13.1 (#52, #56, #58, #59, #60), closes the gaps found while reviewing them, and adds test coverage at every level: +105 fast-suite tests, +3 Neo4j integration tests, a new bolt combo in the slow generated-suite runner, and 2 new tests inside every generated project (fast suite now 1,454 passing; the full CI suite with the connectors extra runs 1,866 passing / 1,881 collected). The new integration coverage immediately exposed — and this release fixes — a long-standing schema-DDL splitter bug that had been silently dropping five indexes/constraints from every seeded database.
Features (community PRs)
NEO4J_DATABASEsupport end-to-end (#60, @henrardo). New--neo4j-databaseflag /NEO4J_DATABASEenv var for the self-hosted backend, threaded through the CLI, wizard (new prompt on manual credential entry), Aura.envimport (previously read and silently discarded), generated.env, the generated app'sSettings, memory-layerMemorySettings, and the raw-driver session inexecute_cypher(). Blank defers to the driver default (neo4j); set it for Aura instances provisioned via the Aura API/CLI, which commonly name the database after the instance id.Memory-layer failures now surface in
/health(#60, @henrardo).store_message()failures are recorded into the same classified error state used at startup connect time; the bolt/healthresponse gainsmemory,memory_error, andmemory_error_detailfields, and the startup lifecycle checks the memory client instead of assuming success once the raw driver connects. Previously a wrong database name meant the app reported "ok" while every memory write failed with only a log line.execute_cypher()works on NAMS (#56, @benmyrgorod). New_execute_nams_cypher()routes throughclient.query.cypherwith result-shape coercion (_coerce_nams_records), so domain agent tools andPOST /cypherexecute read queries on the hosted backend instead of dying on the never-connected bolt driver._require_neo4j()now returns 503 when the NAMS client is missing, for every route.--ontology-filewired up (#58, @irene221b). The flag was documented (and tracked as #50) but had no code path. Scaffolds directly from a hand-written domain YAML — no LLM call — using the domain id declared in the file.Custom domains resolve by id (#52, @ecsricktorzynski, issue #30).
load_domain()now searches~/.create-context-graph/custom-domains/(with a declared-domain.idfallback for renamed files), matching whatlist_available_domains()advertises. Bundled domains shadow same-id custom files.demo_scenariosoptional in practice (#59, @irene221b). The generated Playwright spec indexeddemo_scenarios[0].prompts[0]unconditionally, crashing scaffold generation for any domain that omits scenarios. Falls back to a generic prompt.
Bug Fixes (gaps found reviewing the PRs)
--ontology-filescaffolds now includedata/ontology.yaml. The renderer only wrote the ontology copy for--custom-domain(YAML string) or bundled domains (copy by id); hand-written ontologies matched neither branch, silently producing a scaffold without the file the docs promise. The raw YAML is now carried into the scaffold verbatim, and the flag also works when the wizard collects the remaining settings.--ontology-file+--custom-domainis now an explicit error instead of a silent precedence pick. (cli.py)NEO4J_DATABASEreaches scaffold-time ingest and the generated import script. #60 threaded the database through the generated app but not throughingest.py(_ingest_with_memory_client,_ingest_with_driver,reset_neo4j) or the scaffoldedimport_data.pybolt path — so--demo/--ingest/--reset-database/make importtargeted the default database while the app read from the configured one, producing an empty graph on non-default-database instances. All bolt sessions now honor the setting;validate_connection()gains an optionaldatabaseparameter. (ingest.py,neo4j_validator.py,templates/backend/connectors/import_data.py.j2).env.exampledocumentsNEO4J_DATABASE. #60 updateddot_env.j2only; the example file now carries the same commented block. (templates/base/dot_env_example.j2)Playwright spec survives a scenario with an empty
promptslist. #59's guard handled a missingdemo_scenariosbut still crashed rendering when the first scenario hadprompts: [](legal per the Pydantic model). (templates/frontend/e2e/app.spec.ts.j2)Schema DDL splitter no longer eats statements or executes comment tails. Every consumer of
generate_cypher_schema()output split on;and skipped fragments starting with//— which (a) silently dropped the 5 real statements that sit behind comment headers (person_name,document_title,document_domain,document_name_uniqueand thelocal_file_fulltextindex were never created bymake seed/ingest), and (b) executed the tail of the "dimensions must match your embed model" comment as Cypher, raisingCypherSyntaxErroron every schema apply. New sharedsplit_cypher_statements()strips comment lines before splitting; used byingest.py(both bolt paths), the generatedgenerate_data.py, and the integration suite. (ontology.py,ingest.py,templates/backend/shared/generate_data.py.j2)Test suite is hermetic against
~/.create-context-graph/custom-domains/. With #52,load_domain()joinslist_available_domains()in scanning the user-local directory — so a contributor's saved custom domains leaked into every domain-iterating test (the "football-intelligence" failures reported while developing #60). An autouse conftest fixture isolates the path; tests that need custom domains patch it explicitly. (tests/conftest.py)
NAMS domain ontology activation
NAMS auto-binds every workspace to the generic nams-default ontology "until an explicit ontology is activated" — and pre-registers a server-side ontology for every bundled domain (a 1:1 catalog; the server's healthcare document is field-for-field our healthcare.yaml). Nothing ever activated one, so all data was stamped with (and extraction spoke) the default vocabulary. Now every NAMS touchpoint binds the workspace to the app's domain first:
Generated
memory.py:connect_memory()runs_ensure_nams_ontology()after the client connects — already active → no-op; catalog match by domain id → activate its latest version; unknown domain → create the ontology from the scaffold's newbackend/app/ontology_document.jsonand activate it (the custom-domain path). Best-effort and logged: memory still works onnams-defaultif the ontology API is unavailable. Covers app startup andmake seed(which connects through the same path).CLI ingest (
run_nams_ingest) and the scaffoldedimport_data.pyrun the same ensure sequence as stage 0, pinned by the parity contract test (get_active → list → get → activate, keyword-called so the recorder can compare shapes).build_nams_ontology_document()(ontology.py) produces the server'sOntologyDocumentshape —{domain, entity_types, relationships}, excluding app-side sections (agent_tools,system_prompt,document_templates, …) — used by both the renderer (writesontology_document.jsoninto every scaffold) and the CLI ingest.
Verified against the production service: a fresh workspace on nams-default flips to healthcare on the generated app's first connect (reconnect is a no-op), and a custom test-domain scaffold creates and activates its ontology server-side with the full merged label set. Every stored entity is stamped with the active ontologyVersionId. Known limitation (server-side): the stored entity type remains {Person, Organization, Location, custom} regardless of the active ontology — activation governs the version stamp, validation mode, and extraction vocabulary, not the storage-type enum.
Live NAMS verification (and the bugs it caught)
The full flow — scaffold → ingest → boot → API — was exercised against the production NAMS service (memory.neo4jlabs.com) with a real API key and neo4j-agent-memory 0.5.0 (the version fresh scaffolds install). That surfaced five breaks the mocked suites couldn't see, all fixed and now pinned by tests; 19/19 live API checks pass afterward:
Conversation memory silently failed on every message. The NAMS service only accepts messages addressed to conversation ids it minted at create time — client-chosen session ids 404 with "conversation not found," and
MemoryIntegration(0.5.x) both posts the client id straight through and swallows the failure into an{"error": ...}return value. The generatedmemory.pynow creates the conversation on first use per session and addresses the server-assigned id (_resolve_nams_conversation(), process-local cache — a restart starts a fresh conversation instead of erroring), andstore_message()treats{"error": ...}returns as failures so they surface in/healthrather than reading as success.Every document/body ingest write failed (
role must be user, assistant, or system+ the same conversation-404). All three NAMS ingest implementations (run_nams_ingest, the scaffoldedimport_data.py, andmake seed'singest_fixtures_nams) now create their message channels viacreate_conversationand sendrole="user"with ametadata.kindmarker ("document"/"entity-body"). Before: 0/25 documents ingested; after: clean./api/documentsand/api/schema/visualizationreturned nothing. The live service coerces unknownentity_typevalues (OBJECT,EVENT) tocustom, so the server-side OBJECT filter matched nothing — and it rejects empty search queries (query is required), so the schema view's enumerate-everything search 400'd. Both adapters are now cypher-first (using the scaffold's own_pole_type: OBJECT_description marker for documents, and a type-count aggregation for the schema view), with the search-based flows kept as fallbacks.Graph expand / entity connections were dead.
long_term.get_entity(id)doesn't exist inneo4j-agent-memory0.5.x;expand_node_namsandget_entity_detail_namsnow resolve id-addressed lookups and neighbor edges through the cypher API (which also surfaces the server-createdSAME_ASresolution edges), keeping the old REST flow as a fallback.NAMS reset never deleted anything.
long_term.delete_entitydoesn't exist in 0.5.x (the old code swallowed theAttributeErrorand reported "0 entities removed"), the REST API has no delete endpoint, and the cypher API is read-only.--reset-databaseand the scaffold'smake resetnow say so honestly (with the current entity count) and point at the NAMS dashboard, instead of pretending. Docs updated to match.
Verified unchanged live: client.query.cypher read queries (the PR #56 dispatch) work and write queries are rejected; the reasoning trace ingest (start_trace/add_step/complete_trace) succeeds; add_relationship/add_fact/add_preference exist in 0.5.0 but raise NotSupportedError against NAMS, so the ccg-edges encoding remains the correct design; reasoning.list_traces is NotSupported client-side, so /api/traces degrades to an empty list on NAMS. Upstream issues worth filing against neo4j-agent-memory: MemoryIntegration should create conversations (or the service should honor client ids), add_message shouldn't silently target nonexistent conversations, and add_entity throws a client-side validation error when the server responds with a dedup/merge result.
Testing
tests/test_generated_client_runtime.py(new, 31 tests) — executes the renderedcontext_graph_client.pyandmemory.pyagainst doubles: NAMS dispatch + result coercion + tool-event collection + not-connected error; bolt sessiondatabase=threading;MemorySettingsdatabase pass-through;store_message()error recording/clearing/NotSupportedErrorhandling; the_classify_memory_errorbuckets/healthreports; the NAMS conversation-id translation (created once per session, server id targeted, bolt untouched, create-failure fallback) and the swallowed-{"error"}failure path.test_routes_integration.py(+6) — mounts the generated FastAPI app:POST /cypheron NAMS dispatches throughexecute_cypher(and maps errors to 400), API routes 503 when the NAMS client is missing while/healthreports degraded, bolt/cypherstill injects the$domainparameter, and a livestore_messagefailure flips/healthto degraded with classified fields — then a successful write clears it Three more pin the cypher-first adapters: documents enumerated by description marker (search fallback for custom-typed entities), schema visualization aggregated via cypher.test_cli.py(+12) —TestNeo4jDatabaseFlag(flag→.env, blank default, Aura import, flag-beats-file precedence, dry-run display) andTestOntologyFileFlag(scaffold,data/ontology.yamlcopy, static demo data, invalid YAML exit 1, missing file exit 2,--custom-domainconflict, auto-slug).test_wizard.py(+5) —_parse_aura_envfour-tuple contract: database read/absent/quoted, missing URI/password aborts.test_generated_project.py(+17) — template pins for the database threading (config/client/memory/import script/.env/.env.example, NAMS.envexclusion), memory-error surfacing inmain.py, the NAMS cypher branch, and scenario-fallback rendering (none / empty-prompts / real prompts).test_ontology.py(+9) —split_cypher_statementsunit tests (semicolon-in-comment, comment-header recovery, commented-out DDL dropped, all-domains executable-statement sweep, proof the old pattern droppedperson_name) and custom-domain isolation meta-tests.test_custom_domain.py(+3) — resolution precedence: bundled shadows same-id custom, corrupt custom YAML skipped during the id scan, underscore files ignored.test_bolt_ingest_parity.py(+1) — the scaffolded bolt import session must targetsettings.neo4j_database.test_integration.py(+3,--integration) — explicit-database ingest lands data (viaProjectConfig.neo4j_database),validate_connectionaccepts a database name and rejects an unknown one.TestSchemaCreationnow applies DDL through the shared splitter and asserts the previously-skipped indexes exist.test_generated_tests.py— the slow generated-suite runner now also scaffolds one bolt project (5 combos), and asserts the new backend-specific health tests actually ran. The generatedtest_routes.pygains two tests per backend: NAMS degraded-client reporting, bolt live-write-failure surfacing.scripts/e2e_smoke_test.py— asserts the/healthcontract shape per backend on startup (bolt:neo4j+memoryfields, logging a warning with the classified error when degraded; NAMS:namsfield).
CI
The full test suite now runs on every PR. The
full-suitejob (formerlymatrix, main-push-only) runspytest --slow --functionalon all pull requests and main pushes: the 176-combo domain × framework matrix, performance tests, generated-project venv suites, and the local-file vault functional tests (theconnectorsextra is installed, which both enables--functionaland materializes ~165 connector-dependent tests that module-levelimportorskipguards silently excluded from dev-only CI — the job runs 1,866 tests). The secrets-dependent smoke-test job stays main-only — fork PRs can't access repository secrets.CI installs are lockfile-driven. Every job now uses
uv sync --locked --extra ...+uv run --no-sync. The old recipe (uv pip install -e ".[dev]"followed by bareuv run pytest) letuv run's implicit lockfile sync downgrade locked base dependencies underneath freshly-installed latest extras — a newanyiorelease (requiringtyping_extensions.sentinel, newer than the locked pin) made the skew fatal, failing test collection withImportError: cannot import name 'sentinel' from 'typing_extensions'on every branch.--lockedalso means apyproject.tomldependency change without a matchinguv lockfails fast with a clear message instead of resolving to something untested. Makefile test/lint targets useuv run --extra dev ...so local runs resolve from the lock the same way.14 accidentally-tracked
.pycfiles untracked. They were committed in the initial commit (before.gitignoreapplied) and have silently churned in diffs ever since;.gitignorealready covers__pycache__/going forward.Ruff's rule set and version are pinned. The lint job previously installed unpinned latest ruff with no project config, so ruff 0.16's expanded default rule set broke the build with 294 findings for rules this codebase never adopted.
[tool.ruff.lint]now pinsselect = ["E4", "E7", "E9", "F"](the set the codebase is written against — expand it deliberately, not via upstream default drift), andruff>=0.16,<0.17ships in the dev extra so CI andmake lintrun the same binary. Test-job matrix gainsfail-fast: falseso one Python version's failure no longer cancels the other's signal.
Docs
reference/cli-options.md—--neo4j-databaseand--ontology-filerows,NEO4J_DATABASEin the env-var table.how-to/use-neo4j-aura.md— caution block on Aura API/CLI-provisioned database names and how the failure presents in/health.how-to/add-custom-domain.md—--ontology-filesemantics: domain id from the file,data/ontology.yamlcopy, mutual exclusion with--custom-domain.reference/generated-project-structure.md—.envlisting includesNEO4J_DATABASE.
v0.13.1 — v0.13.0 feedback report triage (2026-05-20)
Addresses the May 20, 2026 v0.13.0 feedback report. The report mixed verified issues with claims that don't match the current codebase; each claim was verified before scoping work. This release closes every real issue, makes the generated app.models module load-bearing, and adds regression tests so the v0.12.0/v0.13.0 fixes can't silently come back.
Bug Fixes
create-context-graph --dry-runno longer demands a NAMS API key. The non-interactive path validatedMEMORY_API_KEYbefore reaching the--dry-runbranch, so users couldn't preview a scaffold without first signing up. The credential gate is now scoped to non-dry-run flows;--dry-runskips it entirely. (cli.py:392)Dead
template_idparameter removed fromlist_documents_nams. The NAMS branch ofGET /documentsalready raises HTTP 501 whentemplate_idis supplied, so the parameter could never reach the function meaningfully. Signature is nowlist_documents_nams(skip, limit). (templates/backend/shared/memory_adapter.py.j2,templates/backend/shared/routes.py.j2)DocumentBrowser entity badges use a stable composite key. The mentioned-entities map was the last
key={\${e.name}-${i}`}(index-tainted) site in the frontend; switched tokey={`${selectedDoc.document.title}-${e.name}`}so badges don't collide when the user navigates back to the same document. (templates/frontend/components/DocumentBrowser.tsx.j2`)
Code Quality
Generated
models.pyusesField(...)for required fields. Previously,generate_pydantic_modelsemittedname: str = ...(bare Ellipsis literal). Valid Pydantic v2, but unfamiliar to contributors and harder to extend with constraints (Field(..., min_length=1)). Required fields now emitname: str = Field(...). (ontology.py:478)New
GET /schema/modelsendpoint wiresapp.modelsinto the runtime. Returns the JSON Schema for every Pydantic entity model generated from the domain ontology, useful for frontend codegen and OpenAPI clients. Makes the previously-unusedapp.modelsmodule load-bearing. (templates/backend/shared/routes.py.j2)
Testing
TestCompositeKeyRegressions(tests/test_frontend_logic.py) — five new assertions pin the composite-key patterns introduced in v0.13.0 (ChatInterfaceentity/preference/tool-call badges,DecisionTracePanelstep keys) plus the newDocumentBrowserfix.TestV0131ModelsPolishandTestV0131TemplateIdRemoval(tests/test_generated_project.py) — assert that the generatedmodels.pyusesField(...)(and never bare= ...), that the/schema/modelsendpoint compiles, and that thelist_documents_namssignature no longer takestemplate_id.Three new Playwright tests (
templates/frontend/e2e/app.spec.ts.j2) — watch the browser console for React duplicate-key warnings across a multi-prompt chat sequence, verify the decision trace step list renders without page errors, and verify the document browser entity badges render without page errors.
Not Changed (and why)
The v0.13.0 feedback report flagged several issues that don't reflect the current code. Documenting here so contributors don't re-litigate:
"Backend connectors removed from scaffolded projects" — false.
templates/backend/connectors/still exists andrenderer.py:474-514renders connector modules +backend/scripts/import_data.pywhenever--connectoris supplied. Runtimemake import/make import-dry-run/make import-retrytargets continue to work on every scaffold."
pyproject.toml.j2bloats NAMS users withsentence-transformers" — false. The template already branches on backend mode at lines 16-20: NAMS scaffolds pinneo4j-agent-memory[litellm], self-hosted scaffolds pinneo4j-agent-memory[litellm,sentence-transformers,extraction,fuzzy]. NAMS users never pull PyTorch."Restore media / insurance / supply-chain domains" — these never existed.
git log --all -- src/create_context_graph/domains/*.yamlshows no history for these labels. v0.13.0's "restored domains" arelegal,education,cybersecurity,government— total domain count remains 27."Unused
iinContextGraphViewline 210" — leave as-is. The unused index is in a fallbackextractNodesAndRelsparser, not a render hot path, and removing it would churn a path that hasn't drifted in months.
v0.13.0 — v0.12.0 feedback report fixes (2026-05-20)
Addresses the May 2026 v0.12.0 feedback report: one runtime bug on the --self-hosted ingest path, one React state bug in the streaming chat, four key={i} re-render hazards, dead/over-fetching code in the document adapter, four restored domains, and documentation for the ccg-edges encoding strategy.
Bug Fixes
_ingest_via_bolt()now async (scaffoldedimport_data.py).app.context_graph_client.get_driver()returns anAsyncDriver, but the generated_ingest_via_bolt()wasdefand calledwith driver.session() as session:followed by syncsession.run(...). Every self-hostedmake import/make import-retryfailed at runtime with a coroutine-not-iterable error. Function is nowasync def, usesasync with driver, driver.session() as session:to own the driver lifecycle, andawaits everysession.run(...). Both call sites (main(),_retry_deadletter()) wrap withasyncio.run(...)to mirror the NAMS branch.ChatInterface"done" handler no longer reads stale streaming state. ThesetMessagescallback in thedoneSSE branch referencedstreamingEntities/streamingPreferencesfrom closure — these areuseState-backed and could be one render behind the most recententities_extracted/preferences_detectedevent. Accumulators are nowuseRef-backed (streamingEntitiesRef,streamingPreferencesRef); thedonehandler reads from.currentand the two-stepsetMessageswas collapsed into one.list_documents_nams()pushes theOBJECTfilter to the server. Previously, the over-fetch buffer (skip + limit + 50) could be exhausted by unrelated POLE+O entities, silently dropping valid documents on busy NAMS instances. Now passesentity_type="OBJECT"tosearch_entities. Deadtemplate_idfilter at the same site removed.useEffectforexternalInputnow also depends onloading. An "Ask about this" click that landed mid-stream was silently dropped because the effect didn't re-fire whenloadingflipped back to false.
Breaking Changes
--framework mafalias removed. Use--framework anthropic-toolsinstead. Click now rejectsmafwith the standard "Invalid value for '--framework'" error. TheFRAMEWORK_ALIASESdict and theresolved_frameworkproperty onProjectConfigare gone — call sites useconfig.frameworkdirectly.
Domains
Restored 4 domains as YAML definitions:
legal,education,cybersecurity,government. Each ships with the full schema (entity_types, relationships, document_templates, decision_traces, demo_scenarios, agent_tools, system_prompt, visualization) plus a deterministic static-fallback fixture. Domain count: 23 → 27.
Code Quality
key={i}replaced with stable identifiers in 4 locations.ChatInterface.tsx: suggested-prompt buttons keyed by prompt text; entity/preference badges keyed by${type}-${name}-${i}and${category}-${preference}-${i}.DecisionTracePanel.tsx: trace steps keyed bystep-${i}-${action.slice(0, 32)}.
Documentation
ccg-edgesencoding strategy documented. New Docusaurus page (docs/docs/explanation/ccg-edges.md) explains the fenced YAML block inside entity descriptions, fragility (what happens if descriptions are edited or truncated), the migration playbook once NAMS adds nativeadd_relationship, and the parity test that pins the format. Scaffolded README gains a short "How NAMS stores relationships" section linking to the page.Custom domain generation walkthrough. New Docusaurus page (
docs/docs/how-to/custom-domains.md) coverscreate-context-graph --custom-domain "..."end-to-end, including the few-shot prompting strategy, the validate-retry loop, and how to convert a generated domain into a permanent contribution.
Testing
Bolt ingest parity test. New
tests/test_bolt_ingest_parity.pymirrorstest_nams_ingest_parity.py— renders the scaffolded template, exec's it against a mockAsyncDriver, and asserts the Cypher statement + parameter sequence matches a frozen golden file.AST async-shape check.
tests/test_generated_project.pynow parses generatedimport_data.pyand asserts_ingest_via_boltisAsyncFunctionDef, everysession.runcall is inside anAwait, and both call sites wrap withasyncio.run.backend/scripts/import_data.pywas added toPYTHON_FILESso it getspy_compile-checked on every scaffold.Streaming ref-accumulation test.
tests/test_frontend_logic.pynow AST-checks that thedonehandler inChatInterface.tsx.j2reads fromstreamingEntitiesRef.current/streamingPreferencesRef.current, not theuseStatevalues.E2E coverage for new panels. Playwright tests for
DecisionTracePanel(tab-switch + step rendering) andDocumentBrowser(pagination + markdown detail view).
v0.12.0 — NAMS-native connector ingest + ccg-edges relationship encoding (2026-05-19)
The big shift in v0.12.0 is that connector ingest (make import in a scaffolded project) now writes through NAMS REST on NAMS scaffolds — previously the generated import_data.py only spoke bolt Cypher, so the SaaS connectors didn't actually work on the default backend. The two ingest paths (CLI demo-fixture seeding and connector-driven imports) now share a single write shape pinned by a contract test.
New Features
ccg-edgesrelationship encoding for NAMS. NAMS REST has noadd_relationshipendpoint yet, so each entity's outbound edges are now encoded into the source entity'sdescriptionas a fencedccg-edgesYAML block (deterministically sorted bytypethentarget). The frontend graph view recognizes this marker and renders edges from it; the agent reads them out naturally as part of the description. A one-shot migration replays them as native edges once NAMS gainsadd_relationship— the seam is_build_ccg_edges_block()in bothsrc/create_context_graph/ingest.pyandsrc/create_context_graph/templates/backend/connectors/import_data.py.j2.Dual-tracked documents on NAMS. Documents now land as both
long_term.add_entity(name=title, type=OBJECT, description=...)ANDshort_term.add_message(role="document", content=...). The long-term entity is the queryable source of truth (matches the bolt:Documentshape and powers/documents); the short-term message is extraction fuel for the NAMS server-side extractor. The document browser now reads from long-term entities and strips theccg-edges/_pole_type:markers for a clean preview.Per-connector
BODY_FIELDSmapping. Each connector declaresBODY_FIELDS: dict[str, str]mappingentity_label → property_namefor the prose body. The ingestor pipes that body throughshort_term.add_messageso the NAMS extractor can mine it for secondary entities. Wired up forComment.body(Linear),Message.content(Claude AI / ChatGPT / Claude Code),DecisionThread.content/Reply.content(Google Workspace), andDocument.description/Section.description(local-file). Pure-metadata entities (Person, Project, Label) opt out by omission.Idempotent connector imports. Generated
import_data.pynow tracks per-connector watermarks in.context-graph/watermarks.jsonso re-runs only fetch deltas. Failed records (one at a time) are appended to.context-graph/deadletter.jsonland the watermark only advances on a clean run. NAMSadd_entityis trusted to merge bynamefor entity-level idempotency.--dry-runand--retrymodes forimport_data.py.--dry-runfetches connectors and writesdata/fixtures.jsonwithout touching the memory backend (useful for sanity-checking a large pull before paying the write cost).--retrydrains.context-graph/deadletter.jsonlback through the writer.New Make targets.
make import-dry-run(fetch-only, writes fixtures.json),make import-retry(drain deadletter). The legacymake import-and-seedtarget collapsed intomake import— it now both fetches and ingests in one step on either backend.run_nams_ingest()extracted as a reusable async function iningest.py. Takes an already-openMemoryClientplus the fixture dict, ontology, optionalbody_fields, and optionalon_eventcallback; returns counts and a list of failure records. Used by both the CLI's Rich-progress path and the scaffoldedimport_data.py. Pinned to the same call sequence as the generated importer via the newtests/test_nams_ingest_parity.pycontract test (~526 LOC, 14 assertions).
Breaking Changes
make import-and-seedremoved from generated Makefiles. Replaced by the now-idempotentmake import, which both fetches from connectors and ingests on either backend. Existing scaffolds with the old target keep working until regenerated; the generatedimport_data.pyis the source of truth./documents?template_id=...returns HTTP 501 on NAMS. Template-based filtering relied on theMENTIONSgraph edges that NAMS doesn't yet have. The bolt path is unchanged; un-filteredGET /documentsworks on both backends.
Bug Fixes
ingest_data()legacy bolt signature restored. v0.11.0 had changed the signature to take aProjectConfigexclusively, breaking library callers that were on the older(neo4j_uri, neo4j_username, neo4j_password)triple.ingest_data()now accepts either: aProjectConfiginstance OR the legacy three positional bolt args;_coerce_ingest_config()synthesizes a boltProjectConfigfrom the legacy triple. CLI usage is unaffected.Cypher identifier injection guards on bolt fallback.
_ingest_with_driverand_ingest_with_memory_clientnow validate relationship types, source labels, and target labels against[A-Za-z_][A-Za-z0-9_]*before string-interpolating them into a Cypher template. Unsafe identifiers log a warning and skip the record instead of executing. Closes the CodeQLpy/code-injection-shaped finding flagged on the bolt ingest path. (NAMS path was never affected — it never builds Cypher.)Labeled MATCH on bolt relationship ingest. The bolt connector path was falling back to a label-less
MATCH (a {name: $name})for relationship endpoints, which would match across labels and silently mis-merge. Now usesMATCH (a:SourceLabel ...)/MATCH (b:TargetLabel ...)when the connector supplies both labels, with the existing sanitization guard.Deadletter retry on partial-failure imports. Records that failed during a connector run (rate limit, transient 5xx) are appended to
.context-graph/deadletter.jsonlwith their original payload;make import-retry(orpython scripts/import_data.py --retry) replays them through the same write path. Records whose failure category isn't retryable (e.g. a permanently unsupported entity shape) are logged but kept in the deadletter for inspection rather than dropped silently.
Documentation
docs/docs/explanation/memory-backends.md— replaced the "best-effort B-partial port" framing with the actual hybrid write shape:ccg-edgesencoding, dual-tracked documents,BODY_FIELDSextractor channel. Added a note about thetest_nams_ingest_parity.pycontract test that pins the two ingest paths together.docs/docs/how-to/use-nams.md— rewrote the "Seeding a relationship-rich graph" section to reflect that NAMS scaffolds now do encode relationships (just inside descriptions) rather than dropping them, with accg-edgesexample block. Kept the--self-hosted --demorecommendation for native-edge workflows (expand_node, GDS, arbitrary Cypher).src/create_context_graph/ingest.py— module docstring rewritten end-to-end documenting the new NAMS write shape, theBODY_FIELDSextension point, and why the two ingestors are duplicated by design (rendered template vs. runtime CLI consumer).
Internal / CI
New
tests/test_nams_ingest_parity.pycontract test — drivesrun_nams_ingestand the renderedimport_data.pyagainst a shared fixture and asserts identical call sequences against a mockMemoryClient. Pins entity → ccg-edges → body → document → trace ordering, fenced-block format, body-field routing, and decision-trace shape.Expanded NAMS test coverage. ~1,500 new test lines across
test_ingest_nams.py,test_memory_adapter.py,test_nams_ingest_parity.py,test_routes_integration.py, andtest_doc_snippets.py— coveringccg-edgesround-trips, dual-tracked document reads,BODY_FIELDSper connector, deadletter retry behavior, watermark persistence, the 501 guard on template-filtered/documents, and the bolt Cypher identifier sanitizers.
v0.11.3 — Streaming for CrewAI/Strands + NAMS hardening (2026-05-19)
Rolls up streaming chat for the last two non-streaming frameworks, a much better NAMS failure-mode UX (classified errors surfaced in /health, memory-backend auto-detection from .env), lighter NAMS dependencies, custom-domain robustness fixes, and silent-failure cleanup across all 8 agent templates.
New Features
Streaming chat for CrewAI and Strands. Both frameworks now implement
handle_message_stream(), so the/chat/streamSSE endpoint streams text deltas as the model produces them — previously these two frameworks emitted tool events live but text only arrived at the end of the run. CrewAI subscribes toLLMStreamChunkEventon the crew event bus; Strands iteratesagent.stream_async(). Both include a 60s timeout, partial-text fallback assembly, and emitentities_extracted/preferences_detectedevents. This closes out the streaming matrix — all 8 frameworks now stream text.--import-previewCLI flag. Parses a chat export file (--import-file …+--import-type …) and prints a sanity-check summary (entity counts, conversation date range, sample titles) without scaffolding or ingesting. Useful before committing to a long import of a 1 GB+ ChatGPT/Claude AI export. Implemented incli.py::_run_import_preview().NAMS error classification surfaced in
/health. New_classify_memory_error()inmemory.py.j2buckets NAMS init failures intoauth/rate_limit/network/config/unknown, with human-readable messages mapped per category (e.g. "NAMS authentication failed — verify MEMORY_API_KEY at https://memory.neo4jlabs.com"). The/healthendpoint now returnsnams_error,nams_error_message,nams_error_detail, andnams_dashboardso the frontend can show a useful diagnostic instead of a generic "memory unavailable". Exposed viaget_error_category()/get_error_message()/get_error_detail()for the FastAPI startup banner.Memory-backend auto-detection from
.env. New@model_validatorinconfig.py.j2reconcilesmemory_backendwith the credentials actually present in.env: flipsnams → boltifMEMORY_API_KEYis blank butNEO4J_URIis set (and vice-versa), printing a warning. An explicitMEMORY_BACKENDenv var still wins. Default Neo4j credentials in generated.envare now empty rather than baked-in placeholder passwords.Lighter NAMS dependency footprint. Generated
pyproject.tomlfor NAMS scaffolds drops thesentence-transformersextra (NAMS does embeddings server-side) — extras shrink from[litellm,sentence-transformers]to[litellm]._resolve_embedding_model()short-circuits toNoneon NAMS so the generated venv no longer pullstorchfor a backend that doesn't use local embeddings.
Bug Fixes
Custom-domain renderer crash.
_get_domains_path()was imported inside a narrowtry:scope inrenderer.py, raisingUnboundLocalErrorin the success path after partially writingontology.yaml. Import hoisted to module scope.Custom-domain generation produced silently-truncated ontologies.
custom_domain.pynow checks the LLM responsestop_reasonfor truncation, validates with Pydantic, and asserts completeness (non-emptysystem_prompt/visualization/agent_tools) before accepting. Provides actionable retry messages and clearer errors when the Anthropic/OpenAI SDK isn't installed.Agent-template degradations across all 8 frameworks. Jinja conditionals that checked
param.defaulttruthiness were rewritten toparam.default is defined, and a silent fallback that swallowed Jinja syntax errors was removed so render failures now surface instead of degrading to stub code. Affects every framework template (anthropic_tools,claude_agent_sdk,crewai,google_adk,langgraph,openai_agents,pydanticai,strands).Partial streamed text discarded on agent errors. Strands and CrewAI now accumulate emitted text deltas and return the partial response when a generator raises mid-stream, instead of throwing away accumulated output. Also drops a redundant
RuntimeErrorbranch from the memory error classifier.NAMS Docker builds crashed on
spacy download. The v0.11.2 fix for the generatedMakefileis now mirrored inDockerfile.backend.j2via{% if not is_nams %}— NAMS images no longer fail at build time on a download command for a package they don't depend on.Frontend "Ask about" button rendered on non-string entity names.
ContextGraphView.tsx.j2adds atypeof === "string"guard before reading.properties.name.E2E selector regex out of date.
e2e/app.spec.ts.j2regexes updated from/try a demo scenario/ito/try these/ito match the current welcome card label.
Documentation
docs/docs/how-to/use-nams.md— new "Seeding a relationship-rich graph" section. Documents NAMS's current lack ofadd_relationshipREST support and shows two working patterns: (Option A) scaffold with--self-hosted --demofor the rich dev experience, flipMEMORY_BACKEND=namsfor production reads; (Option B) seed bolt first then migrate. Includes aTODO(nams-relationships)pointer for the future server-side API.Generated README (
base/README.md.j2) — minor wording updates for the NAMS sign-up flow and the--import-previewworkflow.
Internal / CI
CodeQL
py/incomplete-url-substring-sanitizationcleanup. Test assertions intest_nams_adapter.pyswitched from URL substring checks ("memory.neo4jlabs.com" in env) to full-URL or content-phrase matches.Frontend devDeps pinned (
package.json.j2). Added@types/react-dom ^19.0.0;overridessection pinslodash ^4.17.24andpostcss ^8.5.10to dodge known vulnerable transitive versions.New test coverage: ~600 new test lines spread across
test_nams_adapter.py(NAMS error classification, backend auto-detection, Dockerfile spacy guard),test_renderer.py(template-degradation guards, custom-domain regression),test_custom_domain.py(truncation/completeness validation),test_generated_project.py(CrewAI/Strands streaming surface),test_chat_import.py(--import-preview),test_cli.py,test_doc_snippets.py, andtest_routes_integration.py.
v0.11.2 — Post-release stabilization + pre-release smoke-render target (2026-05-19)
Rolls up three follow-up fixes surfaced by running v0.11.0/v0.11.1 end-to-end on a fresh machine, plus a durable safeguard against the same class of bugs.
Bug Fixes
Full matrix + performance test suites broken on CI.
test_matrix.py(184 combos) andtest_performance.py(23 domains) defined their own localrunner = CliRunner()fixtures that bypassed the auto---self-hostedshim added totest_cli.pyin v0.11.0. With NAMS as the new default, every matrix/perf invocation hit the "NAMS API key required for non-interactive mode" guard and failed. 207 of 1,398 slow-suite tests failed on the v0.11.1 tag. Fix: moved_AutoSelfHostedRunnerand therunner/nams_runnerfixtures totests/conftest.pyso every test file inherits the auto-self-hosted behavior. Removed the now-duplicate fixtures fromtest_cli.py,test_matrix.py, andtest_performance.py.make installand Docker builds crashed on NAMS scaffolds withNo module named spacy. Both the generatedMakefile'sinstall-backendtarget and the generatedDockerfile.backendranpython -m spacy download en_core_web_smunconditionally, but spacy is only present in the[extraction]extra which NAMS scaffolds correctly omit (entity extraction happens server-side on NAMS). Fix: wrapped thespacy downloadline with{% if not is_nams %}in bothMakefile.j2andDockerfile.backend.j2. On bolt scaffolds the Makefile path is additionally guarded by animport spacycheck so it stays robust even if the user uninstalls the extraction extras post-scaffold. Four regression tests intest_nams_adapter.py::TestBoltRenderedTemplates:test_makefile_skips_spacy_download_on_nams,test_makefile_guards_spacy_download_on_bolt,test_dockerfile_skips_spacy_download_on_nams,test_dockerfile_includes_spacy_download_on_bolt.make testin generated projects crashed withNo module named pytest. The generatedpyproject.tomldidn't declare pytest or httpx anywhere, souv syncnever installed them — the generatedtests/test_routes.pyscaffold couldn't run. Fix: added[project.optional-dependencies] dev = ["pytest>=8.0", "httpx>=0.27"]topyproject.toml.j2, and changed the generated Makefile'sinstall-backendtarget fromuv sync→uv sync --extra dev. Generated projects can now runmake testout of the box.
New Tooling
Root
make smoke-rendertarget — full scaffold → install → import-check → run-generated-tests sweep for both backends, in<1 min, no Neo4j / NAMS / LLM keys required. Catches the class of breakage the mocked unit suite can't see:dep-resolution failures (
uv syncconflicts)install-time crashes (e.g. spacy download on NAMS)
import-time failures in generated
app.main(e.g. questionary default validation, framework SDKs that validate API keys at module-load time)generated test-scaffold regressions
Sub-targets
make smoke-render-namsandmake smoke-render-boltfor per-backend runs.make smoke-render-cleanremoves the scratch directory (/tmp/ccg-smoke-renderby default).Verified passing locally:
NAMS: render → install (no spacy) → import-check → 2 generated tests pass
Bolt: render → install (with guarded spacy download) → import-check → 2 generated tests pass
Process Note
The three issues bundled here all surfaced from running the actual product end-to-end on a fresh machine after the v0.11.0/v0.11.1 tags. Each was a class of issue the mocked unit suite couldn't catch by design (CLI fixture bypass, install-time shell commands, generated-project deps). make smoke-render is the durable answer — run it before tagging future releases.
v0.11.1 — Wizard framework-prompt fix (2026-05-19)
Bug Fixes
Interactive wizard crashed at the framework prompt with
ValueError: Invalid 'default' value passed. The value ('Strands') does not exist in the set of choices.—questionary.select(default=...)validates the default againstChoice.title, notChoice.value. The wizard was passing the display label ("Strands") but choices used the framework key ("strands") as their value. Fixed by removing thedefault=argument entirely and reordering the choices list soDEFAULT_FRAMEWORKis first (questionary highlights the first row on entry). Regression testTestQuestionaryConstructionadded totests/test_wizard.py— exercises the realquestionary.selectconstructor (only.askis stubbed) so any baddefault=argument fails at construction time. Total test count: 1,177 → 1,179.
v0.11.0 — NAMS by Default + LiteLLM Provider Injection (2026-05-19)
Breaking Changes
Default memory backend flipped from self-hosted Neo4j to NAMS —
create-context-graph my-appnow scaffolds against the hosted Neo4j Agent Memory Service by default. The wizard collects a NAMS API key as its memory step. Use--self-hosted(or any explicit--neo4j-*flag) to opt into the legacy bolt path. Existing scaffolded projects are unaffected; only newly generated projects pick up the new default.Generated
pyproject.tomlpinsneo4j-agent-memory>=0.4.0,<0.6.0(was>=0.1.0). Extras conditional on backend: NAMS scaffolds get[litellm,sentence-transformers]; self-hosted scaffolds additionally get[extraction,fuzzy]for local entity extraction.ingest_data()library signature changed — now takes aProjectConfiginstead of separate Neo4j credentials. CLI users see no change; programmatic users of thecreate_context_graphpackage must update callers.MEMORY_API_KEYenv var added to generated.envfiles. When set, the library auto-routes to NAMS even ifMEMORY_BACKENDis unspecified.
New Features
NAMS hosted backend support — Generated
app/memory.pynow constructsMemoryClient(MemorySettings(backend="nams", nams=NamsConfig(api_key=...)))on the NAMS path. Sign-up panel printed in the wizard with thehttps://memory.neo4jlabs.comlanding URL.--self-hostedCLI flag — Preserves the legacy bolt-Neo4j path with full demo fixtures, schema DDL, and relationship-rich graph view. Recommended for workshops, screen recordings, demos, and air-gapped use.LiteLLM provider injection — Generated memory layer reads
MEMORY_LLMandMEMORY_EMBEDDINGenv vars (LiteLLM-style provider strings, e.g.anthropic/claude-haiku-4-5,bedrock/anthropic.claude-3-haiku-20240307-v1:0,vertex_ai/gemini-1.5-flash,ollama/llama3). Native adapters resolve first (Anthropic, OpenAI, Bedrock, Vertex AI, SentenceTransformers); everything else routes through LiteLLM. Default fallback:sentence-transformers/all-MiniLM-L6-v2for embeddings,anthropic/claude-haiku-4-5(oropenai/gpt-4o-mini) for entity extraction.Streamlined 6-prompt wizard — Collapsed from 11 prompts. Domain picker switched to
questionary.autocomplete. Inline Anthropic-key prompt removed (deferred to post-scaffold.envediting with a prominent reminder panel). Advanced settings (MCP toggle, extraction toggles, extra API keys) gated behind a single Y/N prompt. Median wizard run is now ~6 prompts vs ~11.Default agent framework: AWS Strands — was previously unselected; the wizard now suggests
strandsas the default. All 8 frameworks remain supported.Backend-aware route adapters — Generated
app/routes.pydispatches/expand,/documents,/traces,/schema/visualization,/entities/{name},/search,/cypherto the NAMS REST adapter (app/memory_adapter.py) or bolt Cypher path based onMEMORY_BACKEND./gds/*returns 501 on NAMS.Backend-aware MCP config —
claude_desktop_config.jsonships in NAMS or bolt shape depending on the scaffold. NAMS forcesmcp_profile=corebecause extended-profile tools rely on unsupported endpoints (preferences/facts).Backend-aware
make reset— On NAMS, enumerates entities via REST and deletes one-by-one (slow but correct, with a printed warning). On bolt, retains today'sMATCH (n) DETACH DELETE n.NAMS-aware
make seed— Generatedgenerate_data.pybranches onsettings.memory_backend. On NAMS, delegates tomemory_adapter.ingest_fixtures_nams()which does the B-partial port (see below). On bolt, applies schema + ingests via Cypher.Health endpoint backend-aware —
/healthreturns{"memory_backend": "nams", "nams": <bool>}on NAMS or{"memory_backend": "bolt", "neo4j": <bool>}on self-hosted.
NAMS Write-Path Caveats (v0.4)
The NAMS REST API exposes a narrower write surface than bolt Cypher. The CLI does best-effort B-partial ingest with these documented gaps:
Relationships are dropped on NAMS —
add_relationshipis not yet exposed by NAMS REST. The CLI logs a single warning per ingest run. The graph view shows entities but no edges.Entity properties collapse into
description— NAMS REST accepts only{name, type, description}per entity. All other properties (status, severity, blood_type, etc.) are serialized into a markdown block insidedescription. The frontend property panel renders this markdown so the data remains readable.Preferences and facts are unsupported —
auto_preferences=Trueis forced off on NAMS viaProjectConfig.effective_auto_preferences.auto_extract=Truestill runs but extracted relationships are silently dropped.Schema DDL skipped on NAMS — NAMS owns its schema.
CREATE CONSTRAINT/CREATE INDEXstatements fromgenerate_cypher_schema()are no-ops on the NAMS path.
For the full relationship-rich demo experience, scaffold with --self-hosted --demo.
New CLI Flags
| Flag | Purpose |
|---|---|
--self-hosted | Use self-hosted Neo4j instead of NAMS (the v0.10 default behavior) |
--nams-api-key | NAMS API key (also reads MEMORY_API_KEY env) |
--nams-endpoint | Override NAMS endpoint URL (defaults to https://memory.neo4jlabs.com/v1) |
--memory-llm | LiteLLM provider string for memory entity extraction |
--memory-embedding | LiteLLM provider string for memory embeddings |
New Docs Pages
Use NAMS — sign-up, API key, switching between NAMS and self-hosted, troubleshooting
Configure Memory Providers — LiteLLM provider strings, native adapters, default fallback behavior, per-provider auth examples
Memory Backends — conceptual NAMS vs self-hosted comparison, choosing per-project, frontend dispatch architecture
Tests
1,177 passing fast tests (was 1,102 in v0.10). 50 new tests across 4 files:
test_ingest_nams.py(15) —_ingest_with_namsdispatch, entity serialization, document/trace ingestion, relationship-skip warning, missing-API-key error path,reset_memory_storefor both backends.test_wizard.py(7) — drives the interactive wizard via patched questionary; covers NAMS happy path, NAMS+advanced, self-hosted Docker, self-hosted existing-Neo4j, and edge cases.test_memory_adapter.py(18) — renders a project, imports the generatedmemory_adapter.pyviaimportlib, exercises every adapter function withAsyncMockMemoryClient.test_routes_integration.py(10, gated bypytest.importorskip("fastapi")) — renders a NAMS or bolt project, mounts the generated FastAPI app viaTestClient, asserts correct dispatch on/health,/documents,/search,/schema/visualization,/expand,/traces,/gds/*.test_nams_adapter.pyextended with 5 runtime dispatch tests.
scripts/e2e_smoke_test.py— added--backend {bolt,nams}flag.boltdefault preserves existing flow;namsexercises the hosted-memory scaffold path (requiresMEMORY_API_KEYenv).[dev]extras — now includefastapi,httpx,pydantic-settingsso route integration tests run in CI.
Implementation Notes
MemorySettings/MemoryClient/MemoryIntegrationconstruction split inmemory.py.j2— explicitMemoryClient(settings)thenMemoryIntegration(client=client, ...)(instead of havingMemoryIntegrationbuild the client implicitly). Enables NAMS backend + LiteLLM provider injection in one place.CodeQL false-positive fix —
test_nams_adapter.pyassertion changed from substring host check ("memory.neo4jlabs.com" in env_example) to full URL match ("https://memory.neo4jlabs.com/v1" in env_example) to satisfypy/incomplete-url-substring-sanitization.Generated test scaffold (
backend/tests/test_routes.py) — fixture patches both bolt and NAMS connect/close paths so the generated test suite works regardless of backend.
v0.10.0 — Local-File Document Connector (2026-05-18)
New Connector
local-file connector — Deterministic ingestion of local Markdown, PDF, HTML, AsciiDoc, and Word documents into
:Document→:Sectionhierarchies, withLINKS_TOedges between sections and documents. No LLMs, no embeddings, no randomness. URI-keyed nodes integrate with the existing MERGE-on-(name, domain)pipeline without changes toingest.py. Section URIs use GitHub/Pandoc slug rules (NFKD-normalize, ASCII-lower,[a-z0-9_]runs collapse to-); duplicate-heading collisions disambiguate per-parent (-1,-2, …); skipped heading levels (e.g. H1 → H3) preserve the original level on the child node rather than synthesizing intermediate H2s. Parser strategy per format: markdown-it-py with GFM extensions (Markdown); three-tier fallback pypdf outline →/StructTreeRoot→ pdfplumber font-size heuristic (PDF); BeautifulSoup + lxml (HTML); pure-Python regex with block-delimiter state tracking (AsciiDoc); python-docx (Word). Adds 8 optional dependencies to theconnectorsextra:markdown-it-py,mdit-py-plugins,pdf-oxide,pypdf,pdfplumber,beautifulsoup4,lxml,python-docx. Implementation inconnectors/local_file_connector.pyandconnectors/_local_file/subpackage (parser, mapper, slug, link-resolver). 1,721-linetest_local_file_connector.pyplustest_local_file_vault.pyfunctional test (make test-functional) round-trips a 14-file fixture vault.
Bug Fixes
reset_database()connection lifecycle — Generatedcontext_graph_client.pypreviously assumed a driver was already open. It now opens its own driver when_driverisNoneand closes it viatry/finally, preserving any pre-existing connection.TestResetDatabaseregression coverage added intests/test_generated_project.py.
Tests
1,102 passing fast tests (1,321 collected including slow/integration/functional).
v0.9.5 — Options Intelligence Domain & GitHub Connector Enhancements (2026-04-29)
New Domain
options-intelligence (23rd domain) — Options market intelligence covering 0DTE analysis, dealer positioning (GEX/DEX/VEX/CHEX), gamma regime classification, key levels, and trading strategies. 8 entity types (Underlying, OptionsContract, ExposureLevel, Regime, KeyLevel, Trade, MarketEvent, Strategy), 17 relationships (HAS_OPTION, EXPOSURE_AT, IN_REGIME, TRIGGERED_BY, FLIPPED_TO, PRECEDED_BY, etc.), 10 agent tools (
get_regime,get_key_levels,get_exposure_by_strike,get_trades_by_strategy, etc.), 5 document templates (market briefs, trade journals, regime analysis), 9 decision traces (trade entry, regime flip, level breach, VIX spike, etc.), 4 demo scenarios. Pre-generated fixture: 65 entities, 125 relationships, 25 documents. 17 new property clamp ranges ingenerator.pyfor options-specific values (delta[-1, 1], gamma[0, 0.15], IV[0.05, 2.0], strike, GEX, etc.). 8 label-specific name pools and ID prefixes added inname_pools.py. Tickers (SPX, SPY, QQQ, IWM, AAPL) added to the global_TICKER_POOL.
GitHub Connector Enhancements
Configurable per-resource limits —
GITHUB_LIMIT=20sets the default cap for issues, PRs, and commits. Override individually withGITHUB_ISSUES_LIMIT,GITHUB_PRS_LIMIT,GITHUB_COMMITS_LIMIT. Pagination now usesitertools.isliceto stream results instead of materializing full pages.Issue/PR body import toggle —
GITHUB_IMPORT_BODY=true(default) controls whether issue and PR bodies are imported asDocumentnodes. Issue/PR bodies are now labeled "Body" rather than "Document" to better reflect their source.Cross-link issues, PRs, and commits —
GITHUB_LINK_ISSUES_PRS=true(default) createsCLOSESandREFERENCESedges between commits, issues, and PRs. Regex matches(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved) #N→CLOSES; bare#N→REFERENCES. GraphQLclosingIssuesReferencesprovides authoritative PR closures.GITHUB_LINK_SOURCE=bothselectsregex/graphql/both(falls back tobothon invalid values).CLOSEStakes precedence overREFERENCESfor the same pair, regex and GraphQL results are deduped, and references to numbers outside the fetched set are silently skipped. GraphQL failures log a warning and return empty rather than hard-failing.
Bug Fixes
Connector relationship field names — All 7 connectors (GitHub, Notion, Jira, Slack, Gmail, Google Calendar, Salesforce) now emit
source_name/target_namein relationship dicts (wassource/target), aligning with the ingest schema.Generated
config.pySettings fields — Added env-var fields for all 7 connectors (GitHub, Notion, Jira, Slack, Salesforce, Linear, etc.) so credentials and toggles are honored. Previously silently dropped byextra: "ignore".Generated
pyproject.toml— Added connector package dependencies (PyGithub,notion-client,atlassian-python-api,slack-sdk, etc.) so generated projects install required SDKs.memory.py.j2boolean rendering — Switched| tojsonto| capitalizeso Jinja-emitted booleans render as PythonTrue/Falserather than JSONtrue/false.CLI command/comment alignment — Fixed inconsistent spacing in CLI help output so commands and comments line up.
Test patch target for
is_connected— Tests now patchapp.main.is_connected(where it's used afterfrom … import is_connected) rather thanapp.context_graph_client.is_connected(where it's defined). Generatedtest_routes.pymock fixture also sets dummy API keys (ANTHROPIC_API_KEY,OPENAI_API_KEY,GOOGLE_API_KEY) before importingapp.main, since PydanticAI'sAgent(...)validates the key at module import time. Added regression guardtest_test_file_mocks_is_connectedintests/test_generated_project.pyso accidental removal is caught in the fast unit suite.options-intelligence fixture quality — Rewrote fixture with consistent per-underlying scoping. Cross-underlying contamination eliminated (each Underlying now has scoped
OptionsContract,ExposureLevel,KeyLevel). Strike scales realistic per underlying (SPX ~5800, SPY ~580, QQQ ~500, IWM ~212, AAPL ~230). Regime timestamps chronologically consistent withFLIPPED_TO/PRECEDED_BYedges. Document content references title entities. Decision-trace placeholders replaced with concrete values from fixture entities. Greeks normalized (delta-1..1, gamma0..0.15, proper put delta signs).
Improvements
make schematarget — Added to the generatedMakefile. Comments onmake seedandmake import-and-seedclarified.Tests — 12 new tests for GitHub linking (regex/GraphQL/dedupe/precedence). 89 new tests for body-import toggle and configurable limits. 54 additional renderer tests covering connector field renames, memory boolean rendering, config Settings fields, and the new Makefile target.
v0.9.4 — GitHub Actions release workflow bugfixes (2026-04-17)
Bug Fixes
Upgrade npm cli for trusted publishing - project currently uses npm 20 but we need the latest npm cli in order to perform the trusted publishing OIDC workflow.
v0.9.3 — GitHub Actions release workflow bugfixes (2026-04-17)
Bug Fixes
Target npm-wrapper directory for node pkg - previously workflow was looing for package.json in top-level directory, but it lives in npm-wrapper.
v0.9.2 — Batch Seeding Performance (2026-04-15)
Bug Fixes
Batch entity seeding with
UNWIND—make seedpreviously executed one MERGE query per entity. With large Claude Code imports (27k+ entities), this caused seeding to appear to hang. Entity, relationship, and document creation now useUNWIND $batchwith batches of 500, reducing ~27,000 round-trips to ~55.Batch ingestion in
import_data.py— The--ingestpath in generated import scripts also usesUNWINDbatching.
v0.9.1 — Claude Code Connector Fixes & Docs (2026-04-15)
Bug Fixes
Fix
make importcrash — The scaffolded Claude Code connector crashed withint(None)whenmax_sessionswas passed asNonefromimport_data.py. All credential reads now use theoridiom for None-safety.Fix missing Settings fields — Added
claude_code_scope,claude_code_since,claude_code_max_sessions,claude_code_content_mode,claude_code_base_pathto the generatedconfig.pySettings class so.envvariables are honored (previously silently dropped byextra: "ignore"). Also addedgoogle_client_id,google_client_secret,gws_folder_idfor the Google Workspace connector.Fix dict vs attribute access — All template connectors return
dictfromfetch(), butimport_data.pyused attribute access (data.entities). Changed todata["entities"]across the board.Don't write empty
fixtures.jsonon crash — The import script now skips writingfixtures.jsonwhen no data was collected, instead of silently overwriting it with empty lists.Fix
make test-connection— Combined two sequentialasyncio.run()calls into one, fixing the "Event loop is closed" error that made it print both "successful" and "failed".
Improvements
Expanded scaffolded connector (268 → 457 lines) — The template connector now extracts 9 entity types (added GitBranch, Error, Decision, Preference, Alternative) with 14 relationship types (added ON_BRANCH, ENCOUNTERED_ERROR, MADE_DECISION, CHOSE, REJECTED, NEXT, PRECEDED_BY, USED_TOOL, EXPRESSES_PREFERENCE). Includes secret redaction, language detection from file extensions, file path validation, and
[rerun: bN]suffix stripping.Claude-Code-specific demo scenarios — When
--connector claude-codeis active, the "Try these" prompts now show relevant questions ("What files have I modified?", "Show me decisions", "What are my coding preferences?") instead of generic software-engineering prompts about PRs and incidents.
Documentation
Fixed dark-mode announcement bar (was white on dark background)
Added explicit
@easyops-cn/docusaurus-search-localplugin configurationMarked
ANTHROPIC_API_KEYas required for the chat agent in the Claude Code tutorialReplaced "copy
.env.exampleto.env" with "edit the generated.env" in the tutorialAdded CLI flag literals next to connector display names in the intro page
Added "Focus" column with one-line disambiguators to the domain catalog
Custom 404 page with links to Introduction, Quick Start, and "Report Broken Link"
"See all 22 domains →" link on the homepage carousel
Tighter scroll transitions for the memory-type explainer
Higher-contrast step numbers on the "How it works" section
Tests
7 new tests (1060 total): Settings fields, dict access, entity types, redaction, scenario override
v0.9.0 — Claude Code Connector, Google Workspace & Security (2026-04-02)
New Connectors
Claude Code connector — Reads local session JSONL files from
~/.claude/projects/with no authentication required. Parses user/assistant messages, tool_use/tool_result blocks, and progress entries. Extracts 7 entity types (Project, Session, Message, ToolCall, File, GitBranch, Error) with 10 relationship types. Includes heuristic decision extraction (user corrections, deliberation markers, error-resolution cycles, dependency changes) and preference extraction (explicit statements, package frequency). Secret redaction (API keys, tokens, passwords, connection strings) applied by default. 8 session intelligence agent tools injected via the renderer. 5 CLI flags (--claude-code-scope,--claude-code-project,--claude-code-since,--claude-code-max-sessions,--claude-code-content). Implementation split intoconnectors/claude_code_connector.pyandconnectors/_claude_code/subpackage (parser, redactor, decision_extractor, preference_extractor).Google Workspace connector — Imports from 6 Google APIs (Drive Files, Comments, Revisions, Activity, Calendar, Gmail) with OAuth2 authentication and dynamic scope building. Extracts decision traces from resolved comment threads in Google Docs (question, deliberation, resolution, participants). 10 decision-focused agent tools (
find_decisions,decision_context,who_decided,document_timeline,open_questions,meeting_decisions,knowledge_contributors,trace_decision_to_source,stale_documents,cross_reference). Cross-connector linking detects Linear issue references in comment bodies, doc names, email subjects, and meeting descriptions. 9 CLI flags for scoping imports. Rate limiting (950 queries/100s with exponential backoff).
Security
Replaced weak cryptographic hashing — Switched from MD5/SHA1 to SHA-256 for content hashing in connectors (code scanning alerts #8 and #9).
Bug Fixes
Session collision fix —
Session.namenow usessession_idas the unique MERGE key to avoid cross-session collisions when importing Claude Code data.Linear connector hardening — Don't fail on blank Linear team key; improved robustness of Linear import with better error handling.
Improvements
Google Workspace connector template improvements and renderer integration
Updated import_data.py template to handle new connectors
10 total SaaS connectors (GitHub, Notion, Jira, Slack, Gmail, Google Calendar, Salesforce, Linear, Google Workspace, Claude Code)
955 passing tests (1,165 collected including slow/integration)
v0.8.2 — Linear Connector (2026-04-02)
New Features
Linear SaaS connector — GraphQL-based connector with cursor-based pagination and rate limiting against
https://api.linear.app/graphql. Maps 12 entity types (Issue, Project, Cycle, Team, Person, Label, WorkflowState, Comment, ProjectUpdate, ProjectMilestone, Initiative, Attachment) to the POLE+O entity model with 26 relationship types. Imports issue relations, threaded comments with resolution tracking, project updates with health status, milestones, initiatives, attachments, and Linear Docs. Issue history entries are transformed into decision traces capturing state transitions, assignment changes, and priority changes with actor attribution. Uses stdlib only (urllib.request).Linear connector hardening — Named constants, structured logging, URLError/JSONDecodeError/429 handling with retry, pagination safety limits (
MAX_PAGES), null-safe field access, team key validation duringauthenticate(), incremental sync viaupdated_after.
Bug Fixes
Fix traces silent failure — Decision trace ingestion no longer silently fails on malformed data.
Documentation
New tutorial:
linear-context-graph.md— end-to-end guide for importing Linear project dataUpdated CLI options reference and SaaS data import guide
v0.8.1 — Schema Node Fix & Responsive Docs (2026-03-31)
Bug Fixes
Click on schema node works again — The
Buttoncomponent was added to the template for the "Ask about [entity]" feature but was never added to the@chakra-ui/reactimport. Clicking a schema node crashed the React component, preventing double-click expand from working.Python 3.14 boundary — Added
<3.14torequires-pythonfor forward compatibility.
Improvements
Improved responsive design for Docusaurus landing page
v0.8.0 — Embedding Fix, Data Quality & Documentation (2026-03-28)
Critical Fixes
neo4j-agent-memory no longer requires OpenAI API key — Removed
[openai]extra from the generatedpyproject.tomldependency. Conversation memory now uses localsentence-transformers(all-MiniLM-L6-v2, 384 dims) by default. IfOPENAI_API_KEYis set in the environment, automatically upgrades to OpenAItext-embedding-3-small(1536 dims). Addedsentence-transformers>=2.0as an explicit dependency so local embeddings work out of the box with zero API keys.openai-agents framework warns about missing API key — CLI now displays a clear warning when
--framework openai-agentsis selected without--openai-api-key. The interactive wizard prompt text changes to indicate the key is "required" (not optional) for this framework.
Data Quality
67 new entity name pools — Added domain-appropriate names for every entity label across all 22 domains.
LABEL_NAMESnow has 118 entries (up from 51), eliminating all "Label 1" / "Label 2" fallback names. Covers agent-memory (Conversation, Memory, Session, ToolCall), digital-twin (Alert, Asset, Sensor, Reading, MaintenanceRecord, System), golf-sports (Round, Handicap, Hole, Course, Tournament), hospitality (Room, Reservation, Guest, Staff), oil-gas (Well, Equipment, Reservoir, Formation, Permit), personal-knowledge (JournalEntry, Note, Bookmark, Contact, Topic, Project), retail-ecommerce (Order, Product, Customer, Campaign, Category), vacation-industry (Booking, Package, Resort, Season), wildlife-management (Sighting, Camera, Habitat, Individual, Threat), conservation (Stakeholder), data-journalism (Correction), GIS (Boundary, Coordinate, Feature, Layer, MapProject, Survey), GenAI/LLM-Ops (Model, Prompt, Evaluation, Experiment), product-management (Epic, Metric, Objective, Release, Feedback, UserPersona), and scientific-research (Paper, Researcher, Grant, Institution).Post-generation value clamping — LLM-generated entities are now post-processed by
_validate_and_clamp()ingenerator.py. Clamps 28 property types to domain-reasonable ranges (e.g.,price_per_night: $30–$2,000;duration_hours: 0.25–24;rating: 1–5;latitude: -90–90). Also corrects taxonomy class mismatches (e.g., Bengal Tiger → "mammalia", not "aves").Richer entity descriptions — Added
_LOCATION_LABELS,_EVENT_LABELS, and_OBJECT_LABELSsets (parallel to existing_PERSON_LABELS/_ORGANIZATION_LABELS) for POLE-type-aware descriptions. Added 7 label-specific description overrides for Medication, Permit, Sensor, Equipment, Paper, Model, and Species. Fallback descriptions no longer say "record tracked in the knowledge graph".digital-twin fixture fix — Fixed label casing in
digital-twin.json(UPPERCASE → PascalCase) to match the domain YAML schema.Domain-scoped entity MERGE keys — Changed entity MERGE from
{name: $name}to{name: $name, domain: $domain}in bothgenerate_data.py.j2andingest.py. Prevents constraint violation warnings when multiple domains share a single Neo4j instance.
Framework Fixes
google-adk AttributeError guard — Added
try/except AttributeErroraroundrunner.run_async()in bothhandle_messageandhandle_message_streamto gracefully handle thegoogle-genaiSDK'sBaseApiClientcleanup error when_async_httpx_clientwas never initialized.
Documentation
Quick-Start page — New
docs/quick-start.mdwith a 5-step guide: scaffold → Neo4j setup → configure → seed → start.use-neo4j-local guide — New
docs/how-to/use-neo4j-local.mdcovering@johnymontana/neo4j-local(npx), Neo4j Desktop, and Docker standalone with troubleshooting tips.Domain catalog — New
docs/reference/domain-catalog.mdlisting all 22 domains with entity types, agent tool counts, sample questions, and scaffold commands. Auto-generated from domain YAML files.Architecture diagram — Mermaid flowchart added to the Introduction page showing CLI → Template Engine → Backend/Frontend → Neo4j data flow. Added
@docusaurus/theme-mermaidfor rendering.switch-frameworks 404 fix — Added
slug: switch-frameworksto frontmatter so/docs/how-to/switch-frameworksresolves correctly.Updated navigation — Sidebar now includes quick-start, use-neo4j-local, and domain-catalog pages.
Frontend UX
Larger status indicator — Backend health dot enlarged from 8px to 12px with a text label ("Connected" / "Degraded" / "Offline").
Health check retry on initial load — First page load now retries the health check 3 times with exponential backoff (1s, 2s, 4s) before showing "Offline". Prevents the transient "Internal Server Error" on initial Next.js compilation.
Improved empty graph state — Empty knowledge graph panel now shows a link icon, "Your knowledge graph will appear here" heading, and actionable guidance text instead of a minimal "No graph data to display" message.
Testing
691 passing tests (89 new), up from 602
New
tests/test_fixtures.py(88 tests) — Cross-validates all 22 domains:Schema alignment: fixture entities have all required YAML properties
Agent tool property references: Cypher queries only reference properties that exist in schema or fixtures
Label coverage: fixtures include entities for every YAML-defined label
Data quality: numeric property values fall within reasonable ranges
v0.7.0 — Documentation Site Redesign & CI (2026-03-28)
New Features
Docusaurus landing page redesign — New animated terminal hero section with domain-specific demo commands, improved hero animation timing, and terminal width/height fixes.
Mobile navigation — Responsive nav bar with mobile layout improvements and design polish.
CI matrix job — Full test suite (including domain × framework matrix, perf, and generated project tests) now runs in the
matrixCI job on push tomain.
Documentation
4 new docs pages — "Use Neo4j Aura", "Use Docker", "Why Context Graphs?", "Framework Comparison"
Updated sidebars with all new pages
Bug Fixes & Data Quality
Bug fixes and data quality improvements across domains
Updated docs and test coverage
v0.6.1 — Stability, Data Quality & Tool Coverage (2026-03-28)
Critical Bug Fixes
CrewAI dependency fix — Changed
crewai>=0.1tocrewai[anthropic]>=0.1in framework dependencies. The crewai agent template usesllm="anthropic/claude-sonnet-4-20250514"which requires the anthropic extra. Without it, the generated project crashes on startup withImportError: Anthropic native provider not available.CLI non-interactive mode fix — The CLI no longer requires a positional
PROJECT_NAMEargument when all flags (--domain,--framework) are provided. Auto-generates a slug likehealthcare-pydanticai-app. Also added TTY detection with helpful error messages for CI/CD environments.
Data Quality Improvements
Document Markdown rendering — Static document content now uses Markdown headings (
##) instead of RST-style===/---separators. The DocumentBrowser component renders content with ReactMarkdown.Entity-derived document titles — Document titles now reference primary entities: "Discharge Summary: Maria Elena Gonzalez" instead of generic "Discharge Summary #1".
Realistic entity descriptions — Replaced generic "Comprehensive patient profile for..." with POLE-type-aware descriptions using domain roles and industries (e.g., "Dr. Sarah Chen, attending physician specializing in healthcare").
Domain-aware Organization.industry — Added
DOMAIN_INDUSTRY_POOLfor all 22 domains. Healthcare organizations get "Hospital Systems" instead of "Technology".Realistic decision trace observations — Observations now reference actual entity names: "Verified Dr. Sarah Chen against healthcare standards" instead of generic "Found 7 relevant records".
Improved thinking text filter — Added continuation patterns to catch multi-sentence agent thinking blocks between tool calls.
New Agent Tools (All 22 Domains)
list_*tools — Every domain now has a list tool for its primary entity type (e.g.,list_patients,list_players,list_accounts) with sort and limit parameters.get_*_by_idtools — Every domain now has a direct ID lookup tool that returns the entity with all connections (e.g.,get_patient_by_id,get_player_by_id).Gaming-specific — Added
get_top_playerstool (sort by level) for the gaming domain.
Frontend Improvements
"Ask about this" button — Clicking a node in the Knowledge Graph shows an "Ask about [entity]" button that sends a query to the chat.
Node hover tooltips — Graph nodes show full name, labels, and key properties on hover.
Health polling optimization — Reduced polling frequency from 30s to 60s.
Responsive hint text — Keyboard shortcut hint hidden on small screens to prevent overlap.
Suggested question max width — Pill buttons capped at 320px to prevent layout stretching.
Scrollable label badges — Label filter badges in the graph panel scroll when they overflow.
Seed constraint fix — Entity seeding now uses
ON CREATE SET / ON MATCH SETto avoid constraint violations on re-seed.
Documentation
4 new docs pages — "Use Neo4j Aura", "Use Docker", "Why Context Graphs?", "Framework Comparison"
Updated sidebars — All new pages added to Docusaurus navigation
Testing
602 passing tests (57 new), up from 545
v0.6.0 — Comprehensive Testing Feedback (2026-03-28)
Framework Fixes
CrewAI no longer hangs — Added explicit
llm="anthropic/claude-sonnet-4-20250514"to prevent defaulting to OpenAI. Added request-level logging and reduced timeout to 60s.Strands serialization fix — Added
_extract_text()helper that robustly extracts text from agent results, handlingParsedTextBlockserialization issues from newer Anthropic SDK versions.Google ADK API key support — Added
--google-api-keyCLI flag (GOOGLE_API_KEYenv), wizard prompt when google-adk is selected, andGOOGLE_API_KEYin generated.env/.env.exampletemplates.
Document & Trace Ingestion Fix
--ingestnow creates proper Document and DecisionTrace nodes — Both ingestion paths now create:Documentand:DecisionTrace/:TraceStepnodes using direct Cypher, matching thegenerate_data.pypattern that the frontend expects. Previously, Documents and Decision Traces panels appeared empty after--ingest.Entity MERGE fix — Direct driver ingestion now uses
MERGE (n:Label {name: $name}) SET ...instead ofMERGE (n:Label {all_props}), preventing duplicate nodes.
Data Quality
Domain-aware base entities — Person, Organization, Location, Event, and Object entities now use domain-specific names and roles (doctors for healthcare, traders for finance, game designers for gaming, etc.).
Fixed templated property values — Properties like "Metformin 500mg - Contraindications" now replaced with realistic values. Added pools for contraindications, dosage_form, allergies, sector, lead_reporter, manufacturer, mechanism_of_action, population_trend, and habitat.
Frontend UI Improvements
Redesigned chat input — Bordered container with focus highlight and keyboard shortcut hint (Chakra UI Pro inspired).
Suggested questions redesign — Pill-shaped buttons with full text (no 60-char truncation), "Try these" label with Sparkles icon.
Message avatars — User and assistant messages now have Circle avatars with User/Bot icons.
Tool progress counter — Shows "Running tool N of M..." during tool execution.
CLI
--democonvenience flag — Shortcut for--reset-database --demo-data --ingest--google-api-keyflag — New CLI flag withGOOGLE_API_KEYenv variable support
Testing
545 passing tests (35 new), up from 510
v0.5.3 — Agent Loop Breakout Fix (2026-03-27)
Bug Fixes
Prevent agents from returning pre-tool text as the final answer — PydanticAI's
run_streamfires aFinalResultEventthe moment anyTextPartbegins streaming. When Claude emits "I'll search for..." alongside a tool call,run_streamtreats that text as the final output and exits before tool results are incorporated. Replacedagent.run_stream()+stream_text()withagent.run()inhandle_message_stream, which completes the full agent loop before emitting text.Ruff lint fixes — Resolved lint errors across connectors, tests, and scripts.
Test assertion fix — Directory conflict test now asserts on "not empty" instead of "already exists" for better cross-platform compatibility.
v0.5.2 — Agent Framework Refinements (2026-03-26)
Improved Anthropic Tools and Claude Agent SDK agent templates
Enhanced
context_graph_clientevent handling and error recoveryChatInterface component improvements
Better error handling in API routes
generate_data.pyimprovements for data quality74 new ontology validation tests
v0.5.1 — UX Improvements & Bug Fixes (2026-03-25)
Bug Fixes
SSR hydration fix in frontend components
PydanticAI tool serialization fix — agent tools now return JSON string types correctly
Google ADK hyphenated domain name sanitization
HuggingFace warning suppression in agent templates
Improvements
Retry button on chat errors
Agent thinking text collapsible filter — reasoning steps render in a collapsible "Show reasoning" section
Strands
max_tokensconfiguration supportCypher query validation tests across all 22 domains
v0.5.0 — Data Quality & Domain Completeness (2026-03-24)
New Features
22 complete domain ontologies with pre-generated LLM fixture data shipped for all domains
Domain-specific static name pools — 200+ realistic names across 50+ entity labels (medical diagnoses, financial instruments, software repos, etc.)
Label-aware ID prefixes (
PAT-for Patient,ACT-for Account, etc.)12+ domain-specific property pools (currency codes, ticker symbols, drug classes, medical specialties, severities)
domainproperty on all ingested entities for cross-domain isolation when sharing a Neo4j instanceStructured document templates for static fallback data generation
Bug Fixes
Fixed missing SSE event messages in chat streaming
Float value clamping for confidence/rating/efficiency fields
Testing
510 passing tests (145 new), up from 365
v0.4.6 — Conversation Fetching Fix (2026-03-24)
Fixed conversation history fetching in
context_graph_clientfor multi-turn sessions
v0.4.5 — Framework & Build Fixes (2026-03-24)
Fixed
pyproject.tomlbuild configuration bugStrands framework default changed from Bedrock to AnthropicModel
Agent template improvements across multiple frameworks
Domain YAML fixes for gaming, genai-llm-ops, healthcare, personal-knowledge, product-management, retail-ecommerce, software-engineering, and trip-planning
v0.4.4 — Strands Model Default (2026-03-24)
Changed Strands agent framework default from AWS Bedrock to Anthropic native model (
AnthropicModel)
v0.4.3 — API Keys & Docker Support (2026-03-23)
Fixed API key handling and validation across agent frameworks
Added
Dockerfile.backendtemplate for Docker buildsMakefile improvements for containerized deployments
v0.4.2 — E2E Testing & Bug Fixes (2026-03-23)
Bug fixes across agent templates
Playwright e2e test scaffolding for generated projects (
app.spec.ts,playwright.config.ts)Improved e2e smoke testing infrastructure
v0.4.1 — Streaming & E2E Infrastructure (2026-03-23)
Server-Sent Events (SSE) streaming for real-time chat responses and tool call visualization
POST /chat/streamendpoint withasyncio.Queue-based event streamingToken-by-token text streaming for PydanticAI, Anthropic Tools, Claude Agent SDK, OpenAI Agents, LangGraph
Real-time tool call events with Timeline/Spinner/Collapsible UI components
Text delta batching (~50ms) to optimize React re-renders
E2E smoke testing infrastructure (
scripts/e2e_smoke_test.py)Documentation updates
v0.4.0 — Hardening, Security & DX (2026-03-23)
Bug Fixes
Critical: Enum identifier sanitization — special characters (
A+,A-,3d_model) in domain ontology enum values now generate valid Python identifiers with value aliasesCritical: Graceful degradation when Neo4j is unavailable — backend starts in degraded mode,
/healthendpoint reports connectivity statusHigh: Cypher injection prevention in GDS client — label parameters validated against entity type whitelist
High: CrewAI async/sync deadlock resolved — replaced bare
asyncio.run()withnest_asyncio-compatible helper, crew execution moved to threadHigh: Claude Agent SDK model version now configurable via
ANTHROPIC_MODELenvironment variableMedium: Silent exception swallowing replaced with structured warning messages in
ingest.pyandvector_client.pyMedium: JSON parsing errors in agent tool calls now return helpful error messages instead of crashing
Medium: Input validation (
max_length) added to chat and search request modelsLow: CLI validates empty project names before entering wizard
Low: Healthcare YAML blood type enums properly quoted
New Features
--dry-runCLI flag — preview what would be generated without creating files--verboseCLI flag — enable debug logging during generation/healthendpoint in generated projects — returns Neo4j connectivity status and app versionCORS origins configurable via
CORS_ORIGINSenvironment variableconstants.pymodule in generated projects — centralizes magic strings (index names, graph projections, embedding dimensions)Document browser pagination (page size 20, prev/next controls)
Semantic HTML landmarks (
<main>,<section>,<aside>) and ARIA labels in frontendActionable error messages in chat interface — distinguishes backend errors, network failures, and Neo4j unavailability
Security
Query timeouts (30s default) on all Neo4j operations
Credential warnings in generated
.env.exampleCORS production configuration guidance
Testing
365 passing tests (51 new), up from 314
New: enum identifier sanitization edge cases
New: models.py compilation across all 22 domains (prevents enum regression)
New: v0.4.0 feature validation (health endpoint, constants, graceful degradation, input validation, CORS, pagination)
New: CLI validation and flag tests
v0.3.0 — Memory Integration, Multi-Turn & Graph Visualization (2026-03-23)
neo4j-agent-memory integration for multi-turn conversations
Interactive NVL graph visualization (schema view, double-click expand, drag/zoom, property panel)
LLM-generated demo data (80-90 entities, 25+ documents, 3-5 decision traces per domain)
Markdown rendering in chat with tool call visualization
Document browser and entity detail panel
Improved graph visualization and frontend styling
Docusaurus documentation site setup and deployment
Improved domain fixture data quality
314 passing tests
v0.2.0 — Connectors & Custom Domains (2026-03-22)
New Features
7 SaaS data connectors — GitHub, Notion, Jira, Slack, Gmail, Google Calendar, Salesforce
Each connector implements
BaseConnectorABC withauthenticate(),fetch(), andget_credential_prompts()Gmail/Google Calendar prefer
gwsCLI with Python OAuth2 fallbackCustom domain generation — generate complete domain ontology YAMLs from natural language descriptions using LLM (Anthropic/OpenAI)
Custom domains saved to
~/.create-context-graph/custom-domains/for reuseNeo4j Aura
.envimport andneo4j-localsupport in wizardDocumentation site (Docusaurus) with deployment configuration
v0.1.1 — Initial Bug Fixes (2026-03-22)
Bug fixes for CLI and template rendering
Test improvements and expanded coverage
Added
.gitignoreto generated projects
v0.1.0 — Initial Release (2026-03-22)
Interactive CLI scaffolding tool (
create-context-graph) invoked viauvxornpx7-step interactive wizard with Questionary prompts
8 agent frameworks: PydanticAI, Claude Agent SDK, OpenAI Agents SDK, LangGraph, CrewAI, Strands, Google ADK, Anthropic Tools
Domain ontology system with YAML definitions and two-layer inheritance (
_base.yaml)Jinja2 template engine generating full-stack projects (FastAPI backend, Next.js + Chakra UI v3 frontend)
Neo4j schema generation (constraints + GDS projections)
Static and LLM-powered synthetic data generation pipeline
Neo4j data ingestion via
neo4j-agent-memoryor direct driver fallbackDomain-specific agent tools with Cypher queries
NVL graph visualization component
344 files · 334 not served here
- .github/workflows/ci.yml (not served here)
- .github/workflows/release.yml (not served here)
- .gitignore (not served here)
- .serena/.gitignore (not served here)
- ATTRIBUTION.md
- AUTOGINEER-RUNS.md
- CHANGELOG.md
- CLAUDE.md
- CONTRIBUTING.md
- LABS_DISCLAIMER.txt (not served here)
- LICENSE
- Makefile (not served here)
- README.md
- ROADMAP.md
- docs/.gitignore (not served here)
- docs/README.md
- docs/docs/explanation/ccg-edges.md (not served here)
- docs/docs/explanation/how-decision-traces-work.md (not served here)
- docs/docs/explanation/how-domain-ontologies-work.md (not served here)
- docs/docs/explanation/memory-backends.md (not served here)
- docs/docs/explanation/three-memory-types.md (not served here)
- docs/docs/explanation/why-context-graphs.md (not served here)
- docs/docs/how-to/add-custom-domain.md (not served here)
- docs/docs/how-to/configure-memory-providers.md (not served here)
- docs/docs/how-to/connect-claude-desktop.md (not served here)
- docs/docs/how-to/import-local-files.md (not served here)
- docs/docs/how-to/import-saas-data.md (not served here)
- docs/docs/how-to/switch-agent-frameworks.md (not served here)
- docs/docs/how-to/use-docker.md (not served here)
- docs/docs/how-to/use-nams.md (not served here)
- docs/docs/how-to/use-neo4j-aura.md (not served here)
- docs/docs/how-to/use-neo4j-local.md (not served here)
- docs/docs/intro.md (not served here)
- docs/docs/quick-start.md (not served here)
- docs/docs/reference/chat-import-schema.md (not served here)
- docs/docs/reference/claude-code-schema.md (not served here)
- docs/docs/reference/cli-options.md (not served here)
- docs/docs/reference/domain-catalog.md (not served here)
- docs/docs/reference/framework-comparison.md (not served here)
- docs/docs/reference/generated-project-structure.md (not served here)
- docs/docs/reference/google-workspace-schema.md (not served here)
- docs/docs/reference/ontology-yaml-schema.md (not served here)
- docs/docs/tutorials/claude-code-sessions.md (not served here)
- docs/docs/tutorials/customizing-domain-ontology.md (not served here)
- docs/docs/tutorials/first-context-graph-app.md (not served here)
- docs/docs/tutorials/google-workspace-decisions.md (not served here)
- docs/docs/tutorials/import-chat-history.md (not served here)
- docs/docs/tutorials/linear-context-graph.md (not served here)
- docs/docs/whats-new.md (not served here)
- docs/docusaurus.config.ts (not served here)
- docs/package-lock.json (not served here)
- docs/package.json (not served here)
- docs/sidebars.ts (not served here)
- docs/src/components/animations/AppPreview.module.css (not served here)
- docs/src/components/animations/AppPreview.tsx (not served here)
- docs/src/components/animations/ContextGraphExplainer.module.css (not served here)
- docs/src/components/animations/ContextGraphExplainer.tsx (not served here)
- docs/src/components/animations/DomainCarousel.module.css (not served here)
- docs/src/components/animations/DomainCarousel.tsx (not served here)
- docs/src/components/animations/FrameworkGrid.module.css (not served here)
- docs/src/components/animations/FrameworkGrid.tsx (not served here)
- docs/src/components/animations/HowItWorks.module.css (not served here)
- docs/src/components/animations/HowItWorks.tsx (not served here)
- docs/src/components/animations/TerminalAnimation.module.css (not served here)
- docs/src/components/animations/TerminalAnimation.tsx (not served here)
- docs/src/components/animations/TrustBar.module.css (not served here)
- docs/src/components/animations/TrustBar.tsx (not served here)
- docs/src/components/ui/BrowserFrame.module.css (not served here)
- docs/src/components/ui/BrowserFrame.tsx (not served here)
- docs/src/components/ui/Terminal.module.css (not served here)
- docs/src/components/ui/Terminal.tsx (not served here)
- docs/src/css/custom.css (not served here)
- docs/src/data/animation-config.ts (not served here)
- docs/src/pages/404.tsx (not served here)
- docs/src/pages/index.module.css (not served here)
- docs/src/pages/index.tsx (not served here)
- docs/src/theme/Root.tsx (not served here)
- docs/static/.nojekyll (not served here)
- docs/static/img/app-three-panel.excalidraw (not served here)
- docs/static/img/app-three-panel.png (not served here)
- docs/static/img/architecture-overview.excalidraw (not served here)
- docs/static/img/architecture-overview.png (not served here)
- docs/static/img/claude-code-data-flow.excalidraw (not served here)
- docs/static/img/claude-code-data-flow.png (not served here)
- docs/static/img/claude-code-data-pipeline.excalidraw (not served here)
- docs/static/img/claude-code-data-pipeline.png (not served here)
- docs/static/img/claude-code-decision-extraction.excalidraw (not served here)
- docs/static/img/claude-code-decision-extraction.png (not served here)
- docs/static/img/claude-code-graph-schema.excalidraw (not served here)
- docs/static/img/claude-code-graph-schema.png (not served here)
- docs/static/img/connector-data-flow.excalidraw (not served here)
- docs/static/img/connector-data-flow.png (not served here)
- docs/static/img/decision-trace-structure.excalidraw (not served here)
- docs/static/img/decision-trace-structure.png (not served here)
- docs/static/img/docusaurus-social-card.jpg (not served here)
- docs/static/img/docusaurus.png (not served here)
- docs/static/img/favicon.ico (not served here)
- docs/static/img/graph-vs-flat.excalidraw (not served here)
- docs/static/img/graph-vs-flat.png (not served here)
- docs/static/img/gws-decision-flow.excalidraw (not served here)
- docs/static/img/gws-decision-flow.png (not served here)
- docs/static/img/gws-graph-schema.excalidraw (not served here)
- docs/static/img/gws-graph-schema.png (not served here)
- docs/static/img/gws-linear-combined.excalidraw (not served here)
- docs/static/img/gws-linear-combined.png (not served here)
- docs/static/img/linear-data-flow.excalidraw (not served here)
- docs/static/img/linear-data-flow.png (not served here)
- docs/static/img/linear-graph-schema.excalidraw (not served here)
- docs/static/img/linear-graph-schema.png (not served here)
- docs/static/img/logo.svg (not served here)
- docs/static/img/memory-architecture.excalidraw (not served here)
- docs/static/img/memory-architecture.png (not served here)
- docs/static/img/ontology-pipeline.excalidraw (not served here)
- docs/static/img/ontology-pipeline.png (not served here)
- docs/static/img/screenshot-frontend.png (not served here)
- docs/static/img/undraw_docusaurus_mountain.svg (not served here)
- docs/static/img/undraw_docusaurus_react.svg (not served here)
- docs/static/img/undraw_docusaurus_tree.svg (not served here)
- docs/tsconfig.json (not served here)
- document-parsing-libraries.md
- npm-wrapper/README.md (not served here)
- npm-wrapper/bin/create-context-graph (not served here)
- npm-wrapper/package.json (not served here)
- pyproject.toml (not served here)
- scripts/e2e_smoke_test.py (not served here)
- scripts/regenerate_fixtures.py (not served here)
- src/create_context_graph/__init__.py (not served here)
- src/create_context_graph/__main__.py (not served here)
- src/create_context_graph/cli.py (not served here)
- src/create_context_graph/config.py (not served here)
- src/create_context_graph/connectors/__init__.py (not served here)
- src/create_context_graph/connectors/_chat_import/__init__.py (not served here)
- src/create_context_graph/connectors/_chat_import/models.py (not served here)
- src/create_context_graph/connectors/_chat_import/zip_reader.py (not served here)
- src/create_context_graph/connectors/_chatgpt/__init__.py (not served here)
- src/create_context_graph/connectors/_chatgpt/parser.py (not served here)
- src/create_context_graph/connectors/_claude_ai/__init__.py (not served here)
- src/create_context_graph/connectors/_claude_ai/parser.py (not served here)
- src/create_context_graph/connectors/_claude_code/__init__.py (not served here)
- src/create_context_graph/connectors/_claude_code/decision_extractor.py (not served here)
- src/create_context_graph/connectors/_claude_code/parser.py (not served here)
- src/create_context_graph/connectors/_claude_code/preference_extractor.py (not served here)
- src/create_context_graph/connectors/_claude_code/redactor.py (not served here)
- src/create_context_graph/connectors/_local_file/__init__.py (not served here)
- src/create_context_graph/connectors/_local_file/mapper.py (not served here)
- src/create_context_graph/connectors/_local_file/parser.py (not served here)
- src/create_context_graph/connectors/_local_file/parsers/__init__.py (not served here)
- src/create_context_graph/connectors/_local_file/parsers/asciidoc.py (not served here)
- src/create_context_graph/connectors/_local_file/parsers/docx.py (not served here)
- src/create_context_graph/connectors/_local_file/parsers/html.py (not served here)
- src/create_context_graph/connectors/_local_file/parsers/markdown.py (not served here)
- src/create_context_graph/connectors/_local_file/parsers/pdf.py (not served here)
- src/create_context_graph/connectors/chatgpt_connector.py (not served here)
- src/create_context_graph/connectors/claude_ai_connector.py (not served here)
- src/create_context_graph/connectors/claude_code_connector.py (not served here)
- src/create_context_graph/connectors/gcal_connector.py (not served here)
- src/create_context_graph/connectors/github_connector.py (not served here)
- src/create_context_graph/connectors/gmail_connector.py (not served here)
- src/create_context_graph/connectors/google_workspace_connector.py (not served here)
- src/create_context_graph/connectors/jira_connector.py (not served here)
- src/create_context_graph/connectors/linear_connector.py (not served here)
- src/create_context_graph/connectors/local_file_connector.py (not served here)
- src/create_context_graph/connectors/notion_connector.py (not served here)
- src/create_context_graph/connectors/oauth.py (not served here)
- src/create_context_graph/connectors/salesforce_connector.py (not served here)
- src/create_context_graph/connectors/slack_connector.py (not served here)
- src/create_context_graph/custom_domain.py (not served here)
- src/create_context_graph/domains/_base.yaml (not served here)
- src/create_context_graph/domains/agent-memory.yaml (not served here)
- src/create_context_graph/domains/conservation.yaml (not served here)
- src/create_context_graph/domains/cybersecurity.yaml (not served here)
- src/create_context_graph/domains/data-journalism.yaml (not served here)
- src/create_context_graph/domains/digital-twin.yaml (not served here)
- src/create_context_graph/domains/education.yaml (not served here)
- src/create_context_graph/domains/financial-services.yaml (not served here)
- src/create_context_graph/domains/gaming.yaml (not served here)
- src/create_context_graph/domains/genai-llm-ops.yaml (not served here)
- src/create_context_graph/domains/gis-cartography.yaml (not served here)
- src/create_context_graph/domains/golf-sports.yaml (not served here)
- src/create_context_graph/domains/government.yaml (not served here)
- src/create_context_graph/domains/healthcare.yaml (not served here)
- src/create_context_graph/domains/hospitality.yaml (not served here)
- src/create_context_graph/domains/legal.yaml (not served here)
- src/create_context_graph/domains/manufacturing.yaml (not served here)
- src/create_context_graph/domains/oil-gas.yaml (not served here)
- src/create_context_graph/domains/options-intelligence.yaml (not served here)
- src/create_context_graph/domains/personal-knowledge.yaml (not served here)
- src/create_context_graph/domains/product-management.yaml (not served here)
- src/create_context_graph/domains/real-estate.yaml (not served here)
- src/create_context_graph/domains/retail-ecommerce.yaml (not served here)
- src/create_context_graph/domains/scientific-research.yaml (not served here)
- src/create_context_graph/domains/software-engineering.yaml (not served here)
- src/create_context_graph/domains/trip-planning.yaml (not served here)
- src/create_context_graph/domains/vacation-industry.yaml (not served here)
- src/create_context_graph/domains/wildlife-management.yaml (not served here)
- src/create_context_graph/fixtures/agent-memory.json (not served here)
- src/create_context_graph/fixtures/conservation.json (not served here)
- src/create_context_graph/fixtures/cybersecurity.json (not served here)
- src/create_context_graph/fixtures/data-journalism.json (not served here)
- src/create_context_graph/fixtures/digital-twin.json (not served here)
- src/create_context_graph/fixtures/education.json (not served here)
- src/create_context_graph/fixtures/financial-services.json (not served here)
- src/create_context_graph/fixtures/gaming.json (not served here)
- src/create_context_graph/fixtures/genai-llm-ops.json (not served here)
- src/create_context_graph/fixtures/gis-cartography.json (not served here)
- src/create_context_graph/fixtures/golf-sports.json (not served here)
- src/create_context_graph/fixtures/government.json (not served here)
- src/create_context_graph/fixtures/healthcare.json (not served here)
- src/create_context_graph/fixtures/hospitality.json (not served here)
- src/create_context_graph/fixtures/legal.json (not served here)
- src/create_context_graph/fixtures/manufacturing.json (not served here)
- src/create_context_graph/fixtures/oil-gas.json (not served here)
- src/create_context_graph/fixtures/options-intelligence.json (not served here)
- src/create_context_graph/fixtures/personal-knowledge.json (not served here)
- src/create_context_graph/fixtures/product-management.json (not served here)
- src/create_context_graph/fixtures/real-estate.json (not served here)
- src/create_context_graph/fixtures/retail-ecommerce.json (not served here)
- src/create_context_graph/fixtures/scientific-research.json (not served here)
- src/create_context_graph/fixtures/software-engineering.json (not served here)
- src/create_context_graph/fixtures/trip-planning.json (not served here)
- src/create_context_graph/fixtures/vacation-industry.json (not served here)
- src/create_context_graph/fixtures/wildlife-management.json (not served here)
- src/create_context_graph/generator.py (not served here)
- src/create_context_graph/ingest.py (not served here)
- src/create_context_graph/name_pools.py (not served here)
- src/create_context_graph/neo4j_validator.py (not served here)
- src/create_context_graph/ontology.py (not served here)
- src/create_context_graph/renderer.py (not served here)
- src/create_context_graph/templates/backend/agents/anthropic_tools/agent.py.j2 (not served here)
- src/create_context_graph/templates/backend/agents/claude_agent_sdk/agent.py.j2 (not served here)
- src/create_context_graph/templates/backend/agents/crewai/agent.py.j2 (not served here)
- src/create_context_graph/templates/backend/agents/google_adk/agent.py.j2 (not served here)
- src/create_context_graph/templates/backend/agents/langgraph/agent.py.j2 (not served here)
- src/create_context_graph/templates/backend/agents/openai_agents/agent.py.j2 (not served here)
- src/create_context_graph/templates/backend/agents/pydanticai/agent.py.j2 (not served here)
- src/create_context_graph/templates/backend/agents/strands/agent.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/__init__.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/claude_code_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/gcal_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/github_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/gmail_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/google_workspace_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/import_data.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/jira_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/linear_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/local_file_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/notion_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/salesforce_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/connectors/slack_connector.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/agent_stub.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/config.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/constants.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/context_graph_client.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/gds_client.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/generate_data.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/main.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/memory.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/memory_adapter.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/models.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/pyproject.toml.j2 (not served here)
- src/create_context_graph/templates/backend/shared/routes.py.j2 (not served here)
- src/create_context_graph/templates/backend/shared/vector_client.py.j2 (not served here)
- src/create_context_graph/templates/backend/tests/test_routes.py.j2 (not served here)
- src/create_context_graph/templates/base/Dockerfile.backend.j2 (not served here)
- src/create_context_graph/templates/base/Dockerfile.frontend.j2 (not served here)
- src/create_context_graph/templates/base/Makefile.j2 (not served here)
- src/create_context_graph/templates/base/README.md.j2 (not served here)
- src/create_context_graph/templates/base/docker-compose.prod.yml.j2 (not served here)
- src/create_context_graph/templates/base/docker-compose.yml.j2 (not served here)
- src/create_context_graph/templates/base/dockerignore.j2 (not served here)
- src/create_context_graph/templates/base/dot_env.j2 (not served here)
- src/create_context_graph/templates/base/dot_env_example.j2 (not served here)
- src/create_context_graph/templates/base/gitignore.j2 (not served here)
- src/create_context_graph/templates/base/mcp/README.md.j2 (not served here)
- src/create_context_graph/templates/base/mcp/claude_desktop_config.json.j2 (not served here)
- src/create_context_graph/templates/cypher/gds_projections.cypher.j2 (not served here)
- src/create_context_graph/templates/cypher/schema.cypher.j2 (not served here)
- src/create_context_graph/templates/frontend/app/globals.css.j2 (not served here)
- src/create_context_graph/templates/frontend/app/layout.tsx.j2 (not served here)
- src/create_context_graph/templates/frontend/app/page.tsx.j2 (not served here)
- src/create_context_graph/templates/frontend/components/ChatInterface.tsx.j2 (not served here)
- src/create_context_graph/templates/frontend/components/ContextGraphView.tsx.j2 (not served here)
- src/create_context_graph/templates/frontend/components/DecisionTracePanel.tsx.j2 (not served here)
- src/create_context_graph/templates/frontend/components/DocumentBrowser.tsx.j2 (not served here)
- src/create_context_graph/templates/frontend/components/ErrorBoundary.tsx.j2 (not served here)
- src/create_context_graph/templates/frontend/components/Provider.tsx.j2 (not served here)
- src/create_context_graph/templates/frontend/e2e/app.spec.ts.j2 (not served here)
- src/create_context_graph/templates/frontend/lib/config.ts.j2 (not served here)
- src/create_context_graph/templates/frontend/next.config.ts.j2 (not served here)
- src/create_context_graph/templates/frontend/package.json.j2 (not served here)
- src/create_context_graph/templates/frontend/playwright.config.ts.j2 (not served here)
- src/create_context_graph/templates/frontend/theme/index.ts.j2 (not served here)
- src/create_context_graph/templates/frontend/tsconfig.json.j2 (not served here)
- src/create_context_graph/wizard.py (not served here)
- tests/__init__.py (not served here)
- tests/conftest.py (not served here)
- tests/fixtures/local_file_vault/README.md (not served here)
- tests/fixtures/local_file_vault/companies/acme-corp.md (not served here)
- tests/fixtures/local_file_vault/companies/betawidgets-inc.md (not served here)
- tests/fixtures/local_file_vault/daily-notes/2026-05-08.md (not served here)
- tests/fixtures/local_file_vault/daily-notes/2026-05-09.md (not served here)
- tests/fixtures/local_file_vault/decisions/2026-q2-thesis-call.md (not served here)
- tests/fixtures/local_file_vault/external/acme-10q-2026q1.pdf (not served here)
- tests/fixtures/local_file_vault/external/sector-report-q1-2026.html (not served here)
- tests/fixtures/local_file_vault/meetings/2026-05-07-portfolio-review.md (not served here)
- tests/fixtures/local_file_vault/memos/acme-investment-memo.docx (not served here)
- tests/fixtures/local_file_vault/methodology/dcf-framework.md (not served here)
- tests/fixtures/local_file_vault/methodology/dcf-spec.adoc (not served here)
- tests/fixtures/local_file_vault/people/dana-liu.md (not served here)
- tests/fixtures/local_file_vault/people/marcus-reyes.md (not served here)
- tests/fixtures/local_file_vault/people/sarah-chen.md (not served here)
- tests/fixtures/local_file_vault/people/tariq-osei.md (not served here)
- tests/fixtures/local_file_vault/people/yuki-tanaka.md (not served here)
- tests/fixtures/local_file_vault_TESTING.md (not served here)
- tests/test_bolt_ingest_parity.py (not served here)
- tests/test_chat_import.py (not served here)
- tests/test_cli.py (not served here)
- tests/test_config.py (not served here)
- tests/test_connectors.py (not served here)
- tests/test_custom_domain.py (not served here)
- tests/test_doc_snippets.py (not served here)
- tests/test_fixtures.py (not served here)
- tests/test_frontend_logic.py (not served here)
- tests/test_generated_client_runtime.py (not served here)
- tests/test_generated_project.py (not served here)
- tests/test_generated_tests.py (not served here)
- tests/test_generator.py (not served here)
- tests/test_ingest_nams.py (not served here)
- tests/test_integration.py (not served here)
- tests/test_local_file_connector.py (not served here)
- tests/test_local_file_vault.py (not served here)
- tests/test_matrix.py (not served here)
- tests/test_memory_adapter.py (not served here)
- tests/test_nams_adapter.py (not served here)
- tests/test_nams_ingest_parity.py (not served here)
- tests/test_neo4j_validator.py (not served here)
- tests/test_ontology.py (not served here)
- tests/test_performance.py (not served here)
- tests/test_renderer.py (not served here)
- tests/test_routes_integration.py (not served here)
- tests/test_security.py (not served here)
- tests/test_wizard.py (not served here)
- uv.lock (not served here)
- vercel.json (not served here)
Advantages
- Rapidly scaffolds full-stack applications with domain-specific ontologies and agent tools in under 5 minutes. evidence: README.md
- Provides flexible memory backend options, supporting both hosted NAMS and self-hosted Neo4j. evidence: README.md
Limitations
- The NAMS hosted memory backend has a narrower write surface compared to self-hosted Neo4j, limiting some Cypher-based operations. evidence: README.md
- Requires specific API keys and environment variables depending on the chosen agent framework and memory provider. evidence: README.md
Security
Risk level: Low risk
This brain runs
Agent instructions that run or fetch something (28)
CLAUDE.md:Invoked via `uvx create-context-graph` or `npx create-context-graph`.CLAUDE.md:(2) every document/body ingest write failed (`role="document"` rejected — only user/assistant/system allowed — plus the conversation-404), fixed across all three NAMS ingest implementations (`run_nams_ingest`, scaffolded `import_data.py`, `make seed`'s `ingest_fixtures_nams`) with `role …[+63 chars]CLAUDE.md:the old loop swallowed the AttributeError and printed "0 removed") — `--reset-database` and `make reset` now honestly report that no delete API exists and point at the NAMS dashboard.CLAUDE.md:**NAMS domain ontology activation (new)**: NAMS pre-registers a server-side ontology for every bundled domain but auto-binds workspaces to `nams-default` until one is activated — generated apps now bind on `connect_memory()` (activate catalog match by domain id, or create-from-`backend …[+359 chars]CLAUDE.md:**Carry-forward from v0.13.1 (feedback-report triage):** `create-context-graph --dry-run` no longer demands a NAMS API key (the credential gate is now scoped to non-dry-run flows in `cli.py:392`).CLAUDE.md:**Carry-forward from v0.13.0 (v0.12.0 feedback-report fixes):** Fixed the bolt async/sync mismatch in the scaffolded `import_data.py` (`_ingest_via_bolt()` is `async def` and both call sites wrap with `asyncio.run`);CLAUDE.md:uv venv && uv pip install -e ".[dev]"CLAUDE.md:# Run testsCLAUDE.md:**Data seeding** (`make seed`): Loads all four data types into Neo4j — entities, relationships, documents (as `:Document` nodes with `:MENTIONS` links to entities), and decision traces (as `:DecisionTrace` → `:HAS_STEP` → `:TraceStep` chains).CLAUDE.md:As tools execute, the collector emits `tool_start` and `tool_end` events (with graph data).CLAUDE.md:CrewAI and Strands are synchronous frameworks that run in worker threads via `asyncio.to_thread()`.CLAUDE.md:When `--with-mcp` is passed (or selected in the wizard), the scaffold generates `mcp/claude_desktop_config.json` (pre-configured for the project's Neo4j instance), `mcp/README.md` (setup instructions), and a `make mcp-server` Makefile target.CLAUDE.md:python-docx (Word).CLAUDE.md:Connectors run at scaffold time AND are generated into the project with `make import` / `make import-and-seed` targets.CLAUDE.md:pytest tests/test_generated_tests.py # Scaffold + install + run generated project test suite for 4 frameworks (slow, 5)CLAUDE.md:Full-stack integration tests that scaffold a project, install dependencies, start the backend, and send chat prompts.CLAUDE.md:make smoke-test # Run 3 key framework tests (pydanticai, google-adk, strands)CLAUDE.md:# Or run directly with more control:CLAUDE.md:python scripts/e2e_smoke_test.py --domain healthcare --framework pydanticai --quickCLAUDE.md:python scripts/e2e_smoke_test.py --all-domains --framework claude-agent-sdk --quickCLAUDE.md:python scripts/e2e_smoke_test.py --domain gaming --framework openai-agents # full mode (all prompts)CLAUDE.md:| Target | Description | |--------|-------------| | `make test` | Fast unit tests (1,454 passing, no external deps) | | `make test-slow` | Full suite including matrix + perf + generated project + connector/functional tests (1,866 passing with connectors extra) | | `make test-matrix` | …[+533 chars]CLAUDE.md:Generate fixture data: run the CLI with `--demo-data` or use `generator.py` directlyCLAUDE.md:| Framework | Directory | Pattern | Streaming | |-----------|-----------|---------|-----------| | PydanticAI | `pydanticai/` | `@agent.tool` decorator + `RunContext[AgentDeps]` | Full (`agent.run_stream()`) | | Claude Agent SDK | `claude_agent_sdk/` | Dict-based TOOLS list + bounded ag …[+787 chars]CLAUDE.md:| Job | Trigger | Description | |-----|---------|-------------| | **test** | All pushes + PRs | Fast unit tests on Python 3.11 and 3.12 (`fail-fast: false` so one version's failure doesn't cancel the other) | | **lint** | All pushes + PRs | Ruff on `src/` and `tests/` (rule set pinned …[+444 chars]CLAUDE.md:**Every job installs from `uv.lock` via `uv sync --locked --extra ...` and runs commands with `uv run --no-sync`.** Never mix `uv pip install` with a bare `uv run` in CI: `uv run` does an implicit lockfile sync that downgrades locked base deps underneath freshly-installed latest extras …[+94 chars]CLAUDE.md:If `--locked` fails, run `uv lock` locally and commit the refreshed lockfile — dependency changes in `pyproject.toml` must ship with a matching `uv.lock`.CLAUDE.md:The Makefile test/lint targets use `uv run --extra dev ...` so local runs resolve from the lock the same way.
Install scripts (1)
Makefile(make install):uv venv && uv pip install -e ".[dev]"
- Low risk: network-instructions (CLAUDE.md:15)
- Low risk: network-instructions (Makefile:10)
- Low risk: scripts-present (scripts/e2e_smoke_test.py)
- Low risk: scripts-present (scripts/regenerate_fixtures.py)
Attribution and licence
- Created by
- neo4j-labs
- Declared authors
- William Lyon (declared in pyproject.toml)
- Publisher
- neo4j-labs (Official neo4j-labs project)
- Source
- neo4j-labs/create-context-graph · commit 926e3b3
- Licence
- Apache License 2.0 (files served here)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by neo4j-labs.
Install from source
334 of its files are not served here, so there is no ZIP. neo4j-labs/create-context-graph at 926e3b3