Getting started
A guided, end-to-end path to a running Agent Protocol server, then to production. Pick the path that matches what you have right now:
- Nothing yet → Path A: one command scaffolds a working project.
- A
langgraph.json→ Path B: a one-line drop-in. - A compiled graph in code → Path C: wrap it in
deps.
All three expose the same Agent Protocol API. For a terse reference instead of a walkthrough, see using-skein.md.
Deployment is a separate choice: keep the default memory drivers while developing, use Postgres/Redis for a shared server, or choose SQLite for a local app or one Node process. The graphs and Agent Protocol remain the same.
Prerequisites
- New projects (Path A): Node 24 is recommended. Generated engines support
^22.12.0 || ^24.0.0 || ^26.0.0. - Existing graphs (Paths B and C): Node ≥ 20 and a package manager (
pnpm/npm). - Node 22, 24 or 26 when selecting SQLite; desktop examples build with Node 24.
- For Paths B and C, a LangGraph.js graph — a
CompiledStateGraphfrom@langchain/langgraph. Path A writes one for you.
Path A — Starting from scratch
No graph, no config, no LangGraph experience. One command:
npm create skein-js@latest my-agent
cd my-agent
npm run dev # → http://localhost:2024, console at /consoleYou get a langgraph.json, a keyless echo graph you can edit, a test, and the whole dev → build → start lifecycle wired up. ESLint and Prettier are enabled by default; --no-linting opts out. The default memory development server needs no API key or database.
Your first agent walks through it end to end — what each generated file does, the four LangGraph concepts you need, adding a model and a tool, then deploying. scaffolding.md is the flag-by-flag reference, and covers doing it by hand if you would rather not run a scaffolder.
Path B — I have a langgraph.json (drop-in)
If you already run langgraph dev, this is a one-line change. Keep your langgraph.json exactly as it is:
// langgraph.json
{ "graphs": { "agent": "./src/agent.ts:graph" } }Swap the CLI:
- "dev": "langgraph dev",
+ "dev": "skein dev",pnpm add -D skein-js
pnpm dev # skein dev — in-process, hot-reload, on http://localhost:2024skein dev loads your TypeScript graphs, hot-reloads on save, and restores development state across restarts. Saving a model key in .env also reloads the graphs. See the CLI reference for supported commands, fields, and limitations.
Prefer to mount it inside your own Express/Fastify/Nest/Next app instead of the CLI? Point an adapter at the same config — { config: "./langgraph.json" } — using the snippets in Mount it on your framework.
Path C — I have a graph in code (embed)
No langgraph.json, no CLI — bring the compiled graph you already hold and wrap it into a ProtocolDeps with embedInMemoryGraphs, then hand { deps } to any adapter:
// server.ts
import { createExpressServer } from "@skein-js/express";
import { embedInMemoryGraphs } from "@skein-js/server-kit";
import { graph } from "./agent.js"; // your CompiledStateGraph
const server = await createExpressServer({ deps: embedInMemoryGraphs({ agent: graph }) });
await server.listen(2024);
console.log("Agent Protocol on http://localhost:2024");pnpm add @skein-js/express @skein-js/server-kit @langchain/langgraph
npx tsx server.ts # or your usual TS runnerThis exposes the same Agent Protocol API. Your host owns development reload and process lifetime; see embedding for graph factories and production drivers.
Verify your project
For CLI paths A and B, open the printed Console URL. Select your graph's Assistant in Playground, send a known input, and compare the response with its expected result. A scaffolded echo graph returns echo: hello when you send hello. For structured graphs, choose JSON and follow the input schema. See Test your graph in the console.
Path C does not mount the console automatically. Use the SDK below, or follow the manual mounting reference.
If you scaffolded a project, run npm test from its directory: the generated echo tests need neither credentials nor a server. See Testing your project for repeatable graph assertions and an SDK smoke test against your own server.
Talk to your server
With the server running on :2024, call it with the standard SDK. Install the client in the calling project if it is not already declared:
pnpm add @langchain/langgraph-sdkThe examples below use the scaffold's echo Assistant and its messages input. For Paths B and C, set assistantId to your configured graph key (such as agent) and adapt the input to its schema.
import { Client } from "@langchain/langgraph-sdk";
const client = new Client({ apiUrl: "http://localhost:2024" });
const assistantId = "echo";
const thread = await client.threads.create();
const reply = await client.runs.wait(thread.thread_id, assistantId, {
input: { messages: [{ role: "user", content: "hello" }] },
});
console.log(reply);Stream tokens as they arrive instead of waiting:
for await (const event of client.runs.stream(thread.thread_id, assistantId, {
input: { messages: [{ role: "user", content: "hello" }] },
})) {
console.log(event.event, event.data);
}Each registered graph has a default Assistant whose assistant_id equals its graph key. The full endpoint surface is in agent-protocol.md; the stream wire format is in streaming.md.
Add a web UI
Follow the frontend SDK guide to install the React binding and build a UI that displays messages, errors, and cancellation controls. Test it against the same Assistant you used above.
A browser on a different origin needs CORS enabled — see the CORS recipe. For a same-origin full-stack app (no CORS), the nextjs-app example serves the protocol and the UI from one Next.js app.
Go to production
The default dev server uses in-memory drivers. For a durable shared server, choose Postgres for state and checkpoints, and add Redis when workers or streaming clients span instances.
For an embedded backend (Path C), install @skein-js/runtime before using the durable helper:
pnpm add @skein-js/runtime// embed path → durable, reading POSTGRES_URI / REDIS_URI from the environment
import { embedPostgresGraphs } from "@skein-js/runtime";
import { createExpressServer } from "@skein-js/express";
import { graph } from "./agent.js";
const { deps, dispose } = await embedPostgresGraphs({ agent: graph });
const server = await createExpressServer({ deps });
await server.listen(2024);
process.on("SIGTERM", async () => {
await server.close();
await dispose(); // release the pools it opened
process.exit(0);
});From a langgraph.json, either call buildRuntime({ store: "postgres", queue: "redis" }) and pass its deps and channels to the adapter, or skip code entirely: skein dev --store postgres --queue redis, and skein build / skein up to containerize. Redis is optional for a single instance but required to run more than one. Details: embedding.md, storage.md, runs-and-redis.md, deploy.md.
Or choose SQLite for a local application
Scaffold with npm create skein-js@latest my-app -- --storage sqlite for SQLite dev/start scripts, or install @skein-js/local and the upstream SQLite saver in an existing project:
pnpm add @skein-js/local @langchain/langgraph-checkpoint-sqlite@~1.0.4
pnpm skein dev --store sqlite --queue sqliteThe CLI defaults to .skein/state.sqlite. For an Electron utility process, a Tauri Node backend, or a CLI using graphs in code, use embedSqliteGraphs and let the host own startup and shutdown. See local deployment for embedding, examples, and failure accounting.
Where to next
- Your first agent — the from-zero walkthrough, if you took Path A.
- Recipes — auth, human-in-the-loop, long-term memory, CORS, background runs, deploy.
- Using skein-js — the terse consumer/agent cheat-sheet.
- Examples — a runnable project per framework and pattern.
- Overview & architecture · Agent Protocol surface