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

agentlayer

v0.0.1

Published

Minimal agent framework on the [Vercel AI SDK](https://ai-sdk.dev). Pluggable runtimes, tools, and session storage with a typed event API.

Readme

agentlayer

Minimal agent framework on the Vercel AI SDK. Pluggable runtimes, tools, and session storage with a typed event API.

Install

npm install agentlayer

Quick start

import { Agent } from "agentlayer";
import { BashTool } from "agentlayer/tools/bash";

const agent = new Agent({
  model: "moonshotai/kimi-k2.5", // any AI SDK LanguageModel
  instructions: "You are a helpful assistant.",
  tools: [BashTool],
});

// One-liner: send + wait + get text
const result = await agent.prompt("How many CPUs does this machine have?");
console.log(result.text);

// Or with streaming
await agent.prompt("How many CPUs?", {
  onText: (t) => process.stdout.write(t),
});

For multi-turn conversations, use sessions:

const session = await agent.createSession();
await session.prompt("How many CPUs?");
console.log(session.text); // last assistant reply

await session.prompt("And RAM?");
console.log(session.text); // updated after each turn

Custom tools

Create type-safe tools with zod schemas via defineTool:

import { defineTool } from "agentlayer";
import { z } from "zod/v4";

const weather = defineTool({
  name: "get_weather",
  label: "Weather",
  description: "Get the current weather for a city",
  schema: z.object({ city: z.string() }),
  needsApproval: true, // fires before-tool-call with needsApproval: true
  execute: async (input) => {
    // input.city is typed as string
    const res = await fetch(`https://wttr.in/${input.city}?format=j1`);
    return JSON.stringify(await res.json());
  },
});

const agent = new Agent({ model, tools: [weather] });

Or implement the Tool interface directly without zod:

const echo: Tool = {
  name: "echo",
  description: "Echo the input",
  parameters: { type: "object", properties: { text: { type: "string" } }, required: ["text"] },
  execute: async (input) => input.text,
};

Subagents

Define named subagents that become task tools automatically:

const agent = new Agent({
  model,
  tools: [BashTool, ReadTool, EditTool],
  subagents: {
    explore: {
      description: "Fast read-only codebase exploration",
      instructions: "Use grep and glob to find files quickly.",
      tools: [ReadTool, GlobTool, GrepTool],
    },
    plan: {
      description: "Create implementation plans",
      instructions: "Plan but don't edit files.",
      tools: [ReadTool, GlobTool],
    },
  },
});
// LLM can now call task_explore and task_plan tools
// Subagent text deltas are forwarded as tool-progress events

Tool call hooks

Approve, deny, or modify tool calls before they execute:

session.on("before-tool-call", (e) => {
  // e.needsApproval is true if the tool declared needsApproval

  // Block dangerous commands
  if (e.toolName === "bash" && /rm -rf/.test(e.input.command as string)) {
    return { deny: "Blocked dangerous command" };
  }

  // Override arguments
  return { input: { ...e.input, timeout: 5000 } };
});

Hook events also include toolLabel (human-readable name) when available.

Other hooks: after-tool-call (includes metadata from tool results), before-model-call, before-stop (can return { preventStop: true } to keep the loop running).

Session persistence

Store sessions to disk and resume them later:

import { JsonlSessionStore } from "agentlayer/store/jsonl";

const agent = new Agent({
  model,
  tools: [BashTool],
  store: new JsonlSessionStore("./sessions"),
});

// First run
const session = await agent.createSession({ id: "my-session" });
await session.prompt("What OS is this?");

// Later: resume with full context
const resumed = await agent.resumeSession("my-session");
await resumed.prompt("And how much RAM does it have?");

Compaction

Compact long conversations to stay within context limits:

const agent = new Agent({
  model,
  compaction: {
    summarize: async (msgs) => {
      /* call LLM to summarize */ return summary;
    },
    keepLast: 4,
  },
});

const session = await agent.createSession();
// ... many turns ...
await session.compact(); // summarizes old messages, keeps last 4

Sending messages

session.prompt() sends and waits. For non-blocking control, use send():

session.send("Hello"); // non-blocking, starts the loop
await session.waitForIdle(); // wait for completion

Interrupt or queue messages while the agent is running:

session.steer("Stop, do this instead"); // interrupts before next model call
session.followUp("Also do this"); // queues after current turn ends

Continue the loop without a new user message:

await session.continue(); // re-enters the loop from current state

Events

Subscribe to individual events or all events at once:

// Individual events
const unsub = session.on("text-delta", (e) => process.stdout.write(e.text));

// All events via subscribe()
session.subscribe((event) => {
  if (event.type === "text-delta") process.stdout.write(event.text);
  if (event.type === "error") console.error(event.error);
});

// Or inline via agent config
const agent = new Agent({
  model,
  onEvent: (e) => {
    if (e.type === "text-delta") process.stdout.write(e.text);
  },
});

Stream events (from AI SDK): text-start, text-delta, text-end, reasoning-start, reasoning-delta, reasoning-end, tool-input-start, tool-input-delta, tool-input-end, tool-call, tool-result, tool-error.

Framework events: message, turn-start, turn-end, error, status, tool-progress, step-start, step-end.

Hook events (can return decisions): before-tool-call, after-tool-call, before-model-call, before-stop.

Dynamic session properties

Change model, tools, instructions, or thinking level mid-session:

session.model = anotherModel;
session.tools = [BashTool, newTool];
session.instructions = "New instructions";
session.thinkingLevel = "high"; // "off" | "minimal" | "low" | "medium" | "high"

Changes take effect on the next turn.

Token usage

const { inputTokens, outputTokens, totalTokens } = session.usage;

Accumulated across all model calls in the session.

Runtimes

Tools call ctx.runtime instead of Node APIs directly, so you can swap execution environments:

import { NodeRuntime } from "agentlayer/runtime/node"; // default
import { VercelSandboxRuntime } from "agentlayer/runtime/sandbox"; // cloud
import { JustBashRuntime } from "agentlayer/runtime/just-bash"; // in-memory

new Agent({ model, runtime: new VercelSandboxRuntime({ sandbox }) });

Agent options

const agent = new Agent({
  model,                              // LanguageModel (required)
  instructions: "You are a ...",      // system prompt
  tools: [BashTool, WebFetchTool],    // optional
  runtime: new NodeRuntime(),         // optional, default: NodeRuntime
  store: new InMemorySessionStore(),  // optional, default: InMemorySessionStore
  maxSteps: 100,                      // optional, default: 100
  sendMode: "steer",                  // "steer" | "queue", default: "steer"
  hooks: { ... },                     // AgentHooks, applied to all sessions
  onEvent: (e) => { ... },           // inline event handler for all events
  thinkingLevel: "medium",            // "off" | "minimal" | "low" | "medium" | "high"
  thinkingBudgets: { medium: 10000 }, // custom token budgets per level
  providerOptions: { ... },           // passed to streamText providerOptions
  transformContext: (msgs) => msgs,   // pre-model message transform
  compaction: { summarize, keepLast },// auto-compaction config
  subagents: { ... },                 // named subagent definitions
});

Built-in tools

| Tool | Import | Description | | ---------------- | ---------------------------- | -------------------------------------------------- | | BashTool | agentlayer/tools/bash | Shell commands with output truncation and timeout | | ReadTool | agentlayer/tools/read | Read file contents (truncated to 100KB) | | WriteTool | agentlayer/tools/write | Write files (creates parent directories) | | EditTool | agentlayer/tools/edit | Search-and-replace with fuzzy matching | | GlobTool | agentlayer/tools/glob | Find files matching glob patterns | | GrepTool | agentlayer/tools/grep | Search file contents with regex | | WebFetchTool | agentlayer/tools/web-fetch | HTTP GET/POST with 15s timeout and 50KB truncation | | createTaskTool | agentlayer/tools/task | Spawn a nested agent loop as a tool call |

Examples

npx tsx examples/basic.ts           # quickstart with custom tool
npx tsx examples/just-bash.ts       # sandboxed in-memory runtime
npx tsx examples/vercel-sandbox.ts  # cloud sandbox runtime
bun examples/tui.ts                 # full terminal UI chat app

License

MIT