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

@sschepis/talkdown

v0.4.0

Published

Markdown is the program. The LLM is the runtime. A workflow orchestration language written in Markdown.

Downloads

760

Readme

Talkdown

Markdown is the program. The LLM is the runtime.

Talkdown is a workflow orchestration language written in Markdown. Each document is a self-contained program that any LLM can execute directly — no interpreter, no runtime, no dependencies. You write structured Markdown with explicit inputs, execution steps, outputs, and routing. The LLM reads and runs it.

The Idea

Every AI workflow tool today requires you to write code that orchestrates LLM calls — Python, TypeScript, YAML configs, visual node editors. The LLM is powerful enough to follow structured instructions on its own. It doesn't need a wrapper.

Talkdown inverts the relationship: the document IS the program. A Talkdown document specifies exactly what an LLM should do, what it needs to start, what it should produce, and where control flows next. Chain documents together and you get multi-step workflows with branching, looping, and conditional routing — all in plain Markdown.

The result is workflow automation that is:

  • Human-readable — anyone can read, write, and review a workflow
  • Version-controllable — diff, branch, and merge workflows like code
  • LLM-agnostic — works with any model that can read Markdown
  • Installablenpm install talkdown to get the full document library

How It Works

  1. Write a Talkdown document (structured Markdown with frontmatter)
  2. Give the LLM the SKILL.md and your document
  3. The LLM reads the document, executes its instructions, and produces output
  4. Routing at the end of each document chains to the next step

That's it. SKILL.md teaches the LLM the Talkdown conventions. Your documents are the programs.

Quick Example

Here's a complete directive that decomposes a task into subtasks:

---
type: directive
title: "Decompose Task"
description: "Breaks a complex task into ordered, actionable subtasks"
inputs:
  - name: task
    type: text
    required: true
    description: "The task to decompose"
outputs:
  - name: subtasks
    type: text
    description: "Ordered list of subtasks with time estimates"
tags: [planning, decomposition]
---

# Decompose Task

Breaks a complex task into smaller, actionable subtasks with
clear ordering, dependencies, and time estimates.

## Inputs

- **task** (text, required): The complete description of the task
  to decompose, including any scope or constraints.

## Execution

1. Identify the main objectives and sub-objectives of the task
2. Break each objective into concrete, actionable subtasks
3. Identify dependencies between subtasks
4. Order subtasks respecting their dependencies
5. Estimate time for each subtask

## Output

- **subtasks** (text): An ordered, numbered list of subtasks.

### Output Format

For each subtask, include:
- A clear, actionable description
- Estimated time to complete
- Dependencies on other subtasks (if any)

Document Types

Talkdown has nine document types:

Core Types

| Type | Purpose | Has Routing? | |------|---------|-------------| | Directive | A stateless transformation — takes input, produces output | No | | Step | One stage in a multi-step workflow | Yes | | Process | An orchestrator that defines a workflow's steps and flow | Yes | | Guard | A quality gate that validates output before advancing | Yes (pass/fail) |

Directives are like pure functions. Give them input, get output.

Steps are stages in a workflow. Each step produces output and routes to the next step. Steps can self-loop for iterative refinement, branch conditionally, or terminate the workflow.

Processes are orchestrators. They define which steps exist, how they connect, and where the workflow starts.

Guards are quality gates inserted between steps. They validate output against criteria and route forward on pass or back on fail — making the validator pattern a first-class concept.

Supporting Types

| Type | Purpose | |------|---------| | Persona | A reusable identity that steps adopt — define a role once, reference it everywhere | | Schema | A data contract defining the exact shape of data flowing between steps | | Trigger | An event definition that specifies when a workflow activates | | Test | Test cases that validate a directive or step produces correct output | | Agent | An event-driven agent that reacts to events using Talkdown documents as handlers |

Personas eliminate duplicated ## Context sections. Define "Senior Editor" or "Security Engineer" once, and any step can reference it via persona: ./personas/editor.md in its frontmatter.

Schemas make step interfaces explicit. Instead of loosely-typed text inputs, a step can declare schema: ./schemas/article.md and both the producer and consumer know exactly what the data looks like.

Triggers document workflow entry points — what event causes a workflow to start and what data it provides.

Tests define input/expected-output pairs for directives and steps, enabling validation that documents behave correctly.

Execution Blocks

The ## Execution section supports three kinds of blocks:

Natural language steps — numbered instructions the LLM follows:

1. Analyze the input data
2. Identify key patterns
3. Generate a summary

AI blocks — self-contained prompts fenced with ```ai:

```ai
Given the following data:
{{input_data}}

