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

@providerprotocol/agents

v0.0.6

Published

Unified Agent Protocol (UAP) 1.0 implementation for @providerprotocol/ai

Readme

@providerprotocol/agents

A powerful, flexible agent framework implementing the Unified Agent Protocol (UAP) 1.0. Built on top of @providerprotocol/ai for seamless multi-provider LLM support.

Features

  • Functional State Management - Immutable state with explicit data flow
  • Execution Strategies - Choose from loop, react, or plan patterns
  • Middleware Pipeline - Composable before/after hooks for logging, guardrails, etc.
  • Multi-Provider Support - Works with Anthropic, OpenAI, Google, Ollama, and more
  • Streaming - Full streaming support with UAP and UPP events
  • Checkpointing - Built-in session persistence and recovery
  • Thread Trees - Branching conversation support
  • Sub-Agent Tools - Helper utilities for creating tools that spawn sub-agents with event propagation
  • Tool Context Injection - Pass execution context (agentId, stateId, toolCallId) to tools
  • Tool Ordering - Execute tool calls respecting dependencies and sequential barriers
  • Type-Safe - 100% TypeScript with full type inference

Installation

bun install @providerprotocol/agents @providerprotocol/ai

Quick Start

import { agent, AgentState } from '@providerprotocol/agents';
import { anthropic } from '@providerprotocol/ai/anthropic';

// Create an agent
const assistant = agent({
  model: anthropic('claude-sonnet-4-20250514'),
  params: { max_tokens: 4096 },
  system: 'You are a helpful assistant.',
});

// Single query (stateless)
const turn = await assistant.query('What is the capital of France?');
console.log(turn.response.text);

// Multi-turn conversation (stateful)
let state = AgentState.initial();
const r1 = await assistant.ask('My name is Alice.', state);
state = r1.state;

const r2 = await assistant.ask('What is my name?', state);
console.log(r2.turn.response.text); // "Alice"

Adding Tools

import { agent, AgentState } from '@providerprotocol/agents';
import { anthropic } from '@providerprotocol/ai/anthropic';

const calculator = {
  name: 'calculate',
  description: 'Evaluate a math expression',
  parameters: {
    type: 'object' as const,
    properties: {
      expression: { type: 'string' as const },
    },
    required: ['expression'],
  },
  run: async (params: { expression: string }) => {
    // Use a proper math parser in production
    return String(eval(params.expression));
  },
};

const mathBot = agent({
  model: anthropic('claude-sonnet-4-20250514'),
  params: { max_tokens: 1000 },
  tools: [calculator],
});

const turn = await mathBot.query('What is 42 * 17?');
console.log(turn.response.text);
console.log(turn.toolExecutions); // Shows calculator was used

Execution Strategies

Choose how your agent thinks and acts:

Loop (Default)

Simple tool loop - keeps executing until no more tool calls.

import { loop } from '@providerprotocol/agents/execution';

const myAgent = agent({
  model: anthropic('claude-sonnet-4-20250514'),
  execution: loop({ maxIterations: 10 }),
});

ReAct

Reason-Act-Observe pattern with explicit reasoning phase.

import { react } from '@providerprotocol/agents/execution';

const myAgent = agent({
  model: anthropic('claude-sonnet-4-20250514'),
  execution: react({ maxSteps: 20 }),
});

Plan

Generate a structured plan, then execute steps with dependencies.

import { plan } from '@providerprotocol/agents/execution';

const myAgent = agent({
  model: anthropic('claude-sonnet-4-20250514'),
  execution: plan({ maxPlanSteps: 10, allowReplan: true }),
});

Streaming

const stream = myAgent.stream('Explain quantum computing', state);

for await (const event of stream) {
  if (event.source === 'upp' && event.upp?.type === 'text_delta') {
    process.stdout.write(event.upp.delta.text ?? '');
  }
}

const { turn, state: newState } = await stream.result;

Middleware

import { logging } from '@providerprotocol/agents/middleware';

const myAgent = agent({
  model: anthropic('claude-sonnet-4-20250514'),
  middleware: [
    logging({ level: 'info', includeTiming: true }),
  ],
});

Create custom middleware:

import type { Middleware } from '@providerprotocol/agents/middleware';

const rateLimiter: Middleware = {
  name: 'rate-limiter',
  async before(context) {
    await checkRateLimit(context.agent.id);
    return context;
  },
  async after(context, result) {
    recordUsage(result.turn.usage);
    return result;
  },
};

