Quickstart
Get Kalibr working in 5 minutes.
Prerequisites
- Python 3.10+ (check with
python --version) - Provider API keys for models you want to use (OpenAI, Anthropic, etc.)
1. Install
Install Kalibr and provider SDKs for your models:
pip install kalibr openai anthropic
npm install @kalibr/sdk openai @anthropic-ai/sdk
2. Set your keys
Get your Kalibr key from dashboard.kalibr.systems
export KALIBR_API_KEY=your-api-key
export KALIBR_TENANT_ID=your-tenant-id
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
Important: You need API keys for each provider in your paths. If you use gpt-4o, you need OPENAI_API_KEY. If you use claude-sonnet-4-20250514, you need ANTHROPIC_API_KEY.
3. Replace your LLM call
Before (hardcoded model):
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Extract the company: Hi from Stripe"}]
)
After (Kalibr picks the model):
from kalibr import Router
router = Router(
goal="extract_company",
paths=["gpt-4o", "claude-sonnet-4-20250514"]
)
response = router.completion(
messages=[{"role": "user", "content": "Extract the company: Hi from Stripe"}]
)
router.report(success=True)
Before (hardcoded model):
import OpenAI from 'openai';
const client = new OpenAI();
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'Extract the company: Hi from Stripe' }],
});
After (Kalibr picks the model):
import { Router } from '@kalibr/sdk';
const router = new Router({
goal: 'extract_company',
paths: ['gpt-4o', 'claude-sonnet-4-20250514'],
});
const response = await router.completion([
{ role: 'user', content: 'Extract the company: Hi from Stripe' }
]);
await router.report(true);
That's it. Kalibr now picks which model to use and learns from the outcome.
3.5 Handle Errors
Provider errors (rate limits, API issues) pass through Kalibr. Wrap your calls in try/catch:
try:
response = router.completion(
messages=[{"role": "user", "content": "Extract the company: Hi from Stripe"}]
)
result = response.choices[0].message.content
router.report(success=len(result) > 0)
except Exception as e:
# Kalibr automatically reports failure on exception
print(f"Error: {e}")
# Handle gracefully - retry, fallback, or alert
try {
const response = await router.completion(messages);
const result = response.choices[0].message.content;
await router.report(result.length > 0);
} catch (error) {
// Kalibr automatically reports failure on exception
console.error('Error:', error);
// Handle gracefully
}
Note: Kalibr automatically reports a failure when an exception occurs, so routing still learns from errors.
4. Report outcomes
Kalibr learns from outcomes. Call report() after you know if it worked.
response = router.completion(messages=[...])
result = response.choices[0].message.content
if result and len(result) > 0:
router.report(success=True)
else:
router.report(success=False, reason="empty_response")
For simple checks, use success_when to auto-report:
router = Router(
goal="extract_company",
paths=["gpt-4o", "claude-sonnet-4-20250514"],
success_when=lambda output: len(output) > 0
)
response = router.completion(messages=[...])
# report() called automatically
const response = await router.completion(messages);
const result = response.choices[0].message.content;
if (result && result.length > 0) {
await router.report(true);
} else {
await router.report(false, 'empty_response');
}
For simple checks, use successWhen to auto-report:
const router = new Router({
goal: 'extract_company',
paths: ['gpt-4o', 'claude-sonnet-4-20250514'],
successWhen: (output) => output.length > 0,
});
const response = await router.completion(messages);
// report() called automatically
More success_when Examples
# Check for email format
router = Router(
goal="extract_email",
paths=["gpt-4o-mini", "claude-sonnet-4-20250514"],
success_when=lambda output: "@" in output and "." in output
)
# Check for valid JSON
router = Router(
goal="generate_json",
paths=["gpt-4o", "claude-sonnet-4-20250514"],
success_when=lambda output: output.strip().startswith("{")
)
# Check minimum word count
router = Router(
goal="write_summary",
paths=["gpt-4o", "claude-sonnet-4-20250514"],
success_when=lambda output: len(output.split()) >= 50
)
// Check for email format
const router = new Router({
goal: 'extract_email',
paths: ['gpt-4o-mini', 'claude-sonnet-4-20250514'],
successWhen: (output) => output.includes('@') && output.includes('.')
});
// Check for valid JSON
const router = new Router({
goal: 'generate_json',
paths: ['gpt-4o', 'claude-sonnet-4-20250514'],
successWhen: (output) => output.trim().startsWith('{')
});
// Check minimum word count
const router = new Router({
goal: 'write_summary',
paths: ['gpt-4o', 'claude-sonnet-4-20250514'],
successWhen: (output) => output.split(' ').length >= 50
});
When NOT to use success_when: Use manual report() if success depends on external APIs, multi-step validation, or you need to include a failure reason.
See which model was chosen
Check the response to see which model Kalibr selected:
response = router.completion(messages=[...])
print(f"Kalibr chose: {response.model}")
# Output: Kalibr chose: gpt-4o-mini
const response = await router.completion(messages);
console.log(`Kalibr chose: ${response.model}`);
// Output: Kalibr chose: gpt-4o-mini
5. Check your dashboard
Go to dashboard.kalibr.systems to see:
- Success rate per model
- Which model Kalibr is routing to
- Cost per successful call
After ~20-50 outcomes per path, routing becomes stable and Kalibr will favor the model that works best for your goal.
What just happened
- Kalibr registered your two paths
- On
completion(), Kalibr picked a model (exploring early on) - The call went directly to the provider (OpenAI or Anthropic)
- On
report(), Kalibr recorded the outcome - Next time, Kalibr uses this to make a better choice
Common Mistakes
- Missing provider SDK - If you get "No module named 'anthropic'", run
pip install anthropic - Forgetting report() - Kalibr can't learn if you don't report outcomes. Always call
report(). - Wrong Python version - Kalibr requires Python 3.10+. Check with
python --version.
Next
- Core Concepts - Goals, paths, how routing works
- API Reference - Full Router API
- Production Guide - Error handling, multi-turn, threads