@metricai/node-sdk
v0.1.0
Published
MetricAI SDK for Node.js - Gemini support through the MetricAI proxy
Downloads
26
Maintainers
Readme
MetricAI Node.js SDK
A lightweight Node.js SDK for using Google Gemini through the MetricAI proxy, providing metering, billing, and cost tracking for AI applications.
What is MetricAI?
MetricAI is an AI billing and metering proxy for India (INR/UPI). It sits between your application and LLM providers to:
- Track usage across agents and users
- Bill accurately with usage-based, outcome-based, or hybrid modes
- Set budget caps to prevent runaway costs
- Provide dashboards for monitoring spend
Features
- 🚀 Simple API — Drop-in replacement for
@google/generative-ai - 💰 Metering & Billing — Automatic cost tracking per agent/user/session
- 🎯 Attribution — Track which agent and user made each request
- 💳 Budget Caps — Set INR limits per request or globally
- 🧾 Billing Modes — Usage, outcome, or hybrid billing
- 🔑 BYOK Support — Bring your own Gemini keys
- 📊 Dashboard Integration — View costs in real-time
- 🔒 TypeScript — Full type safety with IntelliSense
- 🌊 Streaming — Support for streaming responses
Installation
npm install @metricai/node-sdkPeer Dependency Required:
The SDK wraps @google/generative-ai, which you must install separately:
npm install @google/generative-aiQuick Start
1. Get Your API Key
Sign up at metricai.co.in and get your API key (starts with mk_live_ or mk_test_).
2. Basic Usage
import { MetricAI } from '@metricai/node-sdk';
// Initialize the client
const client = new MetricAI({ apiKey: 'mk_live_your_api_key' });
// Get a Gemini model through the MetricAI proxy
const model = client.gemini().getGenerativeModel({
model: 'gemini-2.0-flash',
});
// Make API calls
const result = await model.generateContent('Hello, world!');
console.log(result.response.text());That's it! Your request is now routed through MetricAI and being metered.
Usage Patterns
With Attribution (Track Agents & Users)
const client = new MetricAI({
apiKey: 'mk_live_your_api_key',
agentId: 'my-chatbot', // Which agent/service
userId: 'user-12345', // Which end user
billingMode: 'hybrid', // How to bill
budgetCapInr: 100, // Cap at ₹100 per day
});
// All requests will be attributed to this agent/user
const model = client.gemini().getGenerativeModel({
model: 'gemini-2.0-flash',
});
const result = await model.generateContent('Summarize this document...');Per-Request Overrides
Override attribution settings for specific requests:
const model = client.gemini({
agentId: 'priority-agent',
budgetCapInr: 500,
}).getGenerativeModel({
model: 'gemini-2.0-flash',
});
const result = await model.generateContent('Complex task requiring higher budget...');Multiple Agents
Create separate client instances for different parts of your application:
const chatbotClient = new MetricAI({
apiKey: process.env.METRICAI_API_KEY,
agentId: 'chatbot-agent',
});
const summarizerClient = new MetricAI({
apiKey: process.env.METRICAI_API_KEY,
agentId: 'summarizer-agent',
});
// Chatbot request
const chatModel = chatbotClient.gemini().getGenerativeModel({ model: 'gemini-2.0-flash' });
const chatResult = await chatModel.generateContent('Hello!');
// Summarizer request
const summaryModel = summarizerClient.gemini().getGenerativeModel({ model: 'gemini-pro' });
const summaryResult = await summaryModel.generateContent('Summarize this text...');Bring Your Own Keys (BYOK)
If you have your own Gemini API key, use BYOK mode:
const client = new MetricAI({
apiKey: 'mk_live_metricai_key', // MetricAI key for auth
geminiApiKey: 'your_gemini_api_key', // Your Gemini key for billing
});Generation Configuration
Pass standard Gemini generation config:
const model = client.gemini().getGenerativeModel({
model: 'gemini-2.0-flash',
generationConfig: {
temperature: 0.7,
maxOutputTokens: 2048,
topP: 0.9,
topK: 40,
},
});
const result = await model.generateContent({
contents: [{
role: 'user',
parts: [{ text: 'Explain quantum computing in simple terms.' }],
}],
});System Instructions
const model = client.gemini().getGenerativeModel({
model: 'gemini-2.0-flash',
systemInstruction: {
parts: [{
text: 'You are a helpful coding assistant. Always explain your reasoning.',
}],
},
});
const result = await model.generateContent('How do I sort an array?');Multi-Turn Conversations
const chat = client.gemini().startChat({
history: [
{ role: 'user', parts: [{ text: 'What is Node.js?' }] },
{ role: 'model', parts: [{ text: 'Node.js is a JavaScript runtime...' }] },
],
});
const response = await chat.sendMessage('And what is npm?');
console.log(response.response.text());
const response2 = await chat.sendMessage('Thanks!');
console.log(response2.response.text());Streaming Responses
const model = client.gemini().getGenerativeModel({
model: 'gemini-2.0-flash',
});
const streamingResult = await model.generateContentStream('Write a story about a robot.');
for await (const chunk of streamingResult.stream) {
const text = chunk.text();
process.stdout.write(text);
}
console.log('\n');Raw Headers (Manual HTTP)
If you're not using the SDK directly, you can still use MetricAI headers:
import { buildHeaders, mergeHeaders } from '@metricai/node-sdk';
// Build headers for manual fetch/axios calls
const headers = buildHeaders({
apiKey: 'mk_live_your_api_key',
agentId: 'my-agent',
userId: 'user-123',
billingMode: 'hybrid',
budgetCapInr: 50,
});
// Use with fetch
const response = await fetch(
'https://proxy.metricai.co.in/v1/proxy/gemini/v1beta/models/gemini-2.0-flash:generateContent',
{
method: 'POST',
headers: {
...headers,
'Content-Type': 'application/json',
},
body: JSON.stringify({
contents: [{ parts: [{ text: 'Hello!' }] }],
}),
}
);
const data = await response.json();
console.log(data.candidates?.[0]?.content?.parts?.[0]?.text);Configuration
MetricAIOptions
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiKey | string | required | Your MetricAI API key |
| baseUrl | string | Production proxy | Custom proxy URL (for self-hosted) |
| geminiApiKey | string | MetricAI key | Your Gemini API key (BYOK mode) |
| agentId | string | 'default-agent' | Default agent identifier |
| userId | string | 'anonymous' | Default user identifier |
| sessionId | string | auto-generated | Conversation session ID (UUID) |
| billingMode | BillingMode | 'hybrid' | Billing mode |
| budgetCapInr | number | undefined | Default budget cap in INR |
| environment | Environment | 'production' | 'production' or 'sandbox' |
Billing Modes
| Mode | Description |
|------|-------------|
| usage | Pay per token used (input + output) |
| outcome | Pay on successful outcome (e.g., booking confirmed) |
| hybrid | Combination of usage + outcome charges |
Environment Modes
| Mode | Description |
|------|-------------|
| production | Routes to live MetricAI proxy |
| sandbox | Routes to sandbox/testing environment |
Environment Variables
The SDK automatically reads these environment variables:
| Variable | Description |
|----------|-------------|
| METRICAI_API_KEY | Your MetricAI API key |
Error Handling
import { MetricAI } from '@metricai/node-sdk';
const client = new MetricAI({ apiKey: 'mk_live_your_api_key' });
const model = client.gemini().getGenerativeModel({ model: 'gemini-2.0-flash' });
try {
const result = await model.generateContent('Hello!');
console.log(result.response.text());
} catch (error: any) {
if (error.response) {
// API returned an error
console.error('API Error:', error.response.status, error.response.data);
} else if (error.code === 'ECONNREFUSED') {
// Proxy unreachable (fail-open: request may still go through)
console.error('Could not connect to MetricAI proxy');
} else {
// Other error
console.error('Error:', error.message);
}
}TypeScript Support
The SDK is written in TypeScript and provides full type definitions:
import { MetricAI, MetricAIOptions, BillingMode } from '@metricai/node-sdk';
const options: MetricAIOptions = {
apiKey: 'mk_live_your_api_key',
agentId: 'my-agent',
userId: 'user-123',
billingMode: 'hybrid' as BillingMode,
budgetCapInr: 100,
};
const client = new MetricAI(options);Common Issues
"MetricAI API key is required"
Make sure you've provided a valid API key:
const client = new MetricAI({ apiKey: 'mk_live_your_key' });Requests are not appearing in dashboard
Check that your agentId and userId are being set correctly. Each unique agentId + userId combination creates a separate cost center in the dashboard.
Budget exceeded errors
If you're hitting budget caps, increase the budgetCapInr value or set it to undefined to remove the cap:
const client = new MetricAI({
apiKey: 'mk_live_your_key',
budgetCapInr: undefined, // No budget cap
});SDK Architecture
┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐
│ Your App │────▶│ MetricAI SDK │────▶│ MetricAI │
│ (Node.js) │ │ (adds headers) │ │ Proxy │
└─────────────────┘ └─────────────────┘ └──────────────┘
│
▼
┌──────────────┐
│ Google │
│ Gemini API │
└──────────────┘Testing
# Run unit tests
npm test
# Run tests in watch mode
npm run test:watch
# Type check
npm run lint
# Build
npm run buildLicense
MIT
