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

@kernova/sdk

v1.0.0

Published

Kernova SDK - High-level API for building intelligent applications

Readme

@kernova/sdk

The simplest way to build intelligent applications with Kernova.

5 lines from zero to a working AI app with memory, tools, and multi-agent coordination.

For full-stack apps (frontend + agents), use @kernova/framework instead:

npx create-kernova-app my-app

The SDK is for backend-only agent services or when you have your own frontend.

Installation

npm install @kernova/sdk

Quick Start

import { Kernova } from '@kernova/sdk';

const app = await Kernova.create();
app.agent('assistant', { instructions: 'You are helpful and concise.' });

const { answer } = await app.ask('What is the capital of France?');
console.log(answer); // "Paris"

await app.close();

Set your API key: export OPENAI_API_KEY=sk-...

Autonomous Agent (Quick Start)

Chain scheduling, triggers, channels, and daemon mode to build always-on agents:

import { Kernova, WebhookChannelAdapter } from '@kernova/sdk';

const app = await Kernova.create();

app
  .agent('ops-bot', { instructions: 'You monitor systems and respond to incidents.' })
  .schedule('health-check', '*/5 * * * *', async () => {
    console.log('Running health check...');
  })
  .trigger('on-alert', 'channel.message.*', { goal: 'Triage incoming alert' })
  .channel('webhooks', new WebhookChannelAdapter({ port: 3100 }))
  .onMessage(async (msg) => {
    console.log(`Received: ${msg.content}`);
  });

await app.serve(); // Runs until SIGINT/SIGTERM

Features

Define Agents (1 line)

app.agent('writer', {
  instructions: 'You write clear, engaging technical content.',
});

Add Tools (agents use them automatically)

app.tool('search', {
  description: 'Search the web for information',
  parameters: { type: 'object', properties: { query: { type: 'string' } }, required: ['query'] },
  execute: async ({ query }) => fetchSearchResults(query),
});

// Agent decides when to call search — no manual wiring needed
const { answer } = await app.ask('What happened in tech news today?');

Persistent Memory (survives restarts)

await app.remember('User prefers TypeScript over JavaScript', 'longterm');
await app.remember('Project uses PostgreSQL', 'longterm');

// Later — agent automatically has this context
const { answer } = await app.ask('Suggest a tech stack for my API');
// → Recommends TypeScript + PostgreSQL

Search Memories

const memories = await app.recall('programming preferences');

Stream Responses (token by token)

for await (const token of app.stream('Write a haiku about coding')) {
  process.stdout.write(token);
}

Multi-Agent Delegation

app.agent('researcher', { instructions: 'Research topics thoroughly.' });
app.agent('editor', {
  instructions: 'Coordinate research and writing.',
  async execute(intent, context, tools) {
    const research = await tools.delegate('researcher', intent.goal);
    const article = await tools.complete(`Write about: ${research.response}`);
    return { success: true, summary: article, evidence: { sources: [], confidence: 0.9 }, durationMs: 0 };
  },
});

Budget Control

const kernel = app.getKernel();
kernel.budget.setGlobalBudget({ maxTokens: 100_000, maxCostUsd: 5.00 });

Autonomy Methods

Scheduling

app.schedule(name, cronOrDelay, handler)

Register a recurring or one-shot scheduled job.

  • name — unique job identifier
  • cronOrDelay — cron expression (string) for recurring jobs, or delay in milliseconds (number) for one-shot jobs
  • handler — async function to execute when the job fires

Returns the SDK instance for chaining.

// Recurring cron job — runs every hour
app.schedule('hourly-report', '0 * * * *', async () => {
  const metrics = await gatherMetrics();
  await sendReport(metrics);
});

// One-shot job — fires once after 5 seconds
app.schedule('delayed-init', 5000, async () => {
  await warmUpCache();
});

Task Queue

app.enqueue(handler, payload, options?)

Add a task to the priority queue for async processing with automatic retries.

  • handler — handler name string used to route task execution
  • payload — arbitrary data passed to the task handler
  • options.priority'critical' | 'high' | 'medium' | 'low' (default: 'medium')
  • options.maxRetries — maximum retry attempts with exponential backoff (default: 3)

Returns a Promise<string> resolving to the unique task ID.

// Enqueue with default options
const taskId = await app.enqueue('send-email', {
  to: '[email protected]',
  subject: 'Welcome!',
  body: 'Thanks for signing up.',
});

// Enqueue with high priority and custom retries
const urgentId = await app.enqueue('process-payment', { orderId: 'ord_123' }, {
  priority: 'critical',
  maxRetries: 5,
});

Tasks are persisted in SQLite and survive restarts. Failed tasks are retried with exponential backoff. After exhausting retries, tasks move to the dead-letter queue for manual inspection via kernova queue status.


Channels

app.channel(name, adapter)

Register a channel adapter for inbound/outbound messaging.

  • name — unique channel identifier
  • adapter — a ChannelAdapter implementation (e.g., WebhookChannelAdapter, WebSocketChannelAdapter)

Returns the SDK instance for chaining.

import { WebhookChannelAdapter, WebSocketChannelAdapter } from '@kernova/core';

// HTTP webhook receiver
app.channel('webhooks', new WebhookChannelAdapter({ port: 3100, path: '/incoming' }));

// WebSocket server with ping/pong keepalive
app.channel('ws', new WebSocketChannelAdapter({ port: 3200 }));

app.onMessage(handler)

Register a global message handler that receives inbound messages from all registered channels.

  • handler — async function called with each InboundMessage

Returns the SDK instance for chaining.

app.onMessage(async (msg) => {
  console.log(`[${msg.channel}] ${msg.sender}: ${msg.content}`);
  // Route to an agent, enqueue a task, etc.
});

