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

@jambudipa/dynamic-flow

v0.2.3

Published

A TypeScript library for building dynamic AI-driven workflows with LLM planning and static flow composition using Effect

Readme

DynamicFlow - Runtime AI Planning

CI Status Tests Coverage Node NPM License TypeScript Effect

⚠️ Pre-Release Software: DynamicFlow is under active development. The API may change significantly until the stable v1.0 release. Use in production with caution and expect breaking changes in minor versions until v1.0.

The Only Framework That Generates Complete Execution Graphs at Runtime

Unlike static workflow frameworks or dynamic routing systems, DynamicFlow generates entire execution graphs from scratch for each user prompt. Your AI doesn't just choose paths through a predefined graph - it creates the graph itself, then DynamicFlow executes it deterministically.

Every prompt gets its own custom-generated graph topology. Every graph executes exactly as planned.

📊 Project Health

  • ✅ Tests Passing: 259/267 (97% pass rate)
  • ✅ Test Coverage: 95%+
  • ✅ Build Status: Passing
  • ✅ Type Check: No errors
  • ✅ Dependencies: Up to date
  • ✅ Documentation: Comprehensive

The Problem Nobody Talks About

Most AI frameworks fall into two traps:

  1. Static workflows that can't adapt to varied user requests
  2. Free-form agents that wander off-task during execution

You've seen it: An LLM starts with a good plan, but halfway through execution it "reconsiders", loops indefinitely, or simply forgets what it was doing.

Why DynamicFlow Is Different

The Critical Innovation: Complete Graph Generation

What others do:

  • LangGraph: Define nodes and edges at compile time, route dynamically
  • TaskWeaver: Generate Python code to execute tasks
  • Plan-and-Execute Agents: Create sequences of predefined actions
  • AutoGen: Generate and execute code with multiple LLM calls

What DynamicFlow does:

  • Generates the entire graph topology from the prompt
  • Creates nodes, edges, conditions, and parallel branches dynamically
  • Outputs a JSON graph definition that's safe and debuggable
  • Executes deterministically without any LLM calls

The Two-Phase Architecture That Makes It Possible

Phase 1: AI Planning (Graph Generation)

Your LLM analyzes the user's request and generates a complete execution graph as JSON:

  • Dynamic node creation based on the specific task
  • Custom edge definitions connecting operations
  • Conditional branches determined by the prompt
  • Parallel execution paths when appropriate
  • All topology decisions made upfront

Real Example: "Research Buddhist philosophy on selflessness"

The AI generates this sophisticated research workflow with conditional logic, parallel processing, and multi-stage analysis:

# Run the example
npx tsx src/examples/dynamic/05-selflessness-analysis.ts

Generated Flow Plan:

{
  "version": "1.0",
  "metadata": {
    "name": "Gross vs Subtle Selflessness of Persons - Discovery, Comparison, Clarification, Summary",
    "description": "Search corpus, retrieve relevant book sections and audio, compare gross vs subtle selflessness of persons, clarify if unclear, summarise plainly, and check contradictions.",
    "generated": true,
    "timestamp": "2025-08-19T21:19:09.422Z"
  },
  "nodes": [
    {
      "id": "s1",
      "type": "tool",
      "toolId": "corpus:search",
      "inputs": {},
      "description": "Search corpus for discussions of gross and subtle selflessness of persons in books and audio."
    },
    {
      "id": "s2",
      "type": "parallel",
      "parallel": [
        {
          "id": "s3",
          "description": "Retrieve relevant book section(s) based on $s1.output.",
          "tool": "book:get-section"
        },
        {
          "id": "s4",
          "description": "Retrieve relevant audio transcript(s) based on $s1.output.",
          "tool": "audio:get-transcript"
        }
      ],
      "description": "In parallel, fetch top relevant book sections and audio transcripts."
    },
    {
      "id": "s5",
      "type": "tool",
      "toolId": "llm:compare",
      "description": "Compare how 'gross' vs 'subtle' selflessness of persons are described."
    },
    {
      "id": "s6",
      "type": "if-then",
      "condition": "contains($s5.output, 'unclear') || contains($s5.output, 'overlap')",
      "if_true": [
        {
          "id": "s7",
          "tool": "llm:clarify",
          "description": "Clarify overlapping or unclear points using related texts."
        }
      ],
      "description": "If descriptions appear unclear, run clarification using related texts."
    },
    {
      "id": "s8",
      "type": "tool",
      "toolId": "llm:summarise",
      "description": "Produce a plain-language summary of the distinction."
    },
    {
      "id": "s9",
      "type": "tool",
      "toolId": "llm:check-contradictions",
      "description": "Check the summary for internal contradictions."
    }
  ],
  "edges": [
    {"from": "s1", "to": "s2"},
    {"from": "s2", "to": "s5"},
    {"from": "s5", "to": "s6"},
    {"from": "s6", "to": "s8"},
    {"from": "s8", "to": "s9"}
  ]
}

