NornWeave Configuration

NornWeave is configured through environment variables. This page documents all available options.

Database Configuration

VariableDescriptionDefault
DB_DRIVERDatabase driver (sqlite or postgres)sqlite
POSTGRES_HOSTPostgreSQL hostlocalhost
POSTGRES_PORTPostgreSQL port5432
POSTGRES_DBDatabase namenornweave
POSTGRES_USERDatabase usernornweave
POSTGRES_PASSWORDDatabase passwordRequired

SQLite (Default)

SQLite is the default and requires no additional setup — perfect for getting started:

DB_DRIVER=sqlite
# Leave DATABASE_URL empty to use the default: ./nornweave.db

PostgreSQL

For production deployments, switch to PostgreSQL:

DB_DRIVER=postgres
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=nornweave
POSTGRES_USER=nornweave
POSTGRES_PASSWORD=your-secure-password

Email Provider Configuration

VariableDescriptionDefault
EMAIL_DOMAINDomain for inbox email addresses (e.g. mail.yourdomain.com)Required
EMAIL_PROVIDERProvider to use (mailgun, sendgrid, ses, resend, imap-smtp)mailgun

Mailgun

EMAIL_DOMAIN=mail.yourdomain.com
EMAIL_PROVIDER=mailgun
MAILGUN_API_KEY=your-api-key
MAILGUN_DOMAIN=mail.yourdomain.com
MAILGUN_REGION=us  # or: eu

SendGrid

EMAIL_DOMAIN=yourdomain.com
EMAIL_PROVIDER=sendgrid
SENDGRID_API_KEY=your-api-key

AWS SES

EMAIL_DOMAIN=yourdomain.com
EMAIL_PROVIDER=ses
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_REGION=us-east-1

Resend

VariableDescriptionDefault
RESEND_API_KEYResend API key for sending emailsRequired
RESEND_WEBHOOK_SECRETSvix signing secret for webhook verificationOptional
EMAIL_DOMAIN=yourdomain.resend.app
EMAIL_PROVIDER=resend
RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
RESEND_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxx  # Optional: for webhook signature verification

The RESEND_WEBHOOK_SECRET is the Svix signing secret from your Resend webhook configuration. When set, NornWeave verifies the signature on incoming webhooks to ensure they originated from Resend.

IMAP/SMTP

Use any existing mailbox. SMTP sends outbound email; IMAP polls for inbound.

VariableDescriptionDefault
SMTP_HOSTSMTP server hostnameRequired
SMTP_PORTSMTP server port587
SMTP_USERNAMESMTP auth usernameRequired
SMTP_PASSWORDSMTP auth passwordRequired
SMTP_USE_TLSUse STARTTLStrue
IMAP_HOSTIMAP server hostnameRequired
IMAP_PORTIMAP server port993
IMAP_USERNAMEIMAP auth usernameRequired
IMAP_PASSWORDIMAP auth passwordRequired
IMAP_USE_SSLUse SSL for IMAPtrue
IMAP_POLL_INTERVALSeconds between polls60
IMAP_MAILBOXMailbox folder to pollINBOX
IMAP_MARK_AS_READMark fetched emails as readtrue
IMAP_DELETE_AFTER_FETCHDelete after fetching (requires mark-as-read)false
EMAIL_DOMAIN=yourdomain.com
EMAIL_PROVIDER=imap-smtp
SMTP_HOST=smtp.yourdomain.com
SMTP_PORT=587
SMTP_USERNAME=agent@yourdomain.com
SMTP_PASSWORD=your-app-password
IMAP_HOST=imap.yourdomain.com
IMAP_PORT=993
IMAP_USERNAME=agent@yourdomain.com
IMAP_PASSWORD=your-app-password

See the IMAP/SMTP Guide for detailed setup instructions.

API Configuration

VariableDescriptionDefault
API_KEYAPI key for authentication (not yet enforced)Optional
API_HOSTHost to bind to0.0.0.0
API_PORTPort to listen on8000
LOG_LEVELLogging levelINFO

Example

# API_KEY=your-secure-api-key  # Reserved for future use; not yet enforced
API_HOST=0.0.0.0
API_PORT=8000
LOG_LEVEL=INFO

Attachment Storage Configuration

NornWeave supports multiple storage backends for email attachments. Choose the one that best fits your deployment:

VariableDescriptionDefault
NORNWEAVE_ATTACHMENT_STORAGE_BACKENDStorage backend (local, database, s3, gcs)local
NORNWEAVE_ATTACHMENT_STORAGE_PATHLocal filesystem path for attachments/var/nornweave/attachments
NORNWEAVE_ATTACHMENT_URL_EXPIRYSigned URL expiry time (seconds)3600
NORNWEAVE_ATTACHMENT_URL_SECRETSecret key for URL signingAuto-generated

