Vitto Jarvis — Comprehensive Evolution Design

Complete spec to evolve Vitto into a Jarvis-level super agent. Covers: sub-Vitto engine (parallel orchestration), VM agent tier, OAuth credential delegation, expert sub-agent creation, Vitto soul (personality drift + visual evolution), Teams channel, MongoDB cleanup, full-stack wiring, and the dual-backend data flow contract.

Vitto Jarvis — Comprehensive Evolution Design

Single source of truth for making Vitto smarter, faster, more intuitive, and fun. Informed by: deep codebase analysis (45+ services, 53 collections, 17 tool plugins, 60+ frontend components), competitive research (OpenAI AgentKit, Anthropic Claude SDK, Manus, Devin, CrewAI, Character.AI), and 10 design decisions validated with the product owner.


Design Decisions (Locked)

# Decision Answer Rationale
1 Primary audience All 3 tiers (builders, devs, end users) Different depth per tier
2 Build priority Smarter first, fun second Engine before UX
3 Sub-Vitto autonomy Full — Vitto decides, executes, reports No approval gates
4 VM environments One dynamic base image (Node+Python pre-installed, apt-get for the rest) Zero snapshot maintenance
5 Agent communication Isolated + multi-round orchestration No shared blackboard
6 Creation metaphor Pragmatic character creator for sub-agents, Tamagotchi soul for Vitto only Sub-agents are tools, Vitto is alive
7 Evolution mechanics Personality drift + visual evolution (on Vitto only) Fun reflects intelligence, never gates it
8 OAuth approach Build internal for Google+GitHub (Phase 1), add Composio for scale (Phase 2) CredentialBridgeService abstracts the backend
9 OAuth data ownership gograb-api (backend-api) owns all user OAuth data User data stays with user data. GDPR-clean.
10 Inter-service caching Shared Redis (already deployed on Railway) ~1ms lookups vs ~15ms HTTP hops
11 Delivery model One massive spec, full vision Coherent architecture designed upfront

Architecture Principles

  1. Vitto is the living entity. Only Vitto has personality, conscience, visual evolution. Sub-agents are sharp tools.
  2. backend-ai-api = intelligence. backend-vitto-api = execution. backend-api = user data. None are deprecated. All grow together.
  3. Vitto is sole executor. All LLM calls go through vitto-api. Zero shadow execution paths.
  4. User data belongs to gograb-api. OAuth tokens, preferences, identity — all in the user's database. Vitto reads, never owns.
  5. Shared Redis for cross-service state. All 3 APIs share one Redis. Use it for caches, locks, pub/sub.
  6. If it exists in the backend, it must be visible in the frontend. No orphaned services.
  7. Fun reflects intelligence. Gamification displays real growth, never artificially constrains capability.

Section 1: Sub-Vitto Engine

The Core Primitive

When Vitto encounters a complex task, it deploys sub-Vittos — lightweight clones running the same AgentLoopService engine with scoped context.

New Tool: deploy_agents

Registered in the tool plugin system. Vitto's main agent loop calls it like any other tool:

deploy_agents({
  tasks: [
    { description: "Review auth module for security issues", tier: "in-process" },
    { description: "Write unit tests for the changes", tier: "vm" },
    { description: "Search for similar patterns in past decisions", tier: "in-process" }
  ]
})

Three Tiers

Tier When Startup Tools Available Runs On
In-process Thinking: search, recall, analyze, synthesize ~0ms recall_memory, search_decisions, query_docs, web_search, fetch_webpage, http_request, query_platform, oauth_api_call vitto-api process
VM Doing: write code, run tests, process data, install packages ~2-5s All in-process tools + run_command, write_file, read_file, search_code (via SandboxedToolProxy) Hetzner VM
Browser Web: browse, click, screenshot, automate ~3-5s All in-process tools + browser_navigate, browser_click, browser_screenshot, computer_use Hetzner VM (existing CU infra)

The orchestrator decides the tier based on which tools the subtask likely needs. Keywords "write", "test", "build", "install" → VM. Keywords "browse", "login", "click" → Browser. Otherwise → in-process.

Parallel Execution

All sub-Vittos run via Promise.allSettled()
  → Each gets isolated context (own message history, no shared state)
  → Each has its own cost guard (configurable, default 10 iterations)
  → Failure in one doesn't block others
  → Results collected by orchestrator

Multi-Round Orchestration

