npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@yesvara/svara

v0.2.9

Published

Build AI agents in 15 lines of code. Multi-channel, RAG-ready, production-grade.

Readme

Build AI agents in less than 9 lines. Ship to production.

A batteries-included Node.js framework for building agentic AI backends.
Multi-channel, RAG-ready, and designed for developers who value simplicity.

npm version License: MIT Node.js TypeScript


Why SvaraJS?

Most AI frameworks make you think about infrastructure. SvaraJS makes you think about your agent.

import { SvaraApp, SvaraAgent, createTool } from '@yesvara/svara';

const agent = new SvaraAgent({
  name: 'Support Bot',
  model: 'gpt-4o-mini',       // provider auto-detected
  knowledge: './docs',         // PDF, MD, TXT, just point to a folder
  tools: [tool_1, tool_2, tool_3], // Agent choose the right tool for answer
});

const app = new SvaraApp().route('/chat', agent.handler()).listen(3000);
// Done. Your agent handles 1000 conversations.

That's it. No pipeline setup. No embedding boilerplate. No webhook configuration.
Convention over configuration (like Express, but for AI).


Features

||| |---|---| | Zero-config LLM | Pass a model name, provider is auto-detected | | Instant RAG | Point to a folder, documents are indexed automatically | | Multi-channel | WhatsApp, Telegram, and Web from one agent | | Tool calling | Declarative tools with full TypeScript types | | Conversation memory | Automatic per-session history, configurable window | | Express-compatible | agent.handler() drops into any existing app | | Built-in database | Persistent SQLite for users, sessions, RAG chunks, and state | | RAG per agent | Each agent has isolated knowledge base, no cross-contamination | | RAG persistence | Vector embeddings stored in SQLite, auto-dedup | | User tracking | Auto-tracks users and sessions with timestamps | | CLI included | svara new, svara dev, svara build |


Quick Start

1. Install

npm install @yesvara/svara

2. Create a new project

npx svara new my-agent
cd my-agent

This scaffolds a ready-to-run project with TypeScript, tools, and RAG setup.

3. Configure API keys

nano .env
# Edit .env and add your API keys
OPENAI_API_KEY=sk-...

4. Run the agent

npx svara dev
# Server running at http://localhost:3000

5. Chat with your agent

curl -X POST http://localhost:3000/chat \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Hello! What can you do?",
    "userId": "user-1",
    "sessionId": "user-1-session-1"
  }'
{
  "response": "Hi! I'm my-agent, your AI assistant...",
  "sessionId": "user-1-session-1",
  "usage": { "totalTokens": 142 }
}

6. (Optional) Customize your agent

Edit src/index.ts to customize:

const agent = new SvaraAgent({
  name: 'My Awesome Bot',
  model: 'gpt-4o-mini',                    // Change model
  systemPrompt: 'Custom personality here', // Custom behavior
  knowledge: './docs/**/*',                // Add RAG documents
  tools: [yourTools],                      // Add tools
});

Add more documents anytime — just drop files in docs/ and restart.


Supported Models

SvaraJS auto-detects the LLM provider from the model name. No extra config needed.

| Model string | Provider | Env key | |---|---|---| | gpt-4o, gpt-4o-mini, gpt-4-turbo | OpenAI | OPENAI_API_KEY | | claude-opus-4-6, claude-sonnet-4-6, claude-haiku-* | Anthropic | ANTHROPIC_API_KEY | | llama3, mistral, gemma, phi3 | Ollama (local) | (none) | | llama-3.1-70b-versatile, mixtral-8x7b | Groq | GROQ_API_KEY |

// Switch models in one line — no other changes needed
const agent = new SvaraAgent({ name: 'Aria', model: 'claude-opus-4-6' });
const agent = new SvaraAgent({ name: 'Aria', model: 'llama3' });         // local
const agent = new SvaraAgent({ name: 'Aria', model: 'gpt-4o-mini' });   // cheap & fast

Core Concepts

SvaraAgent

The central class. Configure once, use everywhere.

const agent = new SvaraAgent({
  name: 'Support Bot',         // Display name (used in logs & system prompt)
  model: 'gpt-4o-mini',        // LLM model - provider auto-detected
  systemPrompt: 'You are...', // Optional - sensible default based on name
  knowledge: './docs',         // Optional - folder/glob for RAG
  memory: { window: 20 },      // Optional - conversation history window
  tools: [myTool],             // Optional - functions the agent can call
  temperature: 0.7,            // Optional - creativity (0–2)
  verbose: true,               // Optional - detailed logs
});

