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
- Vitto is the living entity. Only Vitto has personality, conscience, visual evolution. Sub-agents are sharp tools.
- backend-ai-api = intelligence. backend-vitto-api = execution. backend-api = user data. None are deprecated. All grow together.
- Vitto is sole executor. All LLM calls go through vitto-api. Zero shadow execution paths.
- User data belongs to gograb-api. OAuth tokens, preferences, identity — all in the user's database. Vitto reads, never owns.
- Shared Redis for cross-service state. All 3 APIs share one Redis. Use it for caches, locks, pub/sub.
- If it exists in the backend, it must be visible in the frontend. No orphaned services.
- 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:
AgentLoopService.run()requiresAgentLoopOptions(layer,taskId,sseSubject) — sub-Vittos need synthetic valuesAgentLoopService.run()usesToolRegistryService.getToolsForUser()— role-based filtering must integrate with this, not bypass it- The current
SUB_AGENT_TOOLSstatic list must be converted to plugin-style handlers filtered by the sub-agent's role/tier - Sub-Vitto SSE events must be scoped to the parent task (prefixed with
subvitto.*) to avoid polluting the main event stream
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:
- Node.js (LTS) + yarn + npm
- Python 3 + pip
- git, curl, build-essential
- Chrome (for browser-tier — reuses CU infrastructure)
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
- Max VM lifetime: configurable (default 15 min)
- CostGuard applies same as in-process
- VM destroyed after task — no state leaks between users
- Network policy: same
NetworkPolicyServicerules apply - All configurable per user via
VittoUserConfigDoc
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
- Side-by-side: agent vs. default Vitto on same prompt
- Teach by correction: wrong answer → show right answer → auto-saved as training example
- Cost/quality score displayed after each run
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 |
|---|---|---|---|
| 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:
- Card grid: Google, GitHub, Slack, Notion
- Each shows: status, connected email, scopes, last used
- [Connect] / [Manage] / [Disconnect] actions
Admin view at /command/integrations:
- Total connections by status (active/expired/revoked)
- By provider breakdown
- Recent activity feed
- Token health overview
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
- Voice pipeline — explicitly deferred by product owner
- Browser extension relay — VM agents cover 80% of same need
- VWU billing — business/pricing decision
- Visual DAG builder — OpenAI's game, not ours
- Platform skill aggregation — needs 1000+ active users
- Cross-channel genome — valuable but not in this phase. Deferred to next spec.
- Closed-loop skill learning — confidence tiers + anti-pattern mining. Deferred to next spec.
- SSE ticket auth — ALREADY IMPLEMENTED in S232.2 (Track A)
- AgentProcess redirect — ALREADY IMPLEMENTED in S232.2 (Track A)
- 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