Round 1: Fan out → collect results
Orchestrator: "Sub-Vitto B found a bug, but C's tests don't cover it"
Round 2: Fan out 1 more sub-Vitto → "Write a test for the bug"
Final: Synthesize all results → respond to user

Key Implementation Detail — SubAgentService Refactoring

This is a significant refactoring, not a trivial wiring change. SubAgentService.executeTask() currently runs its own while(true) loop (lines 550-614) with independent cost guard checks, tool call processing, and message management. The refactoring replaces this with a call to AgentLoopService.run().

Compatibility concerns that must be addressed:

The result: one engine, N contexts. Sub-Vittos get stuck detection, parallel tool calls, cost guards, and security for free.

Configuration (all via env vars + VittoUserConfigDoc overrides)

VITTO_SUBVITTO_MAX_PARALLEL=5          # max concurrent sub-Vittos
VITTO_SUBVITTO_DEFAULT_ITERATIONS=10   # per sub-Vitto
VITTO_SUBVITTO_DEFAULT_MAX_TOKENS=100000
VITTO_SUBVITTO_MAX_ROUNDS=3            # orchestration rounds

Files to Create/Modify

File Action Purpose
APIs/backend-vitto-api/src/app/tools/plugins/orchestration.plugin.ts NEW deploy_agents tool
APIs/backend-vitto-api/src/app/tools/plugins/plugins.index.ts MODIFY Register orchestration plugin in getAllToolPlugins()
APIs/backend-vitto-api/src/app/engine/sub-agent.service.ts MODIFY Call AgentLoopService.run() instead of own while loop; role-based tool filtering
APIs/backend-vitto-api/src/app/engine/sub-vitto-orchestrator.service.ts NEW Parallel execution + multi-round synthesis
APIs/backend-vitto-api/src/app/engine/engine.module.ts MODIFY Register new services
libs/libs-ai/vitto-chat/src/lib/components/tool-renderers/renderers/ NEW SubVittoOrchestrationRenderer — parallel execution card group

Section 2: VM Agent Infrastructure

Base Snapshot

One pre-warmed Ubuntu image:

Anything else: sub-Vitto installs on demand via run_command("apt-get install -y golang").

SandboxedToolProxy

Thin wrapper intercepting file/shell tools, routing to VM:

Sub-Vitto calls: run_command("yarn test")
  → SandboxedToolProxy intercepts
  → POST to sandbox orchestrator: /sandbox/:vmId/exec { command: "yarn test" }
  → Returns stdout/stderr to agent loop
  → Agent loop doesn't know it ran remotely

Follows the exact pattern ComputerUseSupervisorService already uses.

VM Lifecycle

deploy_agents called with tier: "vm"
  → Request sandbox from orchestrator (or claim from warm pool)
  → Get vmId + connection details
  → Pass vmId to SandboxedToolProxy
  → Sub-Vitto executes via AgentLoopService.run()
  → On completion: release VM back to pool (or destroy)

Warm Pool

Pre-boot VMs from base snapshot for instant startup. Replenish after each use.

Configuration

VITTO_VM_WARM_POOL_SIZE=2              # pre-booted VMs
VITTO_VM_MAX_LIFETIME_MS=900000        # 15 min default
VITTO_VM_DEFAULT_ITERATIONS=10
VITTO_VM_DEFAULT_MAX_TOKENS=100000

OAuth in VMs

VMs NEVER have credentials. API calls go through vitto-api:

VM sub-Vitto calls: oauth_api_call({ service: 'google', endpoint: '...' })
  → SandboxedToolProxy intercepts
  → Forwards to CredentialBridgeService on vitto-api
  → Broker calls backend-api: POST /auth/oauth/proxy
  → Backend-api decrypts token, calls Google, returns clean data
  → Result forwarded to VM

Safety

Files to Create/Modify

File Action Purpose
APIs/backend-vitto-api/src/app/engine/sandboxed-tool-proxy.service.ts NEW Route tool calls to VM
APIs/backend-vitto-api/src/app/engine/vm-pool.service.ts NEW Warm pool management
APIs/backend-vitto-api/src/app/connectivity/infrastructure-client.service.ts MODIFY Add pool management endpoints

Section 3: Expert Sub-Agent System

Sub-agents are sharp tools, not living beings.

Three Creation Paths

