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

@simulacra-ai/core

v0.0.8

Published

Multi-provider agentic conversation engine: core types, conversation base class, workflows, policies, and context transformers

Readme

Simulacra Core

The core package is the foundation of Simulacra. It provides a model-agnostic conversation engine that handles streaming, tool execution, retry policies, and context management.

Installation

npm install @simulacra-ai/core

Quick Start

import { Conversation } from "@simulacra-ai/core";
import { AnthropicProvider } from "@simulacra-ai/anthropic";
import Anthropic from "@anthropic-ai/sdk";

const provider = new AnthropicProvider(new Anthropic(), { model: MODEL_NAME });
using conversation = new Conversation(provider);

await conversation.prompt("Hello!");

console.log(conversation.messages);

Conversation

The Conversation class is the central object that the rest of the system is built on top of. It manages message history, sends prompts, and streams responses. A conversation is created with a ModelProvider, which handles all model-specific concerns like API calls, token limits, and thinking configuration. Providers are available for Anthropic, OpenAI, and Google, and the extensibility model makes it straightforward to add others.

The conversation itself is model-agnostic. All messages and state are represented in a normalized format, so conversations can be serialized, resumed, or switched to a different provider at any time.

// create a conversation with a system prompt
using conversation = new Conversation(provider);
conversation.system = "You are a helpful assistant.";

await conversation.prompt("Hello!");

console.log(conversation.messages);

The developer guide includes the full API.

Tools

Tools give an AI model the ability to take actions and retrieve information. Each tool is a class with a get_definition static method describing what it does and an execute method that runs when the model calls it. Tools are registered on the conversation via toolkit.

Note: A WorkflowManager must be created to drive the tool call loop.

Tool Definition

Each tool must provide a ToolDefinition, which declares its name, description, and parameters. The tool parameters can be primitives or complex types like arrays or objects with their own properties.

Parallel Behavior

The definition can include a parallelizable flag that tells the workflow engine how the tool should be executed. The flag defaults to true, allowing the engine to execute the tool in parallel when multiple tools are called in a batch. When explicitly disabled, the engine will execute the tool on its own before continuing to other tool calls.

Note: Tool call batches are processed in order. Tools within the same batch run concurrently. If a non-parallelizable tool appears between parallelizable ones, the calls before and after it run as separate batches.

Tool Context

The tool class constructor receives a ToolContext object that gives the tool access to the conversation, the active workflow, and any application-specific data passed via context_data.

import type { ToolContext, ToolDefinition, ToolSuccessResult } from "@simulacra-ai/core";

class WeatherTool {
  constructor(context: ToolContext) {
    // context includes conversation, workflow, and context_data
  }

  async execute({ city }: { city: string }): Promise<ToolSuccessResult> {
    // called when the model invokes this tool
    return { result: true, temperature: 72, conditions: "sunny" };
  }

  static get_definition(): ToolDefinition {
    return {
      name: "get_weather",
      description: "Get current weather for a city",
      // parameter types: string, number, boolean, object, array
      parameters: [{ name: "city", type: "string", required: true }],
      // parallelizable defaults to true, set false for tools with side effects
    };
  }
}

Workflows

The workflow engine drives the tool call loop and enables agentic behaviors. The WorkflowManager sits on top of the conversation object, managing workflow state and executing tools on the model's behalf, running them in parallel when possible, and feeding results back until the model produces a final response.

The workflow manager emits events throughout its lifecycle, making it possible to observe the full agentic loop.

// create a conversation and workflow manager
using manager = new WorkflowManager(conversation);

// log the final message when the workflow completes
manager.once("workflow_begin", (workflow) =>
  workflow.once("workflow_end", () => {
    console.log(conversation.messages.at(-1));
  })
);

await conversation.prompt("Use my tools to answer this question.");

The developer guide covers the full event reference.

Policies

Policies control how the underlying model provider is called. They sit between the conversation and the provider, intercepting requests to add behavior like retries, rate limiting, or token budgets. Policies can be used individually or combined with CompositePolicy.

RetryPolicy

RetryPolicy retries failed requests with exponential backoff.

// create a retry policy with an optional filter
const policy = new RetryPolicy({
  max_attempts: 3,
  initial_backoff_ms: 1000,
  backoff_factor: 2,
  retryable: (result) => result.error?.status === 429,
});

CompositePolicy

CompositePolicy chains multiple policies together, executing them from outer to inner.

// combine rate limiting with retries
const policy = new CompositePolicy(
  new RateLimitPolicy({ limit: 10, period_ms: 60_000 }),
  new RetryPolicy({ max_attempts: 3, initial_backoff_ms: 1000, backoff_factor: 2 }),
);

RateLimitPolicy

RateLimitPolicy limits requests per time window.

// create a rate limit policy
const policy = new RateLimitPolicy({ limit: 10, period_ms: 60_000 });

// create a conversation with the policy
using conversation = new Conversation(provider, policy);

// attach so the policy can observe conversation events
policy.attach(conversation);

TokenLimitPolicy

TokenLimitPolicy limits tokens per time window.

// create a token limit policy
const policy = new TokenLimitPolicy({
  period_ms: 60_000,
  total_tokens_per_period: 120_000,
});

// create a conversation with the policy
using conversation = new Conversation(provider, policy);

// attach so the policy can observe conversation events
policy.attach(conversation);

Context Transformers

Context transformers reshape messages on-the-fly without altering the stored conversation history. They operate at two points, before messages are sent to the model (transform_prompt) and after a response comes back (transform_completion). This enables history trimming, content filtering, or constraint enforcement without touching the original messages.

By default, Conversation uses ToolContextTransformer and CheckpointContextTransformer. A custom transformer can be passed to override this.

ToolContextTransformer (default)

Removes orphaned tool calls that lack corresponding tool results, preventing provider errors when tool execution was interrupted.

CheckpointContextTransformer (default)

Replaces pre-checkpoint messages with the checkpoint summary, reducing context size while preserving conversation continuity. See Checkpoints in the developer guide.

CompositeContextTransformer

Chains multiple transformers sequentially.

NoopContextTransformer

Pass-through that disables all conversation-level transformations.

Provider Context Transformers

Model providers can bundle their own transformers via context_transformers. These run before conversation-level transformers and handle provider-specific needs automatically.

The developer guide covers the ProviderContextTransformer interface.

Utilities

  • TokenTracker. Attaches to a conversation to accumulate input/output token counts across requests.
  • CancellationTokenSource / CancellationToken. Cooperative cancellation for async operations.
  • sleep(ms, cancellationToken?). Cancellable delay.
  • deep_merge(original, supplemental). Recursive object merge.

License

MIT