__VERSION__ — Open-source LLM orchestration framework in Go

LLM Orchestration
as DAGs

A high-performance Go library for LLM orchestration and AI agent development. Manage conversations as DAGs with branching, tool use, and multi-provider routing.

👤 User
🤖 LLM
👤 User
🤖 LLM
🤖 LLM
🔧 Tool
🤖 LLM

Built for Performance in Go

A lightweight alternative to LangGraph and LangChain, written in Go for speed, simplicity, and developer experience

⚡ ~1ms Overhead

Pure Go implementation with minimal latency. Ships as a single static binary with zero runtime dependencies — no Python, no JVM.

🌊 Native LLM Streaming

Real-time token streaming via SSE for AI agent responses. WebSocket support for bidirectional communication with any LLM provider.

🔄 Auto Retry

Automatic exponential backoff for transient failures. Multi-provider routing across Anthropic, OpenAI, Gemini, and Grok with weighted fallback.

🌳 Conversation Branching & Forking

Branch from any node in your conversation history. Explore alternative paths, compare LLM responses, and build complex AI agent workflows — all stored as a DAG.

💾 Persistent Storage

SQLite-backed conversation history by default (zero config). Full history replay and conversation tree navigation for debugging AI agents.

📊 Model Catalog

Deployment-aware catalog with canonical models, hosted offerings, deployment-specific native IDs, pricing, context windows, and capabilities.

Simple CLI for LLM Conversations

Start LLM conversations, branch from any node in the conversation history, and manage your AI workflow DAGs with intuitive commands.

Get Started
terminal
$ langdag prompt -m claude-sonnet-4-6 "What is LangDAG?"

# LangDAG responds with streaming output...
Assistant: LangDAG is a high-performance tool that...

$ langdag show k7x2

k7x2m9
└── [1] user: "What is LangDAG?"
    └── [2] assistant: "LangDAG is..."

$ langdag prompt k7x2 "Tell me more"
# Continue from any node to branch the tree

LLM Orchestration SDK for Every Language

Build AI agents and LLM-powered applications with native SDKs for Python, Go, and TypeScript

prompt.py — Start a conversation
from langdag import LangDAGClient

with LangDAGClient() as client:
    # Start a conversation
    node = client.prompt(
        message="What is LangDAG?"
    )
    print(node.content)

    # Continue from any node
    node2 = node.prompt("Tell me more")
branch.py — Branch conversations
# Branch from any node to explore alternatives
alt = node.prompt(
    "Tell me more about branching"
)

# Stream from a node
for event in node.prompt_stream(
    "Explain in detail"
):
    if event.content:
        print(event.content, end="")
explore.py — View tree structure
# List all conversations (root nodes)
roots = client.list_roots()
for node in roots:
    print(f"{node.id}: {node.title}")

# Get full tree from any node
tree = client.get_tree(node_id)
for n in tree.nodes:
    print(f"[{n.type}] {n.content}")
prompt.go — Start a conversation
client := langdag.NewClient("http://localhost:8080")

// Start a conversation
node, err := client.Prompt(ctx, "What is LangDAG?")
fmt.Println(node.Content)

// Continue from any node
node2, err := node.Prompt(ctx, "Tell me more")
branch.go — Branch conversations
// Branch from any node
alt, err := node.Prompt(ctx, "Different angle")

// Stream from a node
stream, err := node.PromptStream(ctx, "Explain in detail")
for event := range stream.Events() {
    fmt.Print(event.Content)
}
result, err := stream.Node()
explore.go — View tree structure
// List all conversations (root nodes)
roots, err := client.ListRoots(ctx)
for _, node := range roots {
    fmt.Printf("%s: %s\n", node.ID, node.Title)
}

// Get full tree from any node
tree, err := client.GetTree(ctx, nodeID)
for _, n := range tree.Nodes {
    fmt.Printf("[%s] %s\n", n.Type, n.Content)
}
agent.go — Embed in your app
import "langdag.com/langdag"

client, _ := langdag.New(langdag.Config{
    StoragePath: "./agent.db",
    APIKeys: map[string]string{
        "anthropic": os.Getenv("ANTHROPIC_API_KEY"),
    },
})
defer client.Close()

