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

zaflow

v1.2.2

Published

ZaFlow - Lightweight TypeScript library for building efficient AI agent workflows optimized for free-tier models

Readme

🚀 Overview   •   🪶 Features   •   📦 Installation   •   ⚡ Quick Start   •   🔌 Providers   •   🎮 Execution Modes   •   🛠️ Tools   •   🤖 Agents   •   📷 Multimodal   •   🎯 Structured Output   •   🤝 Contributing


🚀 Overview

ZaFlow solves the complexity of building AI agent systems by providing a high-level, opinionated API. It is built for developers who need to create chatbots, autonomous agents, or AI-powered workflows without getting bogged down in protocol details.

Targeting Node.js and TypeScript developers, ZaFlow integrates essential features like multi-provider support, tool calling, agent delegation, and flow control out of the box.

✨ Features

  • Lightweight - Minimal dependencies, fast startup, no bloat
  • Multi-Provider - OpenAI, Groq, Ollama, or custom provider
  • 3 Execution Modes - Single, Agentic, Autonomous
  • Tools & Agents - Define tools with Zod schema validation
  • Flow Control - Steps, conditions, loops, parallel execution
  • Multimodal - Image, audio, file support with smart media reference system
  • Output Format - Auto, JSON, WhatsApp formatting
  • Agent Delegation - Autonomous agent-to-agent communication
  • Structured Output - Type-safe responses with Zod schema validation

🎨 Concepts & Architecture

ZaFlow - Your orchestrator. Manages providers, tools, agents, and execution flows.

Provider - AI model connection (OpenAI, Groq, Ollama, or custom).

Tool - Functions that AI can call with validated parameters via Zod schemas.

Agent - Specialized AI with its own provider, prompt, and tools.

ExecutionContext - Rich context object with state, messages, and helpers.

📦 Installation

Install zaflow using your preferred package manager:

npm install zaflow
# or
pnpm add zaflow
# or
bun add zaflow

Note: Requires Node.js v20+ and TypeScript for best experience.

Peer Dependencies (optional)

# For OpenAI provider
npm install openai

# For Groq provider
npm install groq-sdk

# For Ollama provider
npm install ollama

⚡ Quick Start

Here is a minimal example to get your AI agent running:

import { ZaFlow, defineProvider } from 'zaflow';

const GroqProvider = defineProvider({
  type: 'groq',
  apiKey: 'your-api-key',
  defaultModel: 'moonshotai/kimi-k2-instruct',
});

const zaflow = new ZaFlow({
  mode: 'single',
  provider: GroqProvider,
});

const result = await zaflow.run('Explain quantum computing in one sentence');
console.log(result.content);

🛠️ Configuration

The ZaFlow constructor accepts a configuration object:

| Option | Type | Required | Description | | :-------------- | :-------------- | :------- | :------------------------------------------------ | | mode | ExecutionMode | ✅ | Execution mode: single, agentic, autonomous | | provider | Provider | ✅ | AI provider instance | | agents | Agent[] | ❌ | Sub-agents (for autonomous mode) | | tools | Tool[] | ❌ | Tools (for agentic/autonomous mode) | | config | ModelConfig | ❌ | Model configuration | | historyConfig | HistoryConfig | ❌ | History management | | storage | StoragePlugin | ❌ | Storage plugin | | hooks | Hooks | ❌ | Event hooks | | systemPrompt | string | ❌ | Custom system prompt |

💡 Advanced Usage

With Tools

You can define tools with Zod schema validation for type-safe AI function calling.

import { ZaFlow, defineProvider, defineTool } from 'zaflow';
import { z } from 'zod';

const calculator = defineTool({
  name: 'calculator',
  description: 'Perform mathematical calculations',
  schema: z.object({
    expression: z.string().describe('Math expression like "2 + 2"'),
  }),
  execute: ({ expression }) => eval(expression),
});

const zaflow = new ZaFlow({
  mode: 'agentic',
  // if you want to use other provider
  // provider: GroqProvider,
  tools: [calculator],
});

const result = await zaflow.run('What is 15 * 7 + 23?');

🔌 Providers

Quick Jump: OpenAI · Groq · Ollama · Custom

OpenAI

import { defineProvider } from 'zaflow';

const provider = defineProvider({
  type: 'openai',
  apiKey: 'sk-xxx',
  defaultModel: 'gpt-4o-mini',
});

Groq

import { defineProvider } from 'zaflow';

const provider = defineProvider({
  type: 'groq',
  apiKey: 'gsk_xxx',
  defaultModel: 'llama-3.3-70b-versatile',
});

Ollama

import { defineProvider } from 'zaflow';

const provider = defineProvider({
  type: 'ollama',
  baseURL: 'http://localhost:11434',
  defaultModel: 'llama3.2',
});

Custom Provider

import { defineProvider } from 'zaflow';