Chat-based (30 seconds): User tells Vitto what they need → Vitto generates the definition using LLM → auto-tests → ready. NOTE: This requires a NEW SubAgentService.generateDefinition() method. SkillManagerService.generateSkill() generates skills (prompt snippets with triggers), NOT agent definitions (which have their own schema with training examples, knowledge docs, performance tracking, model config). The LLM generation pattern is reusable; the output schema is different.

Template marketplace (2 minutes): Browse community agents → clone → customize → test → publish improvements. NOTE: This requires a NEW SubAgentService.marketplace() method, separate from PersonaService.marketplace(). Personas and sub-agents have completely different schemas. The UX pattern (cards, ratings, publish) is reusable; the data layer is separate.

Manual editor (5 minutes): Full control: name, role, system prompt, tools, training examples, knowledge docs.

Teaching by Example

Training pairs (input + expected output + explanation) injected into sub-agent system prompt during execution. The more examples, the sharper the agent.

Vitto Auto-Discovery

When a task matches a sub-agent's triggers, Vitto deploys it automatically. After success on a novel task type, Vitto suggests creating a specialist: "This type of task comes up often. Want me to create an agent for it?"

Quick Test Enhancements

Marketplace

Extend existing persona marketplace to include sub-agents: publish, rate (1-5 stars), usage count, clone + customize.

Files to Create/Modify

File Action Purpose
libs/libs-ai/vitto-hub/src/lib/components/sub-agent-manager/ MODIFY Add marketplace tab, chat-based creation, teach-by-correction
APIs/backend-vitto-api/src/app/engine/sub-agent.service.ts MODIFY Chat-based creation method, auto-discovery

Section 4: OAuth Credential Delegation

Ownership

backend-api (gograb-api database) owns ALL user OAuth data. This is user data — it belongs with user identity, preferences, billing. GDPR deletion = one database operation.

Schema

New collection: gograb-api.user_oauth_connections

userId              string, indexed, ref to users._id
provider            'google' | 'github' | 'slack' | 'notion'
providerUserId      provider's user ID
providerEmail       for display
scopes              string[]
encryptedRefreshToken  AES-256-GCM ciphertext
encryptionIV        per-token IV
encryptionAuthTag   per-token auth tag
status              'active' | 'expired' | 'revoked' | 'requires_reauth'
tokenExpiresAt      Date
lastUsedAt          Date
lastRefreshedAt     Date
connectedAt         Date
revokedAt           Date (TTL trigger)
providerMetadata    {} (QuickBooks realmID, Salesforce instance_url, etc.)

Indexes:
  { userId: 1, provider: 1 } unique
  { status: 1, tokenExpiresAt: 1 }

Shared Redis Integration

On connect/refresh:
  backend-api → Redis: SET oauth:{userId}:{provider} { status, scopes, expiresAt } EX 300

Status check (from any service, ~1ms):
  any-api → Redis: GET oauth:{userId}:{provider}

Token refresh lock:
  Redis: SET lock:oauth:{userId}:{provider} NX EX 30

Backend-API Endpoints

POST   /auth/oauth/connect          → Initiate OAuth consent flow
GET    /auth/oauth/callback          → Handle provider redirect
GET    /auth/oauth/connections        → List user's connected services
DELETE /auth/oauth/connections/:id    → Disconnect (revoke + delete)
POST   /auth/oauth/proxy             → Make authenticated API call on behalf of user
GET    /auth/oauth/health             → Token health for user's connections

Provider Configs (v1)

Provider Encoding Quirks Setup Time
Google form-encoded prompt param, sensitive scope security review 4 hours
GitHub form-encoded Straightforward 1 hour
Slack form-encoded Parallel user_scopes param 2 hours
Notion JSON (non-standard) No scope param, uses "capabilities" 2 hours

~30-40 lines of config per provider. OAuth 2.1 + PKCE for all.

Data Flow