SvaraApp

A minimal HTTP server. Built on Express, zero config to start.

const app = new SvaraApp({
  cors: true,           // Allow all origins (or pass a specific origin)
  apiKey: 'secret-key', // Optional bearer token auth
});

app.route('/chat', agent.handler());   // Mount agent on a path
app.use(myMiddleware);                 // Add Express middleware
app.listen(3000);

// Access the raw Express app for advanced config
const expressApp = app.getExpressApp();

Tools (createTool)

Give your agent superpowers. The LLM decides when to call each tool.

import { createTool } from '@yesvara/svara';

const weatherTool = createTool({
  name: 'get_weather',
  description: 'Get current weather for a city. Use when the user asks about weather.',
  parameters: {
    city: { type: 'string', description: 'City name', required: true },
    units: { type: 'string', description: 'celsius or fahrenheit', enum: ['celsius', 'fahrenheit'] },
  },
  async run({ city, units = 'celsius' }) {
    const data = await fetchWeather(city as string);
    return { temp: data.temp, condition: data.description };
  },
});

agent.addTool(weatherTool);

// Chainable
agent
  .addTool(weatherTool)
  .addTool(emailTool)
  .addTool(databaseTool);

RAG (Knowledge Base)

Point to your documents. The agent reads them automatically.

const agent = new SvaraAgent({
  name: 'Support Bot',
  model: 'gpt-4o-mini',
  knowledge: './docs',           // folder
  // knowledge: './faqs.pdf',   // single file
  // knowledge: ['./docs', './policies/*.md'], // multiple globs
});

// Or add documents at runtime (hot reload, no restart)
await agent.addKnowledge('./new-policy-2024.pdf');

Supported formats: PDF, Markdown, TXT, DOCX, HTML, JSON

RAG Persistence & Per-Agent Isolation:

Vector embeddings are automatically persisted to SQLite. Each agent has its own isolated knowledge base:

const supportBot = new SvaraAgent({
  name: 'SupportBot',
  model: 'gpt-4o-mini',
  knowledge: './docs/support',  // Knowledge base 1
});

const salesBot = new SvaraAgent({
  name: 'SalesBot',
  model: 'gpt-4o-mini',
  knowledge: './docs/sales',    // Knowledge base 2
});

await supportBot.start();
await salesBot.start();

// Both agents run simultaneously with isolated RAG:
// - SupportBot only searches in support docs
// - SalesBot only searches in sales docs
// - No cross-contamination, efficient storage
// - Embeddings persist across restarts
// - Duplicate content skipped per agent

How it works:

  • Documents are embedded and stored in SQLite with agent name
  • Each agent queries only its own chunks
  • Deduplication happens per agent (same content in different agents is OK)
  • Perfect for multi-agent systems with different domains

Accessing Retrieved Documents:

The /chat endpoint returns retrievedDocuments showing which knowledge was used:

const response = await fetch('http://localhost:3000/chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    message: 'What is the pricing?',
    sessionId: 'user-123'
  })
});

const result = await response.json();
// {
//   response: "Our pricing starts at...",
//   retrievedDocuments: [
//     {
//       source: "./docs/pricing.md",
//       score: 0.89,        // relevance (0-1)
//       excerpt: "# Pricing\n\nOur plans start at..."
//     },
//     {
//       source: "./docs/faq.md",
//       score: 0.76,
//       excerpt: "## Is there a free trial?\n\nYes, 14 days..."
//     }
//   ]
// }

The retrievedDocuments field shows:

  • source: File path of the matching document
  • score: Cosine similarity (0-1, higher = more relevant)
  • excerpt: First 150 characters of the matched chunk

User & Session Tracking

Every message automatically tracks the user and their session.

// Send message with userId and sessionId
const result = await agent.process('Help me with my order', {
  userId: 'user-123',
  sessionId: 'user-123-conversation-1'
});

// Database tracks:
// - svara_users: user-123 (first_seen, last_seen, metadata)
// - svara_sessions: session details, linked to user-123
// - svara_messages: conversation history for this session

Query user data:

