context_builder
The context builder is the central nervous system of every Digitorn application. It sits between the agent and everything else: modules, providers, memory, security, and the outside world. Every tool call passes through it. Every system prompt is assembled by it. Every background task, watcher, and scheduled job is managed by it.
| Property | Value |
|---|---|
| Module ID | context_builder |
| Version | 1.0.0 |
| Type | system (auto-loaded for every application) |
| Source | packages/digitorn/modules/context_builder/ (4,800+ lines across 5 files) |
| Actions | 27 |
What It Does
The context builder is responsible for five core functions:
1. Tool Indexing
When an application starts, the context builder scans every loaded module and builds a searchable index of all available actions.
For each action, it indexes:
- The fully qualified name (
filesystem.read,git.status) - The description from the
@actiondecorator - All tags and aliases (including multilingual)
- Parameter names and their descriptions
- Side effects and risk levels
- Synonym expansions (e.g., "delete" indexes "remove", "destroy", "erase")
The index powers two search strategies:
Keyword search -- exact match, prefix match, and fuzzy match on action names, module names, and aliases. Used when the agent knows roughly what it wants.
Semantic search -- the description, tags, and parameter names are embedded using FastEmbed (paraphrase-multilingual-MiniLM-L12-v2, 384 dimensions, 50+ languages) and stored in an in-memory Qdrant HNSW index. Used when the agent describes what it needs in natural language.
The final ranking uses hybrid scoring: semantic_score * 10 + keyword_boost. This means semantic matches dominate, but exact name matches get a significant bonus.
2. System Prompt Assembly
The context builder generates the complete system prompt that the LLM receives. This is not a static string -- it is assembled dynamically from multiple sources:
The user's YAML system_prompt is always last. The context builder provides everything else automatically. This means the user only defines personality and behavior -- never tool instructions.
The prompt adapts based on:
- Tool injection mode (discovery vs direct): different instruction sets
- Native vs text-based tool calling: native mode uses JSON schemas, text mode includes tool listings in the prompt
- Active modules: only instructions for loaded modules appear
- Memory state: the current memory snapshot is injected first
- Agent role: coordinators see agent pool info, workers do not
3. Execution Routing
When the agent calls a tool, the context builder resolves and routes it:
The routing handles:
- Module resolution from the fully qualified name
- Security profile enforcement (grant/deny/approve)
- Parameter validation against Pydantic models
- MCP virtual tool routing (tools from external MCP servers)
- Error messages with schema hints when parameters are wrong
- Fuzzy name matching with "did you mean?" suggestions
4. Execution Primitives
The context builder provides 22 primitive actions that are available to every agent:
Parallel execution -- run multiple actions concurrently and collect all results.
Background tasks -- launch long-running actions without blocking the agent loop. The agent continues working and gets notified when tasks complete.
Watchers -- persistent monitors that periodically execute an action and notify on changes. Used for monitoring APIs, file changes, or system status.
Scheduler -- schedule actions at specific times (one-shot) or on recurring schedules (cron). Supports natural language time expressions ("in 30 minutes", "every day at 9am").
Remember -- a semantic shortcut for scheduling. The agent says "remind me to check the deployment in 30 minutes" and the system creates a scheduled notification.
Notifications -- send messages through configured output channels (Slack, email, webhook, Telegram, etc.).
Skills -- load reusable workflow instructions on demand.
5. Adaptive Tool Injection
The context builder automatically decides how to present tools to the agent based on two factors:
| Factor | Threshold | Result |
|---|---|---|
| Total tools * 200 tokens | vs 20% of context window | If tools fit: direct mode |
| Tools exceed context budget | Discovery mode |
In direct mode, all tools are injected as native function schemas. The agent calls them by name. Fast, no overhead, but uses context window space.
In discovery mode, only 5 meta-tools are injected. The agent uses search_tools to find what it needs, then execute_tool to call it. Scales to thousands of tools.
Operational tools (memory, agent_spawn) are always injected as direct tools regardless of mode -- the agent should never need to "discover" how to manage its own memory.
Actions (27)
Tool Discovery (5)
| Action | Risk | Description |
|---|---|---|
search_tools | low | Semantic + keyword search across all indexed actions |
get_tool | low | Full schema, metadata, and examples for a specific action |
execute_tool | medium | Execute any action by name with parameters |
list_categories | low | List all available modules with descriptions |
browse_category | low | List all actions in a specific module |
Parallel and Background (7)
| Action | Risk | Description |
|---|---|---|
run_parallel | medium | Execute multiple actions concurrently |
background_run | medium | Launch an action as a background task |
background_status | low | Check if a task is running, completed, or failed |
background_result | low | Get the full result of a completed task |
background_cancel | low | Cancel a running task |
background_list | low | List all background tasks |
background_wait | low | Block until a task completes |
Watchers (7)
| Action | Risk | Description |
|---|---|---|
watch_start | medium | Start a persistent monitor |
watch_stop | low | Stop and remove a watcher |
watch_pause | low | Pause a running watcher |
watch_resume | low | Resume a paused watcher |
watch_status | low | Detailed status and metrics |
watch_list | low | List all watchers |
watch_history | low | Get the last N check results |
Scheduler (5)
| Action | Risk | Description |
|---|---|---|
schedule_once | low | One-shot action at a specific time or after a delay |
schedule_cron | low | Recurring action on a cron schedule |
schedule_cancel | low | Cancel a scheduled job |
schedule_list | low | List all scheduled jobs |
schedule_status | low | Detailed status of a job |
Other (3)
| Action | Risk | Description |
|---|---|---|
remember | low | Schedule a reminder (natural language time) |
send_notification | medium | Send a message through an output channel |
use_skill | low | Load a reusable workflow on demand |
Internal Components
The context builder is implemented across five files:
| File | Lines | Responsibility |
|---|---|---|
module.py | 2,259 | Action implementations, background task management, watcher lifecycle, scheduler, notification delivery |
prompt.py | 1,404 | System prompt assembly, tool instruction generation, structural hints, MCP workflow hints |
builder.py | 608 | Tool index construction, direct tool schema generation, MCP risk inference |
scoring.py | 336 | Hybrid search engine, synonym expansion, tokenization, score calculation |
embeddings.py | 215 | FastEmbed model loading, semantic index (Qdrant), embedding and query |
Configuration
The context builder requires no explicit configuration. It is configured implicitly by:
- The list of modules in the YAML (determines what tools are indexed)
- The agent's brain settings (determines tool injection mode)
- The security profile (determines action permissions)
- The channels block (determines available notification targets)
- The skills list (determines loadable workflows)
- The memory module presence (determines if memory snapshot is injected)
- The agent_spawn module presence (determines if pool info is injected)
How It Integrates
The context builder is the single point of integration. Modules do not know about each other. The agent does not know about module internals. The context builder mediates every interaction.