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

@nexalab/agent-sdk

v0.1.8

Published

Reusable agentic SDK extracted from Nexa Agent OS.

Readme

Nexa Agent SDK

@nexalab/agent-sdk is a composable TypeScript SDK for building agentic assistants, workers, CLIs, app backends, durable workflows, and multi-agent systems.

It is designed around a small happy path for quick integration, plus production hooks for providers, tools, approvals, storage, telemetry, memory, evals, replay, routing, policy, and evidence-backed runs.

Install

pnpm add @nexalab/agent-sdk

For local workspace use:

{
  "dependencies": {
    "@nexalab/agent-sdk": "workspace:*"
  }
}

Documentation

The full documentation site is built with VitePress and lives in docs/. The API reference under docs/api is generated automatically from the TypeScript sources with TypeDoc:

# Regenerate the API reference markdown from src/ into docs/api
pnpm docs:generate

# Develop the docs site (regenerates the API reference, then starts a dev server)
pnpm docs:dev

# Production build (regenerates the API reference, then builds the static site)
pnpm docs:build

# Preview the production build locally
pnpm docs:preview

docs:build requires a successful docs:generate and is also validated in CI for every push/PR. The generated docs/api directory is not committed — it is always produced from source.

Quick Start

Premium agent({...}) Kernel API

Five minutes from npm install to a running agent, with a single config object. model accepts a "provider:model" string resolved against the built-in provider presets (API key read from the matching env var, e.g. OPENAI_API_KEY):

import { agent } from "@nexalab/agent-sdk";
import { z } from "zod";

const assistant = await agent({
  name: "sales-agent",
  model: "openai:gpt-4o-mini",
  instructions: "Eres un agente comercial. Ayudas al cliente a cotizar productos.",
  memory: true
});

const result = await assistant.run("Cotizale 20 tanques a Abraham");
console.log(result.text);

Grows into the full Kernel surface without changing shape — context engine, guardrails, hooks, sessions, structured outputs, and tools all compose onto the same object:

const result = await assistant.run("Analiza este prospecto", {
  outputSchema: z.object({ score: z.number(), reason: z.string(), nextAction: z.string() })
});
result.output; // typed { score, reason, nextAction }

const session = assistant.session("customer-38273");
await session.run("Hola");
await session.run("Recuerdas mi pedido?");

const asTool = assistant.asTool(); // callable from another agent's native tool loop

See Public Modules below (context, sessions, guardrails, hooks, structured-output, kernel) for the building blocks this composes.

Builder API

The lower-level fluent builder remains fully supported for cases that need explicit control over provider wiring, storage, and tracing:

import {
  createAgent,
  defineSdkTool,
  openaiProvider,
  createInMemoryStorage,
  createTelemetry
} from "@nexalab/agent-sdk";
import { z } from "zod";

const getTime = defineSdkTool({
  id: "system.read_time",
  capability: "system.time.read",
  description: "Read the current system time.",
  inputSchema: z.object({}),
  handler: async () => ({
    status: "ok",
    output: { iso: new Date().toISOString() }
  })
});

const builderAgent = await createAgent()
  .useProvider(openaiProvider({
    apiKey: process.env.OPENAI_API_KEY,
    model: "gpt-4o-mini"
  }))
  .useTool(getTime)
  .useStorage(createInMemoryStorage())
  .useTelemetry(createTelemetry())
  .useConsoleTrace()
  .build();

const result = await builderAgent.runMessage("puedes decirme que hora es?");
console.log(result.text);