import { SvaraDB } from '@yesvara/svara';

const db = new SvaraDB('./data/svara.db');

// Get all users
const users = db.query('SELECT * FROM svara_users');

// Get sessions for a user
const sessions = db.query(
  'SELECT * FROM svara_sessions WHERE user_id = ?',
  ['user-123']
);

// Get chat history for a session
const messages = db.query(
  'SELECT * FROM svara_messages WHERE session_id = ? ORDER BY created_at',
  ['user-123-conversation-1']
);

// Check RAG chunks (with dedup tracking)
const chunks = db.query(
  'SELECT id, content, content_hash FROM svara_chunks LIMIT 10'
);

Channels

One agent, multiple platforms.

agent
  .connectChannel('web', { port: 3000, cors: true })
  .connectChannel('telegram', { token: process.env.TG_TOKEN })
  .connectChannel('whatsapp', {
    token: process.env.WA_TOKEN,
    phoneId: process.env.WA_PHONE_ID,
    verifyToken: process.env.WA_VERIFY_TOKEN,
  });

await agent.start(); // Start all channels

Events

Hook into the agent lifecycle.

agent.on('message:received', ({ message, sessionId }) => { /* log it */ });
agent.on('tool:call',        ({ tools }) => { /* monitor usage */ });
agent.on('tool:result',      ({ name, result }) => { /* cache results */ });
agent.on('message:sent',     ({ response }) => { /* analytics */ });
agent.on('channel:ready',    ({ channel }) => { /* notify */ });

Examples

Basic agent

import { SvaraApp, SvaraAgent } from '@yesvara/svara';

const app = new SvaraApp({ cors: true });
const agent = new SvaraAgent({ name: 'Aria', model: 'gpt-4o-mini' });

app.route('/chat', agent.handler());
app.listen(3000);

Agent with tools

import { SvaraAgent, createTool } from '@yesvara/svara';

const agent = new SvaraAgent({ name: 'Aria', model: 'gpt-4o' });

agent.addTool(createTool({
  name: 'get_time',
  description: 'Get the current date and time',
  parameters: {},
  async run() {
    return { time: new Date().toISOString() };
  },
}));

const reply = await agent.chat('What time is it?');
console.log(reply); // "It's currently 14:32 UTC..."

RAG-powered support bot

const agent = new SvaraAgent({
  name: 'Support Bot',
  model: 'gpt-4o-mini',
  knowledge: './docs',  // Auto-loaded on first request
  systemPrompt: 'You are a customer support agent. Answer using the documentation.',
  memory: { window: 20 },
});

const app = new SvaraApp({ cors: true });
app.route('/chat', agent.handler());
app.listen(3000);
// Knowledge indexes automatically on first request

Multi-channel (Web + Telegram + WhatsApp)

const agent = new SvaraAgent({
  name: 'Aria',
  model: 'gpt-4o-mini',
  knowledge: './policies',
});

agent
  .connectChannel('web',      { port: 3000 })
  .connectChannel('telegram', { token: process.env.TG_TOKEN })
  .connectChannel('whatsapp', {
    token:       process.env.WA_TOKEN,
    phoneId:     process.env.WA_PHONE_ID,
    verifyToken: process.env.WA_VERIFY_TOKEN,
  });

await agent.start();

Drop into an existing Express app

import express from 'express';
import { SvaraAgent } from '@yesvara/svara';

const app = express();
app.use(express.json());

const agent = new SvaraAgent({ name: 'Aria', model: 'gpt-4o-mini' });

app.post('/api/chat', agent.handler()); // ← one line
app.listen(3000);

Adding Knowledge & Tools at Runtime

Adding knowledge (dynamic indexing)

After the agent is created, add more documents without restarting:

const agent = new SvaraAgent({
  name: 'Support Bot',
  model: 'gpt-4o-mini',
  knowledge: './docs',  // Initial knowledge
});

// ── Later (no restart needed) ──────────────────────
// Add a single document
await agent.addKnowledge('./policies/new-policy-2024.pdf');

// Add multiple documents
await agent.addKnowledge(['./faq.md', './terms.txt', './pricing.pdf']);

// Agent immediately has the new knowledge

Real-world example — admin endpoint to upload documents:

const app = new SvaraApp({ cors: true });
app.route('/chat', agent.handler());

