Core TypeScript SDK for Airbolt - A production-ready backend for calling LLMs from your frontend securely
🚀 Streaming by default - Responses stream in real-time for better UX. Use chatSync()
for non-streaming.
# Latest stable version
npm install @airbolt/sdk
# Beta version (latest features)
npm install @airbolt/sdk@beta
Looking for React components? Use @airbolt/react-sdk instead for the easiest integration.
Just want to get started? See the main README for the 3-step quickstart guide.
import { chat } from '@airbolt/sdk';
// Simple streaming example (default)
for await (const chunk of chat([
{ role: 'user', content: 'Hello! Tell me a joke.' },
])) {
process.stdout.write(chunk.content);
}
// Output streams in real-time: "Why don't scientists trust atoms? Because they make up everything!"
// Non-streaming example with usage info
import { chatSync } from '@airbolt/sdk';
const response = await chatSync(
[{ role: 'user', content: 'What is TypeScript?' }],
{
baseURL: 'https://your-airbolt-backend.onrender.com',
system: 'You are a helpful assistant. Keep responses concise.',
}
);
console.log(response.content); // The AI response
console.log(
`Tokens used: ${response.usage?.tokens?.used}/${response.usage?.tokens?.limit}`
);
chat()
function with streaming by defaultbaseURL
when you need a custom backendchat(messages, options?)
- Streaming (Default)Stream AI responses in real-time for a better user experience. This is the default behavior.
async function* chat(
messages: Message[],
options?: ChatOptions
): AsyncGenerator<{ content: string; type: 'chunk' | 'done' | 'error' }>;
Parameters:
messages
- Array of chat messagesoptions
- Optional configuration
baseURL
- Your Airbolt backend URL (default: http://localhost:3000
)system
- System prompt to set AI behaviorprovider
- AI provider to use: 'openai'
or 'anthropic'
(default: uses backend environment setting)model
- Specific model to use (e.g., 'gpt-4'
, 'claude-3-5-sonnet-20241022'
). Defaults to provider's default modelReturns: An async generator that yields streaming chunks
chatSync(messages, options?)
- Non-StreamingGet the complete AI response at once (traditional behavior).
function chatSync(
messages: Message[],
options?: ChatOptions
): Promise<ChatResponse>;
Parameters:
chat()
functionReturns: A ChatResponse
object containing:
content
- The complete AI assistant's responseusage
- Optional usage information (tokens used, remaining, limits)Example:
import { chat } from '@airbolt/sdk';
// Stream the response (default behavior)
for await (const chunk of chat([
{ role: 'user', content: 'Tell me a story' },
])) {
if (chunk.type === 'chunk') {
process.stdout.write(chunk.content); // Print as it arrives
} else if (chunk.type === 'done') {
console.log('\nStreaming complete!');
}
}
createChatSession(options?)
Create a persistent chat session for maintaining conversation context.
function createChatSession(options?: ChatOptions): ChatSession;
Returns: A chat session object with methods for sending messages
The SDK provides clear error messages:
import { chat, ColdStartError } from '@airbolt/sdk';
try {
const response = await chat([{ role: 'user', content: 'Hello!' }]);
} catch (error) {
if (error instanceof ColdStartError) {
console.log('Server is waking up from sleep. This may take a moment...');
} else if (error.message.includes('fetch failed')) {
console.error('Backend is not running. Start it with: pnpm dev');
} else if (error.message.includes('401')) {
console.error('Authentication failed. Token may be expired.');
} else if (error.message.includes('429')) {
console.error('Rate limit exceeded. Try again later.');
} else {
console.error('Error:', error.message);
}
}
When rate limits are exceeded, you'll receive a 429 error with usage information:
try {
const response = await chatSync([{ role: 'user', content: 'Hello' }]);
console.log(response.content);
} catch (error) {
if (error.statusCode === 429) {
console.log('Rate limit exceeded. Try again later.');
}
}
// Monitor usage proactively
const response = await chatSync([{ role: 'user', content: 'Hello' }]);
if (response.usage?.tokens) {
const { used, limit, resetAt } = response.usage.tokens;
console.log(
`Used ${used}/${limit} tokens. Resets at ${new Date(resetAt).toLocaleTimeString()}`
);
}
When using free tier deployments (like Render's free tier), servers sleep after inactivity. The SDK automatically handles this:
ColdStartError
if server still doesn't respondMaintain conversation context across multiple messages:
import { createChatSession } from '@airbolt/sdk';
// Create a session
const session = createChatSession({
baseURL: 'https://your-backend.onrender.com',
system: 'You are a helpful coding assistant',
});
// Send messages
const response1 = await session.send('What is React?');
const response2 = await session.send('Show me a simple example');
// response2 remembers the context from response1
The SDK handles JWT tokens automatically, but you can also manage them:
import { clearAuthToken, hasValidToken, getTokenInfo } from '@airbolt/sdk';
// Check if authenticated
if (hasValidToken()) {
const info = getTokenInfo();
console.log('Token expires at:', info.expiresAt);
}
// Clear token (logout)
clearAuthToken();
The SDK is built with TypeScript and provides full type definitions:
import type { Message, ChatOptions, ChatSession } from '@airbolt/sdk';
// Type-safe message arrays
const messages: Message[] = [
{ role: 'system', content: 'You are a helpful assistant' },
{ role: 'user', content: 'Hello!' },
{ role: 'assistant', content: 'Hi! How can I help you?' },
];
// Type-safe options
const options: ChatOptions = {
baseURL: 'https://api.example.com',
system: 'Be concise and friendly',
};
import { chat } from '@airbolt/sdk';
// Streaming (default)
for await (const chunk of chat([{ role: 'user', content: 'What is 2 + 2?' }])) {
process.stdout.write(chunk.content);
}
// Output: "2 + 2 equals 4"
for await (const chunk of chat(
[{ role: 'user', content: 'Write a haiku about coding' }],
{
system: 'You are a poet who writes haikus about technology',
}
)) {
process.stdout.write(chunk.content);
}
for await (const chunk of chat([{ role: 'user', content: 'Hello!' }], {
baseURL: 'https://your-app.onrender.com',
})) {
process.stdout.write(chunk.content);
}
// Use Anthropic Claude
for await (const chunk of chat(
[{ role: 'user', content: 'Explain quantum computing' }],
{
provider: 'anthropic',
model: 'claude-3-5-sonnet-20241022',
}
)) {
process.stdout.write(chunk.content);
}
// Use OpenAI GPT-4
for await (const chunk of chat(
[{ role: 'user', content: 'Write a TypeScript function' }],
{
provider: 'openai',
model: 'gpt-4',
}
)) {
if (chunk.type === 'chunk') {
process.stdout.write(chunk.content);
} else if (chunk.type === 'done' && chunk.usage) {
console.log(`\nUsed ${chunk.usage.total_tokens} tokens`);
}
}
import { chatSync } from '@airbolt/sdk';
// Track token usage
const response = await chatSync([
{ role: 'user', content: 'Explain the theory of relativity' },
]);
if (response.usage) {
console.log(`Request used ${response.usage.total_tokens} tokens`);
if (response.usage.tokens) {
const { used, remaining, limit, resetAt } = response.usage.tokens;
console.log(`Daily usage: ${used}/${limit} tokens`);
console.log(`Remaining: ${remaining} tokens`);
console.log(`Resets: ${new Date(resetAt).toLocaleString()}`);
}
}
The SDK includes working examples:
# Clone the repository
git clone https://github.com/Airbolt-AI/airbolt
cd airbolt/packages/sdk/examples/node-cli
# Install dependencies
npm install
# Run JavaScript example
npm start
# Run TypeScript example
npm run start:ts
The SDK works in multiple environments:
MIT - See LICENSE file in the main repository.
Note: This SDK provides the core functionality used by @airbolt/react-sdk. For React applications, we recommend using the React SDK for the best developer experience.