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

@fancyrobot/fred

v2.0.0

Published

Fred AI agent framework - core package

Downloads

1,192

Readme

@fancyrobot/fred

npm version TypeScript AI agent framework with intent-based routing and pipeline orchestration.

Upgrading from Fred, FredInstance, or manager-style methods? Use the repository migration guide. Package versions are independent; the guide contains the exact compatible release matrix.

Installation

bun add @fancyrobot/[email protected] \
  effect@^3.21.5 @effect/ai@^0.35.0 @effect/platform@^0.96.0

Add at least one provider package:

Quick Start

Recommended workflow: markdown agent files (.md) + config.yaml.

1) Create an agent file

Create src/agents/assistant.md:

---
id: assistant
platform: openrouter
model: openrouter/auto
utterances:
  - hello
  - help
---

You are a concise, practical assistant.

2) Create config.yaml

providers:
  - id: openrouter
    type: openrouter

agentDirs:
  - ./src/agents

routing:
  defaultAgent: assistant
  rules: []

3) Initialize and send a message

import { createFred } from '@fancyrobot/fred';
import '@fancyrobot/fred-openrouter';

const fred = await createFred({ configPath: 'config.yaml' });

const response = await fred.messages.process('Hello Fred!', {
  conversationId: 'quickstart',
});

console.log(response.content);
await fred.shutdown();

Programmatic alternative (secondary)

const fred = await createFred({
  routing: { defaultAgent: 'assistant', rules: [] },
});
await fred.providers.use('openrouter');
await fred.agents.register({
  id: 'assistant',
  systemMessage: 'You are concise and helpful.',
  platform: 'openrouter',
  model: 'openrouter/auto',
});
await fred.messages.process('What can you do?');
await fred.shutdown();

Agents

Markdown Agent Files (Recommended)

Agent files use YAML frontmatter for runtime configuration and markdown body for the prompt.

---
id: support-agent
platform: openai
model: gpt-4o
tools:
  - calculator
utterances:
  - billing
  - invoice
  - /refund/i
---

You are a billing specialist.
Explain charges clearly and ask for missing details.
  • Configure discovery directories with agentDirs and keep agents in src/agents

Programmatic Agents

await fred.agents.register({
  id: 'triage',
  systemMessage: 'Route requests to the right specialist.',
  platform: 'anthropic',
  model: 'claude-sonnet-4-20250514',
  tools: ['calculator'],
  utterances: ['urgent', 'outage', /priority/i],
});

ETA Templates

Prompts support ETA templating for expressions, conditionals, loops, and partials. See the Examples section for end-to-end patterns.

Typed prompts and agent I/O

systemMessage accepts plain text, an explicit ETA template, or a BAML prompt reference. BAML references require @fancyrobot/fred-baml and a BamlPromptSourceLayer; core never imports generated BAML clients.

import { Effect, Schema } from 'effect';

const Input = Schema.Struct({ question: Schema.String });
const Output = Schema.Struct({ answer: Schema.String, confidence: Schema.Number });

const agent = await fred.agents.register({
  id: 'typed-answer',
  platform: 'openai',
  model: 'gpt-4o-mini',
  systemMessage: {
    template: 'Answer as a concise <%= vars.role %>.',
    variables: { role: 'researcher' },
  },
  input: Input,
  output: Output,
  outputRetry: { maxRetries: 1 },
});

const response = await Effect.runPromise(
  agent.run({ question: 'What is Effect?' }),
);
console.log(response.output?.answer);

input and output are programmatic Effect Schemas; YAML and Markdown cannot serialize live schema values. Output schemas must encode to objects; scalar and array roots are rejected at agent creation. outputRetry retries only malformed structured model output, not provider, network, or tool failures. Structured agents use validated processMessage fallback events instead of exposing unvalidated incremental JSON through streamMessage.

Tools

Effect Schema (recommended)

import { Schema } from 'effect';

await fred.tools.register({
  id: 'weather',
  name: 'weather',
  description: 'Get weather for a city',
  schema: {
    input: Schema.Struct({ city: Schema.String }),
    success: Schema.String,
    metadata: { type: 'object', properties: { city: { type: 'string' } }, required: ['city'] },
  },
  execute: async ({ city }) => `Sunny in ${city}`,
});

Legacy JSON Schema

await fred.tools.register({
  id: 'lookup-order',
  name: 'lookup-order',
  description: 'Get order status by ID',
  parameters: {
    type: 'object',
    properties: {
      orderId: { type: 'string' },
    },
    required: ['orderId'],
  },
  execute: async ({ orderId }) => `Order ${orderId}: in transit`,
});

Fred also includes a built-in calculator tool via @fancyrobot/fred/tools.

Intent Routing