// Admin: dynamically add knowledge
app.post('/admin/add-knowledge', async (req, res) => {
  const { path } = req.body;
  try {
    await agent.addKnowledge(path);
    res.json({ status: 'Knowledge added', path });
  } catch (err) {
    res.status(400).json({ error: (err as Error).message });
  }
});

app.listen(3000);

Adding tools (dynamic function calling)

Add tools at runtime with addTool():

import { SvaraAgent, createTool } from '@yesvara/svara';

const agent = new SvaraAgent({
  name: 'Assistant',
  model: 'gpt-4o-mini',
  tools: [initialTool],  // Start with one tool
});

// ── Later ────────────────────────────────────────
// Add more tools dynamically
const newTool = createTool({
  name: 'send_email',
  description: 'Send an email to a user',
  parameters: {
    to: { type: 'string', description: 'Email address', required: true },
    subject: { type: 'string', description: 'Email subject', required: true },
    body: { type: 'string', description: 'Email body', required: true },
  },
  async run({ to, subject, body }) {
    // Call your email service
    return { status: 'sent', to, subject };
  },
});

agent.addTool(newTool);

// Agent can now use send_email tool

Chainable tool registration (multiple tools):

agent
  .addTool(emailTool)
  .addTool(databaseTool)
  .addTool(slackTool)
  .addTool(webhookTool);

CLI

Create a new project

svara new my-app

Output:

✨ Creating SvaraJS project: my-app

  ✓ package.json
  ✓ tsconfig.json
  ✓ .env.example
  ✓ src/index.ts
  ✓ docs/README.md

📦 Installing dependencies...

✅ Project ready!

  cd my-app
  cp .env.example .env
  npm run dev

Options:

  • --template <name> — Use a specific template (default: basic)
    • basic — Simple agent with HTTP endpoint
    • rag — RAG-powered agent with document loader
    • multi-channel — Web + Telegram + WhatsApp setup
    • tools — Agent with tool calling examples

Start development server

svara dev

Features:

  • Hot-reload on file changes
  • Auto-restart agent on code updates
  • Debug logging enabled
  • Serves on http://localhost:3000 (configurable)

