Configuration Reference¶
Overview¶
All Knowledge System configuration is managed through your PAI environment file. This document describes every available configuration option.
Configuration Location¶
Primary: ~/.claude/.env (or $PAI_DIR/.env)
This is the single source of truth for all Madeinoz Knowledge System settings. The config/.env.example file in the pack is a reference template only.
Configuration File Format¶
The configuration file uses standard shell environment variable syntax:
# Comments start with #
VARIABLE_NAME=value
MULTI_LINE_VALUE="can span lines with quotes"
NUMERIC_VALUE=123
BOOLEAN_VALUE=true
LLM Provider Configuration¶
Provider Selection¶
Valid values:
openai- OpenAI API or OpenAI-compatible providers (OpenRouter, Together, etc.)anthropic- Anthropic Claude APIgemini- Google Gemini APIgroq- Groq APIollama- Local Ollama server or Ollama-compatible provider (apikey required)
Model Selection¶
Recommended models:
gpt-4o-mini(OpenAI) - Best balance of cost and qualitygoogle/gemini-2.0-flash-001(OpenRouter) - Cheapest working modelopenai/gpt-4o(OpenRouter) - Fastest extractionmeta-llama/llama-3.1-8b-instruct(OpenRouter) - Lowest cost (may have validation issues)
API Keys¶
MADEINOZ_KNOWLEDGE_OPENAI_API_KEY=sk-your-openai-key-here
MADEINOZ_KNOWLEDGE_ANTHROPIC_API_KEY=sk-ant-your-anthropic-key-here
MADEINOZ_KNOWLEDGE_GOOGLE_API_KEY=your-google-api-key
MADEINOZ_KNOWLEDGE_GROQ_API_KEY=gsk-your-groq-key
Important: Only include the API key for your chosen provider.
Custom Base URL (OpenAI-Compatible Providers)¶
Common values:
https://openrouter.ai/api/v1- OpenRouterhttps://api.together.xyz/v1- Together AIhttps://api.fireworks.ai/inference/v1- Fireworks AIhttps://api.deepinfra.com/v1/openai- DeepInfrahttp://localhost:11434/v1- Local Ollama
For Ollama, use:
MADEINOZ_KNOWLEDGE_OPENAI_BASE_URL=http://host.docker.internal:11434/v1
# On Linux, replace host.docker.internal with your Ollama server IP
Embedder Configuration¶
Embedder Provider¶
Valid values:
openai- OpenAI API or OpenAI-compatible providersanthropic- Anthropic (limited embedding support)ollama- Local Ollama embeddings (recommended for cost)
Embedding Model¶
Recommended models:
mxbai-embed-large(Ollama) - FREE, 87ms, 73.9% qualitytext-embedding-3-small(OpenAI) - $0.02/1M, 78.2% qualityBAAI/bge-large-en-v1.5(Together AI) - Fast, high quality
Embedding Dimensions¶
Important: Must match the embedding model's output dimensions:
mxbai-embed-large→1024text-embedding-3-small→1536text-embedding-3-large→3072nomic-embed-text→768
⚠️ CRITICAL: Changing embedding models breaks existing data. All vectors must have identical dimensions for Neo4j vector search to work. If you change embedding models, you must clear the graph and re-add all knowledge.
Embedder Base URL¶
Set only if using Ollama or another OpenAI-compatible embedder provider.
Database Backend Configuration¶
Database Type¶
Valid values:
neo4j(default) - Native graph database, better special character handlingfalkordb- Redis-based, simpler setup, lower resources
Neo4j Configuration¶
MADEINOZ_KNOWLEDGE_NEO4J_URI=bolt://neo4j:7687
MADEINOZ_KNOWLEDGE_NEO4J_USER=neo4j
MADEINOZ_KNOWLEDGE_NEO4J_PASSWORD=madeinozknowledge
MADEINOZ_KNOWLEDGE_NEO4J_DATABASE=neo4j
Default values work with docker-compose setup.
For external Neo4j:
MADEINOZ_KNOWLEDGE_NEO4J_URI=bolt://neo4j:7687
MADEINOZ_KNOWLEDGE_NEO4J_USER=neo4j
MADEINOZ_KNOWLEDGE_NEO4J_PASSWORD=madeinozknowledge
Changing Neo4j Password¶
Why This Process Is Required¶
Neo4j's security architecture stores credentials inside the persistent data volume, not in environment variables. Understanding this is critical:
-
First Startup Behavior: The
NEO4J_AUTHenvironment variable is only read on first startup when no user data exists. Neo4j uses it to create the initialneo4juser with the specified password. -
Password Persistence: After initialization, the password is stored encrypted in the
/datavolume as part of thesystemdatabase. TheNEO4J_AUTHenvironment variable is ignored on subsequent startups. -
Why Environment Variables Don't Work: Many users expect changing
NEO4J_AUTHto update the password—this is a common misconception. Since the password lives in the data volume, changing environment variables has no effect on existing databases. -
The Correct Approach: You must use Cypher commands (
ALTER CURRENT USERorALTER USER) to modify passwords in a running database. This ensures the change is written to thesystemdatabase where credentials are actually stored.
This design ensures that your credentials remain consistent with your data, and that accidentally changing an environment variable cannot lock you out of your database.
Reference: Neo4j Operations Manual - Manage Users
Method 1: Using Neo4j Browser (Recommended)¶
The Neo4j Browser provides a web interface for database administration.
- Open Neo4j Browser:
- Login with current credentials:
- Username:
neo4j -
Password: (your current password, default:
madeinozknowledge) -
Run the official password change command:
This command requires you to know your current password and changes it atomically in the system database.
- Update your
.envfile to match:
Important: The .env file must match the database password for the MCP server to connect.
- Restart the MCP server to apply the new password:
Method 2: Using Cypher Shell (Command Line)¶
For users who prefer command-line administration.
- Connect to the Neo4j container:
- Run the official password change command:
Then exit the shell:
- Update
.envand restart (same as Method 1, steps 4-5)
Method 3: Admin Changing Another User's Password (Enterprise)¶
If you have admin privileges, you can change any user's password:
Optionally force a password change on next login:
Password Requirements¶
- Minimum 8 characters (Neo4j default)
- Avoid special characters that may cause shell escaping issues
- Store securely - this password protects your knowledge graph
⚠️ CRITICAL: Never Delete Data Volumes¶
NEVER use docker compose down -v or podman compose down -v to "reset" a forgotten password. The -v flag deletes all data volumes, permanently destroying your knowledge graph. This data is irreplaceable.
If you've forgotten your password:
- Try the default password:
madeinozknowledge - Check your
~/.claude/.envforMADEINOZ_KNOWLEDGE_NEO4J_PASSWORD - Use Method 1 or Method 2 above with a password you remember having set
- If all else fails, contact the community for recovery assistance before considering any destructive action
Troubleshooting Password Issues¶
"AuthenticationRateLimit" error: Neo4j blocks connections after too many failed attempts. Wait 30 seconds or restart the Neo4j container:
"Authentication failed" after password change: The MCP server is using the old password. Ensure:
.envfile has the new password- MCP server was restarted after the change
- No shell environment variable is overriding the
.envvalue
FalkorDB Configuration¶
For external FalkorDB:
Knowledge Graph Configuration¶
Group ID¶
Organizes knowledge into logical groups. Enables multiple isolated knowledge graphs:
# Create separate groups for different domains
MADEINOZ_KNOWLEDGE_GROUP_ID=main # Default personal knowledge
MADEINOZ_KNOWLEDGE_GROUP_ID=research # Research findings
MADEINOZ_KNOWLEDGE_GROUP_ID=osint-intel # OSINT/CTI data
Multiple groups can be searched together using the search workflows.
Performance Configuration¶
Rate Limiting¶
Controls request rate limiting per IP address. Protects against abuse and DoS attacks.
| Variable | Default | Description |
|---|---|---|
RATE_LIMIT_MAX_REQUESTS |
60 | Maximum requests per time window per IP |
RATE_LIMIT_WINDOW_SECONDS |
60 | Time window in seconds |
RATE_LIMIT_ENABLED |
true | Set to false to disable (not recommended for production) |
Note: Rate limiting only applies to HTTP transport mode. SSE/stdio modes do not use rate limiting.
Concurrency/Semaphore Limit¶
Controls concurrent API requests to LLM provider. Tune based on API rate limits:
| Tier | Rate Limit | Recommended | Cost |
|---|---|---|---|
| Free | 0 RPM | 1-2 | $0/month |
| Tier 1 | 10 RPM | 3-5 | $5/month |
| Tier 2 | 60 RPM | 8-10 | $20/month |
| Tier 3 | 500 RPM | 10-15 | $100/month |
| Tier 4 | 5000+ RPM | 20-50 | $250/month |
If experiencing rate limit errors:
- Lower this value (e.g., 5)
- Upgrade your API tier
- Check
MADEINOZ_KNOWLEDGE_OPENAI_API_KEYhas credits/quota
Neo4j-Specific Features¶
Search All Groups (Neo4j only)¶
When enabled, searches automatically query all available group_ids without explicitly specifying them. This ensures knowledge stored in different groups is discoverable:
# With SEARCH_ALL_GROUPS=true:
# Finds knowledge in: main, research, osint-intel, etc.
# With SEARCH_ALL_GROUPS=false:
# Only searches specified group_ids (original behavior)
Default: true (enabled)
Cache duration: 30 seconds (balance between performance and freshness)
Telemetry Configuration¶
Telemetry Enabled¶
Controls whether Graphiti sends anonymous telemetry. Default is false (disabled).
Metrics & Observability Configuration¶
Metrics Collection¶
Controls whether Prometheus metrics are collected and exported. Default is true (enabled).
Metrics endpoint: http://localhost:9091/metrics (dev) or http://localhost:9090/metrics (prod)
Debug Logging¶
Enables detailed per-request metrics logging. When true and LOG_LEVEL=DEBUG, logs show:
Default is false (disabled).
Prompt Caching¶
# Prompt caching is DISABLED by default - set to true to enable
MADEINOZ_KNOWLEDGE_PROMPT_CACHE_ENABLED=true
Default: false (disabled)
Controls prompt caching for Gemini models via OpenRouter. When enabled, the system uses explicit cache_control markers in requests (similar to Anthropic's approach), not implicit caching. The /chat/completions endpoint supports multipart format with cache control markers.
Now Available for Gemini
Prompt caching is now functional for Gemini models on OpenRouter. The system routes Gemini models through the /chat/completions endpoint which supports multipart format with cache control markers. Set to true to enable caching and reduce costs on repeated prompts.
For detailed metrics documentation, see the Observability & Metrics reference.
Memory Decay Configuration (Feature 009)¶
Feature 009: Memory Decay Scoring
The memory decay system automatically prioritizes important memories, allows stale information to fade, and maintains sustainable graph growth. See Memory Decay & Lifecycle Management for complete user guide.
Configuration File¶
Location: config/decay-config.yaml
This YAML file controls all memory decay behavior. It is copied into the Docker container at build time.
To modify configuration:
- Edit
config/decay-config.yaml - Rebuild the Docker image:
docker build -f docker/Dockerfile -t madeinoz-knowledge-system:local . - Restart containers:
bun run server-cli stop && bun run server-cli start --dev
Decay Thresholds¶
Control when memories transition between lifecycle states:
decay:
thresholds:
dormant:
days: 30 # Days inactive before ACTIVE → DORMANT
decay_score: 0.3 # Decay score threshold for transition
archived:
days: 90 # Days inactive before DORMANT → ARCHIVED
decay_score: 0.6 # Decay score threshold for transition
expired:
days: 180 # Days inactive before ARCHIVED → EXPIRED
decay_score: 0.9 # Decay score threshold for transition
max_importance: 3 # Only expire if importance ≤ 3
Lifecycle states: - ACTIVE - Recently accessed, full relevance - DORMANT - Not accessed 30+ days, lower search priority - ARCHIVED - Not accessed 90+ days, much lower priority - EXPIRED - Marked for deletion (soft-delete) - SOFT_DELETED - Deleted but recoverable for 90 days
See Memory Decay Guide for details.
Maintenance Schedule¶
Configure automatic maintenance operations:
decay:
maintenance:
batch_size: 500 # Memories to process per batch
max_duration_minutes: 10 # Maximum maintenance run time
schedule_interval_hours: 24 # Hours between automatic runs (0 = disabled)
What maintenance does: - Recalculates decay scores for all memories - Transitions memories between lifecycle states - Soft-deletes expired memories (90-day retention) - Generates health metrics for Grafana
To disable automatic maintenance: Set schedule_interval_hours: 0
Search Weights¶
Configure how search results are ranked:
decay:
weights:
semantic: 0.60 # Vector similarity weight (0.0-1.0)
recency: 0.25 # Temporal freshness weight (0.0-1.0)
importance: 0.15 # Importance score weight (0.0-1.0)
Must sum to 1.0
Formula: weighted_score = (semantic × 0.60) + (recency × 0.25) + (importance × 0.15)
Tuning guidelines:
- Want recent stuff more? Increase recency
- Only care about accuracy? Increase semantic
- Always show important stuff? Increase importance
See Weighted Search Results for examples.
Classification Defaults¶
Configure fallback values when LLM is unavailable:
Importance levels: 1=TRIVIAL, 2=LOW, 3=MODERATE, 4=HIGH, 5=CORE Stability levels: 1=VOLATILE, 2=LOW, 3=MODERATE, 4=HIGH, 5=PERMANENT
Permanent Memory Thresholds¶
Configure which memories are exempt from decay:
permanent:
importance_threshold: 4 # Minimum importance for permanent
stability_threshold: 4 # Minimum stability for permanent
Memories with importance ≥4 AND stability ≥4 are classified as PERMANENT: - Never accumulate decay - Never transition lifecycle states - Exempt from archival and deletion - Always prioritized in search
Half-Life Configuration¶
Base decay rate (adjusted by stability factor):
How it works: - Stability 1 (VOLATILE): 0.33× half-life (60 days) - Stability 3 (MODERATE): 1.0× half-life (180 days) - Stability 5 (PERMANENT): ∞ half-life (never decays)
Higher values = slower decay. See Decay Score for details.
Retention Policy¶
Configure soft-delete retention period:
Soft-deleted memories are permanently purged after this period. Recovery only possible within the retention window.
Query Sanitization (FalkorDB Only)¶
For FalkorDB backend, special characters in group_ids and search queries are automatically sanitized to prevent Lucene query syntax errors.
Escaped characters: + - && || ! ( ) { } [ ] ^ " ~ * ? : \ /
Example:
This is automatic and transparent.
Legacy Configuration (Deprecated)¶
These variables are deprecated in favor of MADEINOZ_KNOWLEDGE_* prefixed versions:
# Old style (still supported as fallback)
OPENAI_API_KEY=sk-your-key
ANTHROPIC_API_KEY=sk-ant-your-key
# New style (preferred)
MADEINOZ_KNOWLEDGE_OPENAI_API_KEY=sk-your-key
MADEINOZ_KNOWLEDGE_ANTHROPIC_API_KEY=sk-ant-your-key
Benefits of migration:
- Isolated configuration per pack
- No conflicts with other tools
- Better organization in .env file
Configuration Examples¶
Minimal Setup (Ollama LLM + Local Embeddings)¶
# LLM - must use cloud provider due to Graphiti limitations
MADEINOZ_KNOWLEDGE_LLM_PROVIDER=openai
MADEINOZ_KNOWLEDGE_MODEL_NAME=openai/gpt-4o-mini
MADEINOZ_KNOWLEDGE_OPENAI_API_KEY=sk-or-v1-your-key
MADEINOZ_KNOWLEDGE_OPENAI_BASE_URL=https://openrouter.ai/api/v1
# Embeddings - free local Ollama
MADEINOZ_KNOWLEDGE_EMBEDDER_PROVIDER=openai
MADEINOZ_KNOWLEDGE_EMBEDDER_BASE_URL=http://host.docker.internal:11434/v1
MADEINOZ_KNOWLEDGE_EMBEDDER_MODEL=mxbai-embed-large
MADEINOZ_KNOWLEDGE_EMBEDDER_DIMENSIONS=1024
# Database
MADEINOZ_KNOWLEDGE_DATABASE_TYPE=neo4j
# Group
MADEINOZ_KNOWLEDGE_GROUP_ID=main
Premium Setup (All Cloud)¶
# LLM
MADEINOZ_KNOWLEDGE_LLM_PROVIDER=openai
MADEINOZ_KNOWLEDGE_MODEL_NAME=gpt-4o
MADEINOZ_KNOWLEDGE_OPENAI_API_KEY=sk-your-openai-key
# Embeddings
MADEINOZ_KNOWLEDGE_EMBEDDER_PROVIDER=openai
MADEINOZ_KNOWLEDGE_EMBEDDER_MODEL=text-embedding-3-small
# Database
MADEINOZ_KNOWLEDGE_DATABASE_TYPE=neo4j
# Performance
MADEINOZ_KNOWLEDGE_SEMAPHORE_LIMIT=20
Multi-Group CTI Setup¶
# LLM with special character support (Neo4j)
MADEINOZ_KNOWLEDGE_LLM_PROVIDER=openai
MADEINOZ_KNOWLEDGE_MODEL_NAME=gpt-4o
MADEINOZ_KNOWLEDGE_OPENAI_API_KEY=sk-your-key
# Embeddings
MADEINOZ_KNOWLEDGE_EMBEDDER_BASE_URL=http://host.docker.internal:11434/v1
MADEINOZ_KNOWLEDGE_EMBEDDER_MODEL=mxbai-embed-large
# Database - Neo4j for hyphenated identifiers
MADEINOZ_KNOWLEDGE_DATABASE_TYPE=neo4j
MADEINOZ_KNOWLEDGE_NEO4J_URI=bolt://neo4j:7687
# Multiple groups for CTI domains
MADEINOZ_KNOWLEDGE_GROUP_ID=main
# Create additional groups by using different group_id in workflows
# Search all groups automatically
GRAPHITI_SEARCH_ALL_GROUPS=true
Verification¶
To verify your configuration is correct:
# Check configuration is loaded
grep MADEINOZ_KNOWLEDGE ~/.claude/.env
# Verify API key is set (don't expose the value)
grep -c MADEINOZ_KNOWLEDGE_OPENAI_API_KEY ~/.claude/.env
# Test connectivity
curl http://localhost:8000/health
Changing Configuration¶
To update configuration after installation:
- Edit PAI .env file:
- Restart the server:
- Verify changes:
Troubleshooting¶
"Invalid API key"¶
- Verify key is correctly copied (no spaces, correct prefix)
- Check key has available credits/quota
- Confirm key is for the right provider
"Unknown model"¶
- Verify model name matches provider's catalog
- Check provider base URL is correct
- Confirm API key can access the model
"Connection refused"¶
- Verify
MADEINOZ_KNOWLEDGE_*_BASE_URLis correct - Check firewall allows connection to provider
- Ensure Ollama server is running (if using local embeddings)
"Rate limit exceeded"¶
- Lower
MADEINOZ_KNOWLEDGE_SEMAPHORE_LIMIT - Upgrade API tier
- Wait for rate limit window to reset
"Vector dimension mismatch"¶
- Verify
MADEINOZ_KNOWLEDGE_EMBEDDER_DIMENSIONSmatches your embedding model - Cannot change embedding models without clearing the graph
- See "Database Backend Configuration" section for model-to-dimension mapping
System Limits Summary¶
All configurable limits in one place:
| Limit | Default | Variable | Notes |
|---|---|---|---|
| Rate limit | 60 req/60s per IP | RATE_LIMIT_MAX_REQUESTS, RATE_LIMIT_WINDOW_SECONDS |
HTTP mode only |
| Concurrent LLM requests | 10 | SEMAPHORE_LIMIT |
Tune based on API tier |
| Search results (nodes) | 10 | MCP max_nodes param |
Per-request |
| Search results (facts) | 10 | MCP max_facts param |
Per-request |
| Search results (episodes) | 10 | MCP max_episodes param |
Per-request |
| Cache minimum tokens | 1024 | N/A | Requests < 1024 tokens skip caching |
| Episode body size | No limit | N/A | Bounded by LLM context window |
Content Size Guidelines¶
While there's no hard limit on episode body size, consider these guidelines:
| Content Size | Behavior |
|---|---|
| < 10 KB | Optimal - fast processing, reliable extraction |
| 10-50 KB | Good - may take longer to process |
| 50-100 KB | Acceptable - consider chunking for bulk import |
| > 100 KB | Not recommended - may hit LLM context limits or timeout |
For large documents: Use the bulk import workflow which automatically handles chunking. See Advanced Usage.
Environment Variable Precedence¶
Configuration is loaded in this order (later values override earlier):
.env.examplein pack (reference only)- PAI .env file (
~/.claude/.envor$PAI_DIR/.env) - Shell environment variables (if set directly)
Recommended: Keep all configuration in PAI .env file for consistency.