Architecture: How should the LLM provider layer be designed for Vitto?
Documentation for Sessions
🏗️ Architecture: How should the LLM provider layer be designed for Vitto?
Date: 2026-02-07
Time: 18:11:03 UTC
Session: gspace1-98.4
Agent: backend
Confidence: 92%
Status: ✅ Documented
📋 Decision Context
Question:
How should the LLM provider layer be designed for Vitto?
Task: Vitto LLM provider abstraction
🎯 Decision Made
Chosen:
Provider-agnostic LLM abstraction with BaseLLMProvider abstract class, concrete providers for Claude/OpenAI/Gemini, and ProviderFactory with env-driven selection and fallback chains
Options Considered:
- Direct Anthropic SDK only
- Provider-agnostic abstraction layer
- LangChain integration
- Custom SDK wrapper per provider
💭 Reasoning
Adopted from gmodules1's battle-tested BaseLLMProvider pattern. Unified interface (sendMessage/streamMessage) with each provider translating to/from native format (Anthropic tool_use blocks, OpenAI function_calling, Google functionCall). Tool definitions are provider-agnostic — ToolRegistry stores unified format, provider adapts at call time. Env-driven via VITTO_LLM_PROVIDER with automatic fallback to next healthy provider.
📁 Files Involved
apis/backend-vitto-api/src/app/llm/base.provider.tsapis/backend-vitto-api/src/app/llm/providers/claude.provider.tsapis/backend-vitto-api/src/app/llm/providers/openai.provider.tsapis/backend-vitto-api/src/app/llm/provider-factory.service.ts
🔗 Related
- Decision ID:
dev_1770487863292_efp5lkq - Session: 98
- Workspace: gspace1
Auto-generated by MCP Smart Consolidation