intents:
  - id: billing
    utterances: [billing, invoice, /refund/i]
    action:
      type: agent
      target: billing-agent

routing:
  defaultAgent: billing-agent
  rules: []

Priority: utterances -> intents -> routing.defaultAgent.

Pipelines

Sequential Pipelines

import { PipelineBuilder, createFred } from '@fancyrobot/fred';

const fred = await createFred();
const pipeline = new PipelineBuilder('classify-plan-summarize')
  .addAgentStep('classifier')
  .addAgentStep('planner')
  .addAgentStep('summarizer')
  .build();

await fred.workflows.define({ ...pipeline, checkpoint: { enabled: true } });
const result = await fred.workflows.run('classify-plan-summarize', 'Draft launch checklist');
console.log(result.finalOutput);

Graph Workflows

import { GraphWorkflowBuilder } from '@fancyrobot/fred';

const workflow = new GraphWorkflowBuilder('research-flow')
  .addNode('classifier', { type: 'agent', agentId: 'classifier' })
  .addNode('factual', { type: 'agent', agentId: 'researcher' })
  .addNode('creative', { type: 'agent', agentId: 'ideator' })
  .addNode('merge', { type: 'agent', agentId: 'synthesizer' })
  .addEdge('classifier', 'factual')
  .setDefaultEdge('classifier', 'creative')
  .addEdge('factual', 'merge')
  .addEdge('creative', 'merge')
  .setEntry('classifier')
  .build();

await fred.workflows.define(workflow);

Checkpoints and Pause/Resume

const resumed = await fred.workflows.resume(runId, {
  humanInput: 'approve',
  resumeBehavior: 'continue',
});

Hooks

Fred exposes hooks across the message lifecycle.

await fred.hooks.register('beforeMessageReceived', async (event) => {
  if (typeof event.data !== 'string') return;
  return { data: event.data.replace(/secret/gi, '[REDACTED]') };
});

await fred.hooks.register('afterResponseGenerated', async (event) => {
  console.log('Generated response:', event.data);
});

Configuration

YAML Config

providers:
  - id: openai
    type: openai

agentDirs:
  - ./src/agents

agents:
  - id: fallback-agent
    systemMessage: ./prompts/fallback.md
    platform: openai
    model: gpt-4o

intents:
  - id: refunds
    utterances: [refund, chargeback]
    action:
      type: agent
      target: support-agent

routing:
  defaultAgent: fallback-agent
  rules: []

Config API

const fred = await createFred({ configPath: 'config.yaml' });

Context and Persistence

SQLite (local development)

import { SqliteContextStorage } from '@fancyrobot/fred/context/sqlite';

const fred = await createFred({
  storage: new SqliteContextStorage({ path: './fred.db' }),
});

Postgres (production)

import { PostgresContextStorage } from '@fancyrobot/fred/context/postgres';

const fred = await createFred({
  storage: new PostgresContextStorage({
    connectionString: process.env.FRED_POSTGRES_URL!,
  }),
});

Providers

| Provider | Package | Env Variable | |----------|---------|-------------| | OpenAI | @fancyrobot/fred-openai | OPENAI_API_KEY | | Anthropic | @fancyrobot/fred-anthropic | ANTHROPIC_API_KEY | | Google | @fancyrobot/fred-google | GOOGLE_GENERATIVE_AI_API_KEY | | Groq | @fancyrobot/fred-groq | GROQ_API_KEY | | OpenRouter | @fancyrobot/fred-openrouter | OPENROUTER_API_KEY | | MiniMax | @fancyrobot/fred-minimax | MINIMAX_API_KEY |

Advanced: Effect Services

Fred is built on Effect and exposes service tags for custom Layer composition.

import { Effect } from 'effect';
import { createFred } from '@fancyrobot/fred';
import {
  AgentService,
  PipelineService,
  ProviderRegistryService,
} from '@fancyrobot/fred/effect';

const program = Effect.gen(function* () {
  const providers = yield* ProviderRegistryService;
  const agents = yield* AgentService;
  const pipelines = yield* PipelineService;

  return {
    providers: yield* providers.listProviders(),
    agents: yield* agents.getAllAgents(),
    pipelines: yield* pipelines.listWorkflows(),
  };
});

// Reuse the client's scoped services. Application entry points own this
// Promise boundary; domain logic stays as Effect.
const fred = await createFred();
const result = await fred.effects.run(program);
console.log(result);
await fred.shutdown();

Use this path when you need low-level service control or custom runtime wiring.

Examples

See the examples guide for the 15-example learning path covering quickstart, tools, routing, pipelines, hooks, observability, evaluation, MCP, CLI/TUI, multi-agent orchestration, and optional HTTP.

License

MIT