Doramagic Project Pack · Human Manual
statewave
Related topics: System Architecture, Getting Started
Overview - What is Statewave?
Related topics: System Architecture, Getting Started
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: System Architecture, Getting Started
Overview - What is Statewave?
Statewave is a self-hosted memory infrastructure for AI agents. It enables AI systems to store, retrieve, compile, and reason over long-term contextual information across conversations and sessions.
Core Concept
Statewave solves the memory problem for AI agents by providing:
- Episode Ingestion — Capture events, conversations, and real-world signals as structured memory units
- Memory Compilation — Transform raw episodes into refined, actionable memories using LLM or heuristic approaches
- Context Assembly — Retrieve and rank relevant memories within token budgets for inference
- Temporal Reasoning — Track state changes and resolution status over time
The system operates as a REST API service that agents and applications query to build persistent, evolving memory without hand-writing custom storage and retrieval logic for each use case.
Architecture Overview
graph TD
subgraph "Sources"
MCP[MCP Server]
GH[GitHub]
MD[Markdown Docs]
SL[Slack]
APP[Application]
end
subgraph "Statewave Core"
INGEST[Ingestion API]
COMPILE[Memory Compiler]
SEARCH[Search API]
CONTEXT[Context Assembly]
end
subgraph "Storage"
PG[(PostgreSQL<br/>+ pgvector)]
end
MCP --> INGEST
GH --> INGEST
MD --> INGEST
SL --> INGEST
APP --> INGEST
INGEST --> PG
COMPILE --> PG
SEARCH --> PG
CONTEXT --> PG
APP --> SEARCH
APP --> CONTEXTKey Components
| Component | Description |
|---|---|
| Episodes | Raw, append-only event records captured from sources (conversations, issues, documents, etc.) |
| Memories | Compiled, refined knowledge derived from episodes through LLM or heuristic processing |
| Subjects | Logical namespaces grouping episodes and memories (typically one per user, customer, or agent persona) |
| Resolutions | Tracking of issue/session completion state per subject |
| Context Bundle | Ranked, token-bounded response assembled from relevant memories for inference |
Data Flow
graph LR
A[Source Event] --> B[POST /v1/episodes]
B --> C[(Episode Store)]
C --> D[POST /v1/memories/compile]
D --> E[(Memory Store)]
E --> F[GET /v1/memories/search]
F --> G[POST /v1/context]
G --> H[Ranked Context Bundle]API Reference
Core Endpoints
| Method | Path | Purpose |
|---|---|---|
POST | /v1/episodes | Ingest a single episode (append-only) |
POST | /v1/episodes/batch | Ingest up to 100 episodes at once |
POST | /v1/memories/compile | Compile memories from episodes (idempotent) |
GET | /v1/memories/search | Search by kind, text, or semantic similarity |
POST | /v1/context | Assemble ranked, token-bounded context bundle |
Subject Management
| Method | Path | Purpose |
|---|---|---|
GET | /v1/timeline | Chronological subject timeline |
GET | /v1/subjects | List known subjects with episode/memory counts |
DELETE | /v1/subjects/{id} | Permanently delete all data for a subject |
GET | /v1/subjects/{id}/health | Customer health score with explainable factors |
GET | /v1/subjects/{id}/sla | SLA metrics — response time, resolution time, breaches |
Resolution Tracking
| Method | Path | Purpose |
|---|---|---|
POST | /v1/resolutions | Track issue resolution state per session |
GET | /v1/resolutions | List resolutions for a subject |
Additional Endpoints
| Method | Path | Purpose |
|---|---|---|
POST | /v1/handoff | Generate compact handoff context pack |
GET | /healthz or /health | Liveness check |
GET | /readyz or /ready | Readiness check |
Sources: README.md:26-49
Connectors
Statewave is not limited to live chat transcripts. Connectors feed real-world events into Statewave as episodes, enabling agents to build memory from diverse sources.
| Source | Memory Shape | Status |
|---|---|---|
| MCP server | Copilot / Claude / Cursor / agent memory | ✅ Shipped |
| GitHub | Issues, PRs, reviews, releases → repo memory | ✅ Shipped |
| Markdown | Local docs, ADRs, RFCs → decision memory | ✅ Shipped |
| Slack | Channel messages → conversation memory | ✅ Shipped |
Sources: README.md:53-60
Deployment
Docker Deployment
Statewave is deployed as a containerized service using Docker Compose:
services:
app:
image: statewavedev/statewave:latest
ports: ["8100:8100"]
environment:
STATEWAVE_DATABASE_URL: postgresql+asyncpg://statewave:statewave@db:5432/statewave
STATEWAVE_LITELLM_API_KEY: sk-...
depends_on:
db:
condition: service_healthy
docker compose up -d
curl http://localhost:8100/healthz
Sources: DOCKER.md
Environment Configuration
| Variable | Default | Description |
|---|---|---|
STATEWAVE_DATABASE_URL | — | PostgreSQL connection string (required) |
STATEWAVE_LITELLM_API_KEY | — | LiteLLM API key for LLM compilation |
STATEWAVE_LOG_LEVEL | INFO | Logging verbosity |
STATEWAVE_MAX_CONTEXT_TOKENS | 4000 | Default token budget for context assembly |
STATEWAVE_CORS_ORIGINS | ["*"] | Allowed CORS origins |
STATEWAVE_RATE_LIMIT | 0 | Requests/min/IP (0 = disabled) |
STATEWAVE_WEBHOOK_URL | — | Webhook callback URL |
STATEWAVE_TENANT_HEADER | X-Tenant-ID | Header for multi-tenant isolation |
Sources: README.md:93-107
Multi-Tenant Support
Statewave supports multi-tenant deployments through application-layer isolation:
- Tenant Header:
X-Tenant-IDheader identifies the tenant (configurable viaSTATEWAVE_TENANT_HEADER) - Query-Scoped Isolation: Data isolation is enforced at the query layer
- Per-Tenant Configuration: Policy bundles and receipts support tenant-specific settings
Sources: README.md:100-107
Documentation System
Statewave includes a documentation-grounded memory system:
- Curated documentation sections are chunked at heading boundaries
- Each section becomes an episode with
source="statewave-docs",type="doc_section" - Episodes carry a deterministic content hash for change detection
- A bundled starter pack provides 276 episodes and 364 compiled memories out of the box
Sources: scripts/docs_loader.py Sources: server/starter_packs/statewave-support-agent/manifest.json
Evaluation Framework
The repository includes an evaluation framework for testing docs-grounded retrieval:
@dataclass
class Question:
task: str
expected_doc_paths: list[str]
expected_terms: list[str]
Sample evaluation questions verify that the system correctly surfaces documentation for queries about deployment, compilation modes, hardware requirements, and API contracts.
Sources: scripts/eval/eval_docs_support.py
Starter Packs
Statewave ships with pre-built starter packs:
| Pack | Description |
|---|---|
statewave-support-agent | Full Statewave Support docs pack with 276 episodes and 364 memories |
demo-support-agent | Support agent persona |
demo-coding-assistant | Coding assistant persona |
demo-sales-copilot | Sales copilot persona |
demo-devops-agent | DevOps agent persona |
demo-research-assistant | Research assistant persona |
Sources: server/starter_packs/statewave-support-agent/manifest.json Sources: scripts/build_demo_packs.py
Health Monitoring
Statewave provides subject-level health monitoring:
- Health Score: Aggregated customer health with explainable factors
- SLA Metrics: Response time, resolution time, and breach tracking
- Snapshot Restore: Restore subject state from snapshots with timestamp shifting
Sources: README.md:46-47 Sources: server/services/snapshots.py
Getting Started
``bash docker compose up db -d python -m venv .venv && source .venv/bin/activate pip install -e ".[dev,llm]" alembic upgrade head uvicorn server.main:app --host 0.0.0.0 --port 8100 ``
- Quick Start:
```bash # Unit tests (no DB required) pytest tests/test_*.py -v
- Run Tests:
# Integration tests (requires Postgres) PGPASSWORD=statewave createdb -h localhost -U statewave statewave_test pytest tests/integration/ -v ```
Sources: CONTRIBUTING.md Sources: README.md:11-19
Current Limitations
| Limitation | Description |
|---|---|
| Rate limiting per-IP | Distributed (Postgres-backed), but keyed by IP only, not per-tenant or per-API-key |
| Multi-tenant app-layer | Query-scoped data isolation + per-tenant config, but no Postgres RLS |
Sources: README.md:117-122
Repository Structure
| Repository | Purpose |
|---|---|
| statewave | Backend API, server, core |
| statewave-py | Python SDK (pip install statewave) |
| statewave-ts | TypeScript SDK (npm install @statewavedev/sdk) |
| statewave-connectors | Connectors (GitHub, Markdown, MCP, etc.) |
| statewave-docs | Documentation |
| statewave-examples | Working code examples |
| statewave-web | Marketing site + embedded demo |
| statewave-admin | Admin dashboard |
Sources: SUPPORT.md:73-83
Sources: README.md:26-49
Getting Started
Related topics: Overview - What is Statewave?, API Endpoints Reference
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview - What is Statewave?, API Endpoints Reference
Getting Started
Overview
The Getting Started guide provides developers and operators with the essential knowledge to install, configure, and run Statewave — an agent memory system that captures, compiles, and retrieves episodic and semantic memory for AI agents. The guide covers three primary deployment paths: Docker Compose for local development, Helm charts for Kubernetes production environments, and Python packages for programmatic integration.
Statewave operates as an append-only memory store where episodes represent raw events (chat messages, commits, support tickets) and memories are compiled, high-confidence knowledge units derived from episodes through LLM or heuristic processing. The system enables agents to assemble token-bounded context bundles for RAG (Retrieval-Augmented Generation) workflows.
Sources: README.md:1-50
System Architecture
graph TD
subgraph "Ingestion Layer"
E[Episodes] --> B[Batch Ingest]
E --> S[Single Ingest]
end
subgraph "Compilation Layer"
S --> COMP[Memory Compiler]
B --> COMP
COMP -->|LLM or Heuristic| M[Memories]
end
subgraph "Retrieval Layer"
M --> CX[Context Assembler]
Q[Query] --> CX
CX --> CB[Token-Bounded Context]
end
subgraph "Storage Layer"
M --> PG[(PostgreSQL)]
E --> PG
end
subgraph "Connectors"
MCP[MCP Server]
GH[GitHub]
MD[Markdown]
SL[Slack]
MCP --> E
GH --> E
MD --> E
SL --> E
endPrerequisites
Before beginning the installation, ensure the following requirements are met:
| Requirement | Minimum Version | Purpose |
|---|---|---|
| Python | 3.11+ | SDK and CLI usage |
| Docker | 24.0+ | Container runtime |
| Docker Compose | 2.20+ | Multi-container orchestration |
| PostgreSQL | 15+ | Primary data store |
| Kubernetes | 1.28+ | Production deployment |
| Helm | 3.14+ | Chart package manager |
Sources: DOCKER.md:1-30
Installation Methods
Quick Start with Docker Compose
The fastest path to a running Statewave instance uses Docker Compose:
# docker-compose.yml
services:
api:
image: statewavedev/statewave:latest
ports: ["8100:8100"]
environment:
STATEWAVE_DATABASE_URL: postgresql+asyncpg://statewave:statewave@db:5432/statewave
STATEWAVE_LITELLM_API_KEY: sk-...
depends_on:
db:
condition: service_healthy
volumes:
pgdata:
Sources: DOCKER.md:40-55
Execute the following commands to start Statewave:
# Start the stack
docker compose up -d
# Verify health
curl http://localhost:8100/healthz
Pinning a Specific Version
Production deployments should pin to a specific version:
STATEWAVE_VERSION=0.7.0 docker compose up -d
Available tagging conventions:
| Tag Pattern | Meaning |
|---|---|
latest | Tip of main branch |
X.Y.Z | Specific semver release |
X.Y | Latest in the minor line |
X | Latest in the major line |
sha-<7> | Specific git commit |
Sources: DOCKER.md:70-85
Verify Build Attestation
For supply chain security, verify the container image:
gh attestation verify \
oci://docker.io/statewavedev/statewave:latest \
--owner smaramwbc
Sources: DOCKER.md:90-95
Environment Configuration
Statewave uses environment variables for all configuration. The following table documents the complete set:
| Variable | Default | Description |
|---|---|---|
STATEWAVE_DATABASE_URL | — | PostgreSQL connection string (required) |
STATEWAVE_LITELLM_API_KEY | — | LLM provider API key |
STATEWAVE_EMBEDDING_PROVIDER | litellm | Embedding backend (litellm, openai, stub) |
STATEWAVE_COMPILER_TYPE | llm | Compilation method (llm or heuristic) |
STATEWAVE_AUTH_API_KEY | — | Static API key for authentication |
STATEWAVE_PORT | 8100 | HTTP server port |
STATEWAVE_LOG_LEVEL | INFO | Logging verbosity |
STATEWAVE_RATE_LIMIT | 0 | Requests per minute per IP |
STATEWAVE_RATE_LIMIT_STRATEGY | distributed | distributed (Postgres) or memory |
STATEWAVE_WEBHOOK_URL | — | Callback URL for async events |
STATEWAVE_WEBHOOK_TIMEOUT | 5.0 | Webhook HTTP timeout (seconds) |
STATEWAVE_TENANT_HEADER | X-Tenant-ID | Multi-tenant isolation header |
STATEWAVE_REQUIRE_TENANT | false | Enforce tenant header presence |
STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS | 4000 | Token budget for context assembly |
STATEWAVE_CORS_ORIGINS | ["*"] | Allowed CORS origins |
Sources: README.md:180-200
API Endpoints
Health and Readiness
| Endpoint | Method | Purpose |
|---|---|---|
/healthz | GET | Liveness check |
/health | GET | Liveness check (alias) |
/readyz | GET | Readiness check |
/ready | GET | Readiness check (alias) |
Core Memory Operations
| Method | Path | Description |
|---|---|---|
POST | /v1/episodes | Ingest a single episode (append-only) |
POST | /v1/episodes/batch | Ingest up to 100 episodes at once |
POST | /v1/memories/compile | Compile memories from episodes (idempotent) |
GET | /v1/memories/search | Search by kind, text, or semantic similarity |
POST | /v1/context | Assemble ranked, token-bounded context bundle |
GET | /v1/timeline | Chronological subject timeline |
GET | /v1/subjects | List known subjects with episode/memory counts |
DELETE | /v1/subjects/{id} | Permanently delete all data for a subject |
Advanced Operations
| Method | Path | Description |
|---|---|---|
POST | /v1/resolutions | Track issue resolution state per session |
GET | /v1/resolutions | List resolutions for a subject |
POST | /v1/handoff | Generate compact handoff context pack |
GET | /v1/subjects/{id}/health | Customer health score with explainable factors |
GET | /v1/subjects/{id}/sla | SLA metrics — response time, resolution time, breaches |
Sources: README.md:30-60
Connectors Ecosystem
Statewave supports external data sources through modular connectors:
# Install connectors individually
npm install @statewavedev/connectors-github
npm install @statewavedev/connectors-markdown
npm install @statewavedev/connectors-slack
npm install @statewavedev/connectors-n8n
npm install @statewavedev/connectors-zapier
npm install @statewavedev/mcp-server
# Meta-package for all connectors
npm install @statewavedev/connectors
Available connectors and their status:
| Source | Memory Shape | Status |
|---|---|---|
| MCP Server | Copilot/Claude/Cursor/agent memory | ✅ Shipped |
| GitHub | Issues, PRs, reviews, releases → repo memory | ✅ Shipped |
| Markdown | Local docs, ADRs, RFCs → decision memory | ✅ Shipped |
| Slack | Channel conversations | ✅ Shipped |
Sources: README.md:250-280
Connector Usage Examples
# Sync GitHub data (dry-run first)
statewave-connectors sync github \
--repo smaramwbc/statewave \
--subject repo:smaramwbc/statewave \
--dry-run
# Sync Markdown documentation
statewave-connectors sync markdown \
--path ./docs \
--subject repo:smaramwbc/statewave \
--dry-run
# Start MCP server
statewave-connectors mcp start
Kubernetes Deployment
For production environments, use the Helm chart:
helm install statewave ./helm/statewave \
--set database.url='postgresql+asyncpg://...' \
--set llm.apiKey='sk-...' \
--set auth.apiKey='replace-me'
The Helm chart runs a pre-install Job (alembic upgrade head) before any API pod admits traffic. Upgrades repeat migration as a pre-upgrade Job.
Sources: helm/statewave/README.md:1-40
Helm Configuration Reference
| Value | Default | Notes |
|---|---|---|
image.tag | "" | Falls back to Chart.AppVersion |
replicaCount | 1 | Check connection-budget math before raising |
database.url / database.existingSecret | — | One is required |
compiler.type | llm | heuristic for demo/no-LLM mode |
embedding.provider | litellm | stub for demo/no-embedding mode |
llm.apiKey / llm.existingSecret | — | Required when compiler.type=llm |
auth.apiKey / auth.existingSecret | — | Strongly recommended in production |
Sources: helm/statewave/README.md:50-70
Running Tests
Statewave includes unit tests (no database required) and integration tests (requires PostgreSQL):
# Unit tests
pytest tests/test_*.py -v
# Integration tests
PGPASSWORD=statewave createdb -h localhost -U statewave statewave_test
pytest tests/integration/ -v
# All tests
pytest tests/ -v
Sources: README.md:210-220
Bootstrap Documentation Pack
After initial deployment, bootstrap the documentation memory pack for a self-hosted support agent:
python -m scripts.bootstrap_docs_pack [--docs-path PATH] [--purge] [--dry-run]
Environment Variables for Bootstrap
| Variable | Default | Purpose |
|---|---|---|
STATEWAVE_URL | http://localhost:8100 | API base URL |
STATEWAVE_API_KEY | — | Authentication key |
STATEWAVE_DOCS_PATH | — | Override documentation path |
Bootstrap Behavior
graph LR
A[Read statewave-docs corpus] --> B[Ingest each section as Episode]
B --> C[Compile Episodes to Memories]
C --> D[Assemble docs-grounded Knowledge Base]
D --> E[Support Agent queries via POST /v1/context]
F[--purge] -.->|Wipe and rebuild| A
G[--dry-run] -.->|No ingestion| AThe bootstrap process is idempotent. By default, it fails if the subject already has episodes. Re-run with --purge to wipe and rebuild from scratch.
Sources: scripts/bootstrap_docs_pack.py:1-50
Seed Demo Subjects
For development and testing, seed demo subjects with sample data:
python -m scripts.seed_demo_subjects [--dry-run]
This creates sample episodes and memories that reference each other, enabling verification of the compilation and retrieval pipeline.
Sources: scripts/seed_demo_subjects.py:1-60
Current Limitations
Statewave v0.8.0 has known limitations:
| Limitation | Description |
|---|---|
| Rate limiting | Per-IP only — not yet per-tenant or per-API-key |
| Multi-tenant isolation | App-layer query-scoped isolation — no Postgres RLS yet |
Sources: README.md:225-235
Next Steps
| Resource | Purpose |
|---|---|
| API v1 contract | Complete API reference |
| Connector docs | Connector configuration |
| Horizontal Scaling Guide | Production scaling guidance |
| Architecture documentation | Context ranking internals |
Sources: README.md:1-50
System Architecture
Related topics: Overview - What is Statewave?, Database Schema & Migrations, Compilation Services
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview - What is Statewave?, Database Schema & Migrations, Compilation Services
System Architecture
Statewave is an AI agent memory system designed to ingest real-world events as episodes, compile them into structured memories, and retrieve ranked, token-bounded context for agentic workflows. The system follows a layered architecture with clear separation between API handling, business logic services, data persistence, and external connectors.
High-Level Architecture Overview
graph TD
subgraph "External Clients"
A[Agents / Applications]
B[Connectors: GitHub, Slack, MCP]
C[SDK Clients]
end
subgraph "API Layer"
D[FastAPI Application]
E[Endpoint Routes]
F[Middleware / Auth]
end
subgraph "Service Layer"
G[Episode Service]
H[Memory Service]
I[Compiler Service]
J[Search Service]
K[Snapshot Service]
end
subgraph "Data Layer"
L[(PostgreSQL)]
M[(Vector Embeddings)]
N[Starter Packs]
end
A --> D
B --> D
C --> D
D --> F
F --> E
E --> G
E --> H
E --> I
E --> J
E --> K
G --> L
H --> L
H --> M
I --> L
J --> M
K --> L
K --> NCore Data Models
Episode
An Episode represents a discrete unit of experience — a chat message, a support ticket update, a GitHub issue event, or a documentation section. Episodes are the atomic ingestion unit in Statewave.
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
subject_id | UUID | Parent subject this episode belongs to |
session_id | str | Session context identifier |
type | str | Kind of episode (e.g., doc_section, chat, ticket) |
source | str | Origin system (e.g., github, slack, statewave-docs) |
content | str | Raw content body |
metadata_ | dict | Arbitrary key-value metadata |
provenance | dict | Source-specific tracking (e.g., content_hash for docs) |
created_at | datetime | Ingestion timestamp |
valid_from | datetime | Temporal anchor for memory derivation |
Sources: server/db/tables.py
Memory
A Memory is a compiled, structured artifact extracted from one or more episodes. Memories have temporal validity windows, confidence scores, and lineage tracking.
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
subject_id | UUID | Parent subject |
kind | str | Memory category (e.g., episode_summary, profile_fact, decision) |
content | str | Compiled memory content |
summary | str | Short summary (max 200 chars) |
confidence | float | Confidence score (0.0-1.0) |
valid_from | datetime | Start of validity window |
valid_to | datetime | End of validity window (nullable) |
source_episode_ids | list[UUID] | Episodes this memory was derived from |
status | str | Memory lifecycle state |
sensitivity_labels | list[str] | Optional sensitivity classification |
Sources: server/api/timeline.py
Subject
A Subject is the central entity in Statewave — a persona, entity, or concept that accumulates memory over time.
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
tenant_id | str | Multi-tenant isolation key |
name | str | Human-readable name |
type_ | str | Subject type classification |
metadata_ | dict | Arbitrary metadata |
embedding | vector | Semantic embedding for similarity search |
Sources: server/db/tables.py
API Layer
REST API v1
The API is served by FastAPI on port 8100 by default and exposes OpenAPI documentation at /docs and ReDoc at /redoc.
graph LR
A[Client] --> B["POST /v1/episodes"]
A --> C["POST /v1/episodes/batch"]
A --> D["POST /v1/memories/compile"]
A --> E["GET /v1/memories/search"]
A --> F["POST /v1/context"]
A --> G["GET /v1/timeline"]
A --> H["GET /v1/subjects"]
A --> I["DELETE /v1/subjects/{id}"]
A --> J["POST /v1/resolutions"]
A --> K["POST /v1/handoff"]
A --> L["GET /v1/subjects/{id}/health"]
A --> M["GET /v1/subjects/{id}/sla"]Core Endpoints
| Method | Path | Purpose |
|---|---|---|
POST | /v1/episodes | Ingest a single episode (append-only) |
POST | /v1/episodes/batch | Ingest up to 100 episodes at once |
POST | /v1/memories/compile | Compile memories from episodes (idempotent) |
GET | /v1/memories/search | Search by kind, text, or semantic similarity |
POST | /v1/context | Assemble ranked, token-bounded context bundle |
GET | /v1/timeline | Chronological subject timeline |
GET | /v1/subjects | List known subjects with episode/memory counts |
DELETE | /v1/subjects/{id} | Permanently delete all data for a subject |
POST | /v1/resolutions | Track issue resolution state per session |
GET | /v1/resolutions | List resolutions for a subject |
POST | /v1/handoff | Generate compact handoff context pack |
Sources: README.md
Health Endpoints
| Endpoint | Purpose |
|---|---|
GET /healthz or GET /health | Liveness check |
GET /readyz or GET /ready | Readiness check |
Sources: README.md
Service Layer
Compiler Service
The compiler extracts memories from episodes. Statewave supports two compilation modes:
| Mode | Description | Use Case |
|---|---|---|
llm | Uses an LLM provider (via LiteLLM) to extract structured memories | Production with semantic understanding |
heuristic | Rule-based extraction for basic facts and summaries | Demo mode, no API key required |
#### Heuristic Compiler
The heuristic compiler extracts two memory kinds from episodes:
- episode_summary: A 500-character truncation of the episode text with 0.8 confidence
- profile_fact: Extracted profile facts with 0.6 confidence
MemoryRow(
kind="episode_summary",
content=text[:500],
summary=text[:200],
confidence=0.8,
valid_from=ep_valid_from,
valid_to=compute_valid_to("episode_summary", ep_valid_from, ttl),
source_episode_ids=[ep.id],
status="active",
)
Sources: server/services/compilers/heuristic.py
#### Temporal Anchoring
The compiler determines episode temporal anchors with the following priority:
payload.event_time— Explicit client override for historical data replaypayload.messages[0].timestamp— First message timestamp in chat-shaped payloads (used by LoCoMo, Slack, Zendesk connectors)created_at— Fallback to ingestion timestamp
graph TD
A[Episode Ingestion] --> B{event_time present?}
B -->|Yes| C[Use event_time]
B -->|No| D{messages timestamp present?}
D -->|Yes| E[Use messages[0].timestamp]
D -->|No| F[Use created_at]Sources: server/services/compilers/heuristic.py
Snapshot Service
Snapshots enable point-in-time restoration of subject data, including episodes, memories, and resolutions.
| Feature | Description |
|---|---|
| Create Snapshot | Captures all subject data with version metadata |
| Restore Snapshot | Clones data with optional time-shifting for temporal consistency |
| Metadata Tracking | Records restored_from_snapshot in restored records |
snapshot = SubjectSnapshotRow(
name=name,
version=version,
source_subject_id=snapshot_subject,
episode_count=len(eps),
memory_count=len(mems),
metadata_=metadata or {},
)
Sources: server/services/snapshots.py
Timeline Service
The timeline service provides chronological event merging across episodes and resolutions within a session.
graph TD
A[Session Request] --> B[Fetch Episodes]
A --> C[Fetch Resolutions]
B --> D[Merge Events Chronologically]
C --> D
D --> E[TimelineResponse]
E --> F[TimelineEpisodeEvent]
E --> G[TimelineResolutionEvent]
F --> H[id]
F --> I[source]
F --> J[type]
F --> K[payload]
F --> L[created_at]
F --> M[citing_memory_count]
G --> N[resolved_at]
G --> O[status]#### Timeline Response Model
| Field | Type | Description |
|---|---|---|
session_id | str | Session identifier |
status | str | Overall session status |
first_message_at | str | Timestamp of first user message |
first_response_at | str | Timestamp of first agent response |
resolved_at | str | Resolution timestamp |
first_response_seconds | float | Time to first response |
resolution_seconds | float | Total resolution time |
first_response_breached | bool | SLA breach indicator |
resolution_breached | bool | Resolution SLA breach indicator |
episode_count | int | Total episodes in session |
events | list | Chronologically merged events |
Sources: server/api/admin.py
Handoff Service
The handoff endpoint generates compact context packs for transferring conversation context between agents or sessions.
| Parameter | Type | Required | Description |
|---|---|---|---|
subject_id | UUID | Yes | Target subject |
session_id | str | No | Optional session context |
reason | str | No | Handoff reason |
max_tokens | int | No | Token budget for context |
caller_id | str | Conditional | Required when tenant config mandates it |
caller_type | str | Conditional | Required when tenant config mandates it |
Sources: server/api/handoff.py
Data Layer
Database Schema
Statewave uses PostgreSQL with SQLAlchemy async for data persistence. Key tables:
| Table | Purpose |
|---|---|
subjects | Central entity registry with embeddings |
episodes | Raw experience ingestion records |
memories | Compiled memory artifacts with validity windows |
resolutions | Issue resolution tracking per session |
policy_bundles | Immutable policy YAML bundles |
policy_receipts | Compliance receipts for policy enforcement |
subject_snapshots | Point-in-time backup metadata |
Multi-Tenancy
Multi-tenant isolation is implemented at the application layer:
| Configuration | Default | Description |
|---|---|---|
STATEWAVE_TENANT_HEADER | X-Tenant-ID | Header for multi-tenant isolation |
STATEWAVE_REQUIRE_TENANT | false | Reject requests without tenant header |
Sources: README.md
Current Limitation: Multi-tenant isolation is query-scoped (application-layer) with no PostgreSQL Row-Level Security (RLS) enforcement.
Connectors
Connectors feed external data sources into Statewave as episodes without requiring custom ingestion code.
graph LR
A[GitHub] -->|Issues, PRs, Reviews| B[Connector]
C[Slack] -->|Messages, Threads| B
D[MCP Server] -->|Agent Memory| B
E[Markdown] -->|Docs, RFCs| B
F[n8n] -->|Workflow Events| B
G[Zapier] -->|Automation Triggers| B
B --> H[Episodes]
H --> I[Statewave API]Available Connectors
| Source | Memory Shape | Status |
|---|---|---|
| MCP Server | Copilot / Claude / Cursor / agent memory | ✅ Shipped |
| GitHub | Issues, PRs, reviews, releases → repo memory | ✅ Shipped |
| Markdown | Local docs, ADRs, RFCs → decision memory | ✅ Shipped |
| Slack | Channel messages → conversation memory | ✅ Shipped |
| n8n | Workflow events → process memory | ✅ Shipped |
| Zapier | Automation triggers → event memory | ✅ Shipped |
Sources: README.md
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
STATEWAVE_DATABASE_URL | — | PostgreSQL connection string (required) |
STATEWAVE_LITELLM_API_KEY | — | LiteLLM API key for LLM compilation |
STATEWAVE_EMBEDDING_PROVIDER | litellm | Embedding provider |
STATEWAVE_COMPILER_TYPE | llm | Compiler mode: llm or heuristic |
STATEWAVE_API_KEY | — | API authentication key |
STATEWAVE_PORT | 8100 | HTTP server port |
STATEWAVE_RATE_LIMIT | 0 | Requests/min/IP (0 = disabled) |
STATEWAVE_RATE_LIMIT_STRATEGY | distributed | distributed (Postgres) or memory |
STATEWAVE_WEBHOOK_URL | — | Webhook callback URL |
STATEWAVE_WEBHOOK_TIMEOUT | 5.0 | Webhook HTTP timeout (seconds) |
STATEWAVE_TENANT_HEADER | X-Tenant-ID | Tenant isolation header |
STATEWAVE_REQUIRE_TENANT | false | Reject requests without tenant |
STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS | 4000 | Default token budget for context |
STATEWAVE_CORS_ORIGINS | ["*"] | Allowed CORS origins |
Sources: README.md
Deployment
Docker Deployment
Statewave is distributed as a Docker image and can be deployed using Docker Compose.
services:
statewave:
image: statewavedev/statewave:latest
ports: ["8100:8100"]
environment:
STATEWAVE_DATABASE_URL: postgresql+asyncpg://statewave:statewave@db:5432/statewave
STATEWAVE_LITELLM_API_KEY: sk-...
depends_on:
db:
condition: service_healthy
#### Image Tags
| Tag | Meaning |
|---|---|
latest | Tip of main |
X.Y.Z | Semver release |
X.Y | Latest in the minor line |
X | Latest in the major line |
sha-<7> | Specific commit |
Sources: DOCKER.md
Helm Chart
Kubernetes deployment is supported via Helm:
| Value | Default | Notes |
|---|---|---|
image.tag | "" | Falls back to Chart.AppVersion |
replicaCount | 1 | See horizontal scaling guide |
database.url | — | Required |
database.existingSecret | — | Alternative to url |
compiler.type | llm | heuristic for demo mode |
embedding.provider | litellm | stub for no-embedding mode |
llm.apiKey | — | Required for LLM mode |
auth.apiKey | — | Recommended for production |
Sources: helm/statewave/README.md
Testing
Test Execution
# Unit tests (no DB required)
pytest tests/test_*.py -v
# Integration tests (requires Postgres)
PGPASSWORD=statewave createdb -h localhost -U statewave statewave_test
pytest tests/integration/ -v
# All tests
pytest tests/ -v
Sources: README.md
Sources: server/db/tables.py
Database Schema & Migrations
Related topics: System Architecture, Governance - Receipts & Policy Engine
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: System Architecture, Governance - Receipts & Policy Engine
Database Schema & Migrations
Overview
The Statewave application uses PostgreSQL as its primary data store, managed through SQLAlchemy ORM with Alembic for schema migrations. The database layer provides persistent storage for the core domain entities: Subjects, Episodes, Memories, Resolutions, and Snapshots.
All tables use UUID v4 as primary keys and include automatic timestamp tracking (created_at, updated_at) with timezone-aware DateTime(timezone=True) columns. The schema is designed to support multi-tenant isolation through a tenant_id column on relevant entities.
Sources: server/db/tables.py
Architecture
graph TD
subgraph "Database Layer"
T[PostgreSQL]
ORM[SQLAlchemy ORM]
MIG[Alembic Migrations]
end
subgraph "Core Tables"
SUBJ[subjects]
EP[episodes]
MEM[memories]
RES[resolutions]
SNAP[snapshots]
POL[policy_bundles]
SES[sessions]
end
T --> ORM
ORM --> SUBJ
ORM --> EP
ORM --> MEM
ORM --> RES
ORM --> SNAP
ORM --> POL
ORM --> SES
MIG -.->|manage schema| TCore Table Definitions
subjects
The central entity representing a user, entity, or concept that episodes and memories are associated with.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | UUID | No | uuid.uuid4() | Primary key |
tenant_id | String(256) | No | — | Tenant isolation |
name | String(512) | Yes | — | Display name |
metadata_ | JSONB | No | {} | Flexible metadata |
version | Integer | No | 1 | Optimistic locking |
created_at | DateTime | No | server_default=func.now() | Creation timestamp |
updated_at | DateTime | No | server_default + onupdate | Last modification |
Sources: server/db/tables.py
episodes
Immutable event records representing interactions, activities, or data points fed into the system via connectors.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | UUID | No | Auto | Primary key |
subject_id | UUID | No | — | FK → subjects |
tenant_id | String(256) | No | — | Tenant isolation |
source | String(64) | No | — | Origin (e.g., slack, github, mcp) |
type | String(64) | No | — | Event type (e.g., doc_section, chat_message) |
payload | JSONB | No | — | Raw event data |
metadata_ | JSONB | No | {} | Extracted metadata |
provenance | JSONB | No | {} | Source attribution (hashes, URLs) |
occurred_at | DateTime | Yes | — | When the event actually occurred |
created_at | DateTime | No | Auto | Ingestion timestamp |
session_id | UUID | Yes | — | Optional session grouping |
Sources: server/db/tables.py Sources: server/services/context.py
memories
Compiled, semantically indexed summaries derived from episodes. Memories have temporal validity windows and confidence scores.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | UUID | No | Auto | Primary key |
subject_id | UUID | No | — | FK → subjects |
tenant_id | String(256) | No | — | Tenant isolation |
kind | String(32) | No | — | Memory category (e.g., episode_summary, profile_fact) |
content | Text | No | — | Full memory content |
summary | String(512) | Yes | — | Abbreviated summary |
confidence | Float | No | — | LLM-assigned confidence (0.0-1.0) |
valid_from | DateTime | No | — | When the memory becomes relevant |
valid_to | DateTime | Yes | — | When the memory expires (TTL) |
source_episode_ids | Array[UUID] | Yes | — | Episodes this memory was compiled from |
embedding | Array[Float] | Yes | — | Vector embedding for semantic search |
metadata_ | JSONB | No | {} | Additional metadata |
status | String(32) | No | — | active, superseded, or tombstoned |
sensitivity_labels | Array[String] | Yes | — | Privacy/classification labels |
created_at | DateTime | No | Auto | Creation timestamp |
updated_at | DateTime | No | Auto | Last modification |
Sources: server/db/tables.py
Status Values:
| Status | Description |
|---|---|
active | Currently valid and usable |
superseded | Replaced by a newer memory covering the same scope |
tombstoned | Soft-deleted, retained for audit trail |
Sources: alembic/versions/0016_memory_status_tombstoned.py
resolutions
Tracks issue or conversation resolution state per session.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | UUID | No | Auto | Primary key |
subject_id | UUID | No | — | FK → subjects |
session_id | UUID | No | — | Session identifier |
tenant_id | String(256) | No | — | Tenant isolation |
status | String(32) | No | — | Resolution status |
resolution_summary | Text | Yes | — | Summary of resolution |
resolved_at | DateTime | Yes | — | When resolution occurred |
metadata_ | JSONB | No | {} | Additional metadata |
created_at | DateTime | No | Auto | Creation timestamp |
updated_at | DateTime | No | Auto | Last modification |
Sources: server/db/tables.py Sources: server/services/snapshots.py
subject_snapshots
Immutable snapshots capturing a point-in-time state of a subject for backup/restore purposes.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | UUID | No | Auto | Primary key |
name | String(512) | No | — | Snapshot name |
version | Integer | No | — | Snapshot version |
source_subject_id | UUID | No | — | Original subject being snapshotted |
episode_count | Integer | No | — | Number of episodes captured |
memory_count | Integer | No | — | Number of memories captured |
metadata_ | JSONB | No | {} | Snapshot metadata |
created_at | DateTime | No | Auto | Creation timestamp |
Sources: server/db/tables.py
policy_bundles
Immutable policy YAML bundles content-addressed by bundle_hash.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | UUID | No | Auto | Primary key |
bundle_hash | String(64) | No | — | SHA-256 content hash (indexed) |
yaml_content | Text | No | — | Full YAML policy content |
active | Boolean | No | False | Whether this bundle is active |
tenant_id | String(256) | Yes | — | Tenant isolation |
Sources: server/db/tables.py
Design Note: Composite unique index on (tenant_id, bundle_hash) NULLS NOT DISTINCT ensures one bundle per (scope, content) combination while allowing multiple tenants to install the same policy independently.
Migration System
Statewave uses Alembic for database schema versioning. Migrations are located in the alembic/versions/ directory and follow a sequential naming convention (e.g., 0016_memory_status_tombstoned.py).
Migration Workflow
graph LR
A[Development] --> B[Create Migration]
B --> C[Review SQL]
C --> D[Apply: alembic upgrade head]
D --> E[Production Deploy]
E --> F[Rollback if needed: alembic downgrade]Migration Naming Convention
Migrations use the format XXXX_<short_description>.py where XXXX is a zero-padded sequence number. This ensures deterministic ordering across distributed development.
Migration Example: Status Rename
The migration 0016_memory_status_tombstoned.py demonstrates the migration pattern:
"""memories.status — rename `deleted` to `tombstoned` (defensive)
Revision ID: 0016_memory_status_tombstoned
Revises: 0015_episode_occurred_at
Create Date: 2026-05-10
Purpose:
- Normalize any existing
deletedvalues totombstoned - Align vocabulary with issue #49 (State-assembly receipts specify
supersession_status: active | superseded | tombstoned) - Provide a visible breadcrumb for future developers tracing the change
Sources: alembic/versions/0016_memory_status_tombstoned.py
Key Migration Characteristics
| Characteristic | Description |
|---|---|
| Reversible | All migrations include downgrade paths |
| Idempotent checks | Migrations verify existing state before modifying |
| Server defaults | Timestamps use server_default=func.now() for consistency |
| Zero-downtime aware | Helm chart runs pre-upgrade Jobs for migrations |
Data Import/Export
The backup service (server/services/backup.py) provides import/export functionality that serializes and deserializes subjects, episodes, and memories.
Import Process
graph TD
A[JSON Archive] --> B[Parse episodes_data]
B --> C[Parse memories_data]
C --> D[Resolve subject_id]
D --> E[Insert Episodes]
E --> F[Insert Memories]
F --> G[Return Import Result]
E -->|preserve_ids| E1[Use original UUIDs]
E -->|new_ids| E2[Generate new UUIDs]Import Flow:
- Validate archive structure
- Resolve target
subject_idbased onconflict_strategy - Insert episodes with optional ID preservation
- Insert memories with source episode ID remapping
- Commit transaction
Sources: server/services/backup.py
Snapshot Restore Process
Snapshots preserve the complete state of a subject including temporal offsets:
# Timestamp shifting during restore
time_shift = restore_time - snapshot.created_at
valid_from = mem_valid_from + time_shift
valid_to = (mem_valid_to + time_shift) if mem_valid_to else None
The metadata_ field receives "restored_from_snapshot": str(snapshot_id) for audit tracking.
Sources: server/services/snapshots.py
Schema Design Patterns
Temporal Modeling
Memories use valid_from and valid_to columns for temporal validity:
def compute_valid_to(kind: str, valid_from: datetime, ttl: dict) -> datetime | None:
"""Compute expiration based on memory kind TTL."""
ttl_hours = ttl.get(kind, DEFAULT_TTL_HOURS)
return valid_from + timedelta(hours=ttl_hours)
Sources: server/services/compilers/heuristic.py
Temporal Anchoring
The system extracts temporal anchors from episodes with priority:
payload.event_time— explicit client overridepayload.messages[0].timestamp— first message timestamp in chat payloadscreated_at— fallback to ingestion time
Sources: server/services/compilers/heuristic.py
JSONB Flexibility
Columns like payload, metadata_, and provenance use PostgreSQL's JSONB type for schema flexibility:
- payload: Raw event data varying by source connector
- metadata_: Extracted structured data
- provenance: Source attribution with content hashes
This allows the system to evolve connectors without schema migrations.
Composite Indexes
Key indexes for query performance:
| Index | Columns | Purpose |
|---|---|---|
policy_bundles.bundle_hash | bundle_hash | Content-addressed lookups |
memories.subject_id + kind | (implied) | Subject memory filtering |
episodes.subject_id + occurred_at | (implied) | Timeline queries |
See Also
- API v1 Contract — Database operations via REST API
- Deployment Guide — Database configuration
- Helm Chart Configuration — Migration job settings
Sources: server/db/tables.py
API Endpoints Reference
Related topics: Context Assembly & Ranking
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Context Assembly & Ranking
API Endpoints Reference
Overview
The Statewave API provides a comprehensive set of RESTful endpoints for managing agent memory, tracking session context, and enabling multi-tenant workspace isolation. The API is built on FastAPI and follows OpenAPI standards with automatic documentation at /docs (Swagger UI) and /redoc (ReDoc).
Base URL: http://localhost:8100
API Version: v1
All endpoints support multi-tenant isolation through the X-Tenant-ID header, configurable via the STATEWAVE_TENANT_HEADER environment variable. The API enforces query-scoped data isolation for multi-tenant deployments. Sources: README.md
Source: https://github.com/smaramwbc/statewave / Human Manual
Context Assembly & Ranking
Related topics: API Endpoints Reference, Embedding Services, Governance - Receipts & Policy Engine
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: API Endpoints Reference, Embedding Services, Governance - Receipts & Policy Engine
Context Assembly & Ranking
Context Assembly & Ranking is the core mechanism that transforms raw episodic memory into a curated, token-bounded context bundle for LLM consumption. When an agent queries Statewave for context, the system retrieves relevant memories and episodes, scores them by relevance, and assembles them within a configurable token budget.
Architecture Overview
The context assembly system operates as a multi-stage pipeline:
- Retrieval — Query memories and episodes by subject, kind, text, or semantic similarity
- Scoring — Assign relevance scores to each item using configurable strategies
- Ranking — Sort items by score and enforce token budget constraints
- Assembly — Build the final context bundle with proper formatting and ordering
graph TD
A[Client Request: POST /v1/context] --> B[ContextService.assemble]
B --> C[Retrieve Memories by Query]
B --> D[Retrieve Episodes by Query]
C --> E[_ScoredItem Scoring Loop]
D --> E
E --> F[Apply Ranking Strategy]
F --> G[Token Budget Enforcement]
G --> H[Context Bundle Response]
E -->|score, kind, text, section| ECore Data Model
`_ScoredItem` Class
The fundamental unit used throughout the ranking pipeline is the _ScoredItem class, defined in server/services/context.py:
class _ScoredItem:
"""An item (memory or episode) with its computed relevance score."""
__slots__ = ("score", "kind", "memory_row", "episode_row", "text", "section")
def __init__(
self,
score: float,
kind: str,
text: str,
section: str,
memory_row: Any = None,
episode_row: Any = None,
) -> None:
self.score = score
self.kind = kind
self.memory_row = memory_row
self.episode_row = episode_row
self.text = text
self.section = section
| Attribute | Type | Description |
|---|---|---|
score | float | Computed relevance score (higher = more relevant) |
kind | str | Item type: "memory" or "episode" |
memory_row | Any | MemoryRow instance when kind == "memory" |
episode_row | Any | EpisodeRow instance when kind == "episode" |
text | str | Extracted text content for scoring |
section | str | Section identifier for display/breadcrumb |
Sources: server/services/context.py:49-67
Memory Response Model
When context is assembled, memories are returned with full provenance:
MemoryResponse(
id=m.id,
subject_id=m.subject_id,
kind=m.kind,
content=m.content,
summary=m.summary,
confidence=m.confidence,
valid_from=m.valid_from,
valid_to=m.valid_to,
source_episode_ids=m.source_episode_ids or [],
metadata=m.metadata_,
status=m.status,
sensitivity_labels=list(m.sensitivity_labels or []),
created_at=m.created_at,
updated_at=m.updated_at,
)
Sources: server/api/timeline.py:1-20
Context Assembly Flow
Endpoint: `POST /v1/context`
Assembles a ranked, token-bounded context bundle from a subject's episodic memory.
sequenceDiagram
participant Client
participant API as /v1/context
participant ContextService
participant MemoryStore
participant EpisodeStore
Client->>API: POST /v1/context {subject_id, query, max_tokens}
API->>ContextService: assemble(request)
ContextService->>MemoryStore: search_memories(query)
MemoryStore-->>ContextService: [MemoryRow...]
ContextService->>EpisodeStore: search_episodes(query)
EpisodeStore-->>ContextService: [EpisodeRow...]
ContextService->>ContextService: score_and_rank(items)
ContextService->>ContextService: enforce_token_budget(items, max_tokens)
ContextService-->>API: ContextResponse
API-->>Client: 200 OKToken Budget Enforcement
The system enforces a configurable token budget via the STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS environment variable (default: 4000 tokens). This ensures that:
- Large subjects don't overwhelm LLM context windows
- The most relevant items are prioritized
- Lower-scored items are truncated when budget is exhausted
| Parameter | Default | Description |
|---|---|---|
STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS | 4000 | Default token budget for context assembly |
Sources: README.md:1-100
Ranking Strategies
The ranking system supports multiple strategies that can be applied in combination:
1. Semantic Similarity Ranking
For queries with semantic intent, memories are ranked by vector similarity against the query embedding. This is the default strategy when using kind="semantic" in search requests.
2. Confidence-Based Ranking
Memories include a confidence field (0.0–1.0) that reflects the compiler's certainty. Higher-confidence memories are ranked higher by default.
| Memory Kind | Typical Confidence Range |
|---|---|
episode_summary | 0.8 |
profile_fact | 0.6 |
key_event | 0.7–0.9 |
| Custom | Variable |
Sources: server/services/compilers/heuristic.py:1-100
3. Temporal Recency Ranking
For timeline-sensitive queries, items can be weighted by recency (valid_from, created_at). Recent memories receive higher ranking weights.
4. Composite Scoring
The _ScoredItem system enables composite scoring:
final_score = (
semantic_weight * semantic_score +
confidence_weight * confidence +
recency_weight * recency_score
)
Memory Kinds and Their Role in Context
Statewave supports structured memory kinds that inform ranking behavior:
| Kind | Description | Ranking Priority |
|---|---|---|
episode_summary | Auto-generated summary of an episode | High |
profile_fact | Extracted subject facts | Medium-High |
key_event | Significant events in subject history | High |
resolution | Issue resolution tracking | Context-dependent |
| Custom kinds | User-defined memory types | User-defined |
Sources: server/services/compilers/heuristic.py:50-100
Configuration Options
Environment Variables
| Variable | Default | Description |
|---|---|---|
STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS | 4000 | Token budget for context assembly |
STATEWAVE_LITELLM_API_KEY | — | LLM API key for embedding-based ranking |
STATEWAVE_EMBEDDING_PROVIDER | litellm | Provider for semantic embeddings |
Sources: README.md:100-150
Helm Chart Configuration
For Kubernetes deployments:
compiler:
type: llm # or 'heuristic' for no-LLM mode
embedding:
provider: litellm # or 'stub' for demo mode
Sources: helm/statewave/README.md:1-50
API Response Structure
Success Response: `200 OK`
{
"subject_id": "uuid",
"query": "user query string",
"memories": [
{
"id": "uuid",
"subject_id": "uuid",
"kind": "episode_summary",
"content": "...",
"summary": "...",
"confidence": 0.8,
"valid_from": "2024-01-15T10:00:00Z",
"valid_to": "2024-01-20T10:00:00Z",
"source_episode_ids": ["uuid1", "uuid2"],
"metadata": {},
"status": "active",
"sensitivity_labels": [],
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"episodes": [],
"total_tokens": 3500,
"truncated": false
}
Snapshot Integration
Context assembly respects snapshot-restored memories. When memories are restored from snapshots, they carry provenance:
metadata_={
**mem.metadata_,
"restored_from_snapshot": str(snapshot_id),
}
Sources: server/services/snapshots.py:1-50
Memory Evolution and Context
The memory evolution system tracks superseding relationships:
class MemoryEvolutionResponse(BaseModel):
memory_id: str
status: str
created_at: str
superseding_memory: Optional[MemoryRelation]
superseded_memories: list[MemoryRelation]
sibling_memories: list[MemoryRelation]
source_episode_count: int
When assembling context, superseded memories may be excluded or marked, ensuring agents see the most current information.
Sources: server/api/admin.py:1-100
Evaluation and Testing
The scripts/eval/eval_docs_support.py module provides evaluation patterns for context quality:
Question(
task="How does context ranking work?",
expected_doc_paths=["architecture/ranking.md"],
expected_terms=["ranking", "score"],
)
This validates that the ranking system correctly surfaces relevant memories for queries.
Sources: scripts/eval/eval_docs_support.py:1-50
Best Practices
- Set Appropriate Token Budgets: Balance context richness against LLM limits. Start with 4000 and adjust based on model context window.
- Use Semantic Search for Complex Queries: When users ask complex questions, semantic similarity ranking outperforms keyword matching.
- Leverage Memory Kinds: Structure memories with appropriate kinds to enable kind-filtered context retrieval.
- Monitor Confidence Scores: Low-confidence memories may indicate compilation issues or ambiguous data.
- Snapshot Before Major Changes: Use snapshots to preserve context state before bulk operations.
Related Endpoints
| Method | Path | Description |
|---|---|---|
POST | /v1/context | Assemble ranked, token-bounded context bundle |
GET | /v1/memories/search | Search by kind, text, or semantic similarity |
GET | /v1/timeline | Chronological subject timeline |
GET | /v1/subjects | List known subjects with episode/memory counts |
Sources: README.md:50-80
Sources: server/services/context.py:49-67
Compilation Services
Related topics: System Architecture
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: System Architecture
Compilation Services
Compilation Services transform raw episodes into structured memories within Statewave. This process extracts meaningful information from conversation events, resolves conflicts between overlapping facts, and produces durable knowledge representations that agents can retrieve during context assembly.
Overview
Statewave's compilation pipeline operates as a multi-stage process that converts incoming episode data into memory entities. The system supports two distinct compilation modes — heuristic and LLM — allowing deployments to choose between performance and intelligence based on infrastructure constraints.
graph TD
A[Episode Ingest] --> B{Compilation Mode}
B -->|Heuristic| C[Heuristic Compiler]
B -->|LLM| D[LLM Compiler]
C --> E[Memory Rows]
D --> E
E --> F[Conflict Resolution]
F --> G[Finalized Memories]
H[Context Assembly] --> I[Memory Retrieval]
G --> ICompilation Modes
Statewave ships with two compiler implementations, each suited to different operational contexts.
Heuristic Compiler
The heuristic compiler performs rule-based extraction without external AI dependencies. It analyzes episode text using pattern matching and natural language heuristics to identify structured facts.
Supported Memory Kinds:
| Kind | Description | Confidence | TTL |
|---|---|---|---|
episode_summary | Concise summary of episode content | 0.8 | 30 days |
profile_fact | Extracted user profile attributes | 0.6 | 90 days |
preference | User-stated preferences | 0.7 | 60 days |
fact | General factual statements | 0.65 | 60 days |
The heuristic compiler processes each episode independently, extracting profile facts through pattern recognition and generating episode summaries through text truncation and normalization.
LLM Compiler
The LLM compiler leverages large language models to perform semantic understanding of episodes. This mode produces higher-quality memories with better contextual awareness but requires external LLM infrastructure.
Key Capabilities:
- Multi-episode summarization across conversation turns
- Inference of implicit facts not explicitly stated
- Better handling of ambiguous or complex dialogue
- Cross-episode fact consolidation
Temporal Anchoring
Every memory requires a temporal anchor to support time-bounded queries and historical reasoning. The compilation system determines validity windows using a priority cascade.
graph LR
A[Temporal Anchor Priority] --> B[payload.event_time]
B --> C[payload.messages[0].timestamp]
C --> D[Episode created_at]
E[compute_valid_to] --> F[Memory.valid_from]
F --> G[Memory.valid_to]Anchor Resolution Order:
- Explicit
event_timein episode payload (connector replay scenarios) - First message timestamp in chat-shaped payloads
- Episode creation timestamp (fallback)
The valid_to date derives from the memory kind's configured TTL (time-to-live), ensuring automatic expiration of transient information.
Conflict Resolution
When multiple episodes produce overlapping memories, the conflict resolution service determines which information takes precedence.
graph TD
A[New Memory] --> B{Same Subject?}
B -->|No| C[Insert Directly]
B -->|Yes| D{Overlapping Time Range?}
D -->|No| E[Insert Directly]
D -->|Yes| F{Conflicting Content?}
F -->|No| G[Insert as Sibling]
F -->|Yes| H[Apply Resolution Strategy]
H --> I{Strategy: Supersede}
H --> J{Strategy: Merge}
H --> K{Strategy: Retain Both}
I --> L[Mark Older as Superseded]
J --> M[Combine Content]
K --> N[Link as Alternatives]Resolution Strategies:
| Strategy | Behavior | Use Case |
|---|---|---|
supersede | Replace older conflicting memory | Corrected information |
merge | Combine facts from both memories | Complementary details |
retain_both | Keep both as alternatives | Ambiguous or opinion-based |
Compilation Job Management
Long-running compilation tasks are managed through an asynchronous job system that prevents API timeouts and supports retry logic.
graph TD
A[POST /v1/memories/compile] --> B{Currently Compiling?}
B -->|Yes| C[Return 409 Conflict]
B -->|No| D[Queue Job]
D --> E[Job Created]
E --> F[Background Processing]
F --> G{Success?}
G -->|Yes| H[Memories Created]
G -->|No| I{Retryable?}
I -->|Yes| J[Retry with Backoff]
I -->|No| K[Mark Failed]
J --> FJob States:
pending— Queued for processingrunning— Actively compilingcompleted— Successfully finishedfailed— Unrecoverable errorcancelled— Manually aborted
Data Models
Episode to Memory Flow
EpisodeRow
├── id: UUID
├── subject_id: UUID
├── source: str (e.g., "mcp-server", "github", "statewave-docs")
├── type: str (e.g., "conversation", "doc_section", "issue")
├── payload: dict
│ ├── title: str
│ ├── text: str
│ ├── messages: list[dict]
│ └── ...
├── metadata_: dict
├── provenance: dict
│ └── content_hash: str
└── created_at: datetime
↓ Compilation
MemoryRow
├── id: UUID
├── subject_id: UUID
├── kind: str (e.g., "episode_summary", "profile_fact")
├── content: str
├── summary: str
├── confidence: float (0.0 - 1.0)
├── valid_from: datetime
├── valid_to: datetime
├── source_episode_ids: list[UUID]
├── metadata_: dict
├── status: str ("active", "superseded", "redacted")
├── sensitivity_labels: list[str]
├── embedding: vector (optional)
└── created_at, updated_at: datetime
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
STATEWAVE_COMPILER_TYPE | llm | Compiler mode: llm or heuristic |
STATEWAVE_LLM_API_KEY | — | API key for LLM provider |
STATEWAVE_LLM_MODEL | gpt-4o | Model identifier for LLM compiler |
STATEWAVE_COMPILE_TIMEOUT | 300 | Compilation timeout in seconds |
Helm Chart Configuration
| Value | Default | Notes |
|---|---|---|
compiler.type | llm | heuristic for no-LLM mode |
llm.apiKey | — | Required when compiler.type=llm |
llm.model | gpt-4o | Override default model |
Idempotency
Compilation is designed to be idempotent. Re-running compilation on episodes that have already been compiled will not create duplicate memories. The system tracks source_episode_ids to prevent reprocessing and uses content hashing in provenance metadata to detect unchanged source material.
This design supports:
- Safe re-compilation after configuration changes
- Incremental updates from connector replay
- Bootstrap and refresh workflows
API Integration
Compilation is triggered through the REST API:
POST /v1/memories/compile
The endpoint accepts a subject_id and initiates asynchronous processing. Polling the job status or receiving webhooks (if configured) provides completion feedback.
Request Example:
{
"subject_id": "550e8400-e29b-41d4-a716-446655440000",
"force": false
}
Response:
{
"status": "queued",
"job_id": "660e8400-e29b-41d4-a716-446655440001"
}Source: https://github.com/smaramwbc/statewave / Human Manual
Embedding Services
Related topics: Context Assembly & Ranking
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Context Assembly & Ranking
Embedding Services
Embedding Services provide semantic vector representations for memories and episodes in Statewave, enabling similarity-based search, context ranking, and retrieval-augmented generation workflows.
Overview
The embedding layer is a pluggable component that converts textual content into high-dimensional vector embeddings. These vectors power the semantic search capabilities of the /v1/memories/search endpoint and the relevance scoring in context assembly (POST /v1/context).
Statewave supports two embedding providers:
| Provider | Purpose | Use Case |
|---|---|---|
litellm | Real embeddings via LiteLLM proxy | Production deployments with LLM API access |
stub | Zero vectors (all dimensions = 0) | Development, demos, or when embeddings are disabled |
Sources: helm/statewave/README.md
Architecture
graph TD
subgraph "Embedding Services Layer"
LLM[LiteLLM Embeddings<br/>litellm.py]
STUB[Stub Embeddings<br/>stub.py]
CACHE[Query Cache<br/>query_cache.py]
end
subgraph "Backfill Operations"
BF[Backfill Service<br/>backfill.py]
end
subgraph "Consumers"
SEARCH[Memory Search<br/>/v1/memories/search]
CONTEXT[Context Assembly<br/>/v1/context]
COMPILER[Memory Compiler]
end
LLM --> CACHE
STUB --> CACHE
CACHE --> SEARCH
CACHE --> CONTEXT
CACHE --> COMPILER
BF --> LLM
BF --> STUBConfiguration
Embedding behavior is controlled via environment variables:
| Environment Variable | Default | Description |
|---|---|---|
STATEWAVE_EMBEDDING_PROVIDER | litellm | Embedding provider: litellm or stub |
STATEWAVE_LITELLM_API_KEY | — | API key for LiteLLM |
STATEWAVE_LITELLM_BASE_URL | — | Custom LiteLLM base URL (for proxy deployments) |
STATEWAVE_EMBEDDING_MODEL | provider default | Specific embedding model to use |
Sources: helm/statewave/README.md
Providers
LiteLLM Provider
The LiteLLM provider (server/services/embeddings/litellm.py) routes embedding requests through the LiteLLM proxy library, which standardizes access to multiple LLM backends including OpenAI, Azure, Cohere, and custom providers.
Key responsibilities:
- Accept text input and return normalized embedding vectors
- Handle API authentication via
STATEWAVE_LITELLM_API_KEY - Support custom base URLs via
STATEWAVE_LITELLM_BASE_URL - Model selection via
STATEWAVE_EMBEDDING_MODEL - Normalize embedding dimensions across providers
Stub Provider
The stub provider (server/services/embeddings/stub.py) returns zero vectors for all inputs. This is useful for:
- Development environments without API access
- Demo deployments where semantic search is not required
- Testing the rest of the system without embedding dependencies
Sources: server/services/embeddings/stub.py
Query Cache
The query cache (server/services/embeddings/query_cache.py) reduces redundant embedding computations by caching the results of previously generated embeddings.
Cache Strategy
graph LR
A[Embedding Request] --> B{Hit in Cache?}
B -->|Yes| C[Return Cached Vector]
B -->|No| D[Compute Embedding]
D --> E[Store in Cache]
E --> F[Return Vector]
C --> FCache Behavior
- Cache key is derived from the text content being embedded
- Cached vectors are returned directly on cache hit
- Reduces API calls and latency for repeated queries
- Particularly effective for search queries that repeat across requests
Sources: server/services/embeddings/query_cache.py
Backfill Operations
The backfill service (server/services/embeddings/backfill.py) handles bulk embedding regeneration for existing data.
Use Cases
- Model migration: When switching embedding models, regenerate all existing embeddings
- Corruption recovery: Rebuild embeddings for data with missing or corrupted vectors
- Schema changes: When embedding schema or normalization changes
Backfill Process
graph TD
A[Start Backfill] --> B[Query Rows Missing Embeddings]
B --> C{Process Batch}
C -->|Has More| D[Fetch Batch]
D --> E[Generate Embeddings]
E --> F[Update Database]
F --> C
C -->|Complete| G[Backfill Complete]Sources: server/services/embeddings/backfill.py
Integration with Memory System
Embeddings are stored alongside memory records and used for relevance scoring:
graph LR
subgraph "Memory Row Schema"
M1[id]
M2[content]
M3[embedding]
M4[source_episode_ids]
end
subgraph "Usage Flow"
S[Search Query] --> E[Generate Query Embedding]
E --> SC[Compute Similarity Scores]
M3 --> SC
SC --> R[Ranked Results]
endThe embedding field in MemoryRow stores the vector representation of memory content, enabling:
- Semantic similarity search via cosine similarity
- Context relevance scoring during context assembly
- Deduplication by detecting high-similarity memory candidates
Sources: server/services/context.py
API Endpoints Using Embeddings
| Endpoint | Embedding Usage |
|---|---|
GET /v1/memories/search | Query embedding vs stored memory embeddings |
POST /v1/context | Rank episode and memory candidates by relevance |
POST /v1/memories/compile | Generate embeddings for new memories |
Deployment Considerations
Production Deployment
For production with semantic search enabled:
- Set
STATEWAVE_EMBEDDING_PROVIDER=litellm - Configure
STATEWAVE_LITELLM_API_KEYwith appropriate permissions - Optionally specify
STATEWAVE_EMBEDDING_MODELfor a specific model - For proxy deployments, set
STATEWAVE_LITELLM_BASE_URL
Demo Mode
For demos or development without API costs:
- Set
STATEWAVE_EMBEDDING_PROVIDER=stub - Full functionality except semantic search (returns zero similarity)
Sources: helm/statewave/README.md
Helm Configuration
embedding:
provider: litellm # or "stub" for demo mode
model: "" # optional: specify model
Related Services
- Compiler Services: Use embeddings during memory compilation
- Context Assembly: Uses embeddings for relevance scoring
- Memory Search: Primary consumer of embedding similarity
- Snapshots: Preserves embeddings when snapshotting subject state
Sources: server/services/snapshots.py
Sources: helm/statewave/README.md
Governance - Receipts & Policy Engine
Related topics: Multi-tenancy & Security, Context Assembly & Ranking
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Multi-tenancy & Security, Context Assembly & Ranking
Governance - Receipts & Policy Engine
Overview
The Governance layer in Statewave provides two interrelated mechanisms for operational accountability and data access control:
- State Assembly Receipts — Immutable audit records that capture exactly which memories and episodes were included in a
/v1/contextor/v1/handoffresponse, enabling full traceability of AI-generated context. - Policy Engine — A content-addressed bundle system that enforces sensitivity-label-based filtering on memories before they appear in responses, with configurable enforcement modes.
These systems work together to ensure that when a context bundle is assembled for downstream AI consumption, there is a verifiable record of what was included, why it was included, and what policy rules were applied.
Sources: server/schemas/responses.py
Sources: server/schemas/responses.py
Multi-tenancy & Security
Related topics: Governance - Receipts & Policy Engine
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Governance - Receipts & Policy Engine
Multi-tenancy & Security
Overview
Statewave implements a multi-tenant architecture with comprehensive security controls for enterprise deployments. The system provides query-scoped data isolation, per-tenant policy enforcement, caller identity validation, and distributed rate limiting—all coordinated through a Postgres-backed shared infrastructure.
Architecture
graph TD
subgraph "API Layer"
A[Incoming Request] --> B[Tenant Resolution]
B --> C[Auth Middleware]
C --> D[Rate Limiter]
D --> E[Policy Engine]
E --> F[Business Logic]
end
subgraph "Security Components"
C -->|API Key| Auth[Auth Service]
D -->|Distributed| RL[Rate Limit Store]
E -->|Bundle Hash| PB[Policy Bundles]
E -->|caller_id/caller_type| CI[Caller Identity]
end
subgraph "Tenant Isolation"
B -->|tenant_id| TI[Tenant Isolation Layer]
TI -->|query scoping| DB[(Postgres)]
PB -->|per-tenant| TI
endTenant Resolution
Tenant Header Configuration
Statewave uses a configurable HTTP header for tenant identification. The header name defaults to X-Tenant-ID but can be customized via environment variables.
| Environment Variable | Default | Description |
|---|---|---|
STATEWAVE_TENANT_HEADER | X-Tenant-ID | Header for multi-tenant isolation |
STATEWAVE_REQUIRE_TENANT | false | Reject requests without tenant header |
When STATEWAVE_REQUIRE_TENANT is set to true, any request missing the tenant header receives a 400 Bad Request response. When false, requests without a tenant header are processed with an anonymous tenant context.
Sources: README.md:env-vars (configuration documentation)
Tenant Resolution Flow
sequenceDiagram
participant C as Client
participant A as API Server
participant T as Tenant Resolver
participant DB as Postgres
C->>A: Request + X-Tenant-ID header
A->>T: Extract tenant_id
T->>DB: Lookup tenant config
DB-->>T: TenantConfigResponse
T-->>A: Tenant context
A->>A: Apply tenant-scoped logicTenant Configuration API
Configuration Schema
The TenantConfigResponse schema defines the tenant configuration structure:
| Field | Type | Description | |
|---|---|---|---|
tenant_id | str | Unique tenant identifier | |
config | dict[str, Any] | Full configuration document | |
version | int | Optimistic-concurrency counter | |
created_at | `datetime \ | None` | First configuration timestamp |
updated_at | `datetime \ | None` | Last modification timestamp |
Configuration Keys
| Key | Type | Description |
|---|---|---|
receipts | string | Emission mode: "always", "never", "on_request" |
receipt_retention_days | int | Days to retain receipts before cleanup |
policy_mode | string | "log_only" or "enforce" |
require_caller_identity | bool | Enforce caller_id/caller_type presence |
Sources: server/schemas/responses.py:tenant-config-schema (response schema definition)
Admin Endpoints
| Method | Path | Description |
|---|---|---|
GET | /admin/tenants/{id}/config | Retrieve tenant configuration |
PATCH | /admin/tenants/{id}/config | Update tenant configuration |
#### PATCH Request Shape
The PATCH operation performs a merge update with optimistic concurrency control:
# Expected version must match current state
{
"expected_version": 5,
"config": {
"policy_mode": "enforce",
"receipt_retention_days": 90
}
}
If expected_version does not match the current database version, the update fails with a 409 Conflict response.
Sources: server/api/admin.py:config-endpoints (admin API implementation)
Authentication & Authorization
API Key Authentication
Statewave supports API key authentication via the Authorization header:
Authorization: Bearer <api_key>
Or via query parameter for specific integration scenarios:
GET /v1/context?api_key=<api_key>
Caller Identity Validation
When require_caller_identity is enabled in tenant config, every context and handoff request must include:
| Field | Type | Description |
|---|---|---|
caller_id | str | Unique identifier of the calling agent/user |
caller_type | str | Type classification (e.g., "agent", "user", "system") |
Requests missing these fields receive a 401 Unauthorized response:
{
"detail": "tenant config requires caller_id and caller_type on every context call"
}
Sources: server/api/handoff.py:identity-validation (identity enforcement)
Rate Limiting
Rate Limit Strategy
Statewave supports two rate limiting backends:
| Strategy | Backend | Use Case |
|---|---|---|
distributed | Postgres | Multi-instance deployments |
memory | In-process | Single instance / development |
Configuration
| Environment Variable | Default | Description |
|---|---|---|
STATEWAVE_RATE_LIMIT | 1000 | Requests per window |
STATEWAVE_RATE_WINDOW | 60 | Window duration in seconds |
STATEWAVE_RATE_LIMIT_STRATEGY | distributed | Backend strategy selection |
Current Limitations
Note: Rate limiting is currently keyed by IP address only, not per-tenant or per-API-key. This is a known limitation in v0.8.0.
Sources: README.md:rate-limiting-limits (documentation of limitations)
Policy Engine
Policy Bundle Structure
Policy bundles are declarative YAML/JSON documents that define filtering rules. Each bundle is:
- Immutable: Once created, content cannot be modified
- Content-addressed: Identified by
bundle_hash(SHA-256) - Per-tenant: Same bundle content can exist independently per tenant
# Example policy bundle
version: 1
rules:
- id: redact_sensitive
predicates:
- kind: label_match
args:
label: PII
- kind: caller_type
args:
type: external_agent
action: redact
Predicate Types
| Predicate | Description |
|---|---|
label_match | Match memory by sensitivity label |
caller_type | Match by calling agent type |
caller_id | Match by specific caller identifier |
Actions
| Action | Behavior |
|---|---|
deny | Reject the memory from context |
redact | Remove sensitive content, keep metadata |
Policy Modes
| Mode | Behavior |
|---|---|
log_only | Record decisions to receipts, no filtering applied |
enforce | Drop denied memories before ranking |
Sources: server/db/tables.py:policy-bundle-row (database schema)
Receipts System
Receipt Emission Logic
Receipts record policy decisions for audit and compliance. The emission decision follows a priority cascade:
flowchart TD
A[Receipt Request] --> B{Global Kill Switch?}
B -->|Enabled| E[Emit = False]
B -->|Disabled| C{Bundle Force Off?}
C -->|Yes| E
C -->|No| D{Tenant Mode?}
D -->|always| F[Emit = True]
D -->|never| E
D -->|on_request| G{Request Flag?}
G -->|True| F
G -->|False| EKill Switch
Global environment variable disables all receipt emission:
STATEWAVE_RECEIPTS_DISABLED=true # or "1", "yes"
Receipt Data Model
| Field | Description |
|---|---|
id | ULID identifier |
tenant_id | Associated tenant |
policy_bundle_hash | Hash of applied policy bundle |
policy_mode | Mode at time of decision |
filters_applied | List of applied filter rules |
filters_skipped | List of bypassed filter rules |
caller_id | Identity of requesting agent |
caller_type | Type of requesting agent |
Sources: server/services/receipts.py:emission-decision (emission logic)
Multi-Tenant Data Isolation
Query-Scoped Isolation
All database queries include tenant_id in their WHERE clauses. This is enforced at the service layer:
# Example isolation pattern
query = select(MemoryRow).where(
MemoryRow.tenant_id == tenant_id,
MemoryRow.subject_id == subject_id
)
Composite Unique Index
Policy bundles use a composite unique index to enforce:
UNIQUE (tenant_id, bundle_hash) NULLS NOT DISTINCT
This allows multiple tenants to install identical policy content while maintaining row-level separation.
Sources: server/db/tables.py:composite-index (index definition)
Security Best Practices
Recommended Configuration
For production deployments:
# Kubernetes/Helm values
auth:
apiKey: <use-external-secret>
database:
url: <use-external-secret>
existingSecret: statewave-db
existingSecretKey: STATEWAVE_DATABASE_URL
# Tenant configuration
policy_mode: enforce
require_caller_identity: true
receipts: always
receipt_retention_days: 90
Secret Management
The Helm chart supports two patterns:
- Inline secrets: Set via
--setfor development - External secrets: Reference existing secrets (recommended for production)
| Secret | Purpose |
|---|---|
statewave-db | Database connection URL |
statewave-llm | LLM provider API key |
statewave-auth | API authentication key |
Sources: helm/statewave/README.md:secret-management (Helm documentation)
Current Limitations
| Feature | Status | Notes |
|---|---|---|
| Rate limiting per-IP | ✅ Shipped | Distributed but IP-only |
| Rate limiting per-tenant | 🔜 Planned | Not yet implemented |
| Rate limiting per-API-key | 🔜 Planned | Not yet implemented |
| Postgres RLS | 🔜 Planned | App-layer isolation only |
| Multi-tenant policy bundles | ✅ v0.8 | Content-hashed, per-tenant |
| Caller identity validation | ✅ v0.8 | Configurable per tenant |
Sources: README.md:current-limitations (version 0.8.0 status)
Sources: README.md:env-vars (configuration documentation)
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
The project should not be treated as fully validated until this signal is reviewed.
Users cannot judge support quality until recent activity, releases, and issue response are checked.
The project may affect permissions, credentials, data exposure, or host boundaries.
The project may affect permissions, credentials, data exposure, or host boundaries.
Doramagic Pitfall Log
Doramagic extracted 6 source-linked risk signals. Review them before installing or handing real data to the project.
1. Capability assumption: README/documentation is current enough for a first validation pass.
- Severity: medium
- Finding: README/documentation is current enough for a first validation pass.
- User impact: The project should not be treated as fully validated until this signal is reviewed.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: capability.assumptions | github_repo:1219923941 | https://github.com/smaramwbc/statewave | README/documentation is current enough for a first validation pass.
2. Maintenance risk: Maintainer activity is unknown
- Severity: medium
- Finding: Maintenance risk is backed by a source signal: Maintainer activity is unknown. Treat it as a review item until the current version is checked.
- User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: evidence.maintainer_signals | github_repo:1219923941 | https://github.com/smaramwbc/statewave | last_activity_observed missing
3. Security or permission risk: no_demo
- Severity: medium
- Finding: no_demo
- User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: downstream_validation.risk_items | github_repo:1219923941 | https://github.com/smaramwbc/statewave | no_demo; severity=medium
4. Security or permission risk: no_demo
- Severity: medium
- Finding: no_demo
- User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: risks.scoring_risks | github_repo:1219923941 | https://github.com/smaramwbc/statewave | no_demo; severity=medium
5. Maintenance risk: issue_or_pr_quality=unknown
- Severity: low
- Finding: issue_or_pr_quality=unknown。
- User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: evidence.maintainer_signals | github_repo:1219923941 | https://github.com/smaramwbc/statewave | issue_or_pr_quality=unknown
6. Maintenance risk: release_recency=unknown
- Severity: low
- Finding: release_recency=unknown。
- User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: evidence.maintainer_signals | github_repo:1219923941 | https://github.com/smaramwbc/statewave | release_recency=unknown
Source: Doramagic discovery, validation, and Project Pack records
Community Discussion Evidence
These external discussion links are review inputs, not standalone proof that the project is production-ready.
Count of project-level external discussion links exposed on this manual page.
Open the linked issues or discussions before treating the pack as ready for your environment.
Community Discussion Evidence
Doramagic exposes project-level community discussion separately from official documentation. Review these links before using statewave with real data or production workflows.
- policy_bundles: support cross-tenant bundle reuse via composite (tenant_ - github / github_issue
- v0.8.0 - github / github_release
- v0.7.2 - github / github_release
- v0.7.0: Admin Dashboard API - github / github_release
- README/documentation is current enough for a first validation pass. - GitHub / issue
Source: Project Pack community evidence and pitfall evidence