API Provider Standardization - Implementation Plan
API Provider Standardization - Implementation Plan
Date: 2025-12-11
Author: CTO Developer (Claude Code Session)
Status: Ready for Implementation
Reference: ARCHITECTURE_API_Provider_Standardization_2025-12-11.md
Executive Summary
This document extends the architecture report with a complete implementation plan addressing two distinct layers:
- Service Metadata Layer (Phases 1-3) - From architecture doc
- Runtime API Format Layer (Phase 4) - From earlier debugging session
The architecture doc correctly identifies the service metadata standardization needs, but does not address the runtime API calling mechanism that was fixed during the chat debugging session (see DATA_WORKFLOW_Chat_API_Flow_2025-12-11.md).
Two-Layer Problem Analysis
Layer 1: Service Metadata (Architecture Doc Scope)
Problem: 492 providers in vendor library, only 7 have detailed configs. Missing fields prevent:
- Displaying available models (GPT-4, Claude 3, etc.)
- OAuth scope requirements
- Multi-credential providers (account_name + api_key)
- Onboarding guidance
Solution: Extend ai.service.type model with new fields, create JSON schema validation.
Layer 2: Runtime API Format (Earlier Session Scope)
Problem: Different providers use different API formats at runtime:
- Anthropic format: messages array + separate system parameter
- OpenAI format: messages array with system as first message
Current State: Hardcoded API_FORMAT_MAP in ai_service.py (30+ providers mapped to 2 formats)
Solution: Move format mapping to database/JSON for UI-based configuration.
4-Phase Implementation Plan
┌─────────────────────────────────────────────────────────────────────────────┐
│ PHASE OVERVIEW │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ PHASE 1: Model Enhancement (ai.service.type) [1-2 hrs] │
│ ├── Add 6 new fields to Odoo model │
│ ├── Add config_completeness computed field │
│ └── Update ACL if needed │
│ │
│ PHASE 2: Service Populator Update [1 hr] │
│ ├── Map new JSON fields to Odoo model │
│ ├── Handle missing fields gracefully │
│ └── Set config_completeness based on data │
│ │
│ PHASE 3: JSON Schema & Validation [1-2 hrs] │
│ ├── Create service_config.schema.json │
│ ├── Add schema_version to existing 7 service configs │
│ └── Optional: Add schema validation to populator │
│ │
│ PHASE 4: Runtime API Format (Data-Driven) [2-3 hrs] │
│ ├── Add api_format field to api.service.provider │
│ ├── Remove hardcoded API_FORMAT_MAP from ai_service.py │
│ ├── Read format from provider record at runtime │
│ └── Update cache to include api_format │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Phase 1: Model Enhancement
Priority: HIGH
Effort: 1-2 hours
File: ai_sam_base/models/ai_service_type.py
New Fields to Add
# ==========================================================================
# PHASE 1: Service Metadata Enhancement (2025-12-11)
# Reference: ARCHITECTURE_API_Provider_Standardization_2025-12-11.md
# ==========================================================================
# Schema Version Tracking
schema_version = fields.Char(
string='Schema Version',
default='1.0',
help='Version of the service config schema this record follows'
)
# Supported Models (for AI providers)
supported_models = fields.Json(
string='Supported Models',
help='List of model identifiers (e.g., ["gpt-4", "gpt-3.5-turbo", "claude-3-sonnet"])'
)
# OAuth Scopes (for OAuth providers)
required_scopes = fields.Json(
string='Required OAuth Scopes',
help='OAuth scopes required (e.g., ["gmail.send", "gmail.readonly"])'
)
# Multi-Credential Support
required_credentials = fields.Json(
string='Required Credentials',
help='Additional credential fields beyond API key (e.g., account_name for ActiveCampaign)'
)
# Configuration Hints (onboarding help)
configuration_hints = fields.Json(
string='Configuration Hints',
help='Setup instructions: {auth_setup: "...", common_issues: [...]}'
)
# Config Completeness Tracking
config_completeness = fields.Selection([
('none', 'Not Configured'),
('basic', 'Basic (Metadata Only)'),
('full', 'Full (Ready for Integration)')
], string='Configuration Completeness', default='none',
compute='_compute_config_completeness', store=True)
Compute Method
@api.depends('api_base_url', 'operations', 'auth_method')
def _compute_config_completeness(self):
"""Determine config completeness based on populated fields"""
for record in self:
if record.operations and record.api_base_url and record.auth_method:
record.config_completeness = 'full'
elif record.vendor_key and record.service_key:
record.config_completeness = 'basic'
else:
record.config_completeness = 'none'
Success Criteria
- [ ] 6 new fields added to model
- [ ] Module upgrade succeeds without errors
- [ ] Existing data preserved
- [ ] Can filter by
config_completeness = 'full'
Phase 2: Service Populator Update
Priority: HIGH
Effort: 1 hour
File: ai_sam_base/controllers/service_populator_controller.py
Update service_values Dict
service_values = {
# ... existing fields ...
# NEW: Schema version (Phase 1)
'schema_version': service_data.get('schema_version', '1.0'),
# NEW: Model support
'supported_models': service_data.get('supported_models', []),
# NEW: OAuth scopes
'required_scopes': service_data.get('required_scopes', []),
# NEW: Multi-credential support
'required_credentials': service_data.get('required_credentials', []),
# NEW: Configuration hints
'configuration_hints': service_data.get('configuration_hints', {}),
}
Success Criteria
- [ ] Populator handles new fields
- [ ] Missing fields default gracefully (no errors)
- [ ] Re-import existing 7 services works
- [ ] New fields populated where present in JSON
Phase 3: JSON Schema & Validation
Priority: MEDIUM
Effort: 1-2 hours
Files:
- ai_sam/static/src/vendor_library/_schema/service_config.schema.json (NEW)
- ai_sam/static/src/vendor_library/OpenAi/services/*.json (UPDATE)
- ai_sam/static/src/vendor_library/Google/services/*.json (UPDATE)
- ai_sam/static/src/vendor_library/ActiveCampaign/services/*.json (UPDATE)
Create Schema File
See architecture doc for full schema. Key additions:
- schema_version (string, default "1.0")
- supported_models (array of strings)
- required_scopes (array of strings)
- required_credentials (array of objects)
- configuration_hints (object)
Update Existing Service Configs
Add to each of the 7 existing service JSON files:
{
"schema_version": "1.0",
// ... existing fields ...
}
Success Criteria
- [ ] Schema file created and valid JSON Schema
- [ ] All 7 existing configs validate against schema
- [ ] schema_version added to all existing configs
Phase 4: Runtime API Format (Data-Driven)
Priority: HIGH (impacts chat functionality)
Effort: 2-3 hours
Files:
- ai_sam_base/models/api_service_provider.py - Add field
- ai_sam_base/models/ai_service.py - Remove hardcoded map, use field
- ai_sam_base/models/sam_user_settings.py - Include in cache
Current State (Hardcoded)
From ai_service.py:
API_FORMAT_MAP = {
'anthropic': 'anthropic',
'claude': 'anthropic',
'openai': 'openai',
'azure_openai': 'openai',
'groq': 'openai',
'together': 'openai',
'mistral': 'openai',
'deepseek': 'openai',
'ollama': 'openai',
'openrouter': 'openai',
# ... 20+ more providers
}
Target State (Data-Driven)
Step 4.1: Add Field to api.service.provider
# In api_service_provider.py
api_format = fields.Selection([
('openai', 'OpenAI Compatible'),
('anthropic', 'Anthropic/Claude'),
('google', 'Google/Gemini'),
('custom', 'Custom Handler'),
], string='API Format', default='openai',
help='Which API format this provider uses for chat completions')
Step 4.2: Update ai_service.py
Replace:
api_format = self._get_api_format(config.api_provider) # Uses hardcoded map
With:
# Get format from provider record (data-driven)
api_format = config.api_format or self._get_api_format_fallback(config.api_provider)
Keep API_FORMAT_MAP as fallback for providers without explicit format set.
Step 4.3: Update Provider Cache
In sam_user_settings.py, the cached config already includes api_provider. Add api_format:
cache_data = {
'provider_id': selected_provider.id,
'provider_name': selected_provider.name,
'model_name': recommended_model_name,
'api_provider': config.api_provider,
'api_format': config.api_format, # NEW
'estimated_cost': recommendation.get('estimated_cost', 0),
}
Step 4.4: Auto-Populate Format from Supplier
When provider is created/updated with a supplier value, auto-set api_format:
def write(self, vals):
result = super().write(vals)
# Auto-set api_format based on supplier if not explicitly set
if 'supplier' in vals and 'api_format' not in vals:
for provider in self:
if not provider.api_format:
provider.api_format = provider._detect_api_format_from_supplier()
return result
def _detect_api_format_from_supplier(self):
"""Detect API format from supplier name"""
supplier = (self.supplier or '').lower()
if 'anthropic' in supplier or 'claude' in supplier:
return 'anthropic'
elif 'google' in supplier or 'gemini' in supplier:
return 'google'
else:
return 'openai' # Default to OpenAI format (most common)
Success Criteria
- [ ]
api_formatfield added toapi.service.provider - [ ] Existing providers auto-populated with correct format
- [ ] Chat works with format read from database
- [ ] Hardcoded
API_FORMAT_MAPonly used as fallback - [ ] Cache includes
api_format - [ ] UI allows changing provider's API format
Dependency Graph
Phase 1 ──┬── Phase 2 ──── Phase 3
│
└── (independent) ── Phase 4
- Phases 1-2 are tightly coupled (model + populator)
- Phase 3 depends on Phases 1-2 (needs fields to exist)
- Phase 4 is independent (different model:
api.service.providervsai.service.type)
Recommended Execution Order
Option A: Metadata First (Architecture Doc Path)
- Phase 1 + Phase 2 together (2-3 hours)
- Phase 3 (1-2 hours)
- Phase 4 (2-3 hours)
Total: ~6-8 hours
Option B: Runtime First (Chat Functionality Priority)
- Phase 4 (2-3 hours) - Immediate benefit to chat
- Phase 1 + Phase 2 (2-3 hours)
- Phase 3 (1-2 hours)
Total: ~6-8 hours (same, different order)
Recommendation
Option B - Phase 4 first, because:
- Chat is already working with hardcoded map
- Making it data-driven enables UI configuration immediately
- Phases 1-3 are about future-proofing the vendor library (less urgent)
Risk Assessment
| Phase | Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|---|
| 1 | Field type errors | Low | Medium | Use Json fields for flexibility |
| 2 | Missing field breaks import | Low | High | Default all new fields |
| 3 | Schema too strict | Medium | Low | Start permissive, tighten later |
| 4 | Wrong format breaks chat | Medium | High | Keep fallback map, test thoroughly |
Version Tracking
After each phase, bump module version:
| Phase | Module | Version | Comment |
|---|---|---|---|
| Current | ai_sam_base | 18.0.2.25 | Defensive caching |
| Phase 1 | ai_sam_base | 18.0.2.26 | Service type model enhancement |
| Phase 2 | ai_sam_base | 18.0.2.27 | Populator new field mapping |
| Phase 3 | ai_sam | TBD | JSON schema validation |
| Phase 4 | ai_sam_base | 18.0.2.28 | Data-driven API format |
Files to Modify (Complete List)
Phase 1
| File | Action |
|---|---|
ai_sam_base/models/ai_service_type.py |
Add 6 fields + compute method |
ai_sam_base/__manifest__.py |
Bump version |
Phase 2
| File | Action |
|---|---|
ai_sam_base/controllers/service_populator_controller.py |
Map new fields |
ai_sam_base/__manifest__.py |
Bump version |
Phase 3
| File | Action |
|---|---|
ai_sam/static/src/vendor_library/_schema/service_config.schema.json |
CREATE |
ai_sam/static/src/vendor_library/OpenAi/services/*.json |
Add schema_version |
ai_sam/static/src/vendor_library/Google/services/*.json |
Add schema_version |
ai_sam/static/src/vendor_library/ActiveCampaign/services/*.json |
Add schema_version |
Phase 4
| File | Action |
|---|---|
ai_sam_base/models/api_service_provider.py |
Add api_format field |
ai_sam_base/models/ai_service.py |
Use field instead of hardcoded map |
ai_sam_base/models/sam_user_settings.py |
Include api_format in cache |
ai_sam_base/__manifest__.py |
Bump version |
Related Documents
- ARCHITECTURE_API_Provider_Standardization_2025-12-11.md - Original architecture analysis
- DATA_WORKFLOW_Chat_API_Flow_2025-12-11.md - Chat debugging session that revealed Phase 4 need
Document Status: Ready for Implementation
Next Action: Decide execution order (Option A or B), then begin Phase 1 or Phase 4
Estimated Total Effort: 6-8 hours across all phases