Local Filesystem Storage (Default)

Store attachments on the local filesystem. Good for development and single-server deployments.

NORNWEAVE_ATTACHMENT_STORAGE_BACKEND=local
NORNWEAVE_ATTACHMENT_STORAGE_PATH=/var/nornweave/attachments

Database Storage

Store attachments as BLOBs in the database. Simple deployments without separate storage infrastructure.

NORNWEAVE_ATTACHMENT_STORAGE_BACKEND=database
Database storage is suitable for small attachments. For large files or high-volume use, consider S3 or GCS.

AWS S3 Storage

Store attachments in Amazon S3 or any S3-compatible storage (MinIO, DigitalOcean Spaces, etc.).

Requires the s3 extra:

pip install nornweave[s3]

Configuration:

NORNWEAVE_ATTACHMENT_STORAGE_BACKEND=s3
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_S3_BUCKET=nornweave-attachments
AWS_S3_REGION=us-east-1

# Optional: for S3-compatible storage (MinIO, etc.)
AWS_S3_ENDPOINT_URL=http://localhost:9000

Google Cloud Storage

Store attachments in Google Cloud Storage.

Requires the gcs extra:

pip install nornweave[gcs]

Configuration:

NORNWEAVE_ATTACHMENT_STORAGE_BACKEND=gcs
GCS_BUCKET=nornweave-attachments
GCS_PROJECT=your-project-id

# Optional: explicit credentials path
GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json

Storage Backend Comparison

BackendBest ForRequires ExtraNotes
localDevelopment, single serverNoFast, no external deps
databaseSimple deploymentsNoSmall files only
s3Production, scalable[s3]Presigned URLs
gcsGoogle Cloud deployments[gcs]Presigned URLs

LLM Thread Summarization

NornWeave can automatically generate thread summaries using your LLM provider. This allows AI agents to understand long threads by reading just the summary instead of every message.

The feature is disabled by default. To enable it, set LLM_PROVIDER to one of the supported providers and provide the API key.

VariableDescriptionDefault
LLM_PROVIDERLLM provider (openai, anthropic, or gemini)(disabled)
LLM_API_KEYAPI key for the selected providerRequired when provider is set
LLM_MODELModel override (auto-selected per provider if empty)(auto)
LLM_SUMMARY_PROMPTCustom system prompt for summarizationBuilt-in default
LLM_DAILY_TOKEN_LIMITMax tokens per day (0 = unlimited)1000000

Requires the provider’s optional dependency:

pip install nornweave[openai]    # For OpenAI (default model: gpt-4o-mini)
pip install nornweave[anthropic]  # For Anthropic (default model: claude-haiku)
pip install nornweave[gemini]     # For Gemini (default model: gemini-2.0-flash)
pip install nornweave[llm]        # All providers

Example

# Enable with OpenAI
LLM_PROVIDER=openai
LLM_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx
LLM_DAILY_TOKEN_LIMIT=500000

# Optional: custom model and prompt
LLM_MODEL=gpt-4o
LLM_SUMMARY_PROMPT="Summarize this email thread in 3 bullet points."
Summaries are generated after each new message. If the daily token limit is reached, summarization is paused until the next day (UTC). Token usage is tracked in the database and can be queried from the llm_token_usage table.

Rate Limiting

NornWeave supports global send rate limiting to protect against runaway agents or integrations exhausting provider quotas. Limits are enforced in-memory with a sliding-window counter — no Redis or external dependencies needed.

VariableDescriptionDefault
GLOBAL_SEND_RATE_LIMIT_PER_MINUTEMax outbound emails per rolling minute0 (unlimited)
GLOBAL_SEND_RATE_LIMIT_PER_HOURMax outbound emails per rolling hour0 (unlimited)

Both windows are enforced independently. When either limit is exceeded, the API returns HTTP 429 Too Many Requests with a Retry-After header (in seconds) so callers know when to retry.

Examples

# Cap at 10 emails per minute, 200 per hour
GLOBAL_SEND_RATE_LIMIT_PER_MINUTE=10
GLOBAL_SEND_RATE_LIMIT_PER_HOUR=200

# Only cap per hour (no per-minute limit)
GLOBAL_SEND_RATE_LIMIT_PER_MINUTE=0
GLOBAL_SEND_RATE_LIMIT_PER_HOUR=500
Rate-limit counters are in-memory and reset on process restart. Only successfully sent emails count against the limit — domain-filtered or failed sends do not. Rejected requests are logged at WARNING level for observability.