// with your external AI API
const customAI = defineProvider({
  type: 'custom',
  name: 'my-ai',
  adapter: async (messages, config) => {
    const res = await fetch('https://my-api.com/chat', {
      method: 'POST',
      body: JSON.stringify({ messages }),
    });

    const json = await res.json();
    return {
      content: json.response,
      usage: {
        promptTokens: 0,
        completionTokens: 0,
        totalTokens: 0,
      },
    };
  },
});

const zaflow = new ZaFlow({ mode: 'single', provider: customAI });

⚠️ AI Model Quality Affects Tool Calling & Agent Delegation

The quality of your AI model significantly impacts whether tool calls and agent delegations work correctly. When using Custom Provider with external APIs:

  • Low-quality models may ignore tool instructions and respond directly instead of returning the required JSON format {"tool": "...", "params": {...}}
  • Inconsistent behavior - The same prompt may sometimes trigger tools and sometimes not
  • Empty responses - Some APIs may return empty responses causing execution errors

Recommendations:

| Use Case | Recommended Models | | -------------------- | ------------------------------------------------------ | | Tool Calling | GPT-4, GPT-4o, Claude 3, Llama 3.1 70B+, Qwen 2.5 72B+ | | Agent Delegation | GPT-4o, Claude 3 Opus, Llama 3.3 70B | | Simple Chat | Any model works fine |

For best results with tool calling and agent features, use built-in providers (openai, groq, ollama) with high-quality models that have native function calling support.

🎯 Execution Modes

Quick Jump: Single · Agentic · Autonomous

Single Mode

One chat call without tools. Fastest and most token-efficient.

const zaflow = new ZaFlow({
  mode: 'single',
  provider: GroqProvider,
});

const result = await zaflow.run('Hello!');

Agentic Mode

AI can automatically call tools when needed.

const zaflow = new ZaFlow({
  mode: 'agentic',
  provider: GroqProvider,
  tools: [weatherTool],
});

const result = await zaflow.run('Search weather in Jakarta');

Autonomous Mode

AI can call tools AND delegate to other agents.

const zaflow = new ZaFlow({
  mode: 'autonomous',
  provider: GroqProvider,
  agents: [visionAgent, poetAgent],
  tools: [analysisTool],
});

const result = await zaflow.run('Analyze this image and generate a poem');

🛠️ Tools

Quick Jump: Define Tool · Tool Config · Media Handling

Defining Tool

import { defineTool } from 'zaflow';
import { z } from 'zod';

const weatherTool = defineTool({
  name: 'get_weather',
  description: 'Get current weather for a city',
  schema: z.object({
    city: z.string().describe('City name'),
    unit: z.enum(['celsius', 'fahrenheit']).optional(),
  }),
  execute: async ({ city, unit = 'celsius' }) => {
    // const data = await fetchWeatherAPI...
    return `Currently in ${city} is 20°`;
  },
});

Tool Configuration

const tool = defineTool({
  name: 'my_tool',
  description: 'My tool description',
  schema: z.object({ input: z.string() }),
  execute: async ({ input }) => input,
  cache: 300000, // TTL in ms, or true for default
  retry: {
    maxAttempts: 3,
    delayMs: 1000,
    backoff: 'exponential',
  },
});

Tool with Media Handling

const imageAnalyzer = defineTool({
  name: 'analyze_image',
  description: 'Analyze image content',
  schema: z.object({ imageUrl: z.string() }),
  handles: ['image'],
  execute: async ({ imageUrl }) => {
    // const data = await fetchAIImageAnalyzer...
    return 'The picture shows the sun rising!';
  },
});

🤖 Agents

Quick Jump: Define Agent · Media Support · Register

Defining an Agent

import { defineAgent, defineProvider } from 'zaflow';

const codeReviewer = defineAgent({
  name: 'Code Reviewer',
  role: 'Expert code reviewer',
  systemPrompt: `You are an expert code reviewer. Review code for bugs, security issues, and best practices.`,
  provider: GroqProvider,
  model: 'llama-3.3-70b-versatile',
  config: { temperature: 0.3 },
  tools: [lintTool, securityScanTool],
});

const contentWriter = defineAgent({
  name: 'Content Writer',
  role: 'Creative content writer',
  systemPrompt: 'You are a creative content writer.',
  provider: GroqProvider,
  config: { temperature: 0.8 },
});

Agent with Media Support

const visionAgent = defineAgent({
  name: 'Vision Analyzer',
  role: 'Image analysis expert',
  systemPrompt: 'You analyze images and describe their content.',
  provider: GroqProvider,
  // Tools that handle media will automatically be available
});

Register Agents

const zaflow = new ZaFlow({
  mode: 'autonomous',
  provider: GroqProvider,
  agents: [codeReviewer, contentWriter, visionAgent],
});

📷 Multimodal Support

Quick Jump: Image URL · Image Base64 · Media Reference

Image from URL

