— No reviews yet
0 installs
17 views
0.0% view→install
Install
$ agentstack add skill-bobmatnyc-claude-mpm-skills-openrouter ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Are you the author of Openrouter? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claimAbout
OpenRouter - Unified AI API Gateway
Overview
OpenRouter provides a single API to access 200+ language models from OpenAI, Anthropic, Google, Meta, Mistral, and more. It offers intelligent routing, streaming, cost optimization, and standardized OpenAI-compatible interface.
Key Features:
- Access 200+ models through one API
- OpenAI-compatible interface (drop-in replacement)
- Intelligent model routing and fallbacks
- Real-time streaming responses
- Cost tracking and optimization
- Model performance analytics
- Function calling support
- Vision model support
Pricing Model:
- Pay-per-token (no subscriptions)
- Volume discounts available
- Free tier with credits
- Per-model pricing varies
Installation:
npm install openai # Use OpenAI SDK
# or
pip install openai # Python
Quick Start
1. Get API Key
# Sign up at https://openrouter.ai/keys
export OPENROUTER_API_KEY="sk-or-v1-..."
2. Basic Chat Completion
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://openrouter.ai/api/v1',
apiKey: process.env.OPENROUTER_API_KEY,
defaultHeaders: {
'HTTP-Referer': 'https://your-app.com', // Optional
'X-Title': 'Your App Name', // Optional
}
});
async function chat() {
const completion = await client.chat.completions.create({
model: 'anthropic/claude-3.5-sonnet',
messages: [
{ role: 'user', content: 'Explain quantum computing in simple terms' }
],
});
console.log(completion.choices[0].message.content);
}
3. Streaming Response
async function streamChat() {
const stream = await client.chat.completions.create({
model: 'openai/gpt-4-turbo',
messages: [
{ role: 'user', content: 'Write a short story about AI' }
],
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
process.stdout.write(content);
}
}
Model Selection Strategy
Available Model Categories
Flagship Models (Highest Quality):
const flagshipModels = {
claude: 'anthropic/claude-3.5-sonnet', // Best reasoning
gpt4: 'openai/gpt-4-turbo', // Best general purpose
gemini: 'google/gemini-pro-1.5', // Best long context
opus: 'anthropic/claude-3-opus', // Best complex tasks
};
Fast Models (Low Latency):
const fastModels = {
claude: 'anthropic/claude-3-haiku', // Fastest Claude
gpt35: 'openai/gpt-3.5-turbo', // Fast GPT
gemini: 'google/gemini-flash-1.5', // Fast Gemini
llama: 'meta-llama/llama-3.1-8b-instruct', // Fast open source
};
Cost-Optimized Models:
const budgetModels = {
haiku: 'anthropic/claude-3-haiku', // $0.25/$1.25 per 1M tokens
gemini: 'google/gemini-flash-1.5', // $0.075/$0.30 per 1M tokens
llama: 'meta-llama/llama-3.1-8b-instruct', // $0.06/$0.06 per 1M tokens
mixtral: 'mistralai/mixtral-8x7b-instruct', // $0.24/$0.24 per 1M tokens
};
Specialized Models:
const specializedModels = {
vision: 'openai/gpt-4-vision-preview', // Image understanding
code: 'anthropic/claude-3.5-sonnet', // Code generation
longContext: 'google/gemini-pro-1.5', // 2M token context
function: 'openai/gpt-4-turbo', // Function calling
};
Model Selection Logic
interface ModelSelector {
task: 'chat' | 'code' | 'vision' | 'function' | 'summary';
priority: 'quality' | 'speed' | 'cost';
maxCost?: number; // Max cost per 1M tokens
contextSize?: number;
}
function selectModel(criteria: ModelSelector): string {
if (criteria.task === 'vision') {
return 'openai/gpt-4-vision-preview';
}
if (criteria.task === 'code') {
return criteria.priority === 'quality'
? 'anthropic/claude-3.5-sonnet'
: 'meta-llama/llama-3.1-70b-instruct';
}
if (criteria.contextSize && criteria.contextSize > 100000) {
return 'google/gemini-pro-1.5'; // 2M context
}
// Default selection by priority
switch (criteria.priority) {
case 'quality':
return 'anthropic/claude-3.5-sonnet';
case 'speed':
return 'anthropic/claude-3-haiku';
case 'cost':
return criteria.maxCost && criteria.maxCost line.trim());
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') continue;
try {
const parsed = JSON.parse(data);
const content = parsed.choices[0]?.delta?.content || '';
setResponse(prev => prev + content);
} catch (e) {
// Skip invalid JSON
}
}
}
}
} catch (error) {
console.error('Streaming error:', error);
} finally {
setIsStreaming(false);
}
}
return (
handleSubmit('Explain AI')}>
{isStreaming ? 'Streaming...' : 'Send'}
);
}
Function Calling
Basic Function Calling
const tools = [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get current weather for a location',
parameters: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'City name, e.g. San Francisco',
},
unit: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
},
},
required: ['location'],
},
},
},
];
async function chatWithFunctions() {
const completion = await client.chat.completions.create({
model: 'openai/gpt-4-turbo',
messages: [
{ role: 'user', content: 'What is the weather in Tokyo?' }
],
tools,
tool_choice: 'auto',
});
const message = completion.choices[0].message;
if (message.tool_calls) {
for (const toolCall of message.tool_calls) {
console.log('Function:', toolCall.function.name);
console.log('Arguments:', toolCall.function.arguments);
// Execute function
const args = JSON.parse(toolCall.function.arguments);
const result = await getWeather(args.location, args.unit);
// Send result back
const followUp = await client.chat.completions.create({
model: 'openai/gpt-4-turbo',
messages: [
{ role: 'user', content: 'What is the weather in Tokyo?' },
message,
{
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(result),
},
],
tools,
});
console.log(followUp.choices[0].message.content);
}
}
}
Multi-Step Function Calling
async function multiStepFunctionCall(userQuery: string) {
const messages = [{ role: 'user', content: userQuery }];
let iterationCount = 0;
const maxIterations = 5;
while (iterationCount maxCostPerRequest) {
// Try cheaper models
const cheapEstimate = estimateCost(
prompt,
1000,
'anthropic/claude-3-haiku'
);
if (cheapEstimate.totalCost > maxCostPerRequest) {
selectedModel = 'google/gemini-flash-1.5';
} else {
selectedModel = 'anthropic/claude-3-haiku';
}
}
console.log(`Selected model: ${selectedModel}`);
const completion = await client.chat.completions.create({
model: selectedModel,
messages: [{ role: 'user', content: prompt }],
});
return completion.choices[0].message.content;
}
Batching for Cost Reduction
async function batchProcess(prompts: string[], model: string) {
// Process multiple prompts in parallel with rate limiting
const concurrency = 5;
const results = [];
for (let i = 0; i
client.chat.completions.create({
model,
messages: [{ role: 'user', content: prompt }],
max_tokens: 500, // Limit tokens to control cost
})
)
);
results.push(...batchResults);
// Rate limiting delay
if (i + concurrency setTimeout(resolve, 1000));
}
}
return results;
}
Model Fallback and Retry Strategy
Automatic Fallback
const modelFallbackChain = [
'anthropic/claude-3.5-sonnet',
'openai/gpt-4-turbo',
'anthropic/claude-3-haiku',
'google/gemini-flash-1.5',
];
async function chatWithFallback(
prompt: string,
maxRetries: number = 3
): Promise {
for (const model of modelFallbackChain) {
try {
console.log(`Trying model: ${model}`);
const completion = await client.chat.completions.create({
model,
messages: [{ role: 'user', content: prompt }],
max_tokens: 2000,
});
return completion.choices[0].message.content || '';
} catch (error) {
console.warn(`Model ${model} failed:`, error);
// Continue to next model
if (model === modelFallbackChain[modelFallbackChain.length - 1]) {
throw new Error('All models failed');
}
}
}
throw new Error('No models available');
}
Exponential Backoff for Rate Limits
async function retryWithBackoff(
fn: () => Promise,
maxRetries: number = 5
): Promise {
let lastError: Error;
for (let i = 0; i setTimeout(resolve, delay));
} else {
throw error; // Non-retryable error
}
}
}
throw lastError!;
}
// Usage
const result = await retryWithBackoff(() =>
client.chat.completions.create({
model: 'anthropic/claude-3.5-sonnet',
messages: [{ role: 'user', content: 'Hello' }],
})
);
Prompt Engineering Best Practices
System Prompts for Consistency
const systemPrompts = {
concise: 'You are a helpful assistant. Be concise and direct.',
detailed: 'You are a knowledgeable expert. Provide comprehensive answers with examples.',
code: 'You are an expert programmer. Provide clean, well-commented code with explanations.',
creative: 'You are a creative writing assistant. Be imaginative and engaging.',
};
async function chatWithPersonality(
prompt: string,
personality: keyof typeof systemPrompts
) {
const completion = await client.chat.completions.create({
model: 'anthropic/claude-3.5-sonnet',
messages: [
{ role: 'system', content: systemPrompts[personality] },
{ role: 'user', content: prompt },
],
});
return completion.choices[0].message.content;
}
Few-Shot Prompting
async function fewShotClassification(text: string) {
const completion = await client.chat.completions.create({
model: 'openai/gpt-4-turbo',
messages: [
{
role: 'system',
content: 'Classify text sentiment as positive, negative, or neutral.',
},
{ role: 'user', content: 'I love this product!' },
{ role: 'assistant', content: 'positive' },
{ role: 'user', content: 'This is terrible.' },
{ role: 'assistant', content: 'negative' },
{ role: 'user', content: 'It works fine.' },
{ role: 'assistant', content: 'neutral' },
{ role: 'user', content: text },
],
});
return completion.choices[0].message.content;
}
Chain of Thought Prompting
async function reasoningTask(problem: string) {
const completion = await client.chat.completions.create({
model: 'anthropic/claude-3.5-sonnet',
messages: [
{
role: 'user',
content: `${problem}\n\nLet's solve this step by step:\n1.`,
},
],
max_tokens: 3000,
});
return completion.choices[0].message.content;
}
Rate Limits and Throttling
Rate Limit Handler
class RateLimitedClient {
private requestQueue: Array Promise> = [];
private processing = false;
private requestsPerMinute = 60;
private requestInterval = 60000 / this.requestsPerMinute;
async enqueue(request: () => Promise): Promise {
return new Promise((resolve, reject) => {
this.requestQueue.push(async () => {
try {
const result = await request();
resolve(result);
} catch (error) {
reject(error);
}
});
this.processQueue();
});
}
private async processQueue() {
if (this.processing || this.requestQueue.length === 0) return;
this.processing = true;
while (this.requestQueue.length > 0) {
const request = this.requestQueue.shift()!;
await request();
await new Promise(resolve => setTimeout(resolve, this.requestInterval));
}
this.processing = false;
}
}
// Usage
const rateLimitedClient = new RateLimitedClient();
const result = await rateLimitedClient.enqueue(() =>
client.chat.completions.create({
model: 'anthropic/claude-3.5-sonnet',
messages: [{ role: 'user', content: 'Hello' }],
})
);
Vision Models
Image Understanding
async function analyzeImage(imageUrl: string, question: string) {
const completion = await client.chat.completions.create({
model: 'openai/gpt-4-vision-preview',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: question },
{ type: 'image_url', image_url: { url: imageUrl } },
],
},
],
max_tokens: 1000,
});
return completion.choices[0].message.content;
}
// Usage
const result = await analyzeImage(
'https://example.com/image.jpg',
'What objects are in this image?'
);
Multi-Image Analysis
async function compareImages(imageUrls: string[]) {
const completion = await client.chat.completions.create({
model: 'openai/gpt-4-vision-preview',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Compare these images and describe the differences:' },
...imageUrls.map(url => ({
type: 'image_url' as const,
image_url: { url },
})),
],
},
],
});
return completion.choices[0].message.content;
}
Error Handling and Monitoring
Comprehensive Error Handler
interface ErrorResponse {
error: {
message: string;
type: string;
code: string;
};
}
async function robustCompletion(prompt: string) {
try {
const completion = await client.chat.completions.create({
model: 'anthropic/claude-3.5-sonnet',
messages: [{ role: 'user', content: prompt }],
});
return completion.choices[0].message.content;
} catch (error: any) {
// Rate limit errors
if (error.status === 429) {
console.error('Rate limit exceeded. Please wait.');
throw new Error('RATE_LIMIT_EXCEEDED');
}
// Invalid API key
if (error.status === 401) {
console.error('Invalid API key');
throw new Error('INVALID_API_KEY');
}
// Model not found
if (error.status === 404) {
console.error('Model not found');
throw new Error('MODEL_NOT_FOUND');
}
// Server errors
if (error.status >= 500) {
console.error('OpenRouter server error');
throw new Error('SERVER_ERROR');
}
// Unknown error
console.error('Unknown error:', error);
throw error;
}
}
Request/Response Logging
class LoggingClient {
async chat(prompt: string, model: string) {
const startTime = Date.now();
console.log('[Request]', {
timestamp: new Date().toISOString(),
model,
promptLength: prompt.length,
});
try {
const completion = await client.chat.completions.create({
model,
messages: [{ role: 'user', content: prompt }],
});
const duration = Date.now() - startTime;
console.log('[Response]', {
timestamp: new Date().toISOString(),
duration,
usage: completion.usage,
finishReason: completion.choices[0].finish_reason,
});
return completion;
} catch (error) {
console.error('[Error]',
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [bobmatnyc](https://github.com/bobmatnyc)
- **Source:** [bobmatnyc/claude-mpm-skills](https://github.com/bobmatnyc/claude-mpm-skills)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.