Core Capabilities

  • Agentic task/run runtime
  • Mission runtime
  • Goal interpretation contracts
  • Success criteria and evidence model
  • Executable plan model
  • Plan validation
  • Completion gate
  • Loop guard
  • Normalized runtime events
  • Permission-aware tool registry
  • Zod-friendly tool factory
  • Local tool executor
  • Approval manager
  • Human-in-the-loop approval primitives
  • Multi-round transparent tool loop
  • Native model-requested tool-call loop
  • Async runStream(...) event stream
  • In-memory event bus
  • In-memory memory store
  • Advanced memory with dedupe, recency boost, and contextual retrieval
  • Vector memory with pluggable embeddings
  • JSON file storage
  • SQLite storage adapter contract
  • Postgres storage adapter contract
  • Redis storage adapter contract
  • Pluggable storage interfaces
  • Queue adapter and in-memory queue
  • OpenAI-compatible provider registry
  • Provider presets for OpenAI, OpenRouter, Ollama, and custom OpenAI-compatible APIs
  • OpenAI-compatible /v1/models lookup
  • OpenAI-compatible chat completions and streaming
  • Model routing and budget accounting
  • Telemetry hooks for events, tool traces, and spans
  • OpenTelemetry-compatible sink bridge
  • Agent eval harness
  • HTTP request handler
  • Checkpointed workflow runtime
  • Replay/debug timeline helpers
  • Tool policy helpers for deny/approval rules
  • Multi-agent coordinator and delegation helpers
  • Premium agent({...}) Kernel config API on top of the builder/runtime
  • Context Engine (user/tenant/conversation/knowledge/dynamic sections, token budget, compression)
  • Sessions/threads with history, compact, reset, and fork
  • Structured outputs (real Zod -> JSON Schema conversion, typed result.output)
  • Guardrails (declarative input/output checks, distinct from policy/approvals)
  • Lifecycle hooks (beforeRun/afterRun/beforeModel/afterModel/beforeTool/afterTool/onError/...)
  • Skills (instructions + tool subsets injected into an agent's context and native tool loop)
  • Typed artifacts surfaced from tool evidence (result.artifacts)
  • Multimodal message content (text/image/file parts) across OpenAI, Anthropic, and Gemini formats
  • Native MCP client (stdio and streamable-HTTP transports, real JSON-RPC handshake and tool discovery)
  • Agent-to-agent primitives: agent.asTool(), agentAsTool(), handoffs, and createTeam() (supervisor/router/parallel strategies)
  • Knowledge/RAG (createKnowledge, text/file/directory sources, chunking, retrieval over the existing vector memory store)
  • Provider capability registry (vision/tools/structuredOutputs/reasoning per provider) and adaptive model routing (strategy: "adaptive")
  • Pluggable response cache (createInMemoryCache) wired into agent.run()
  • Execution guarantees: real per-step retries with backoff, WAITING_FOR_APPROVAL/WAITING_FOR_RETRY states, resumable runs that skip already-completed steps
  • Secrets (secret() references resolved only inside tool execution, never placed into model-visible messages)
  • Tenancy: agent.run(text, { tenant: { tenantId, userId } }) namespaces memory/cache; config.permissions filters tools at agent construction
  • Node-process-level workspace sandbox (createWorkspace, workspaceTools) — jailed fs root, timeout/output-capped exec, snapshot/restore
  • YAML agent manifests (loadAgentManifest) and a nexa CLI (nexa run <manifest.yaml> "message", nexa inspect <manifest.yaml>)
  • ModelHarness — a public, overridable contract for the agent's model/tool-calling strategy (basicHarness() ships as the OSS reference; third parties can implement their own)

Public Modules

import { createAgent, agent } from "@nexalab/agent-sdk";
import { openaiProvider, openRouterProvider, ollamaProvider, anthropicProvider, geminiProvider } from "@nexalab/agent-sdk/providers";
import { defineSdkTool, toOpenAIChatTool } from "@nexalab/agent-sdk/tools";
import { AgentRuntime } from "@nexalab/agent-sdk/runtime";
import { createInMemoryStorage } from "@nexalab/agent-sdk/storage";
import { createJsonFileStorage } from "@nexalab/agent-sdk/storage/file";
import { createSqliteStorage } from "@nexalab/agent-sdk/storage/sqlite";
import { createPostgresStorage } from "@nexalab/agent-sdk/storage/postgres";
import { createRedisStorage } from "@nexalab/agent-sdk/storage/redis";
import { createTelemetry } from "@nexalab/agent-sdk/telemetry";
import { createOpenTelemetrySink } from "@nexalab/agent-sdk/telemetry/otel";
import { runAgentEvals } from "@nexalab/agent-sdk/evals";
import { createAgentRequestHandler } from "@nexalab/agent-sdk/http";
import { runNativeToolLoop } from "@nexalab/agent-sdk/native-tool-loop";
import { createWorkflowRuntime } from "@nexalab/agent-sdk/workflow";
import { replayRun, replayEvents } from "@nexalab/agent-sdk/replay";
import { createToolPolicy } from "@nexalab/agent-sdk/policy";
import { createModelRouter } from "@nexalab/agent-sdk/model-router";
import { createMultiAgentCoordinator } from "@nexalab/agent-sdk/multi-agent";
import { createAdvancedMemoryStore } from "@nexalab/agent-sdk/advanced-memory";
import { createVectorMemoryStore } from "@nexalab/agent-sdk/vector-memory";
import { createInMemoryQueue } from "@nexalab/agent-sdk/queue";
import { runHarness } from "@nexalab/agent-sdk/harness";
import { agent, resolveModelString } from "@nexalab/agent-sdk/kernel";
import { createContextEngine } from "@nexalab/agent-sdk/context";
import { createSession, loadSession } from "@nexalab/agent-sdk/sessions";
import { defineGuardrail, runInputGuardrails, runOutputGuardrails } from "@nexalab/agent-sdk/guardrails";
import { createHookDispatcher } from "@nexalab/agent-sdk/hooks";
import { zodSchemaToJsonSchema, parseStructuredOutput } from "@nexalab/agent-sdk/structured-output";
import { defineFlow } from "@nexalab/agent-sdk/guided-flows";

Guided Flows

Build stateful, multi-turn conversations that must satisfy explicit requirements before completion.

Guided Flows combine natural conversation with typed state, step-specific tools, validation, branching, confirmations, and structured final outputs. Attach one or more to agent({ flows }); the runtime fills state from free-form messages in any order, never re-asks for what it already has, scopes tool availability per step (never beyond what the agent itself is permitted), and only returns a Zod-validated structured output once every requirement holds.

import { agent, defineFlow } from "@nexalab/agent-sdk";
import { z } from "zod";

const gasOrderFlow = defineFlow({
  id: "gas-order",
  version: 1,
  name: "Gas order",
  goal: "Crear un pedido de gas valido y confirmado",
  stateSchema: z.object({
    customerName: z.string().optional(),
    phone: z.string().optional(),
    confirmed: z.boolean().default(false),
    orderId: z.string().optional()
  }),
  initialState: { confirmed: false },
  requirements: [
    { id: "customer", description: "Customer identity known", satisfied: ({ state }) => Boolean(state.customerName && state.phone) },
    { id: "confirmation", description: "Order confirmed", satisfied: ({ state }) => state.confirmed === true }
  ],
  steps: [
    { id: "identify_customer", collect: ["customerName", "phone"] },
    { id: "confirmation", collect: ["confirmed"], exit: ({ state }) => state.confirmed === true, tools: { denied: ["order.create"] } },
    { id: "create_order", when: ({ state }) => state.confirmed === true, tools: { required: ["order.create"] }, exit: ({ state }) => Boolean(state.orderId) }
  ],
  protectedFields: { orderId: ["tool"] },
  tools: { bindings: { "order.create": { applyResult: ({ result }) => ({ set: { orderId: result.output.orderId }, source: "tool" } as const) } } },
  completion: ({ requirements, state }) => requirements.every((r) => r.satisfied) && Boolean(state.orderId),
  outputSchema: z.object({ type: z.literal("gas_order"), orderId: z.string() }),
  mapOutput: ({ state }) => ({ type: "gas_order" as const, orderId: state.orderId! })
});

const salesAgent = await agent({ name: "gas-sales-agent", model: "openai:gpt-4o-mini", flows: [gasOrderFlow], tools: [orderCreateTool] });
const result = await salesAgent.session("whatsapp:5214771234567").run("Quiero pedir gas");
console.log(result.text, result.flow, result.state, result.output);

See the full guide at docs/guide/guided-flows.md and a complete runnable conversation at examples/guided-gas-order (pnpm demo:guided-flow).

Agent Manifests + CLI

Agents can be declared as YAML and run without writing code for the identity/model/instructions surface:

# agent.yaml
name: nexa
model: openai:gpt-4o-mini
instructions: Eres un agente comercial. Ayudas al cliente a cotizar productos.
memory: true
nexa run agent.yaml "Cotizale 20 tanques a Abraham"
nexa inspect agent.yaml

Tools/skills/guardrails/storage are code objects, not YAML-expressible — wire them in via loadAgentManifest(path, extend):

import { loadAgentManifest } from "@nexalab/agent-sdk/manifest";

const app = await loadAgentManifest("./agent.yaml", { tools: [myTool], guardrails: [myGuardrail] });

Model Harness

ModelHarness is the pluggable strategy behind agent.run()'s tool-calling loop — how many rounds to run, when to stop, how to react to tool results:

import { agent } from "@nexalab/agent-sdk";
import { basicHarness, type ModelHarness } from "@nexalab/agent-sdk/model-harness";

const assistant = await agent({
  model: "openai:gpt-4o-mini",
  name: "assistant",
  tools: [...],
  harness: basicHarness() // default if omitted; wraps the built-in native tool loop unchanged
});

Implement ModelHarness directly to swap in a custom orchestration strategy:

class MyHarness implements ModelHarness {
  async run(ctx) {
    // ctx.client / ctx.messages / ctx.tools — same shape basicHarness() receives
    return { text: "...", messages: ctx.messages, toolCalls: [], toolResults: [], rounds: 1 };
  }
}

Supplying any explicit harness (including basicHarness()) switches the loop to this Promise-based contract, which does not emit the granular native-tool events agent.runStream() emits by default — that streaming behavior is unchanged when no harness is configured. See docs/architecture/open-core-target.md for the design rationale.

Not to be confused with src/harness.ts's runHarness/assertHarness — an unrelated CI/release-check runner (pnpm harness) used to smoke-test the package before publishing. Same word, two different concepts; see the architecture docs for why they aren't merged.

Architecture

The SDK is adapter-driven:

  • Providers: bring OpenAI, OpenRouter, Ollama, Anthropic, Gemini, local gateways, or any OpenAI-compatible API.
  • Tools: define metadata, capability, schema, and handler independently.
  • Runtime: create runs, plans, observations, evidence, completion decisions, and events.
  • Storage: persist runs, events, memory, approvals, and workflow checkpoints.
  • Policy: allow, deny, or require approval based on tool id/capability/name.
  • Telemetry: capture events, tool traces, spans, and bridge them to OpenTelemetry.
  • Workflows: run checkpointed DAGs for durable background jobs.
  • Evals: regression-test agent behavior with simple or custom judges.
  • Replay: turn stored run/events into a timeline for debugging and audit.
  • Multi-agent: delegate tasks to specialized workers by capability.
  • Routing: select models under priority, tag, input-size, and budget constraints.

Native Tool Loop

When tools are registered, runMessage(...) can execute model-requested tool calls:

const result = await agent.runMessage("Read the time and answer in Spanish.");

console.log(result.nativeToolTurn?.toolCalls);
console.log(result.nativeToolTurn?.toolResults);

For UI and worker integrations, use the structured event stream:

for await (const event of agent.runStream("do the task")) {
  if (event.type === "status") console.log(event.label, event.detail);
  if (event.type === "token") process.stdout.write(event.token);
  if (event.type === "native-tool") console.log(event.event.type);
  if (event.type === "final") console.log(event.result.text);
}

Provider Compatibility

The SDK supports three provider formats:

  • openai: OpenAI-compatible chat-completions APIs such as OpenAI, OpenRouter, Groq, Ollama, LM Studio, and compatible gateways.
  • anthropic: Anthropic Messages API, normalized into the SDK chat/tool-call result shape.
  • gemini: Gemini generateContent, normalized into the SDK chat/tool-call result shape.

Use presets:

const openai = openaiProvider({ apiKey, model: "gpt-4o-mini" });
const anthropic = anthropicProvider({ apiKey, model: "claude-3-5-sonnet-latest" });
const gemini = geminiProvider({ apiKey, model: "gemini-1.5-pro" });

OpenAI-compatible providers support native SSE streaming. Anthropic and Gemini currently normalize non-streaming responses through the same complete(...) contract and expose a final stream chunk through stream(...).

Storage

In-memory storage is useful for tests and demos:

const storage = createInMemoryStorage();

JSON file storage is useful for local durable workers:

const storage = createJsonFileStorage("./.nexa");

SQLite is exposed as a driver adapter, so the SDK does not force a native dependency:

const storage = createSqliteStorage(db);

Postgres and Redis are also exposed as driver adapters:

const postgresStorage = createPostgresStorage(pgClient);
await postgresStorage.migrate();

const redisStorage = createRedisStorage(redisClient, "my-app:nexa");

Workflows

const workflow = createWorkflowRuntime({ storage });

const run = workflow.create({
  name: "ship-report",
  nodes: [
    { id: "collect", title: "Collect", run: () => ({ ok: true }) },
    { id: "verify", title: "Verify", dependsOn: ["collect"], run: () => ({ verified: true }) }
  ]
});

await workflow.run({ runId: run.id, nodes });

Policy And Approvals

const policy = createToolPolicy([
  ...requireApprovalForCapabilities(["filesystem.write"], "LOCAL_WRITE"),
  ...denyCapabilities(["system.delete"])
]);

const risk = policy.approvalRiskFor(tool);

Evals

const report = await runAgentEvals({
  agent,
  cases: [
    { id: "time-es", input: "que hora es?", expected: ["hora"] }
  ]
});

Model Routing

const router = createModelRouter([
  { id: "fast", providerId: "openai", model: "gpt-4o-mini", priority: 10, tags: ["fast"] },
  { id: "deep", providerId: "openai", model: "gpt-4.1", priority: 5, tags: ["deep"] }
], {
  maxCalls: 100,
  maxEstimatedCost: 5
});

const decision = router.select({ prompt: "summarize this", requiredTags: ["fast"] });
router.record(decision);

Multi-Agent

const coordinator = createMultiAgentCoordinator([
  {
    id: "builder",
    description: "Builds SDK integrations",
    capabilities: ["code", "examples"],
    run: async ({ task }) => agent.runMessage(task)
  }
]);

const delegated = await coordinator.delegate({
  task: "build an integration example",
  requiredCapabilities: ["examples"]
});

Examples

The examples are documented in examples/README.md.

Run the full offline frontier v3 tour:

pnpm demo:v3

That example walks through:

  • JSON storage
  • Telemetry
  • Advanced memory
  • Tool definitions
  • Policy and approvals
  • Checkpointed workflows
  • Multi-agent coordination
  • Model routing and budget accounting
  • Evals
  • HTTP adapter
  • Replay/debug timeline

Other useful demos:

pnpm demo:message
pnpm demo:chain
pnpm demo:chat
pnpm demo:native-loop
pnpm demo:stream
pnpm demo:storage
pnpm demo:evals
pnpm demo:http
pnpm demo:workflow
pnpm demo:policy
pnpm demo:telemetry

Environment

For real provider calls:

NEXA_BASE_URL=https://api.openai.com
NEXA_API_KEY=...
NEXA_MODEL=gpt-4o-mini
NEXA_TRACE=1

PowerShell example:

$env:NEXA_BASE_URL="https://api.openai.com"
$env:NEXA_API_KEY="..."
$env:NEXA_MODEL="gpt-4o-mini"
pnpm demo:chat

OpenRouter example:

$env:NEXA_BASE_URL="https://openrouter.ai/api"
$env:NEXA_API_KEY="..."
$env:NEXA_MODEL="openai/gpt-4o-mini"
pnpm demo:chat

Current Status

This package currently targets Node.js >=22.19.0, TypeScript, ESM, and OpenAI-compatible chat APIs.

The package is designed to stay dependency-light. Optional production integrations such as SQLite drivers, OpenTelemetry SDKs, web frameworks, vector databases, and queues are expected to be provided by the host app through adapters.

Production Checks

pnpm typecheck
pnpm test
pnpm build
pnpm smoke
pnpm harness
pnpm pack:check

Recommended production wiring:

  • Use createPostgresStorage(...) or createRedisStorage(...) for app backends.
  • Use createJsonFileStorage(...) for local workers and desktop apps.
  • Use createOpenTelemetrySink(...) for traces.
  • Use createToolPolicy(...) plus ApprovalManager for risky tools.
  • Use runStream(...) for UI or server-sent-event style integration.
  • Use runAgentEvals(...) in CI for regression protection.
  • Use createVectorMemoryStore(...) with your embedding provider for semantic memory.
  • Use pnpm harness as the production readiness gate.
  • Use pnpm smoke and pnpm pack:check before publishing.
## Frontier-ready architecture

Nexa Agent SDK is designed with a frontier-style agent architecture: native tool calling, structured streaming, durable storage adapters, policy and approvals, evals, telemetry, replay, workflows, routing, multi-agent coordination, vector memory, queue contracts, package smoke checks, and an extensible `ModelHarness` contract.

The SDK remains dependency-light. Production applications provide their own infrastructure drivers and deployment policies through adapters.

## Extensible by design

Nexa is built around stable contracts instead of hardcoded orchestration strategies.

Developers can extend or replace major runtime behaviors through interfaces for:

- model harnesses
- providers
- tools
- context
- memory
- storage
- routing
- telemetry
- evals

This makes it possible to build custom agent architectures without forking the core SDK.

## Release safety

The repository includes automated checks for package boundaries, accidental credential exposure, and npm tarball contents:

```bash
pnpm verify:boundaries
pnpm verify:secrets
pnpm verify:publish-safety