Consent flow:
  Frontend → backend-api: POST /auth/oauth/connect?provider=google
  → PKCE code_verifier generated
  → state = HMAC(sessionCookie + userId + timestamp + random, secret)
  → state + code_verifier + userId stored in Redis (10-min TTL, key: oauth_state:{state})
  → Returns authUrl → frontend opens popup
  → User completes consent → Google redirects to callback
  → backend-api validates: state matches Redis entry AND userId matches authenticated user
  → (Prevents login CSRF: attacker can't initiate flow for victim)
  → Exchanges code + code_verifier for tokens
  → Encrypts refresh token (AES-256-GCM), stores in MongoDB
  → Updates Redis cache
  → Popup closes, frontend updates

Agent needs credentials:
  vitto-api → Redis: GET oauth:{userId}:google (~1ms, status check)
  → If active: POST backend-api /auth/oauth/proxy { userId, provider, method, endpoint }
  → backend-api: decrypt token → call Google → return clean data
  → Agent loop receives sanitized response (never sees tokens)

Token refresh (cron every 30 min on backend-api):
  → Query connections where tokenExpiresAt < now + 1 hour
  → For each: acquire Redis lock → refresh → store new token → release lock
  → Rotation: if provider issues new refresh token, store it, invalidate old

Security Guarantees

Threat Mitigation
Agent exfiltrates credentials Pattern 7: credentials never enter agent context
VM compromise leaks tokens API calls made FROM vitto-api via backend-api, not from VM
Database breach AES-256-GCM encryption. Key in Railway env var, not in DB
Refresh token replay Rotation: each use issues new token. Reuse = full revocation
Concurrent refresh race Redis distributed lock per user+provider
Provider-side revocation Health cron detects expired/revoked, marks requires_reauth
Cross-user access userId enforced on all queries + compound unique index

Phase 2: Composio Integration (When Needed)

When exceeding 4 providers, add ComposioClientService as another backend behind CredentialBridgeService. Agents and tools don't change. The broker routes: known provider → internal OAuth, unknown → Composio.

Frontend

User view at /vitto/channels → "Connected Services" tab:

Admin view at /command/integrations:

Files to Create/Modify

File Action Purpose
libs/libs-api/backend-core/src/lib/schemas/user-oauth-connection.schema.ts NEW Schema in shared lib
APIs/backend-api/src/app/auth/oauth/oauth.controller.ts NEW Consent flow + callback + proxy
APIs/backend-api/src/app/auth/oauth/oauth.service.ts NEW Token management + encryption
APIs/backend-api/src/app/auth/oauth/oauth-health.service.ts NEW Cron: refresh expiring tokens
APIs/backend-api/src/app/auth/oauth/providers/*.ts NEW Per-provider config (4 files)
APIs/backend-vitto-api/src/app/tools/credential-broker.service.ts MODIFY Add OAuth proxy path via backend-api
APIs/backend-vitto-api/src/app/tools/plugins/oauth.plugin.ts NEW oauth_connect (returns auth URL as clickable chat link), oauth_api_call, oauth_disconnect, oauth_status tools
APIs/backend-vitto-api/src/app/tools/plugins/plugins.index.ts MODIFY Register oauth plugin in getAllToolPlugins()
libs/libs-ai/vitto-hub/src/lib/components/channel-manager/ MODIFY Add Connected Services tab

Section 5: Dual-Backend Data Flow

Who Owns What

Data Owner Why
User identity, OAuth tokens, billing backend-api (gograb-api) User data
Decisions, embeddings, patterns, episodes backend-ai-api (ai-agents, ai-memory, ai-mcp-dev) Intelligence layer
Agent execution, tools, SSE, personas, skills backend-vitto-api (vitto-mind) Execution layer
User intelligence (dossiers, job mastery) backend-vitto-api (vitto-users) Vitto's understanding of users

Per Sub-Vitto Execution Data Flow

BEFORE execution — PULL:
  vitto-api → ai-api: getLearningIntelligence(), findSimilarDecisions(), recallEpisodes()
  vitto-api → Redis: GET oauth:{userId}:* (connection status, ~1ms)
  → These enrich the sub-Vitto's system prompt

DURING execution — vitto-api only:
  AgentLoopService.run() → tools → SSE events
  (ai-api NOT called during loop — no latency penalty)
  (OAuth calls proxy through backend-api when tools need external APIs)

AFTER execution — PUSH:
  vitto-api → ai-api: logDecision(), createReflection(), reportOutcome()
  ai-api processes asynchronously: embed, trigger evaluation, pattern mining

What Gets Smarter Over Time

ai-api intelligence grows:
  More decisions → better vector search
  More outcomes → more accurate patterns
  More reflections → richer episodic memory
  More users → stronger platform intelligence (anonymous)
  Daily golden sync → sub-agents inherit best practices

vitto-api execution improves:
  Strategy memories → SmartRouter picks better models
  Trust scores → autonomy escalates
  Skill confidence → better skills injected
  User dossier → persona drift reflects real expertise
  Execution traces → observability catches regressions
  Eval framework → nightly quality gates

Section 6: Vitto's Soul — Personality Drift + Visual Evolution

Only Vitto Gets a Soul

Vitto Sub-Agents
Identity Living, evolving, unique Functional, purpose-built
Personality Drifts over time based on interaction patterns Fixed system prompt
Visual Avatar evolves with accumulated knowledge depth Simple icon per role
Memory Deep, cross-channel, permanent Task-scoped, discarded after
Conscience Yes — SSE stream of inner monologue No

Personality Drift

DossierPersonaAdapterService (already built, S231.2) enhanced with auto-apply:

Confidence Action
> 0.8 Apply automatically, notify via conscience event
0.5 - 0.8 Suggest via conscience, wait for user reaction
< 0.5 Log internally, don't surface

Drift mechanics: user message length patterns → explanationDepth, technical vocabulary → formality, response speed to tones → humorLevel, explicit corrections → immediate.

Max 10% slider change per cycle. 24h per-user cooldown (already implemented).

Visual Evolution

Maturity score (computed, not stored). Each input normalized to 0-1 before weighting:

normalize(memoryCount, 500) × 30      // 500 memories = fully mature on this axis
+ normalize(executionCount, 200) × 20  // 200 tasks = fully mature
+ normalize(dossierDepth, 50) × 30     // 50 facts/preferences = fully mature
+ normalize(skillsUsed, 20) × 20       // 20 distinct skills = fully mature
= 0-100

where normalize(value, max) = min(value / max, 1.0)
Score Stage Mood Aura
0-20 Nascent Curious — simple, minimal features
20-40 Aware Attentive — more defined
40-60 Connected Engaged — rich details, warm aura
60-80 Attuned Confident — complex features
80-100 Transcendent Masterful — full visual richness

Uses existing MoodDefinitionService (14 moods, 27 facial/body properties).

Conscience event on stage change:

evolution.visual → { stage, previousStage, trigger }

Files to Create/Modify

File Action Purpose
APIs/backend-vitto-api/src/app/engine/dossier-persona-adapter.service.ts MODIFY Add auto-apply with confidence thresholds
APIs/backend-vitto-api/src/app/engine/vitto-evolution.service.ts NEW Maturity score computation + stage transitions
libs/libs-ai/vitto-hub/src/lib/components/brain/ MODIFY Wire brain visualization to live maturity data

Section 7: Teams Channel Adapter

Follows existing adapter pattern exactly.

Files to Create/Modify

NOTE: Existing channel adapters live in APIs/backend-vitto-api/src/app/engine/adapters/ (e.g., WhatsAppChannelAdapter, WebChatChannelAdapter), NOT in libs/libs-api/messaging-core/. Follow existing pattern.

File Action Purpose
APIs/backend-vitto-api/src/app/engine/adapters/teams-channel.adapter.ts NEW Bot Framework adapter (follows WhatsApp adapter pattern)
APIs/backend-vitto-api/src/app/connectivity/teams/teams-webhook.controller.ts NEW Incoming webhook handler
APIs/backend-vitto-api/src/app/engine/engine.module.ts MODIFY Register TeamsChannelAdapter in CHANNEL_ADAPTERS factory
libs/libs-ai/vitto-hub/src/lib/components/channel-manager/ MODIFY Add Teams to channel wizard

Frontend

Add "Microsoft Teams" to ChannelManagerComponent wizard at /vitto/channels.

Package: yarn add botbuilder @microsoft/botframework-connector Env vars: TEAMS_APP_ID, TEAMS_APP_PASSWORD Effort: 1 session.


Section 8: Full-Stack Wiring Map

Rule: If it exists in the backend, it must be visible and usable in the frontend.

Route Integration

All new functionality integrates into existing VittoUnifiedShell:

/vitto
  ├── /brain            → Wire visual evolution from live conscience events
  ├── /maker            → Sub-agent creation shortcut in capabilities section
  ├── /agents           → Extend: marketplace tab, chat-based creation, teach-by-correction
  ├── /channels         → Add: Connected Services tab (OAuth), Teams wizard
  ├── /conscience       → Wire evolution events (personality drift)
  ├── /settings         → Add VM config (pool size, limits) for admins
  └── /identity         → Wire evolution milestones

/operations
  ├── /agents           → Show active sub-Vittos with live progress
  ├── /system           → Add VM pool health
  └── NEW: /live        → Agent Teamwork View (parallel sub-Vitto monitor)

/command
  ├── /costs            → Per-sub-Vitto cost breakdown
  └── NEW: /integrations → OAuth admin dashboard

Chat Panel — Sub-Vitto Activity Renderer

When Vitto deploys sub-Vittos, the chat shows a collapsible card group:

┌─────────────────────────────────────┐
│ Deploying 3 agents                  │
│                                     │
│ ▸ Security Review (in-process) ✓    │
│ ▸ Test Writer (VM) ⏳ running...    │
│ ▸ Decision Search (in-process) ✓    │
│                                     │
│ Round 1 complete. Synthesizing...   │
└─────────────────────────────────────┘

New renderer: SubVittoOrchestrationRenderer — follows existing tool renderer pattern.

SSE Events

Existing (keep): agent.iteration, agent.text, tool.starting, tool.called,
                 phase.started, phase.completed, task.stuck

New:
  subvitto.spawned    → { parentTaskId, subTaskId, tier, description }
  subvitto.progress   → { subTaskId, iteration, currentTool }
  subvitto.completed  → { subTaskId, result, cost, duration }
  subvitto.failed     → { subTaskId, error }
  orchestrator.round  → { roundNumber, subTaskIds, synthesis }
  evolution.drift     → { trait, oldValue, newValue, reason }
  evolution.visual    → { stage, previousStage, trigger }

Async Patterns (No New Communication Patterns)

Communication Pattern Already Used By
vitto-api → ai-api intelligence BackendAiClientService HTTP Context assembly
vitto-api → backend-api user data BackendApiClientService HTTP User resolution
vitto-api → backend-api OAuth proxy BackendApiClientService HTTP NEW — same pattern
vitto-api → sandbox orchestrator InfrastructureClientService HTTP Computer Use
vitto-api → frontend SSE via events$ Subject Chat streaming
Cross-service cache Shared Redis Rate limiting, BullMQ
OAuth status Shared Redis NEW — same Redis
Sub-Vitto results → orchestrator Promise.allSettled() in-process Agent loop parallel tools
Evolution events → conscience VittoNarrativeService.emitConscience() Already exists

Section 9: MongoDB Cleanup

Collections to DROP from vitto-mind

Collection Reason Command
channel-user-links Orphaned since S129. No schema, no writer. User identity lives in gograb-api.user-channel-identities. db.getCollection('channel-user-links').drop()
vitto-task-history Ghost entry in retention policy. No schema exists. db.getCollection('vitto-task-history').drop() (if exists)

Code Cleanup

File Action Change
APIs/backend-vitto-api/src/app/engine/compliance.service.ts MODIFY Remove { collection: 'vitto-task-history', maxAgeDays: 180, enabled: true } from retentionPolicies array

Collections That Stay in vitto-mind (Clarification)

Collection Concern Verdict
user-budgets Billing? KEEP. Vitto's per-user LLM cost limits. Billing is in gograb-api.billing_accounts.
user-briefs User profile? KEEP. Vitto-generated 200-token summaries. Regenerated daily. Not user-owned.
user-patterns User data? KEEP. Vitto's detected patterns. Vitto's intelligence, not user profile.
user-notification-prefs Preferences? KEEP. Vitto notification routing. Not same as gograb-api.user_preferences.
vitto-user-configs Settings? KEEP. Vitto execution mode, autonomy. Vitto-scoped.
encrypted-secrets Credentials? KEEP for Vitto operational secrets only. New user OAuth → gograb-api.user_oauth_connections.
spending-records Billing? KEEP. Per-task LLM cost records. Vitto's operational ledger.

New Collection (on gograb-api)

Collection Database Purpose
user_oauth_connections gograb-api User OAuth tokens + connection state

Section 10: Success Criteria

Feature Metric Target
Sub-Vitto engine Parallel dispatch completes 3 sub-tasks All 3 return results, synthesis coherent
VM agents Code agent writes + tests in sandbox yarn test passes in VM, results returned
OAuth (Google) End-to-end: connect → agent reads calendar Calendar events displayed in chat
OAuth (GitHub) Agent creates issue on user's repo Issue appears on GitHub
Expert sub-agents Chat-based creation + Quick Test Agent created in <30s, test returns result
Personality drift Auto-adjustment after 10+ interactions Persona slider moves, conscience event emitted
Visual evolution Brain visualization changes at stage boundary Avatar aura changes from Nascent → Aware
Teams channel Message in Teams → Vitto responds End-to-end within 5s
MongoDB cleanup Drop orphaned collections 2 collections removed, zero data loss
Inter-service perf OAuth status check latency <2ms via Redis (not 15ms HTTP)

Section 11: Build Order

Week 1-2: Sub-Vitto Engine
  └── deploy_agents tool + SubVittoOrchestratorService
  └── SubAgentService calls AgentLoopService.run()
  └── Role-based tool filtering
  └── SSE events for sub-Vitto progress
  └── Chat renderer for parallel execution

Week 3-4: VM Agent Tier + MongoDB Cleanup
  └── SandboxedToolProxy
  └── VM pool service (warm pool)
  └── Base snapshot creation
  └── Drop orphaned collections
  └── Remove ghost retention policy entry

Week 4-5: OAuth Infrastructure
  └── Verify RedisModule is imported in all 3 APIs (backend-api, ai-api, vitto-api)
  └── UserOAuthConnection schema in backend-core
  └── OAuth controller + service on backend-api
  └── Google + GitHub provider configs
  └── CredentialBridgeService OAuth proxy path on vitto-api
  └── oauth_connect + oauth_api_call tool plugins + register in plugins.index.ts
  └── Redis cache integration (oauth:{userId}:{provider} keys)
  └── Connected Services UI component in /vitto/channels

Week 5-6: Expert Sub-Agent UX + Teams
  └── SubAgentService.generateDefinition() (chat-based creation)
  └── SubAgentService.marketplace() (separate from PersonaService)
  └── Teach-by-correction flow in Sub-Agent Manager
  └── Teams channel adapter (in engine/adapters/, not messaging-core)
  └── Admin OAuth dashboard at /command/integrations
  └── Operations /live route for parallel sub-Vitto monitor

Week 6-7: Vitto's Soul
  └── Personality drift auto-apply
  └── VittoEvolutionService (maturity score)
  └── Brain visualization wired to live data
  └── Conscience events for drift + visual changes

Week 7-8: Integration + Polish
  └── Slack + Notion OAuth providers (or Composio for these)
  └── Operations live view (parallel sub-Vitto monitor)
  └── Per-sub-Vitto cost breakdown in command dashboard
  └── Full wiring verification (every backend feature visible in UI)

Appendix A: Existing Infrastructure Leverage

What We're Building Existing Infrastructure We Reuse
Sub-Vitto execution AgentLoopService.run() — same engine, different context
VM tool routing InfrastructureClientService — already connects to Hetzner
OAuth encryption SecretVaultService pattern — AES-256-GCM, proven
OAuth Redis cache Shared Redis — already deployed, connected to all 3 APIs
OAuth consent flow McpOAuthController — PKCE pattern already implemented
Sub-agent marketplace PersonaService marketplace UX pattern (cards, ratings, publish). Data layer: new SubAgentService.marketplace()
Chat-based creation SkillManagerService.generateSkill() LLM generation pattern. Output: new SubAgentService.generateDefinition()
Teams adapter 2 existing adapter classes (WhatsAppChannelAdapter, WebChatChannelAdapter) + ChannelGatewayService as templates
Evolution events VittoNarrativeService.emitConscience() — SSE already wired
Brain visualization VittoBrainVisualizationComponent — exists, just static
Tool security ToolSecurityService — audit, allowlist, injection guard
Cost tracking CostTrackerService — per-task USD, fixed in S231.2
Trust escalation TrustEscalationService — per-action adaptive thresholds

Appendix B: What This Spec Does NOT Cover

  1. Voice pipeline — explicitly deferred by product owner
  2. Browser extension relay — VM agents cover 80% of same need
  3. VWU billing — business/pricing decision
  4. Visual DAG builder — OpenAI's game, not ours
  5. Platform skill aggregation — needs 1000+ active users
  6. Cross-channel genome — valuable but not in this phase. Deferred to next spec.
  7. Closed-loop skill learning — confidence tiers + anti-pattern mining. Deferred to next spec.
  8. SSE ticket auth — ALREADY IMPLEMENTED in S232.2 (Track A)
  9. AgentProcess redirect — ALREADY IMPLEMENTED in S232.2 (Track A)
  10. Audit TTL — ALREADY IMPLEMENTED in S232.2 (Track A)

Owner: fguijarro Session: S232 Date: 2026-03-18 Estimated effort: ~8 weeks, phased delivery Next step: Implementation plan via writing-plans skill