2026 03 23 Intelligence Bridge Design
Documentation for Plans
Intelligence Bridge — Sub-project 1 Design
Date: 2026-03-23 Session: S262 Status: Draft Scope: Wire MCP decision intelligence into Vitto's runtime, fix pattern mining quality, add decision categorization, sync specializations to sub-agents Depends on: Command Center single-pipe (completed in S262) Enables: Sub-project 2 (Training Pipeline), Sub-project 3 (Command Center Control Plane)
Problem
Vitto and the MCP intelligence system are two islands. 12K+ MCP decisions sit in backend-ai-api's MongoDB. Pattern mining runs every 6 hours. Agent specializations are computed. Golden decisions are curated. But Vitto never reads any of this at runtime.
The only bridge is LearningSyncService — a daily cron job at 6AM that dumps patterns into sub-agent knowledge docs. That's batch, lossy, and stale by definition.
When Vitto is about to make an architecture decision, it has no idea that 50 past sessions already solved the same problem. When it delegates to a sub-agent, the sub-agent's knowledge is 24 hours old at best.
Meanwhile, the pattern mining pipeline has a dedup bug that creates 20+ copies of the same pattern, polluting the data.
Gaps to Close (5 concrete fixes)
Gap 1: No real-time intelligence in Vitto's decision loop
Current: Vitto's agent-loop.service.ts and phase-prompt-builder.service.ts never call getLearningIntelligence(). The only intelligence fetch is the daily cron.
Fix: Inject intelligence context into Vitto's context assembly before each task execution. When Vitto starts a task, call getPyramidContext() on ai-api with the task summary. Inject the response (core rules, relevant patterns, similar decisions) into the system prompt alongside existing context (dossier, memory, skills).
Where: context-assembly.service.ts — add a getLearningContext() step to the context pipeline.
Constraint: 2-second timeout with graceful degradation (already exists in BackendAiClientService). If ai-api is down, Vitto proceeds without intelligence context — same as today, no regression.
Gap 2: Pattern mining creates duplicates
Current: pattern-mining.job.ts generates pattern IDs using a simple character sum + Date.now(). This produces unique IDs for identical patterns across mining runs. No uniqueness constraint on pattern text.
Fix:
- Replace
generatePatternId()with a deterministic hash:crypto.createHash('sha256').update(normalizedPattern + category).digest('hex').slice(0, 16) - Add a MongoDB unique index on
{ normalizedText: 1, category: 1 }to thelearned_patternscollection - Use
findOneAndUpdate({ normalizedText, category }, { $set: ..., $addToSet: ... }, { upsert: true })instead of separate find+create
Result: Each unique pattern exists exactly once. Reruns update the existing entry.
Gap 3: Decisions have no domain categorization
Current: Decisions have a type field (architecture, implementation, bugfix, etc.) and optional tags[], but no category/domain field. The LearningRouterService detects domains heuristically at routing time, but this classification is not persisted on the decision itself.
Fix:
- Add
domains: string[]field to the Decision schema (computed at creation time) - In
decision.service.ts create(), callLearningRouterService.detectDomains()and store the result - Add
audience: stringfield to the Decision schema — values:developer(MCP/Cursor users),platform-builder(Space builders),admin(GoGrab internal),all - Default
audiencebased on the agent's platform type and user role
Result: Every decision is tagged with its domains and target audience at creation time. Queries can filter by domain and audience.
Gap 4: Golden decisions don't feed Vitto's context
Current: Golden decisions exist in golden_decisions collection. LearningSyncService syncs them to sub-agent knowledge docs daily. But Vitto's main agent loop never queries them.
Fix: In BackendAiClientService.getLearningIntelligence(), add a goldenDecisions field to the response. LearningService.getPyramidContext() should query golden_decisions filtered by the task's detected domains and return the top 3-5 most relevant.
Where:
learning.service.ts— addgetGoldenDecisionsForTask(task, domains)learning.controller.ts— include golden decisions in the pyramid context responsebackend-ai-client.service.ts— parse and forward the golden decisions
Gap 5: Agent specializations don't sync to sub-agent definitions
Current: AgentSpecializationService computes per-agent domain success rates from decision outcomes. SubAgentService in vitto-api has persistent definitions with performance metrics. These are separate, never synced.
Fix: Extend LearningSyncService to also sync specialization data:
- Fetch specializations from ai-api:
GET /ai-api/agents/specializations - For each sub-agent definition in vitto-api, match by role/domain overlap
- Update the sub-agent's
performancefield with the computed success rates - This runs on the existing daily cron — specializations don't need real-time sync
Result: Sub-agent definitions show real performance metrics computed from actual decision outcomes, not hardcoded zeros.
Architecture
MCP logs decision
↓
ai-api: decision.service.create()
├── Persist to MongoDB (decisions collection)
├── Detect domains → store on decision [Gap 3]
├── Forward to vitto-api SSE (decision.created) [Done in S262]
└── EventEmitter → pattern mining pipeline (async)
ai-api: pattern-mining.job.ts @Cron('0 */6 * * *')
├── Mine patterns from recent decisions
└── Upsert with deterministic hash (no duplicates) [Gap 2]
ai-api: learning.service.getPyramidContext(task)
├── Core rules (by domain)
├── Relevant patterns (deduped, by domain)
├── Similar decisions (semantic search)
└── Golden decisions (top 3-5 by domain) [Gap 4]
vitto-api: context-assembly.service.ts
├── Dossier (user context)
├── Memory (vector recall)
├── Skills (available tools)
└── Learning Intelligence (from ai-api) [Gap 1]
↓
Agent Loop makes informed decisions
vitto-api: learning-sync.service.ts @Cron('0 6 * * *')
├── Sync patterns → sub-agent knowledge docs
└── Sync specializations → sub-agent performance [Gap 5]
Files Modified
Gap 1: Real-time intelligence in context assembly
| File | Change |
|---|---|
APIs/backend-vitto-api/src/app/engine/context-assembly/context-assembly.service.ts |
Add getLearningContext() step that calls BackendAiClientService.getLearningIntelligence() |
APIs/backend-vitto-api/src/app/connectivity/backend-ai-client.service.ts |
Add goldenDecisions to response type, add audience param |
Gap 2: Pattern dedup fix
| File | Change |
|---|---|
APIs/backend-ai-api/src/app/learning/jobs/pattern-mining.job.ts |
Replace generatePatternId() with SHA-256 hash, use upsert |
APIs/backend-ai-api/src/app/schemas/ai-infrastructure.schema.ts |
Add unique compound index on { normalizedText: 1, category: 1 } for learned_patterns |
Gap 3: Decision categorization
| File | Change |
|---|---|
APIs/backend-ai-api/src/app/schemas/ai-infrastructure.schema.ts |
Add domains: string[] and audience: string to Decision schema |
APIs/backend-ai-api/src/app/infrastructure/services/decision.service.ts |
Call detectDomains() and set audience in create() |
APIs/backend-ai-api/src/app/command-center/learning-router.service.ts |
Export detectDomains() for use by decision service |
Gap 4: Golden decisions in context
| File | Change |
|---|---|
APIs/backend-ai-api/src/app/learning/learning.service.ts |
Add getGoldenDecisionsForTask(), include in getPyramidContext() |
APIs/backend-ai-api/src/app/learning/learning.controller.ts |
Return golden decisions in intelligence endpoint response |
Gap 5: Specialization sync
| File | Change |
|---|---|
APIs/backend-vitto-api/src/app/engine/learning-sync.service.ts |
Add specialization fetch and sync in daily cron |
APIs/backend-vitto-api/src/app/connectivity/backend-ai-client.service.ts |
Add getSpecializations() method |
Risks
Context window bloat: Adding intelligence context to every task increases token usage. Mitigate with strict token budgets (500 tokens max for intelligence context) and relevance filtering.
Latency: The
getLearningIntelligence()call adds 100-500ms to task startup. Acceptable — already has 2-second timeout with graceful degradation.Pattern migration: Existing 20+ duplicate patterns need a one-time cleanup script. Not blocking — new patterns will be clean, old ones can be deduped in a migration.
Schema migration: Adding
domainsandaudienceto Decision schema requires backfill for existing 12K decisions. Can be done as a background job — new decisions get tagged immediately.
What This Does NOT Cover (Sub-projects 2 & 3)
- Sub-agent training UI (creating, editing, training agents from the Command Center)
- Decision browser UI (searching, filtering, promoting decisions)
- Pattern effectiveness tracking (measuring if injected patterns improve outcomes)
- Real-time pattern mining (currently every 6 hours — fine for now)
- Cross-agent knowledge sharing (agent A learns from agent B's decisions)