New:Socket for Asana Is Now Available.Learn more
Get Started

linforge

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

linforge

Embeddable workbench for LangGraph Agent apps — edit, run, debug, and monitor in one place

latest
Source
npmnpm
Version
0.3.2
Version published
Weekly downloads
1
-85.71%
Maintainers
1
Weekly downloads
 
Created
Source

Linforge

Embeddable workbench for LangGraph Agent applications — design topology on canvas, implement logic in code, compile into executable graphs.

Why Linforge

LangGraph Studio (official)Linforge
Desktop appWeb-embeddable — integrates into your product UI
Code-only graph definitionVisual canvas + code hybrid
Dev-only toolProduct managers sketch graphs, developers implement nodes
Dev-time debuggingBuilt-in run history, step replay, and prompt versioning

Install

npm install linforge
# or
pnpm add linforge

Peer dependencies (install only what you need):

# Server
pnpm add koa @koa/router

# UI
pnpm add react react-dom @xyflow/react

Quick Start

A minimal server in ~30 lines:

import Koa from 'koa';
import cors from '@koa/cors';
import bodyParser from 'koa-bodyparser';
import { StateSchema } from '@langchain/langgraph';
import { z } from 'zod/v4';
import { defineNodeFor } from 'linforge/core';
import { linforgeMiddleware } from 'linforge/server';

// 1. Define state
const MyState = new StateSchema({
  messages: z.array(z.string()).default([]),
  result: z.string().default(''),
});

// 2. Define nodes — state type is inferred automatically
const defineMyNode = defineNodeFor(MyState);

const greeter = defineMyNode({
  key: 'greeter',
  label: 'Greeter',
  run: async (state) => ({
    messages: [...state.messages, '[greeter] Hello!'],
    result: 'Greeting complete.',
  }),
});

// 3. Start server
const app = new Koa();
app.use(cors());
app.use(bodyParser());
app.use(linforgeMiddleware({
  stateSchema: MyState,
  nodes: [greeter],
}));

app.listen(3001);

This gives you a full REST API at http://localhost:3001/linforge — graph CRUD, run execution, step recording, and prompt management.

Package Exports

linforge          Re-exports all submodules
linforge/core     defineNode, Registry, Compiler, RunManager, PromptLoader, Store interfaces
linforge/server   Koa HTTP API (linforgeMiddleware + mountRoutes)
linforge/react    React hooks for graph editing, runs, and prompts
linforge/testing  In-memory Store implementations (dev/test)

Core Concepts

Three-Layer Architecture

Code Layer:    Node implementations + StateSchema + Route predicates    [developer]
Visual Layer:  Topology + Wiring + Prompts + Parameters                [canvas / DB]
Auto Layer:    Compiler merges both into a LangGraph Runnable           [linforge]

defineNode

Create node implementations with defineNode() or the type-safe defineNodeFor():

import { defineNodeFor } from 'linforge/core';

const defineMyNode = defineNodeFor(MyState);

const planner = defineMyNode({
  key: 'planner',
  run: async (state) => ({
    plan: 'Step 1: fetch. Step 2: analyze.',
  }),
  // Optional: conditional routing
  routes: {
    has_plan: (state) => !!state.plan,
  },
});

Store Interfaces

Four database-agnostic interfaces — implement them to plug in any database:

InterfacePurpose
GraphStoreGraph definition CRUD
RunStoreRun record lifecycle
StepPersisterStep data write/query
PromptStorePrompt version management

PromptLoader

createPromptLoader(store) creates a cached prompt loader with Mustache template rendering:

import { createPromptLoader, renderPrompt } from 'linforge/core';

const loader = createPromptLoader(promptStore);

// Load active prompt, render variables, with fallback
const result = await loader.render('node-id', { name: 'World' }, {
  template: 'Hello {{name}}!',
  temperature: 0.7,
});
// result.text → "Hello World!"
// result.source → 'store' | 'fallback'

// Pure function (no store needed)
const text = renderPrompt('Hello {{name}}!', { name: 'World' });

Linforge ships in-memory implementations (linforge/testing) for development. For production, use an adapter package (e.g., linforge-adapter-prisma) or implement the interfaces yourself.

Server API

One-line setup that auto-creates all internal components:

// Single-agent mode (backward compatible)
app.use(linforgeMiddleware({
  stateSchema: MyState,     // required — LangGraph StateSchema
  nodes: [planner, tools],  // required — node definitions
  prefix: '/linforge',      // default: "/linforge"
  stores: {                 // optional — custom Store implementations
    graphStore,
    runStore,
    stepPersister,
    promptStore,
  },
}));

Multi-Agent mode

Bind distinct stateSchema and nodes per Agent:

app.use(linforgeMiddleware({
  agents: [
    { slug: 'qa-bot', name: 'QA Bot', stateSchema: QAState, nodes: [retriever, answerer] },
    { slug: 'coder', name: 'Coder', stateSchema: CoderState, nodes: [planner, coder] },
  ],
  sharedNodes: [logger],  // available to all agents
}));

Each agent gets its own NodeRegistry and GraphCompiler. Routes resolve context by slug. The middleware auto-creates empty graph definitions in GraphStore on first request (code-first mode).

OptionTypeDefaultDescription
agentsAgentConfig[]Multi-agent config (mutually exclusive with stateSchema/nodes)
sharedNodesNodeDefinition[][]Common nodes registered to every agent
stateSchemaStateSchemaSingle-agent: LangGraph StateSchema
nodesNodeDefinition[]Single-agent: node definitions

mountRoutes (low-level)

For full control over component creation. See examples/full-stack/ for a complete example.

REST Endpoints

All endpoints are prefixed with /linforge by default.

MethodPathDescription
GET/graphsList graphs
POST/graphsCreate graph
PATCH/graphs/:slugUpdate graph metadata
GET/graph/:slugGet graph definition
PUT/graph/:slugSave graph definition
POST/graph/:slug/runTrigger a run
GET/graph/:slug/runsList run history
GET/runs/:runIdGet run details
GET/runs/:runId/stepsList steps for a run
GET/registry/nodesList registered nodes
GET/prompts/:nodeIdList prompt versions
GET/prompts/:nodeId/activeGet active prompt
POST/prompts/:nodeIdCreate prompt version
POST/prompts/:nodeId/versions/:id/activateActivate prompt version
GET/templatesList available templates
POST/graph/:slug/apply-templateApply template to graph

Optional stores (runStore, stepPersister, promptStore) return 501 when not provided.

React Hooks

import {
  useLinforgeGraph,
  useLinforgeGraphList,
  useLinforgeRuns,
  useLinforgePrompt,
} from 'linforge/react';
HookPurpose
useLinforgeGraphGraph editing (nodes, edges, save)
useLinforgeGraphListGraph list CRUD
useLinforgeRunsRun management (trigger, list, detail)
useLinforgePromptPrompt version management

Custom Store Adapter

Implement the four interfaces to connect any database:

import type { GraphStore, RunStore, StepPersister, PromptStore } from 'linforge/core';

class MyGraphStore implements GraphStore {
  async getGraph(slug: string) { /* ... */ }
  async saveGraph(graph) { /* ... */ }
  async listGraphs() { /* ... */ }
}

// Pass to middleware
app.use(linforgeMiddleware({
  stateSchema: MyState,
  nodes: [planner],
  stores: { graphStore: new MyGraphStore() },
}));

See linforge-adapter-prisma for a reference implementation.

Examples

  • Quick Start — Minimal server (~30 lines)
  • Full Stack — Manual assembly with all components

License

MIT

Keywords

langgraph

FAQs

Package last updated on 27 Feb 2026

Related posts