Problem
When using custom abstractions or wrapper classes around LangGraph's StateGraph, the create-langgraph config CLI command fails to detect your graphs:
┌ 🦜 create-langgraph config
│
◇ Found 0 agent(s) in 96 file(s)
│
└ No LangGraph agents found.
Make sure your agents are defined using one of these patterns:
- createAgent({ ... })
- createReactAgent({ ... })
- new StateGraph(...).compile()
- workflow.compile()This occurs because the CLI uses static regex pattern matching to discover graphs, which doesn't recognize custom class hierarchies or abstraction patterns.
Solution
The LangGraph Platform runtime fully supports factory functions - you just need to bypass the auto-detection and manually configure your langgraph.json.
Step 1: Export a Factory Function
Add a factory function that returns your compiled graph:
// SampleGraph.ts
import { StateGraph, START, END } from "@langchain/langgraph";
import type { LangGraphRunnableConfig } from "@langchain/langgraph";
export abstract class AgentGraph {
abstract build(graph: StateGraph<State>): StateGraph<State>;
compile() {
const stateGraph = new StateGraph<State>(StateSchema);
return this.build(stateGraph).compile();
}
}
export class SampleGraph extends AgentGraph {
build(graph: StateGraph<State>) {
return graph
.addNode("a", nodeA)
.addNode("b", nodeB)
.addEdge(START, "a")
.addEdge("a", "b")
.addEdge("b", END);
}
}
// Factory function for LangGraph Platform
export function makeSampleGraph() {
return new SampleGraph().compile();
}
// Or with runtime config access:
export function makeSampleGraphWithConfig(config: LangGraphRunnableConfig) {
const userId = config.configurable?.user_id;
// Can customize graph based on config
return new SampleGraph().compile();
}Step 2: Manually Create langgraph.json
Instead of using create-langgraph config, manually create your configuration file:
{
"node_version": "20",
"graphs": {
"SampleGraph": "./src/authoring/graph/SampleGraph.ts:makeSampleGraph"
},
"env": ".env"
}The format is ./path/to/file.ts:exportedFunctionName.
How It Works
The LangGraph Platform runtime dynamically imports your module and checks if the export is a function. If so, it calls the function (optionally passing config) and expects a CompiledStateGraph or StateGraph in return:
// From the runtime - factory functions are fully supported
if (typeof graph === "function") {
return async (config) => {
const graphLike = await graph(config);
return afterResolve(graphLike);
};
}Key Points
CLI auto-detection is limited - It only recognizes specific static patterns in source code
Runtime is flexible - Factory functions returning compiled graphs work perfectly
Manual config is fine - You don't need CLI auto-detection; manually writing
langgraph.jsonis fully supportedConfig parameter is optional - Your factory can accept
LangGraphRunnableConfigif you need runtime customization