// Prompt with streaming
result, _ := client.Prompt(ctx, "What is LangDAG?")
for chunk := range result.Stream {
    fmt.Print(chunk.Content)
}
routing.go — Multi-provider routing
// Weighted routing + fallback
client, _ := langdag.New(langdag.Config{
    Routing: []langdag.RoutingEntry{
        {Provider: "anthropic", Weight: 80},
        {Provider: "openai", Weight: 20},
    },
    FallbackOrder: []string{
        "anthropic", "openai",
    },
    APIKeys: map[string]string{
        "anthropic": anthropicKey,
        "openai":    openaiKey,
    },
})
dag.go — Navigate conversations
// Continue from any node
r2, _ := client.PromptFrom(ctx, result.NodeID, "Tell me more")

// List all conversations
convs, _ := client.ListConversations(ctx)

// Get full subtree
tree, _ := client.GetSubtree(ctx, nodeID)

// Testing — inject mock deps
c, _ := langdag.NewWithDeps(mockProvider, tempDB)
prompt.ts — Start a conversation
import { LangDAGClient } from 'langdag';

const client = new LangDAGClient();

// Start a conversation
const node = await client.prompt("What is LangDAG?");
console.log(node.content);

// Continue from any node
const node2 = await node.prompt("Tell me more");
branch.ts — Branch conversations
// Branch from any node
const alt = await node.prompt("Different angle");

// Stream from a node
const stream = await node.promptStream(
  "Explain in detail"
);
for await (const event of stream.events()) {
  process.stdout.write(event.content);
}
const result = await stream.node();
explore.ts — View tree structure
// List all conversations (root nodes)
const roots = await client.listRoots();
for (const node of roots) {
  console.log(`${node.id}: ${node.title}`);
}

// Get full tree from any node
const tree = await client.getTree(nodeId);
for (const n of tree.nodes) {
  console.log(`[${n.type}] ${n.content}`);
}

Use as a Go Module

Import langdag directly into your Go application — no server, no extra dependencies

go get langdag.com/langdag
agent.go
import "langdag.com/langdag"

client, _ := langdag.New(langdag.Config{
    StoragePath: "./agent.db",
    APIKeys: map[string]string{
        "anthropic": os.Getenv("ANTHROPIC_API_KEY"),
    },
})
defer client.Close()

result, _ := client.Prompt(ctx, "What is LangDAG?",
    langdag.WithModel("claude-opus-4-6"),
)
for chunk := range result.Stream {
    if chunk.Done {
        fmt.Printf("\n[node %s]\n", chunk.NodeID)
    } else {
        fmt.Print(chunk.Content)
    }
}

// Continue from any node — branch your conversation DAG
result2, _ := client.PromptFrom(ctx, result.NodeID, "Tell me more")

Start Building AI Agents in Seconds

Install the LangDAG SDK for your language and start orchestrating LLM conversations

pip install langdag
go get langdag.com/langdag/sdks/go
go get langdag.com/langdag

Embed langdag directly in your Go app — persistent DAG storage, multi-provider routing, no server required.

npm install langdag

Or run the server: git clone https://github.com/aduermael/langdag && cd langdag && go run ./cmd/langdag serve

View on GitHub View Examples

Migrating from LangGraph?

LangDAG is a lightweight Go alternative to LangGraph, LangChain, and other Python-based LLM frameworks

LangDAG vs LangGraph

LangGraph requires a Python runtime and the full LangChain ecosystem. LangDAG is a single Go binary with ~1ms overhead, native DAG-based conversation history, and built-in conversation forking — no Python required.

LangDAG vs LangChain

LangChain provides a broad Python toolkit for LLM applications. LangDAG focuses on conversation orchestration and persistent DAG storage in Go, making it ideal for production AI agents that need performance and a small footprint.

Built-in LangGraph Import

Already using LangGraph? LangDAG includes a migration tool that imports your existing LangGraph conversation history — from JSON exports or directly from LangGraph's SQLite checkpoints. Migration guide →