Execution Result:

{
  "s1": {
    "results": [
      {
        "id": "bk-chandrakirti-12",
        "kind": "book",
        "title": "Introduction to Madhyamaka – Selflessness of Persons",
        "score": 0.94,
        "tags": ["selflessness", "persons", "gross", "analysis"]
      },
      {
        "id": "bk-shantideva-9",
        "kind": "book", 
        "title": "Bodhicaryavatara – View Chapter notes",
        "score": 0.86,
        "tags": ["selflessness", "persons", "subtle", "aggregate"]
      },
      {
        "id": "aud-2021-03-14",
        "kind": "audio",
        "title": "Weekend Teaching – Twofold Selflessness",
        "score": 0.78,
        "tags": ["teaching", "selflessness", "clarification"]
      }
    ]
  },
  "s8": {
    "summary": "Gross selflessness of persons says there is no permanent, unitary, independent 'me' that stands apart from or controls the body and mind. It denies a fixed, soul-like self and targets the coarse belief in an inner boss. Subtle selflessness of persons goes further: even the changing, everyday 'I' lacks any inherent core; it exists only as a label dependent on the aggregates, causes, and concepts. So, while persons work perfectly well in everyday life, no self can be found under ultimate analysis. Realizing the gross level weakens crude self-grasping; realizing the subtle level uproots the deeper belief in inherent existence."
  },
  "s9": {
    "contradictions": ["None detected"]
  }
}

Phase 2: Deterministic Execution

DynamicFlow's execution engine interprets the JSON graph:

  • No more LLM calls during execution
  • No graph structure changes mid-execution
  • Predictable, debuggable behavior
  • Full type safety through Effect
  • Guaranteed completion without infinite loops

Core Features

🎯 True Runtime Graph Generation

The only framework that generates complete execution graphs per-prompt - not routing, not code, but actual graph structures.

⚡ Effect-Based Architecture

First AI framework built on Effect for robust error handling, dependency injection, and composability.

🔄 Production-Ready Persistence

Complete state management with multiple backends and human-in-the-loop workflows:

  • Multiple storage backends (Filesystem, PostgreSQL, Redis, MongoDB, Neo4j)
  • Automatic state serialization with encryption
  • Suspension/resumption with branded SuspensionKey types
  • Human approval and input workflows

🤖 LLM Conversation Routing

Advanced LLM integration with intelligent routing:

  • Flow.switchRoute for LLM-powered decision making
  • Conversation memory and context preservation
  • Real-time terminal interfaces
  • Structured conversation flows with persistence

🔌 MCP Server Integration (NEW)

Production-ready Model Context Protocol server discovery and integration:

  • Real MCP server discovery with automatic tool generation
  • Type-safe MCP tools with proper TypeScript inference
  • Per-server tool generation from discovered capabilities
  • Production MCP connections (no mocks) with cleanup

Featured Examples - Try Them Now!

🗣️ Interactive LLM Conversation with Persistence

Experience DynamicFlow's conversation capabilities:

export OPENAI_API_KEY=your_key_here
npx tsx src/examples/static/16-conversation-final.ts

Features demonstrated:

  • LLM-powered conversation routing using Flow.switchRoute
  • Filesystem persistence with automatic state saving
  • Natural terminal conversation interface
  • Real OpenAI integration with memory
  • Proper suspension/resumption handling

🔧 MCP Server Integration

See real MCP server discovery and tool generation:

npx tsx src/examples/static/15-mcp-curl.ts