Checkpointing

Persist agent sessions for recovery:

import { fileCheckpoints } from '@providerprotocol/agents/checkpoint';

const store = fileCheckpoints({ dir: '.checkpoints' });

const myAgent = agent({
  model: anthropic('claude-sonnet-4-20250514'),
  checkpoints: store,
  sessionId: 'my-session',
});

// Execute - state automatically saved after each step
await myAgent.generate('Hello', AgentState.initial());

// Later: restore and continue
const saved = await store.load('my-session');
if (saved) {
  const state = AgentState.fromJSON(saved);
  await myAgent.generate('Continue...', state);
}

Lifecycle Hooks

const myAgent = agent({
  model: anthropic('claude-sonnet-4-20250514'),
  strategy: {
    stopCondition: (state) => state.step > 50,
    onStepStart: (step, state) => console.log(`Step ${step}`),
    onAct: (step, toolCalls) => console.log('Tools:', toolCalls),
    onComplete: (result) => console.log('Done!'),
    onError: (error, state) => console.error(error),
  },
});

Provider Support

Works with all providers from @providerprotocol/ai:

import { anthropic } from '@providerprotocol/ai/anthropic';
import { openai } from '@providerprotocol/ai/openai';
import { google } from '@providerprotocol/ai/google';
import { ollama } from '@providerprotocol/ai/ollama';

// Anthropic
agent({ model: anthropic('claude-sonnet-4-20250514'), params: { max_tokens: 4096 } });

// OpenAI
agent({ model: openai('gpt-4o'), params: { max_output_tokens: 4096 } });

// Google
agent({ model: google('gemini-2.0-flash'), params: { maxOutputTokens: 4096 } });

// Ollama (local)
agent({ model: ollama('llama3:8b'), params: { num_predict: 4096 } });

Environment Variables

Create a .env file with your API keys:

ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...
GOOGLE_API_KEY=AI...

API Reference

agent(options)

Creates an agent instance.

| Option | Type | Description | |--------|------|-------------| | model | ModelReference | Required. Model from UPP provider | | params | object | LLM parameters (provider-specific) | | system | string | System prompt | | tools | Tool[] | Available tools | | execution | ExecutionStrategy | Strategy: loop(), react(), plan() | | middleware | Middleware[] | Middleware pipeline | | strategy | AgentStrategy | Lifecycle hooks | | checkpoints | CheckpointStore | Session persistence | | sessionId | string | Session identifier |

Agent Methods

| Method | Returns | Description | |--------|---------|-------------| | generate(input, state) | Promise<GenerateResult> | Execute with state | | stream(input, state) | AgentStreamResult | Stream execution | | ask(input, state) | Promise<GenerateResult> | Multi-turn convenience | | query(input) | Promise<Turn> | Stateless single-turn |

AgentState

Immutable state with chainable operations:

state.withMessage(msg)       // Add message
state.withMessages(msgs)     // Add messages
state.withContext(msgs)      // Replace all messages
state.withStep(n)            // Set step number
state.withMetadata(k, v)     // Add metadata
state.withReasoning(text)    // Add reasoning trace
state.withPlan(steps)        // Set execution plan
state.toJSON()               // Serialize
AgentState.fromJSON(json)    // Deserialize

Examples

See the examples/ directory for complete examples:

  • coding-agent - A Claude Code-style coding assistant with file operations, bash, search, and sub-agents

Run the coding agent example:

ANTHROPIC_API_KEY=sk-... bun examples/coding-agent/index.ts "List all TypeScript files"

Interactive mode:

ANTHROPIC_API_KEY=sk-... bun examples/coding-agent/index.ts -i

TUI mode:

ANTHROPIC_API_KEY=sk-... bun examples/coding-agent/index.ts --tui

Testing

bun test              # All tests
bun test:unit         # Unit tests
bun test:live         # Live API tests
bun lint              # Lint
bun typecheck         # Type check

Philosophy

"UAP is a pipe, not a nanny."

This framework provides orchestration primitives with sensible defaults but no artificial limits. By default:

  • Execution continues until naturally complete (no max iterations)
  • State is explicit and immutable
  • All UPP types flow through without abstraction
  • You control safety, budgets, and constraints

Documentation

  • llms.md - Comprehensive API documentation for LLMs and developers
  • CLAUDE.md - Project coding guidelines and @providerprotocol/ai usage

License

MIT

Related