Architecture¶
Processing Pipeline¶
Every message goes through this pipeline:
User Message
│
▼
AgentRouter ──────── agents/*.yaml (TF-IDF routing, hot-reload)
│
▼
ContextPlanner
│ intent : coding | personal | task | knowledge | conversation
│ budget : { working:5, episodic:2, semantic:4, skills:3 }
▼
ContextEngine
├── Retriever → collect candidates from storage
├── Resolver → TTL check, mark expired nodes
├── Filter → active nodes only
├── Scorer → rank by relevance + importance + recency + path
└── Selector → enforce budget + max_nodes + max_chars
│
▼
PromptBuilder (deterministic, bullet-format per tier)
│
▼
LLM ←→ Gemini / OpenAI / Claude / Ollama / any
│
▼
MemoryProcessor
├── store messages → working tier
├── extract facts → semantic tier (rule-based, no LLM)
├── dedup → Jaccard similarity ≥ 0.65
├── conflict resolve → confidence-based supersedes
└── update importance scores
Components¶
AgentRouter¶
Routes each message to the most appropriate agent using TF-IDF keyword matching. Agents are defined in YAML files and hot-reloaded without restart.
result = sc.router.route(user_id, message)
# result.agent_id → "coding"
# result.personality_level → "expert"
# result.system_prompt → full system prompt string
ContextPlanner¶
Analyzes the message to determine:
- Intent — what type of request is this?
- Budget — how many nodes from each tier?
- Focus — any specific tags or paths to prioritize?
plan = sc.planner.plan(message, user_id, profile)
# plan.intent → "coding"
# plan.budget → {"working": 5, "episodic": 2, "semantic": 4}
ContextEngine¶
Orchestrates the full retrieval pipeline: retrieve → resolve → filter → score → select.
ContextRetriever¶
Collects candidate nodes from storage:
- Working tier nodes (recent messages, task state)
- Episodic tier nodes (session summaries)
- Semantic tier nodes + keyword search (facts, knowledge)
- Skills namespace (agent-specific skills)
- Focus paths (preferred paths from plan)
ContextScorer¶
Ranks nodes using a weighted formula:
Relevance is computed from token overlap (text, tags, path) with fuzzy matching fallback.
Recency uses exponential decay with tier-specific half-lives:
| Tier | Half-life |
|---|---|
| Working | 1 hour |
| Episodic | 72 hours |
| Semantic | 720 hours |
PromptBuilder¶
Builds a deterministic, structured system prompt from selected nodes:
[System prompt from agent]
## Working Memory
- [recent message 1]
- [recent message 2]
## Knowledge
- user name: Alice
- user uses: Python, FastAPI
MemoryProcessor¶
Processes each turn after the LLM responds:
- Stores messages to working tier
- Extracts facts using rule-based patterns (no LLM required)
- Deduplicates using Jaccard similarity ≥ 0.65
- Resolves conflicts using confidence scores
- Updates importance scores for used nodes
Storage Layer¶
SimpleContext supports multiple storage backends:
| Backend | Install | Best For |
|---|---|---|
| SQLite | Zero (built-in) | Development, small deployments |
| Memory | Zero (built-in) | Testing, ephemeral use |
| Redis | pip install redis | Production, multi-instance |
| PostgreSQL | pip install psycopg2-binary | Production, advanced queries |
Plugin System¶
Plugins attach to the pipeline via hooks:
on_message_saved ← after each message stored
on_context_build ← before messages sent to LLM
on_before_llm ← final chance to modify messages
on_after_llm ← after LLM responds
on_agent_routed ← when routing decision is made
on_prompt_build ← after system prompt is built
See Plugin Development for details.
File Structure¶
simplecontext/
├── core.py ← SimpleContext + ChatContext (main entry point)
├── memory.py ← Memory (v3) + TieredMemory (v4)
├── skills.py ← Skills: groups, conditions, inheritance
├── enums.py ← Tier, NodeKind, NodeStatus, Intent
├── context/
│ ├── node.py ← ContextNode dataclass
│ ├── planner.py ← ContextPlanner + RetrievalPlan
│ ├── engine.py ← ContextEngine + LRU cache
│ ├── retriever.py ← candidate collection
│ ├── resolver.py ← TTL → mark expired
│ ├── scorer.py ← scoring formula
│ ├── selector.py ← budget enforcement
│ ├── builder.py ← PromptBuilder
│ ├── processor.py ← MemoryProcessor + decay
│ ├── fuzzy.py ← fuzzy matching
│ ├── graph.py ← relationship graph
│ ├── patterns.py ← interaction pattern detection
│ ├── adaptive.py ← adaptive scoring from feedback
│ └── cache.py ← LRU cache (30s TTL)
├── storage/
│ ├── sqlite.py
│ ├── redis.py
│ └── postgres.py
├── agent/
│ ├── schema.py ← parse YAML agent definitions
│ ├── registry.py ← hot-reload
│ └── router.py ← TF-IDF routing + chaining
└── plugins/
├── base.py ← BasePlugin + AppCommandContext
├── loader.py ← dynamic loader + dependency resolver
└── state.py ← persistent plugin state