Features demonstrated:

  • Real MCP filesystem server connections
  • Type-safe tool generation (string returns, not unknown)
  • Production MCP protocol integration
  • Automatic cleanup and connection management

Generate your own MCP tools:

# Discover MCP servers
npx tsx src/lib/cli/mcp-discovery.ts discover --source network > servers.json

# Generate typed tools
npx tsx src/lib/cli/mcp-discovery.ts generate -i servers.json -o src/generated/mcp-tools

# Use in your flows with full type safety!

Human-in-the-Loop Workflows

DynamicFlow provides powerful persistence capabilities for workflows requiring human interaction:

import { Effect, Schema, Duration } from 'effect'
import { createPersistenceHub, AwaitInputPresets, BackendFactory } from '@jambudipa/dynamic-flow'

// Setup filesystem storage backend
const backend = await Effect.runPromise(
  BackendFactory.create({
    type: 'filesystem',
    config: { basePath: './suspended-flows' }
  })
)

// Create persistence hub
const hub = await Effect.runPromise(
  createPersistenceHub(backend, {
    enableEncryption: false,
    enableCompression: true,
    defaultTimeout: Duration.hours(24)
  })
)

// Create approval tool that suspends flow
const approvalTool = AwaitInputPresets.approval(
  'manager-approval',
  'Manager Approval',
  'Requires manager approval'
).withTimeout(Duration.hours(4)).build(hub)

// Execute tool directly - this will suspend
try {
  const result = await Effect.runPromise(
    approvalTool.execute(undefined, executionContext)
  )
} catch (suspensionSignal) {
  if (suspensionSignal instanceof FlowSuspensionSignal) {
    console.log('Flow suspended:', suspensionSignal.suspensionKey)
    
    // Later, resume with approval
    const approval = { approved: true, approvedBy: "[email protected]" }
    const resumed = await Effect.runPromise(
      hub.resume(suspensionSignal.suspensionKey, approval)
    )
  }
}

LLM Conversation Routing

DynamicFlow treats LLMs as powerful tools with intelligent routing capabilities:

import { Flow } from '@jambudipa/dynamic-flow'
import { LLMServiceLive } from '@jambudipa/dynamic-flow'
import { Effect, pipe } from 'effect'

// Available tools for conversation
const availableTools = [
  weatherTool,
  calculatorTool, 
  emailTool,
  fileSearchTool
]

// Create conversation flow with LLM routing
const conversationFlow = pipe(
  Flow.succeed(conversationInput),
  
  // LLM decides which tool to use based on user input
  Flow.switchRoute(
    'Analyze the user request and select the most appropriate tool',
    availableTools,
    {
      weather: (input) => handleWeatherRequest(input),
      calculator: (input) => handleCalculation(input),
      email: (input) => handleEmail(input),
      fileSearch: (input) => handleFileSearch(input)
    }
  )
)

// Execute with OpenAI integration
const result = await Effect.runPromise(
  pipe(
    Flow.run(conversationFlow),
    Effect.provide(LLMServiceLive)
  )
)

Real Working Example:

npx tsx src/examples/static/16-conversation-final.ts

MCP Server Integration

DynamicFlow includes production-ready MCP (Model Context Protocol) integration:

Discover & Generate Tools

# Discover available MCP servers
npx tsx src/lib/cli/mcp-discovery.ts discover --source network --output json

# Generate tools from specific server
npx tsx src/lib/cli/mcp-discovery.ts discover \
  --source url \
  --filter "stdio://npx @modelcontextprotocol/server-filesystem /tmp" \
  > filesystem-server.json

# Generate TypeScript tools with proper typing
npx tsx src/lib/cli/mcp-discovery.ts generate \
  -i filesystem-server.json \
  -o src/generated/filesystem-tools

Use Generated Tools with Full Type Safety

// Generated tools have proper TypeScript types
import { read_text_fileTool, list_directoryTool } from '../generated/filesystem-tools'

// read_text_fileTool returns string (not unknown!)
const fileContent: string = await read_text_fileTool.execute({ 
  path: '/path/to/file.txt' 
})

// list_directoryTool returns Array<{name: string, type: 'file' | 'directory', size?: number}>
const files = await list_directoryTool.execute({ path: '/path/to/dir' })

