Full Chain Example¶
Complete end-to-end workflow demonstrating the full SaaS LiteLLM platform lifecycle.
Overview¶
This example shows the complete workflow from organization setup to making LLM calls:
- Create organization
- Create model groups
- Create team with credits
- Create job
- Make LLM calls
- Complete job
- Track credits
Prerequisites¶
- SaaS API running on
http://localhost:8003 - LiteLLM Backend running on
http://localhost:8002 - LiteLLM configured with at least one model (e.g.,
gpt-3.5-turbo)
Python Example¶
Complete Workflow¶
import requests
import json
from typing import Dict, Any
# Configuration
API_URL = "http://localhost:8003/api"
ADMIN_KEY = "sk-admin-key-change-me" # For org/team creation
class SaaSLiteLLMClient:
"""Complete client for SaaS LiteLLM platform"""
def __init__(self, api_url: str = "http://localhost:8003/api"):
self.api_url = api_url
self.admin_headers = {
"Authorization": f"Bearer {ADMIN_KEY}",
"Content-Type": "application/json"
}
self.team_headers = None
self.team_id = None
self.virtual_key = None
# ========================================================================
# Step 1: Organization Management
# ========================================================================
def create_organization(self, org_id: str, name: str, metadata: Dict = None) -> Dict[str, Any]:
"""Create a new organization"""
response = requests.post(
f"{self.api_url}/organizations/create",
headers=self.admin_headers,
json={
"organization_id": org_id,
"name": name,
"metadata": metadata or {}
}
)
if response.status_code == 400 and "already exists" in response.text:
print(f"Organization {org_id} already exists, fetching details...")
return self.get_organization(org_id)
response.raise_for_status()
return response.json()
def get_organization(self, org_id: str) -> Dict[str, Any]:
"""Get organization details"""
response = requests.get(
f"{self.api_url}/organizations/{org_id}",
headers=self.admin_headers
)
response.raise_for_status()
return response.json()
# ========================================================================
# Step 2: Model Group Management
# ========================================================================
def create_model_group(
self,
group_name: str,
display_name: str,
description: str,
models: list
) -> Dict[str, Any]:
"""Create a model group with prioritized models"""
response = requests.post(
f"{self.api_url}/model-groups/create",
headers=self.admin_headers,
json={
"group_name": group_name,
"display_name": display_name,
"description": description,
"models": models
}
)
if response.status_code == 400 and "already exists" in response.text:
print(f"Model group {group_name} already exists")
return self.get_model_group(group_name)
response.raise_for_status()
return response.json()
def get_model_group(self, group_name: str) -> Dict[str, Any]:
"""Get model group details"""
response = requests.get(
f"{self.api_url}/model-groups/{group_name}",
headers=self.admin_headers
)
response.raise_for_status()
return response.json()
# ========================================================================
# Step 3: Team Management
# ========================================================================
def create_team(
self,
organization_id: str,
team_id: str,
team_alias: str,
model_groups: list,
credits_allocated: int
) -> Dict[str, Any]:
"""Create team with LiteLLM integration and credits"""
response = requests.post(
f"{self.api_url}/teams/create",
headers=self.admin_headers,
json={
"organization_id": organization_id,
"team_id": team_id,
"team_alias": team_alias,
"model_groups": model_groups,
"credits_allocated": credits_allocated
}
)
if response.status_code == 400 and "already exists" in response.text:
print(f"Team {team_id} already exists, fetching details...")
return self.get_team(team_id)
response.raise_for_status()
result = response.json()
# Store virtual key for future requests
self.virtual_key = result.get("virtual_key")
self.team_id = team_id
self.team_headers = {
"Authorization": f"Bearer {self.virtual_key}",
"Content-Type": "application/json"
}
return result
def get_team(self, team_id: str) -> Dict[str, Any]:
"""Get team details"""
response = requests.get(
f"{self.api_url}/teams/{team_id}",
headers=self.admin_headers
)
response.raise_for_status()
return response.json()
def set_virtual_key(self, virtual_key: str, team_id: str):
"""Set virtual key for team operations"""
self.virtual_key = virtual_key
self.team_id = team_id
self.team_headers = {
"Authorization": f"Bearer {virtual_key}",
"Content-Type": "application/json"
}
# ========================================================================
# Step 4: Credit Management
# ========================================================================
def get_credit_balance(self) -> Dict[str, Any]:
"""Get credit balance for authenticated team"""
if not self.team_headers:
raise ValueError("No team authenticated. Call create_team or set_virtual_key first.")
response = requests.get(
f"{self.api_url}/credits/teams/{self.team_id}/balance",
headers=self.team_headers
)
response.raise_for_status()
return response.json()
def add_credits(self, credits: int, reason: str = "Manual allocation") -> Dict[str, Any]:
"""Add credits to team"""
if not self.team_headers:
raise ValueError("No team authenticated")
response = requests.post(
f"{self.api_url}/credits/teams/{self.team_id}/add",
headers=self.team_headers,
json={
"credits": credits,
"reason": reason
}
)
response.raise_for_status()
return response.json()
# ========================================================================
# Step 5: Job & LLM Call Workflow
# ========================================================================
def create_job(self, job_type: str, metadata: Dict = None) -> str:
"""Create a new job"""
if not self.team_headers:
raise ValueError("No team authenticated")
response = requests.post(
f"{self.api_url}/jobs/create",
headers=self.team_headers,
json={
"team_id": self.team_id,
"job_type": job_type,
"metadata": metadata or {}
}
)
response.raise_for_status()
result = response.json()
return result["job_id"]
def make_llm_call(
self,
job_id: str,
model_group: str,
messages: list,
purpose: str = None,
temperature: float = 0.7,
max_tokens: int = None
) -> Dict[str, Any]:
"""Make an LLM call within a job"""
if not self.team_headers:
raise ValueError("No team authenticated")
payload = {
"model_group": model_group,
"messages": messages,
"temperature": temperature
}
if purpose:
payload["purpose"] = purpose
if max_tokens:
payload["max_tokens"] = max_tokens
response = requests.post(
f"{self.api_url}/jobs/{job_id}/llm-call",
headers=self.team_headers,
json=payload
)
response.raise_for_status()
return response.json()
def complete_job(
self,
job_id: str,
status: str = "completed",
error_message: str = None
) -> Dict[str, Any]:
"""Complete a job and get cost summary"""
if not self.team_headers:
raise ValueError("No team authenticated")
payload = {"status": status}
if error_message:
payload["error_message"] = error_message
response = requests.post(
f"{self.api_url}/jobs/{job_id}/complete",
headers=self.team_headers,
json=payload
)
response.raise_for_status()
return response.json()
def get_job(self, job_id: str) -> Dict[str, Any]:
"""Get job details"""
if not self.team_headers:
raise ValueError("No team authenticated")
response = requests.get(
f"{self.api_url}/jobs/{job_id}",
headers=self.team_headers
)
response.raise_for_status()
return response.json()
# ============================================================================
# Complete End-to-End Example
# ============================================================================
def full_workflow_example():
"""
Complete workflow:
1. Create organization
2. Create model groups
3. Create team
4. Create job
5. Make LLM calls
6. Complete job
7. Check credits
"""
client = SaaSLiteLLMClient()
print("="*70)
print("SAAS LITELLM - FULL WORKFLOW EXAMPLE")
print("="*70)
# Step 1: Create Organization
print("\n[1/7] Creating Organization...")
org = client.create_organization(
org_id="acme-corp",
name="Acme Corporation",
metadata={"industry": "technology", "tier": "enterprise"}
)
print(f"✓ Organization created: {org['organization_id']}")
# Step 2: Create Model Groups
print("\n[2/7] Creating Model Groups...")
# Fast model group for quick tasks
fast_group = client.create_model_group(
group_name="ChatFast",
display_name="Fast Chat Model",
description="Quick responses for simple queries",
models=[
{"model_name": "gpt-3.5-turbo", "priority": 0},
{"model_name": "gpt-4o-mini", "priority": 1}
]
)
print(f"✓ Model group created: {fast_group['group_name']}")
# Advanced model group for complex tasks
advanced_group = client.create_model_group(
group_name="ChatAdvanced",
display_name="Advanced Chat Model",
description="Powerful model for complex reasoning",
models=[
{"model_name": "gpt-4", "priority": 0},
{"model_name": "gpt-4-turbo", "priority": 1}
]
)
print(f"✓ Model group created: {advanced_group['group_name']}")
# Step 3: Create Team
print("\n[3/7] Creating Team with Credits...")
team = client.create_team(
organization_id="acme-corp",
team_id="engineering-team",
team_alias="Engineering Team",
model_groups=["ChatFast", "ChatAdvanced"],
credits_allocated=100
)
print(f"✓ Team created: {team['team_id']}")
print(f" Virtual Key: {team['virtual_key'][:50]}...")
print(f" Credits: {team['credits_allocated']}")
print(f" Model Groups: {', '.join(team['model_groups'])}")
# Step 4: Check Initial Credits
print("\n[4/7] Checking Initial Credit Balance...")
credits = client.get_credit_balance()
print(f"✓ Credits available: {credits['credits_remaining']}/{credits['credits_allocated']}")
# Step 5: Create Job
print("\n[5/7] Creating Job...")
job_id = client.create_job(
job_type="customer_support",
metadata={
"customer_id": "customer_12345",
"priority": "high"
}
)
print(f"✓ Job created: {job_id}")
# Step 6: Make LLM Calls
print("\n[6/7] Making LLM Calls...")
# First call - initial response
print(" → Call 1: Initial customer query...")
response1 = client.make_llm_call(
job_id=job_id,
model_group="ChatFast",
messages=[
{
"role": "system",
"content": "You are a helpful customer support assistant."
},
{
"role": "user",
"content": "How do I reset my password?"
}
],
purpose="initial_response"
)
print(f" Response: {response1['response']['content'][:100]}...")
print(f" Tokens: {response1['metadata']['tokens_used']}")
print(f" Latency: {response1['metadata']['latency_ms']}ms")
# Second call - follow-up
print("\n → Call 2: Follow-up question...")
response2 = client.make_llm_call(
job_id=job_id,
model_group="ChatFast",
messages=[
{
"role": "system",
"content": "You are a helpful customer support assistant."
},
{
"role": "user",
"content": "How do I reset my password?"
},
{
"role": "assistant",
"content": response1['response']['content']
},
{
"role": "user",
"content": "I didn't receive the reset email."
}
],
purpose="follow_up"
)
print(f" Response: {response2['response']['content'][:100]}...")
print(f" Tokens: {response2['metadata']['tokens_used']}")
# Third call - complex analysis using advanced model
print("\n → Call 3: Complex analysis...")
response3 = client.make_llm_call(
job_id=job_id,
model_group="ChatAdvanced",
messages=[
{
"role": "user",
"content": "Analyze this customer interaction and suggest improvements to our password reset process."
}
],
purpose="analysis",
temperature=0.3
)
print(f" Response: {response3['response']['content'][:100]}...")
print(f" Tokens: {response3['metadata']['tokens_used']}")
# Step 7: Complete Job
print("\n[7/7] Completing Job...")
completion = client.complete_job(
job_id=job_id,
status="completed"
)
print(f"✓ Job completed: {completion['job_id']}")
print(f"\n Cost Summary:")
print(f" Total calls: {completion['costs']['total_calls']}")
print(f" Successful: {completion['costs']['successful_calls']}")
print(f" Failed: {completion['costs']['failed_calls']}")
print(f" Total tokens: {completion['costs']['total_tokens']}")
print(f" Total cost: ${completion['costs']['total_cost_usd']:.6f}")
print(f" Avg latency: {completion['costs']['avg_latency_ms']}ms")
print(f" Credit applied: {completion['costs']['credit_applied']}")
print(f" Credits remaining: {completion['costs']['credits_remaining']}")
# Final credit check
print("\n[FINAL] Credit Balance After Job...")
final_credits = client.get_credit_balance()
print(f"✓ Credits: {final_credits['credits_remaining']}/{final_credits['credits_allocated']}")
print(f" Credits used: {final_credits['credits_used']}")
print("\n" + "="*70)
print("WORKFLOW COMPLETED SUCCESSFULLY!")
print("="*70)
return {
"organization": org,
"team": team,
"job_id": job_id,
"completion": completion
}
if __name__ == "__main__":
try:
result = full_workflow_example()
print("\n✅ All steps completed successfully!")
except requests.exceptions.ConnectionError as e:
print(f"\n❌ Connection Error: Could not connect to API")
print("Make sure SaaS API is running: http://localhost:8003")
except Exception as e:
print(f"\n❌ Error: {str(e)}")
import traceback
traceback.print_exc()
JavaScript/Node.js Example¶
const axios = require('axios');
class SaaSLiteLLMClient {
constructor(apiUrl = 'http://localhost:8003/api') {
this.apiUrl = apiUrl;
this.adminKey = 'sk-admin-key-change-me';
this.virtualKey = null;
this.teamId = null;
}
// Create Organization
async createOrganization(orgId, name, metadata = {}) {
try {
const response = await axios.post(
`${this.apiUrl}/organizations/create`,
{
organization_id: orgId,
name: name,
metadata: metadata
},
{
headers: {
'Authorization': `Bearer ${this.adminKey}`,
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
if (error.response?.status === 400 && error.response.data.detail?.includes('already exists')) {
return await this.getOrganization(orgId);
}
throw error;
}
}
// Create Model Group
async createModelGroup(groupName, displayName, description, models) {
try {
const response = await axios.post(
`${this.apiUrl}/model-groups/create`,
{
group_name: groupName,
display_name: displayName,
description: description,
models: models
},
{
headers: {
'Authorization': `Bearer ${this.adminKey}`,
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
if (error.response?.status === 400) {
return await this.getModelGroup(groupName);
}
throw error;
}
}
// Create Team
async createTeam(organizationId, teamId, teamAlias, modelGroups, creditsAllocated) {
const response = await axios.post(
`${this.apiUrl}/teams/create`,
{
organization_id: organizationId,
team_id: teamId,
team_alias: teamAlias,
model_groups: modelGroups,
credits_allocated: creditsAllocated
},
{
headers: {
'Authorization': `Bearer ${this.adminKey}`,
'Content-Type': 'application/json'
}
}
);
this.virtualKey = response.data.virtual_key;
this.teamId = teamId;
return response.data;
}
// Get team headers
getTeamHeaders() {
if (!this.virtualKey) {
throw new Error('No team authenticated');
}
return {
'Authorization': `Bearer ${this.virtualKey}`,
'Content-Type': 'application/json'
};
}
// Create Job
async createJob(jobType, metadata = {}) {
const response = await axios.post(
`${this.apiUrl}/jobs/create`,
{
team_id: this.teamId,
job_type: jobType,
metadata: metadata
},
{ headers: this.getTeamHeaders() }
);
return response.data.job_id;
}
// Make LLM Call
async makeLLMCall(jobId, modelGroup, messages, options = {}) {
const response = await axios.post(
`${this.apiUrl}/jobs/${jobId}/llm-call`,
{
model_group: modelGroup,
messages: messages,
temperature: options.temperature || 0.7,
purpose: options.purpose,
max_tokens: options.maxTokens
},
{ headers: this.getTeamHeaders() }
);
return response.data;
}
// Complete Job
async completeJob(jobId, status = 'completed', errorMessage = null) {
const response = await axios.post(
`${this.apiUrl}/jobs/${jobId}/complete`,
{
status: status,
error_message: errorMessage
},
{ headers: this.getTeamHeaders() }
);
return response.data;
}
// Get Credit Balance
async getCreditBalance() {
const response = await axios.get(
`${this.apiUrl}/credits/teams/${this.teamId}/balance`,
{ headers: this.getTeamHeaders() }
);
return response.data;
}
}
// Full workflow example
async function fullWorkflowExample() {
const client = new SaaSLiteLLMClient();
console.log('='.repeat(70));
console.log('SAAS LITELLM - FULL WORKFLOW EXAMPLE (JavaScript)');
console.log('='.repeat(70));
try {
// 1. Create Organization
console.log('\n[1/6] Creating Organization...');
const org = await client.createOrganization(
'acme-corp-js',
'Acme Corporation (JS)',
{ industry: 'technology' }
);
console.log(`✓ Organization: ${org.organization_id}`);
// 2. Create Model Group
console.log('\n[2/6] Creating Model Group...');
const modelGroup = await client.createModelGroup(
'ChatFastJS',
'Fast Chat (JS)',
'Quick responses',
[
{ model_name: 'gpt-3.5-turbo', priority: 0 },
{ model_name: 'gpt-4o-mini', priority: 1 }
]
);
console.log(`✓ Model Group: ${modelGroup.group_name}`);
// 3. Create Team
console.log('\n[3/6] Creating Team...');
const team = await client.createTeam(
'acme-corp-js',
'js-team',
'JavaScript Team',
['ChatFastJS'],
50
);
console.log(`✓ Team: ${team.team_id}`);
console.log(` Credits: ${team.credits_allocated}`);
// 4. Create Job
console.log('\n[4/6] Creating Job...');
const jobId = await client.createJob('demo', { example: 'javascript' });
console.log(`✓ Job: ${jobId}`);
// 5. Make LLM Call
console.log('\n[5/6] Making LLM Call...');
const response = await client.makeLLMCall(
jobId,
'ChatFastJS',
[
{ role: 'user', content: 'What is Node.js?' }
],
{ purpose: 'demo' }
);
console.log(`✓ Response: ${response.response.content.substring(0, 100)}...`);
console.log(` Tokens: ${response.metadata.tokens_used}`);
// 6. Complete Job
console.log('\n[6/6] Completing Job...');
const completion = await client.completeJob(jobId);
console.log(`✓ Job completed`);
console.log(` Total calls: ${completion.costs.total_calls}`);
console.log(` Credits remaining: ${completion.costs.credits_remaining}`);
console.log('\n' + '='.repeat(70));
console.log('WORKFLOW COMPLETED SUCCESSFULLY!');
console.log('='.repeat(70));
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
}
// Run the example
fullWorkflowExample();
cURL Example¶
#!/bin/bash
# Configuration
API_URL="http://localhost:8003/api"
ADMIN_KEY="sk-admin-key-change-me"
echo "======================================================================"
echo "SAAS LITELLM - FULL WORKFLOW EXAMPLE (cURL)"
echo "======================================================================"
# 1. Create Organization
echo -e "\n[1/6] Creating Organization..."
ORG_RESPONSE=$(curl -s -X POST "${API_URL}/organizations/create" \
-H "Authorization: Bearer ${ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"organization_id": "acme-corp-curl",
"name": "Acme Corporation (cURL)",
"metadata": {"industry": "technology"}
}')
echo "✓ Organization created"
# 2. Create Model Group
echo -e "\n[2/6] Creating Model Group..."
curl -s -X POST "${API_URL}/model-groups/create" \
-H "Authorization: Bearer ${ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"group_name": "ChatFastCurl",
"display_name": "Fast Chat (cURL)",
"description": "Quick responses",
"models": [
{"model_name": "gpt-3.5-turbo", "priority": 0}
]
}' > /dev/null
echo "✓ Model Group: ChatFastCurl"
# 3. Create Team
echo -e "\n[3/6] Creating Team..."
TEAM_RESPONSE=$(curl -s -X POST "${API_URL}/teams/create" \
-H "Authorization: Bearer ${ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"organization_id": "acme-corp-curl",
"team_id": "curl-team",
"team_alias": "cURL Team",
"model_groups": ["ChatFastCurl"],
"credits_allocated": 50
}')
VIRTUAL_KEY=$(echo $TEAM_RESPONSE | jq -r '.virtual_key')
echo "✓ Team created"
echo " Virtual Key: ${VIRTUAL_KEY:0:50}..."
# 4. Create Job
echo -e "\n[4/6] Creating Job..."
JOB_RESPONSE=$(curl -s -X POST "${API_URL}/jobs/create" \
-H "Authorization: Bearer ${VIRTUAL_KEY}" \
-H "Content-Type: application/json" \
-d '{
"team_id": "curl-team",
"job_type": "demo",
"metadata": {"example": "curl"}
}')
JOB_ID=$(echo $JOB_RESPONSE | jq -r '.job_id')
echo "✓ Job: $JOB_ID"
# 5. Make LLM Call
echo -e "\n[5/6] Making LLM Call..."
LLM_RESPONSE=$(curl -s -X POST "${API_URL}/jobs/${JOB_ID}/llm-call" \
-H "Authorization: Bearer ${VIRTUAL_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model_group": "ChatFastCurl",
"messages": [
{"role": "user", "content": "What is cURL?"}
],
"purpose": "demo"
}')
TOKENS=$(echo $LLM_RESPONSE | jq -r '.metadata.tokens_used')
echo "✓ LLM Call completed"
echo " Tokens: $TOKENS"
# 6. Complete Job
echo -e "\n[6/6] Completing Job..."
COMPLETE_RESPONSE=$(curl -s -X POST "${API_URL}/jobs/${JOB_ID}/complete" \
-H "Authorization: Bearer ${VIRTUAL_KEY}" \
-H "Content-Type: application/json" \
-d '{
"status": "completed"
}')
CREDITS_REMAINING=$(echo $COMPLETE_RESPONSE | jq -r '.costs.credits_remaining')
echo "✓ Job completed"
echo " Credits remaining: $CREDITS_REMAINING"
echo -e "\n======================================================================"
echo "WORKFLOW COMPLETED SUCCESSFULLY!"
echo "======================================================================"
Expected Output¶
======================================================================
SAAS LITELLM - FULL WORKFLOW EXAMPLE
======================================================================
[1/7] Creating Organization...
✓ Organization created: acme-corp
[2/7] Creating Model Groups...
✓ Model group created: ChatFast
✓ Model group created: ChatAdvanced
[3/7] Creating Team with Credits...
✓ Team created: engineering-team
Virtual Key: sk-b6f4a8c2d1e9f3a7b8c4d2e1f9a8b7c6d5e4f3a2b1c...
Credits: 100
Model Groups: ChatFast, ChatAdvanced
[4/7] Checking Initial Credit Balance...
✓ Credits available: 100/100
[5/7] Creating Job...
✓ Job created: 550e8400-e29b-41d4-a716-446655440000
[6/7] Making LLM Calls...
→ Call 1: Initial customer query...
Response: To reset your password, please click on the "Forgot Password" link on the login page...
Tokens: 156
Latency: 842ms
→ Call 2: Follow-up question...
Response: If you didn't receive the reset email, please check your spam folder...
Tokens: 134
→ Call 3: Complex analysis...
Response: Based on this interaction, I suggest the following improvements to your password reset...
Tokens: 287
[7/7] Completing Job...
✓ Job completed: 550e8400-e29b-41d4-a716-446655440000
Cost Summary:
Total calls: 3
Successful: 3
Failed: 0
Total tokens: 577
Total cost: $0.000867
Avg latency: 783ms
Credit applied: True
Credits remaining: 99
[FINAL] Credit Balance After Job...
✓ Credits: 99/100
Credits used: 1
======================================================================
WORKFLOW COMPLETED SUCCESSFULLY!
======================================================================
✅ All steps completed successfully!
Key Concepts Demonstrated¶
1. Organization Hierarchy¶
- Organizations contain teams
- Teams have model groups and credits
- Isolation between organizations
2. Model Groups¶
- Abstract model selection from clients
- Support fallback models
- Centralized model management
3. Credit System¶
- Pre-allocated credits per team
- 1 credit per successfully completed job
- Failed jobs don't consume credits
4. Job-Based Tracking¶
- Jobs group related LLM calls
- Track costs per business operation
- Associate metadata with jobs
5. Authentication¶
- Admin key for setup operations
- Virtual keys for team operations
- Team isolation enforced
Next Steps¶
- Agent Integration - Use with AI agent frameworks
- Streaming Examples - Real-time streaming responses
- Structured Outputs - Type-safe structured data
- Error Handling - Production error handling
- Best Practices - Production deployment guide