Domain Filtering (Allow/Blocklists)

NornWeave supports domain-level allow/blocklists for both inbound (receiving) and outbound (sending) email. Use these to restrict which external domains your instance interacts with.

Each variable accepts a comma-separated list of regex patterns (Python re syntax). Patterns are matched against the full domain using re.fullmatch (no partial matches).

VariableDirectionSemanticsDefault
INBOUND_DOMAIN_ALLOWLISTInboundSender domain must match at least one pattern(empty — allow all)
INBOUND_DOMAIN_BLOCKLISTInboundSender domain rejected if it matches any pattern(empty — block none)
OUTBOUND_DOMAIN_ALLOWLISTOutboundRecipient domain must match at least one pattern(empty — allow all)
OUTBOUND_DOMAIN_BLOCKLISTOutboundRecipient domain rejected if it matches any pattern(empty — block none)

Evaluation order: Blocklist is checked first. If a domain matches the blocklist it is rejected, regardless of the allowlist. If the allowlist is non-empty, only matching domains pass.

Examples

# Only accept inbound email from your own domain
INBOUND_DOMAIN_ALLOWLIST=(.*\.)?yourcompany\.com

# Block known spam domains from inbound
INBOUND_DOMAIN_BLOCKLIST=spam\.com,junk\.org

# Allow sending only to specific partners
OUTBOUND_DOMAIN_ALLOWLIST=partner\.com,client\.org

# Block a subdomain while allowing the parent
INBOUND_DOMAIN_ALLOWLIST=(.*\.)?example\.com
INBOUND_DOMAIN_BLOCKLIST=noreply\.example\.com
Patterns use Python regex syntax. Escape dots with \. for literal matching. Use (.*\.)?example\.com to match a domain and all its subdomains. Invalid patterns cause a startup error.

MCP Server Configuration

The MCP server connects AI agents to NornWeave. Configure it using environment variables:

VariableDescriptionDefault
NORNWEAVE_API_URLNornWeave REST API base URLhttp://localhost:8000
NORNWEAVE_API_KEYAPI key for authentication(none)
NORNWEAVE_MCP_HOSTHost to bind MCP server (SSE/HTTP)0.0.0.0
NORNWEAVE_MCP_PORTPort for MCP server (SSE/HTTP)3000

Example

# MCP server configuration
NORNWEAVE_API_URL=http://localhost:8000
NORNWEAVE_API_KEY=your-api-key
NORNWEAVE_MCP_HOST=0.0.0.0
NORNWEAVE_MCP_PORT=3000

CLI Options

The MCP server also accepts command-line options:

nornweave mcp --help

Options:
  --transport [stdio|sse|http]  MCP transport type [default: stdio]
  --host TEXT                   Host to bind (SSE/HTTP) [default: 0.0.0.0]
  --port INTEGER                Port to listen (SSE/HTTP) [default: 3000]
  --api-url TEXT                NornWeave API URL [default: http://localhost:8000]

Complete Example

Here’s a complete .env file:

# Database (SQLite is the default — no config needed for quickstart)
# For production, switch to PostgreSQL:
# DB_DRIVER=postgres
# POSTGRES_HOST=postgres
# POSTGRES_PORT=5432
# POSTGRES_DB=nornweave
# POSTGRES_USER=nornweave
# POSTGRES_PASSWORD=super-secret-password

# Email Domain (used to construct inbox addresses: username@EMAIL_DOMAIN)
EMAIL_DOMAIN=mail.example.com

# Email Provider (Mailgun)
EMAIL_PROVIDER=mailgun
MAILGUN_API_KEY=key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MAILGUN_DOMAIN=mail.example.com
MAILGUN_REGION=us

# API
# API_KEY=nw-xxxxxxxxxxxxxxxxxxxxxxxxxxxx  # Not yet enforced
API_HOST=0.0.0.0
API_PORT=8000
LOG_LEVEL=INFO

# Attachment Storage (S3 example)
NORNWEAVE_ATTACHMENT_STORAGE_BACKEND=s3
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
AWS_S3_BUCKET=nornweave-attachments
AWS_S3_REGION=us-east-1

# MCP Server
NORNWEAVE_API_URL=http://localhost:8000
NORNWEAVE_API_KEY=nw-xxxxxxxxxxxxxxxxxxxxxxxxxxxx

# LLM Thread Summarization (optional)
LLM_PROVIDER=openai
LLM_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
LLM_DAILY_TOKEN_LIMIT=1000000

Next Steps