Triggers

app.trigger(name, eventPattern, action)

Register a proactive trigger rule that fires when events matching a glob pattern are published on the EventBus.

  • name — unique trigger name
  • eventPattern — glob-style pattern to match event types (e.g., 'channel.message.*', '*.failed')
  • action — trigger action definition:
    • action.goal — intent goal string submitted when the trigger fires
    • action.priority — optional intent priority ('critical' | 'high' | 'medium' | 'low')
    • action.cooldownMs — minimum milliseconds between firings (default: 1000)

Returns the SDK instance for chaining.

// Fire on any incoming message
app.trigger('on-message', 'channel.message.*', {
  goal: 'Process incoming message',
  priority: 'high',
});

// Fire on intent failures with cooldown
app.trigger('on-failure', 'intent.failed', {
  goal: 'Investigate and retry failed intent',
  cooldownMs: 5000,
});

Planning

app.plan(goal, options?)

Decompose a complex goal into steps and execute them sequentially using the Agent Planner (plan-and-execute pattern).

  • goal — the high-level goal string for the LLM to decompose
  • options.maxSteps — maximum number of steps to prevent unbounded execution (default: 10)

Returns a Promise<IntentResult> with the overall outcome and step details.

const result = await app.plan('Deploy the new version to staging');
console.log(result.summary);
// → "Plan completed: 4/4 steps executed"
console.log(result.data.steps);
// → [{ description: 'Run tests', status: 'completed' }, ...]

// Limit steps for constrained execution
const result = await app.plan('Migrate database schema', { maxSteps: 5 });

If a step fails, the planner automatically replans remaining steps based on the error context.


Threads

app.thread(threadId)

Get or create a conversation thread for multi-turn dialogue with automatic sliding window context management.

  • threadId — unique thread identifier (creates the thread if it doesn't exist)

Returns a ThreadHandle with the following methods:

| Method | Description | |--------|-------------| | thread.addMessage(role, content) | Add a message ('user', 'assistant', or 'system') | | thread.getContext() | Get { summary, messages } formatted for model consumption |

const thread = app.thread('support-session-42');

await thread.addMessage('user', 'How do I reset my password?');
await thread.addMessage('assistant', 'Go to Settings → Security → Reset Password.');
await thread.addMessage('user', 'Thanks! And how do I enable 2FA?');

const ctx = thread.getContext();
// ctx.messages — recent messages within the sliding window
// ctx.summary — summarized older messages (if window overflowed)

When messages exceed the configured window size (default: 50), older messages are automatically summarized and condensed.


Daemon Mode

app.serve(options?)

Start the Kernel in daemon mode for persistent, always-on execution. Handles signal-based graceful shutdown and periodic heartbeat.

  • options.configPath — path to agent config file or directory
  • options.watch — enable hot-reload of config files (default: false)
  • options.port — port for webhook/gateway listeners
  • options.dataDir — data directory override
  • options.shutdownTimeoutMs — graceful shutdown timeout in ms (default: 30000)
  • options.heartbeatIntervalMs — heartbeat interval in ms (default: 60000)

Returns a Promise<void> that resolves when the daemon stops.

// Basic daemon — runs until SIGINT/SIGTERM
await app.serve();

// With configuration
await app.serve({
  configPath: './agents/',
  watch: true,
  shutdownTimeoutMs: 10000,
  heartbeatIntervalMs: 30000,
});

The daemon:

  • Starts all registered autonomy modules (scheduler, task queue, triggers)
  • Handles SIGINT and SIGTERM for graceful shutdown
  • Waits up to shutdownTimeoutMs for active intents to complete
  • Emits daemon.heartbeat events at the configured interval

Full API

| Method | Description | |--------|-------------| | Kernova.create(config?) | Create and start a Kernova instance | | app.agent(name, spec) | Register an agent | | app.tool(name, spec) | Register a tool | | app.ask(goal, options?) | Submit an intent, get an answer | | app.stream(goal) | Stream response tokens | | app.remember(content, layer?, tags?) | Store a memory | | app.recall(query, options?) | Search memories | | app.workflow(definition) | Register a workflow | | app.runWorkflow(id, input?) | Execute a workflow | | app.schedule(name, cronOrDelay, handler) | Register a scheduled job (cron or one-shot) | | app.enqueue(handler, payload, options?) | Add a task to the priority queue | | app.channel(name, adapter) | Register a channel adapter | | app.onMessage(handler) | Register a global message handler | | app.trigger(name, eventPattern, action) | Register a proactive trigger rule | | app.plan(goal, options?) | Plan and execute a complex goal | | app.thread(threadId) | Get/create a conversation thread | | app.serve(options?) | Start daemon mode | | app.getKernel() | Access the underlying kernel | | app.close() | Shut down gracefully |

Backward Compatibility

The Nexus class is available as a deprecated alias for users migrating from older versions:

import { Nexus } from '@kernova/sdk'; // ← deprecated, use Kernova instead
import { Kernova } from '@kernova/sdk'; // ← preferred

Both resolve to the same class.

Supported Providers (20+)

Set any of these environment variables — Kernova auto-detects:

OPENAI_API_KEY · ANTHROPIC_API_KEY · GEMINI_API_KEY · DEEPSEEK_API_KEY · GROQ_API_KEY · MISTRAL_API_KEY · TOGETHER_API_KEY · OPENROUTER_API_KEY · XAI_API_KEY · COHERE_API_KEY · FIREWORKS_API_KEY · PERPLEXITY_API_KEY

Local (no key): Ollama · LM Studio · vLLM · llama.cpp

Requirements

  • Node.js 20+
  • At least one AI model provider (or Ollama for local)

Documentation

Full docs, guides, and API reference at kernova.dev