Identify the three most significant trends and explain each.
```

Code blocks — executable code for LLMs with tool-use capability:

results = analyze(data)
print(json.dumps(results, indent=2))

Routing

Steps chain together via routing. The ## Routing section at the end of each step determines where control flows next.

Linear — unconditional next step:

- next: ./03-report-generation.md

Conditional — choose based on state:

- if: "analysis is complete and verified"
  then: ./04-presentation.md
- default: ./03-analysis.md

Self-loop — iterate until done:

- if: "the model is validated"
  then: ./05-review.md
- default: ./04-modeling.md

Guard gate — pass/fail quality check:

- on_pass: ./04-publish.md
- on_fail: ./02-draft.md

Terminal — end the workflow:

- next: none

Agent Layer

Talkdown 0.4 adds a reactive agent runtime that turns the batch pipeline into an event-driven system. An agent is a long-running event loop that matches incoming events to Talkdown documents (or inline functions), executes them, and manages state across invocations. Zero new runtime dependencies — you provide the LLM, event sources, and optional persistence via simple interfaces.

import { createAgent } from '@sschepis/talkdown/agent';

Quick Start

import { createAgent } from '@sschepis/talkdown/agent';
import type { EventSource, LLMProvider } from '@sschepis/talkdown/agent';

// 1. Provide your LLM
const llm: LLMProvider = {
  complete: async ({ system, prompt }) => {
    const res = await fetch('https://api.openai.com/v1/chat/completions', {
      method: 'POST',
      headers: { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json' },
      body: JSON.stringify({
        model: 'gpt-4',
        messages: [
          ...(system ? [{ role: 'system', content: system }] : []),
          { role: 'user', content: prompt },
        ],
      }),
    });
    const data = await res.json();
    return { content: data.choices[0].message.content };
  },
  evaluateCondition: async ({ condition, context }) => {
    const res = await llm.complete({
      prompt: `Given this context:\n${context}\n\nIs this true? "${condition}"\nAnswer "yes" or "no".`,
    });
    return { result: res.content.toLowerCase().includes('yes'), explanation: res.content };
  },
};

// 2. Create an event source
const webhookSource: EventSource = {
  name: 'webhook',
  start(emit) {
    app.post('/hook', (req, res) => {
      emit(req.body.event, req.body.payload);
      res.sendStatus(200);
    });
  },
  stop() { /* cleanup */ },
};

// 3. Create and start the agent
const agent = createAgent({
  id: 'my-agent',
  llm,
  sources: [webhookSource],
  bindings: [
    { event: 'task_created', handler: './handlers/triage.md' },
    { event: 'review_requested', handler: './handlers/review.md', source: 'webhook' },
    { event: '*', handler: async (ctx) => {
      console.log(`Unhandled: ${ctx.event.type}`);
      return { output: {}, emitted: [] };
    }},
  ],
});

await agent.start();

Event Sources

An EventSource is anything that produces events — webhooks, timers, file watchers, message queues:

interface EventSource {
  readonly name: string;
  start(emit: EventEmitFn): Promise<void> | void;
  stop(): Promise<void> | void;
}

The emit callback wraps your data with an ID, timestamp, and source name automatically:

const timerSource: EventSource = {
  name: 'timer',
  start(emit) {
    this._iv = setInterval(() => emit('tick', { at: Date.now() }), 60_000);
  },
  stop() { clearInterval(this._iv); },
};

Sources can be added and removed at runtime via agent.addSource() and agent.removeSource().

Event Bindings

Bindings map event types to handlers. A handler is either a path to a Talkdown document or an inline async function:

const bindings: EventBinding[] = [
  // Document handler — runs the Talkdown document with event payload as inputs
  { event: 'pr_opened', handler: './handlers/review.md' },

  // Restrict to a specific source
  { event: 'comment', handler: './handlers/reply.md', source: 'github' },

  // Conditional — evaluated by the LLM or constraint engine
  { event: 'alert', handler: './handlers/escalate.md', condition: 'severity is critical' },

  // Wildcard — matches any event type
  { event: '*', handler: './handlers/log.md' },

  // Inline function handler
  {
    event: 'ping',
    handler: async (ctx) => {
      ctx.state.set('lastPing', ctx.event.timestamp);
      return { output: { pong: true }, emitted: [] };
    },
  },
];

Function handlers receive a HandlerContext with the event, agent state, an emit function for producing follow-up events, and the LLM provider.

State Management

Agent state persists across handler invocations. Optionally backed by any storage via AgentStateStore:

const redisStore: AgentStateStore = {
  async load(id) {
    const data = await redis.get(`agent:${id}`);
    return data ? JSON.parse(data) : {};
  },
  async save(id, state) {
    await redis.set(`agent:${id}`, JSON.stringify(state));
  },
};

const agent = createAgent({
  id: 'stateful-agent',
  llm,
  bindings,
  state: { counter: 0 },     // initial state
  stateStore: redisStore,     // auto-loads on start, auto-saves after mutations
});

Middleware

Intercept the event pipeline for logging, filtering, transformation, or error handling:

const logger: AgentMiddleware = {
  async beforeEvent(event, state) {
    console.log(`[${event.type}] from ${event.source}`);
    return event;   // return null to drop the event
  },
  async afterHandler(event, result, state) {
    console.log(`Produced ${Object.keys(result.output).length} outputs`);
  },
  async onError(event, error, state) {
    console.error(`Failed: ${event.type}`, error.message);
  },
};

Programmatic Events and Lifecycle

// Listen for lifecycle events
agent.on('handler:complete', (event, result) => console.log('Done:', event.type));
agent.on('handler:error', (event, err) => console.error('Error:', err));

// Emit events directly (no source required)
agent.emit('manual_trigger', { taskId: 42 });

| Event | When | |-------|------| | started / stopped | Agent starts or stops | | event:received | Any event enters the queue | | event:unmatched | No binding matched | | handler:start / handler:complete / handler:error | Handler lifecycle | | state:change | Agent state was mutated |

Circuit Breaker and Concurrency

Built-in protection against runaway handlers and infinite event loops:

const agent = createAgent({
  id: 'safe-agent',
  llm,
  bindings,
  circuitBreaker: {
    maxHandlerExecutions: 100,   // per handler (default: 100)
    maxEventSelfEmit: 5,         // self-referential chain depth (default: 5)
  },
  concurrency: 3,                // parallel event processing (default: 1)
});

Custom Executor and Code Runner

The default executor handles single documents and full multi-step workflows. You can replace it or provide a code runner for executable code blocks:

const agent = createAgent({
  id: 'custom-agent',
  llm,
  bindings,
  codeRunner: async (lang, source) => {
    // Your sandboxed code execution
    return runInSandbox(lang, source);
  },
});

Cross-Environment Support

Works in Node.js, browsers, and edge runtimes. Set documentRoot explicitly when running outside Node:

const agent = createAgent({
  id: 'edge-agent',
  llm,
  bindings,
  documentRoot: '/app/handlers',
});

For a complete working example, see examples/agent-github-reviewer.ts.

Repository Structure

talkdown/
  SKILL.md              # Teaches any LLM to process Talkdown documents
  README.md             # This file

  src/
    agent/              # Reactive agent runtime (event loop, executor, state)

  docs/
    authoring-guide.md  # How to write Talkdown documents
    format-reference.md # Complete format specification
    examples.md         # Worked examples and patterns

  templates/            # One template per document type
    directive.md        # Stateless transformations
    step.md             # Workflow stages
    process.md          # Workflow orchestrators
    guard.md            # Quality gates
    persona.md          # Reusable identities
    schema.md           # Data contracts
    trigger.md          # Event definitions
    test.md             # Test cases

  directives/           # Reusable, standalone directives
  processes/            # Multi-step workflows
  examples/             # Complete working examples

Installation

npm install talkdown

Or clone the repository directly:

git clone https://github.com/sschepis/talkdown.git

Getting Started

  1. Read SKILL.md to understand how Talkdown processing works
  2. Look at the examples/ directory for complete working documents
  3. Read the Authoring Guide to write your own
  4. Use the Format Reference when you need specifics
  5. Start from a template and customize

Why Talkdown?

vs. Workflow Engines (Airflow, Prefect, Temporal)

No infrastructure, no deployment, no runtime. The specification IS the implementation. Works anywhere an LLM can read text.

vs. Prompt Chains (LangChain, LlamaIndex, DSPy)

Pure Markdown — version-controllable, diffable, reviewable by non-engineers. LLM-agnostic: not tied to any provider, SDK, or framework.

vs. Agent Frameworks (CrewAI, AutoGen, Swarm)

Deterministic flow control — routing is explicit, not emergent. Auditable: every step is documented in the document itself. Composable: directives and processes are modular and reusable. No "agents arguing with each other" failure mode. With the agent layer, you get reactive event-driven agents backed by the same deterministic Talkdown documents — zero new dependencies, bring your own LLM.

vs. Visual Workflow Builders (n8n, Make, Zapier)

Text-native — lives in your repo, not a proprietary platform. Full git workflow: branch, diff, review, merge. No vendor lock-in. Runs on any LLM.

Contributing

Contributions are welcome! Please read the Contributing Guide before submitting a pull request.

This project follows the Contributor Covenant Code of Conduct.

License

MIT