Options:

  • --port <number> — Custom port (default: 3000)
  • --watch <glob> — Watch additional paths (default: src/**)
  • --env <file> — Load custom .env file

Build for production

svara build

Outputs:

  • dist/ — Compiled JavaScript
  • dist/index.js — Entry point (ready for Node or Docker)
  • Source maps and type declarations included

Options:

  • --minify — Minify output
  • --sourcemaps — Include source maps (default: true)
  • --outdir <path> — Custom output directory (default: dist/)

Running built projects

# After building
node dist/index.js

# Or with env file
NODE_ENV=production OPENAI_API_KEY=sk-... node dist/index.js

Database management

# Initialize database (auto-creates tables)
svara db init

# Show database schema
svara db schema

# Export users and conversation history
svara db export --format json
svara db export --format csv --table svara_messages

# Query database directly
svara db query "SELECT COUNT(*) FROM svara_users"

# Reset database (⚠️ deletes all data)
svara db reset

# Backup database
svara db backup --output backup-2026-01-15.db

# Restore from backup
svara db restore --input backup-2026-01-15.db

Options:

  • --db <path> — Custom database path (default: ./data/svara.db)
  • --format <type> — Export format: json, csv, sql (default: json)
  • --table <name> — Specific table to export
  • --output <path> — Output file path
  • --force — Skip confirmation prompts (use with reset carefully!)

Built-in Database

Persistent SQLite for users, sessions, conversation history, and RAG vectors.

import { SvaraDB } from '@yesvara/svara';

const db = new SvaraDB('./data/svara.db');

// Built-in tables (auto-created):
// - svara_users: user registry with timestamps
// - svara_sessions: conversation sessions linked to users
// - svara_messages: conversation history
// - svara_chunks: RAG vectors with deduplication
// - svara_kv: key-value store for app state

// Query users
const activeUsers = db.query(
  'SELECT id, display_name, last_seen FROM svara_users WHERE last_seen > unixepoch() - 86400'
);

// Get conversation history
const history = db.query(
  'SELECT role, content FROM svara_messages WHERE session_id = ? ORDER BY created_at',
  ['session-id']
);

// Key-value store
db.kv.set('feature:rag', true);
const enabled = db.kv.get<boolean>('feature:rag');

// Transactions
db.transaction(() => {
  db.run('INSERT INTO orders ...', [...]);
  db.run('UPDATE inventory ...', [...]);
});

Architecture

@yesvara/svara/
├── src/
│   ├── core/
│   │   ├── agent.ts        # SvaraAgent — the main class
│   │   ├── llm.ts          # LLM abstraction + provider auto-detection
│   │   └── types.ts        # Internal types
│   ├── app/
│   │   └── index.ts        # SvaraApp — HTTP framework wrapper
│   ├── channels/
│   │   ├── web.ts          # REST API + SSE streaming
│   │   ├── telegram.ts     # Telegram Bot API (polling + webhook)
│   │   └── whatsapp.ts     # Meta WhatsApp Cloud API
│   ├── rag/
│   │   ├── loader.ts       # Document loading (PDF, MD, DOCX, ...)
│   │   ├── chunker.ts      # Chunking strategies (sentence, paragraph, fixed)
│   │   └── retriever.ts    # Vector similarity search
│   ├── memory/
│   │   ├── conversation.ts # Per-session history with auto-trim
│   │   └── context.ts      # LLM message builder + RAG injection
│   ├── tools/
│   │   ├── index.ts        # createTool() helper
│   │   ├── registry.ts     # Tool store
│   │   └── executor.ts     # Concurrent execution with timeout protection
│   ├── database/
│   │   ├── sqlite.ts       # SvaraDB wrapper (query, kv, transaction)
│   │   └── schema.ts       # Internal SQLite schema
│   ├── cli/                # svara new / dev / build
│   ├── types.ts            # Public types (exported to users)
│   └── index.ts            # Public API surface
└── examples/
    ├── 01-basic/           # 10-line agent
    ├── 02-with-tools/      # createTool + events
    ├── 03-rag-knowledge/   # Document Q&A
    └── 04-multi-channel/   # Web + Telegram + WhatsApp

Web API Reference

When using app.route('/chat', agent.handler()):

POST /chat

Request:

{
  "message": "What is the refund policy?",
  "userId": "[email protected]",
  "sessionId": "alice-session-1"
}

Response:

{
  "response": "Our refund policy allows returns within 30 days...",
  "sessionId": "alice-session-1",
  "usage": {
    "promptTokens": 312,
    "completionTokens": 89,
    "totalTokens": 401
  },
  "toolsUsed": []
}

Note: userId and sessionId are automatically tracked in the SQLite database for user management and conversation history.

GET /health — always returns { "status": "ok" }


Database Schema

SvaraJS automatically creates and manages these SQLite tables:

| Table | Purpose | Auto-Managed | |-------|---------|--------------| | svara_users | User registry (first_seen, last_seen, metadata) | ✅ Yes | | svara_sessions | Conversation sessions linked to users | ✅ Yes | | svara_messages | Full conversation history per session | ✅ Yes | | svara_chunks | RAG vectors isolated per agent with deduplication | ✅ Yes | | svara_documents | Document registry and metadata | ✅ Yes | | svara_kv | Key-value store for app state | ✅ Yes | | svara_meta | Framework metadata and versions | ✅ Yes |

RAG Isolation:

Each agent's RAG data is stored separately using the agent_name column:

// Query RAG chunks for specific agent
const supportChunks = db.query(
  'SELECT COUNT(*) as count FROM svara_chunks WHERE agent_name = ?',
  ['SupportBot']
);

const salesChunks = db.query(
  'SELECT COUNT(*) as count FROM svara_chunks WHERE agent_name = ?',
  ['SalesBot']
);

// Export conversation analytics
db.query(`
  SELECT u.id, u.display_name, COUNT(m.id) as message_count
  FROM svara_users u
  LEFT JOIN svara_messages m ON u.id = (
    SELECT user_id FROM svara_sessions WHERE id = m.session_id
  )
  WHERE u.last_seen > unixepoch() - 86400
  GROUP BY u.id
  ORDER BY message_count DESC
`);

Contributing

Contributions are welcome! Please read CONTRIBUTING.md first.

git clone https://github.com/yogiswara92/svarajs
cd svara
npm install
npm run dev

License

MIT © Yesvara


Built with ❤️ for developers who want to ship AI, not fight infrastructure.

Documentation · Examples · npm