Skip to content

Serving

Getting the protocol in front of clients: which adapter, the non-chat surface, and browser access.

Pick a framework adapter

Every adapter serves the identical protocol and takes the same { config } | { deps } seam — pick the framework you already run. Each has a standalone entry (a dedicated server) and an embedded one (mount beside your existing routes).

FrameworkPackageStandaloneEmbeddedExamples
Express@skein-js/expresscreateExpressServerskeinRouterexpress-basic, embed-graph
Fastify@skein-js/fastifycreateFastifyServerskeinPluginfastify-basic, fastify-app
NestJS@skein-js/nestjscreateNestServerSkeinModule.forRootnestjs-basic, nestjs-app
Next.js@skein-js/nextjsroute handlerscreateSkeinRouteHandlers (App) · createSkeinPagesHandler (Pages)nextjs-app, nextjs-basic

Bun and Deno use @skein-js/fetch, selected with skein build --runtime. For a framework skein doesn't ship, the adapters are ~40-line shims over one handler table — see building-an-adapter.md. Mount snippets: using-skein.md.

Serve a graph as a plain endpoint

For a classifier, extractor, or a workflow another service calls — no threads, no runs. The request body is the graph input; the response is its final state.

ts
const { router } = await skeinInvokeRouter({ deps: embedInMemoryGraphs({ triage }) });
app.use(router);
// curl -X POST localhost:2024/invoke/triage -d '{"text":"…"}'

Working version: invoke-endpoint — two non-chat graphs, no model, no API key. Details: serving-a-single-graph.md.

CORS for a browser client

CORS is off by default. Same-origin needs nothing — see nextjs-app, which serves the protocol and the UI from one app.

jsonc
// langgraph.json — matches the LangGraph CLI
{ "http": { "cors": { "allow_origins": ["http://localhost:3000"] } } }

Or pass cors to any adapter (true for permissive dev, false to force off). Cross-origin example: react-usestream.