import { msg, text, image } from 'zaflow';

const messages = [
  ...,
  msg.user([
    text('What is in this image?'),
    image('https://example.com/photo.jpg')
  ])
];

const result = await zaflow.run(messages);

Image from Base64

import { msg, text, imageBase64 } from 'zaflow';

const messages = [
  ...,
  msg.user([
    text('Describe this:'),
    imageBase64(base64Data, 'image/png')
  ])
];

const result = await zaflow.run(messages, { mode: 'autonomous' });

Smart Media Reference System

ZaFlow automatically uses a reference system for large media files (token efficient!):

// 20MB image is NOT copied to every agent
// Only reference ID is passed around
image(massive20MBBase64);

// Agents that need the image: needsMedia: ['image']
// → Receives full resolved data

// Agents that don't need the image
// → Media is stripped, saving tokens!

🎯 Structured Output

Force AI to respond in a specific JSON structure with Zod schema validation:

import { ZaFlow, defineProvider } from 'zaflow';
import { z } from 'zod';

const zaflow = new ZaFlow({
  mode: 'single',
  provider: GroqProvider,
});

// Define your expected response schema
const personSchema = z.object({
  name: z.string(),
  age: z.number(),
  occupation: z.string(),
  skills: z.array(z.string()),
});

const result = await zaflow.run('Extract info: John Doe is a 28 year old software engineer skilled in TypeScript and React', {
  schema: personSchema,
});

// result.content  → response string (may contain JSON)
// To get validated data, you need to parse result.content based on schema
console.log(result.content); // Raw response

Complex Schema Example

const articleSchema = z.object({
  title: z.string(),
  summary: z.string().max(200),
  tags: z.array(z.string()).min(1).max(5),
  sentiment: z.enum(['positive', 'negative', 'neutral']),
  metadata: z.object({
    wordCount: z.number(),
    readingTime: z.string(),
  }),
});

const result = await zaflow.run('Analyze this article: ...', {
  schema: articleSchema,
});

Note: The schema option guides the AI to output in the specified structure, but you'll need to parse result.content to get typed data.

🎯 Execution Options

const result = await zaflow.run(input, {
  config: {
    maxTokens: 4096,
    temperature: 0.7,
    topP: 0.9,
  },
  schema: responseSchema,
  detailed: true,
  persistContext: false,
  systemPrompt: 'You are a helpful assistant.',
});

AI Personalization with systemPrompt

Customize AI behavior without affecting library's internal prompts:

const result = await zaflow.run('Halo!', {
  systemPrompt: `Kamu adalah JawiBot, asisten AI berbahasa Jawa.
Jawab semua pertanyaan dalam bahasa Jawa yang sopan.
Gunakan emoji sesekali untuk membuat percakapan lebih hidup.`,
});

// Output: "Sugeng enjing! Aku JawiBot, asisten AI sing siap mbantu sampeyan! 😊"

Note: systemPrompt is injected before library's internal prompts (tools, agents), ensuring your personalization takes priority.

📊 Execution Result

const result = await zaflow.run(input);

result.content; // Response content (string)
result.metadata; // Execution metadata (if detailed: true)
result.metadata?.tokensUsed; // Token usage { prompt, completion, total }
result.metadata?.toolsCalled; // Array of tool names called
result.metadata?.agentsCalled; // Array of agent names called
result.metadata?.executionTime; // Execution time in milliseconds
result.metadata?.model; // Model name used
result.error; // Error object (if any)

📋 TypeScript Types

import type {
  ZaFlowOptions,
  ZaFlowResponse,
  RunOptions,
  StreamOptions,
  ModelConfig,
  HistoryConfig,
  Message,
  QuotedMessage,
  ExecutionMode,
  TokenUsage,
  ExecutionMetadata,
  ErrorResponse,
  Provider,
  ProviderDefinition,
  ProviderAdapter,
  ProviderResponse,
  ProviderMessage,
  ToolCall,
  RateLimit,
  Tool,
  ToolDefinition,
  ToolContext,
  SharedMemory,
  StorageInterface,
  Agent,
  AgentDefinition,
  AgentCapability,
  AgentConstraints,
  Hooks,
  ErrorContext,
  StoragePlugin,
  StorageAdapter,
  StorageDefinition,
  OptimizationConfig,
  RetryConfig,
  CacheConfig,
  TokenBudget,
  ContentPart,
  TextPart,
  ImagePart,
  AudioPart,
  FilePart,
  MediaType,
  QuoteConfig,
} from 'zaflow';

🤝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository.
  2. Create new branch: git checkout -b feature/my-feature.
  3. Commit your changes: git commit -m 'Add some feature'.
  4. Push to the branch: git push origin feature/my-feature.
  5. Open Pull Request.

🎯 Issues & Feedback

If you encounter any problems or have feature requests, please open an issue

📜 License

Distributed under the MIT License. See LICENSE for details.