Architecture
1. Parser Layer
Purpose: Extract structured decisions from messy LLM output. Implementation:ParserLayer.ts (lines 14-539)
3-Tier Fallback Strategy
StandardResponse Schema
Parser Examples
Clean JSON (Tier 2): LLM Output:2. Deduplication Guard
Purpose: Prevent repeated identical tool calls within the same action. Implementation:DecisionPipeline.ts (lines 45-120)
Strategy
Tracks recently executed tools using a sliding window:Exemptions
Sequential UI components are exempt from deduplication (they’re intentionally called multiple times in sequence):Example Block
3. Loop Detection
Purpose: Prevent infinite cycles of the same tool or tool sequences. Implementation:DecisionPipeline.ts (lines 121-180)
Patterns Detected
1. Same-tool loops (3+ in a row):Loop Recovery Suggestions
When a loop is detected, the pipeline injects recovery guidance:4. Channel Policy Guard
Purpose: Enforce cross-channel isolation and autonomy delivery rules. Implementation:Agent.ts (lines 878-906)
Rules
1. Cross-channel send blocking (non-admin):send_email (intentionally cross-channel for “email this” requests)
2. Channel configuration check:
Example Block
5. Safety Checks
Purpose: Prevent dangerous operations in safe mode and validate tool arguments. Implementation:DecisionPipeline.ts (lines 181-250)
Safe Mode Blocks
Argument Validation
Restricted Path Access
6. Termination Review
Purpose: Prevent premature task completion before delivering substantive results. Implementation:BlockReviewer.ts (lines 52-797)
Review Trigger
Runs when LLM setscompleted: true:
Audit Codes
| Code | Meaning | Example | Fix |
|---|---|---|---|
NO_SEND | No user-visible reply sent for a channel task | User asks question, agent searches but never sends answer | Use send_telegram before completing |
UNSENT_RESULTS | Deep tool output (search/browse/command) exists after last message | Agent runs web_search but completes without sharing results | Send summary: “Here’s what I found: [results]“ |
NO_SUBSTANTIVE | Only acknowledgements sent, no actual content | Agent says “Working on it…” then completes | Replace with concrete findings |
ACK_ONLY | Only status updates, no deliverable output | ”I’m searching…” → completes | Send: “Found: [actual results]“ |
ERROR_UNRESOLVED | Tool errors without explanation or recovery | web_search fails, agent completes silently | Explain: “Search failed due to [reason]” or retry |
GENERIC | Fallback for uncategorized issues | — | Review action memories manually |
Audit Logic
Example Block
Prompt Helpers (PromptRouter)
Purpose: Modular, task-aware prompt assembly that activates only relevant guidance. Implementation:PromptRouter.ts (lines 45-797) + src/core/prompts/ (8 helpers)
Active Helpers
The PromptRouter analyzes the task and selectively activates helpers:Token Savings
By only including relevant helpers, the router saves ~2,000-4,000 tokens per step:Helper Example: ResearchHelper
Autopilot Mode
Purpose: Suppress clarification requests for fully autonomous operation. Configuration:Skill Routing Rules
Purpose: Intent-based skill selection for better tool matching. Configuration:Information Boundaries
Purpose: Prevent cross-user information leakage in multi-tenant deployments. Rules:Performance Metrics
Pipeline overhead per step:- Parser: ~10-50ms
- Deduplication: ~1-5ms
- Loop detection: ~2-10ms
- Channel policy: ~1-5ms
- Safety checks: ~2-10ms
- Termination review: ~500-2,000ms (LLM call)
- Total: ~520-2,080ms per step
- System prompt helpers: ~2,500-4,500 tokens (depends on task)
- Feedback injections: ~100-300 tokens per block
- Termination review prompt: ~500-1,000 tokens
Debugging Pipeline Blocks
1. Enable pipeline logs:Configuration Reference
Further Reading
- Agent Loop — How decisions are executed
- Memory System — Context assembly and retrieval
- Skills System — Available tools
- Architecture — Overall system design