MCP Integration Features:

  • Per-server discovery: Each MCP server gets its own tool file
  • Smart type inference: Tool return types inferred from names and capabilities
  • Real connections: Production MCP protocol, not mocks
  • Automatic cleanup: Proper connection management and disconnection

Quick Start

npm install @jambudipa/dynamic-flow effect

Basic Flow Composition

import { Flow } from '@jambudipa/dynamic-flow'
import { Effect, pipe } from 'effect'

// Create a simple flow
const myFlow = pipe(
  Effect.succeed("Hello"),
  Flow.andThen(greeting => Effect.succeed(`${greeting}, World!`)),
  Flow.map(message => message.toUpperCase())
)

// Run the flow
const result = await Effect.runPromise(
  Flow.run(myFlow)
)
console.log(result) // "HELLO, WORLD!"

Create Tools with Schema Validation

import { Tools } from '@jambudipa/dynamic-flow'
import { Schema } from 'effect'

const weatherTool = Tools.createTool({
  id: 'weather',
  name: 'Weather Fetcher',
  description: 'Get current weather for a city',
  inputSchema: Schema.Struct({
    city: Schema.String
  }),
  outputSchema: Schema.Struct({
    temperature: Schema.Number,
    conditions: Schema.String,
    humidity: Schema.Number
  }),
  execute: (input, context) => Effect.succeed({
    temperature: 72,
    conditions: 'sunny',
    humidity: 45
  })
})

// Use in flows with full type safety
const weatherFlow = Flow.pipe(
  Flow.input(CitySchema),
  Flow.tool(weatherTool),
  Flow.map(weather => `It's ${weather.temperature}°F and ${weather.conditions}`)
)

Learn More

📚 Documentation

Comprehensive guides and API references are available in the /docs directory:

🚀 Getting Started

📖 API Reference

📚 Guides

🚀 More Examples

💬 Community

Join the discussion: GitHub Issues | GitHub Discussions

Why Choose DynamicFlow?

| Feature | DynamicFlow | LangGraph | TaskWeaver | CrewAI | AutoGen | |---------|------------|-----------|------------|---------|----------| | Runtime Graph Generation | ✅ Complete | ❌ Static | ❌ Code only | ❌ Static | ❌ Code only | | Graph Topology Per-Prompt | ✅ Yes | ❌ No | ❌ No | ❌ No | ❌ No | | Deterministic Execution | ✅ Always | ⚠️ Optional | ✅ Yes | ✅ Flows | ⚠️ Varies | | Type Safety | ✅ Full Effect | ✅ TypeScript | ⚠️ Python | ⚠️ Python | ⚠️ Python | | Persistence | ✅ Multi-backend | ✅ Yes | ⚠️ Stateful | ✅ Yes | ❌ No | | LLM Conversation | ✅ Advanced routing | ⚠️ Basic | ❌ No | ⚠️ Basic | ✅ Multi-agent | | MCP Integration | ✅ Production ready | ❌ No | ❌ No | ❌ No | ❌ No | | Effect Based | ✅ Yes | ❌ No | ❌ No | ❌ No | ❌ No |

The Bottom Line

DynamicFlow is the only framework that:

  1. Generates complete execution graphs (not just plans or code) at runtime
  2. Creates unique graph topologies for each prompt (not routing through static graphs)
  3. Executes deterministically without LLM involvement after planning
  4. Uses Effect for functional, type-safe workflow composition
  5. Provides production-ready persistence with multiple backends and human workflows
  6. Includes intelligent LLM conversation routing with memory and context
  7. Integrates with MCP servers for real tool discovery and type-safe generation

This isn't an incremental improvement - it's a fundamentally different approach to AI orchestration.

Status

  • Production-ready core: Flow composition, persistence, and MCP integration are stable
  • Active development: Performance optimizations and additional features in progress
  • Feedback welcome: Please share ideas via GitHub Issues or Discussions

Next Steps

  • Performance optimizations for dynamic flow generation
  • Additional MCP server integrations
  • Enhanced conversation routing capabilities
  • More comprehensive testing suite

License

MIT © DynamicFlow Contributors


Built with ❤️ by JAMBUDIPA