CLI scaffolder for LangGraph projects
Project description
langgraph-init-cli
A production-oriented scaffolding CLI for LangGraph projects. Generate opinionated project layouts that start simple and scale into a full agentic architecture - with graph orchestration, LLM provider abstraction, prompt versioning, tool registries, evaluation, observability, and LangSmith-ready tracing.
pip install langgraph-init-cli
langgraph-init my-app --template advanced
Why langgraph-init?
Starting a LangGraph project from scratch means a lot of boilerplate: wiring state graphs, organizing nodes, managing prompts, hooking up LangSmith. langgraph-init gives you a well-structured starting point so you can skip the scaffolding and focus on the agent logic that matters.
Installation
pip install langgraph-init-cli
Or for a cleaner global CLI experience:
pipx install langgraph-init-cli
Usage
langgraph-init <project-name> --template <template>
Available templates:
| Template | Best For |
|---|---|
base |
Quick experiments and prototypes |
advanced |
Modular team projects with clean graph structure |
production |
Full production systems with tooling, observability, and evaluation |
Example:
langgraph-init my-app --template production
cd my-app
cp .env.example .env
pip install -e .
python -m src.app.main
Templates
base
A minimal LangGraph starter to get something running fast. No LLM, no config — just the graph fundamentals. Runnable via src.app.main:run
src/app/
├── state.py # AppState TypedDict
├── nodes.py # intake_node, draft_node, output_node
└── main.py # StateGraph wiring + run()
Three nodes (intake -> draft -> output), a typed state, and a working app.invoke() call. Replace the stub logic with real LLM calls when you're ready.
advanced
A modular architecture for teams that want clean structure with a real LLM wired in — without full production overhead.
src/app/
├── llm/provider.py # get_llm() — OpenAI / Anthropic / Google / WatsonX
├── graph/ # builder, state, edges, constants, registry
├── memory/checkpointer.py # MemorySaver for in-process conversation persistence
├── nodes/ # intent_node, processing_node, output_node
├── prompts/versions/ # .txt prompt files loaded by task + version
├── services/prompt_service.py
├── tools/calculator.py # Pydantic-validated arithmetic tool
└── utils/logger.py # JSON structured logger
Names/Nodes/Tagspattern for readable graph wiringChatPromptTemplate+get_llm()in every node - real LLM calls from day one- Conditional routing with retry logic (
route_after_process) - Calculator tool with Pydantic input/output validation
MemorySavercheckpointer wired in - samethread_idresumes a conversation
production
A complete scaffold intended for real systems. Everything is modular, runnable without external services, and ready to extend.
src/app/
├── config.py # Settings dataclass — all config from .env
├── llm/provider.py # get_llm() — OpenAI / Anthropic / Google / WatsonX
├── graph/ # builder, state, edges (retry + error routing), constants, registry
├── memory/checkpointer.py # MemorySaver / SqliteSaver / PostgresSaver via MEMORY_BACKEND env var
├── nodes/ # intent, processing, validation, output, error
├── services/ # llm_service, prompt_service, tool_service, evaluation_service, versioning_service
├── prompts/versions/ # intent/v1+v2, extraction/v1, validation/v1
├── tools/ # BaseTool + registry + calculator, retriever, db query, http tools
├── models/ # ExtractionSchema + WorkflowResult (Pydantic)
├── storage/ # workflow_store, prompt_store, cache (in-memory singletons)
├── observability/ # metrics counters, @traceable decorator, LangSmith config
├── evaluation/ # field coverage evaluator + confidence scoring formula
└── api/ # FastAPI-ready /run + /health endpoints
- Graph orchestration with
StateGraph, conditional routing (complete / retry / error), and retry cap from config RunnableParallelfor concurrent extraction and analysis inprocessing_node- Prompt versioning system (
prompts/versions/<task>/v1.txt,v2.txt) with version config inconfig.py - Full tool framework with
BaseTool, registry, and four demo tools (calculator, retriever, DB query, HTTP) ExtractionSchemaandWorkflowResultPydantic models - type-safe extraction and serialization- Evaluation: field coverage + confidence scoring → validation pass/fail → auto retry
- Structured JSON logging, metrics counters,
trace_block()context manager - LangSmith integration
@traceabledecorator for LangSmith (environment-driven, safe when disabled) - In-memory storage singletons (
workflow_store,prompt_store,cache) designed to swap for a real DB
Generated layout:
src/app/
├── main.py
├── config.py
├── graph/
├── nodes/
├── services/
├── tools/
├── prompts/
├── models/
├── storage/
├── utils/
├── observability/
├── evaluation/
└── api/
Graph Wiring Pattern
The advanced and production templates use a three-concept pattern to keep graph wiring readable and maintainable:
class Names:
INTENT = "intent" # Stable node identifiers
class Nodes:
INTENT = intent_node # Callable implementations
class Tags:
COMPLETE = "complete" # Routing labels for conditional edges
RETRY = "retry"
ERROR = "error"
This separates string identifiers from executable functions, making edges easy to read and refactor. constants.py is always the first file to update when adding a new node.
Understanding the Generated Files
Here's what each file and folder does, and where to make changes when building your own agent.
config.py — App Settings
Centralizes all configuration in a Settings dataclass. Every module imports the shared settings instance — nothing reads .env directly.
from src.app.config import settings
settings.log_level # "INFO"
settings.default_prompt_versions # {"intent": "v2", "extraction": "v1", "validation": "v1"}
settings.max_validation_retries # 2
settings.langsmith_tracing # True/False
# What's inside:
project_name # Your app name
environment # "development" | "production" (from APP_ENV)
log_level # "INFO" by default (from LOG_LEVEL)
langsmith_tracing # Toggle LangSmith tracing on/off (from LANGSMITH_TRACING)
langsmith_api_key # Your LangSmith API key (from LANGSMITH_API_KEY)
default_prompt_versions # e.g. {"intent": "v2", "extraction": "v1"}
max_validation_retries # How many times to retry failed validation (default: 2)
What to change here: your project name,default_prompt_versions to activate a new prompt version, max_validation_retries for retry behavior. Add any new env-driven fields your agent needs.
main.py — Entrypoint
Builds the graph and runs it with app.invoke() and a thread_id for conversation memory. This is what executes when you run python -m src.app.main
sample_state = {
"input_text": "Please calculate 12 + 7 and validate the answer.",
"retry_count": 0,
"messages": [],
"prompt_versions": settings.default_prompt_versions.copy(),
"tool_results": {},
}
result = app.invoke(sample_state, config={"configurable": {"thread_id": "session-1"}})
What to change here: replace sample_state with your real input schema.
Swap the input_text for whatever your agent actually receives (a user message, a document, an API payload, etc.).
graph/ — Graph Orchestration
| File | Purpose |
|---|---|
builder.py |
Wires nodes and edges into a StateGraph - start here to understand the flow |
state.py |
WorkflowState TypedDict - every field that flows between nodes |
edges.py |
Routing functions + EDGE_MAP for conditional edges |
constants.py |
Names, Nodes, Tags — update this first when adding a new node |
registry.py |
NODE_REGISTRY dict - loaded by builder.py |
What to change here: add new nodes in registry.py, define new routes in edges.py, and expand the state schema in state.py.
nodes/ — Node Implementations
| File | What it does |
|---|---|
intent.py |
Step 1: classifies input via ChatPromptTemplate + LLM |
processing.py |
Step 2: parallel enrichment + tool dispatch |
validation.py |
Step 3: scores quality, decides retry or continue |
output.py |
Step 4: builds WorkflowResult, saves to workflow_store |
error.py |
Fallback: structured error response |
What to change here: this is where most of your agent logic lives. Replace stub LLM calls with real provider clients. The function signature - (state: WorkflowState) -> WorkflowState - stays the same.
services/ — Reusable Logic
Holds logic that multiple nodes share:
| File | What it does |
|---|---|
llm_service.py |
classify_intent + parallel_enrich via RunnableParallel |
prompt_service.py |
load_prompt(task, version) with fallback + access logging |
evaluation_service.py |
Coordinates field coverage + confidence scoring |
versioning_service.py |
switch_version() for runtime prompt switching |
tool_service.py |
Dispatches tool calls from the registry |
What to change here: replace the keyword-matching stubs in llm_service.py with real get_llm() calls.
tools/ — Tool Framework
BaseTool contract + ToolRegistry. Comes with four demo tools you can run immediately and replace later.
| Tool | What it does |
|---|---|
calculator_tool.py |
Safe arithmetic with Pydantic input/output validation |
retriever_tool.py |
Stub retriever (returns fixed text) |
query_tool.py |
Stub DB query (returns fixed result) |
http_tool.py |
Stub HTTP tool (returns fixed response) |
What to change here: add your own tools by implementing BaseTool, register in tools/registry.py, call in tool_service.py.Delete the demo tools when you no longer need them.
prompts/ — Prompt Versioning
Prompts are plain .txt files. Edit them directly without touching Python code. Add a v2.txt alongside v1.txt to iterate safely — the registry falls back to v1.txt if a requested version doesn't exist.
prompts/versions/
├── intent/
│ ├── v1.txt
│ └── v2.txt
├── extraction/
│ └── v1.txt
└── validation/
└── v1.txt
The prompt service loads the version specified in config.py and falls back to v1 if a version doesn't exist. This lets you iterate on prompts without changing code - just add a new version file and update the config.
What to change here: edit the .txt files directly. Add new task folders as your agent gains new capabilities.
observability/ — Logging and Tracing
Structured JSON logging and metrics counters out of the box. Trace decorators make it easy to instrument any function for LangSmith.
metrics.py—metrics.increment("event")/metrics.snapshot()— global counterslangsmith.py—@traceable(name="...")decorator — sends traces to LangSmith whenLANGSMITH_TRACING=true
What to change here: add custom metrics or extend the trace decorators for new nodes.
evaluation/ — Output Scoring
Field coverage evaluation and confidence scoring to measure output quality. Feeds the validation node's retry decision.
score = (field_coverage × 0.6) + (confidence × 0.4)
is_valid = field_coverage >= 0.5 AND score >= 0.5
What to change here: expand the scoring rubric to match your domain's definition of a good output.
storage/ — Persistence Layer
In-memory singletons designed to swap for a real database without changing node code:
| File | What it stores |
|---|---|
workflow_store.py |
WorkflowResult.model_dump() after each successful run |
prompt_store.py |
Which prompt version ran per task per call |
cache.py |
Simple key-value cache |
Designed to be swapped for a real database (Postgres, Redis, S3, etc.) without changing node code.
What to change here: implement the storage interface for your target database when you're ready to persist results.
api/ — Optional API Surface
A thin API layer (FastAPI-ready) you can enable if you want to expose the agent as an HTTP service.
FastAPI app with /run and /health already wired in routes.py. Serve it when ready:
pip install fastapi uvicorn
uvicorn src.app.api.routes:api --reload
What to change here: add your routes and request/response models here when you're ready to serve the agent over HTTP.
After Generation
Recommended next steps once you have your scaffold:
- Set your
.env— provider, model, log level, memory backend - Uncomment the right provider in
pyproject.tomland runpip install -e . - Replace keyword-matching stubs in
llm_service.pywithget_llm()calls - Update
state.py,schema.py, andworkflow.pyfor your domain's data shape - Add domain-specific tools in
tools/implementingBaseTool - Add real persistence in
storage/for your target database - Set
LANGSMITH_TRACING=trueand addLANGSMITH_API_KEYto activate tracing - Add tests around graph routing and node behavior
Generated langgraph.json
All projects include:
{
"dependencies": ["."],
"graphs": {
"<project-name>": "src.app.main:run"
}
}
This keeps the entrypoint consistent and compatible with LangGraph tooling.
Links
- PyPI: https://pypi.org/project/langgraph-init-cli/
- GitHub: https://github.com/varshasathya/langgraph-init-project
- LangGraph docs: https://langchain-ai.github.io/langgraph/
- LangSmith: https://smith.langchain.com/
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file langgraph_init_cli-0.1.5.tar.gz.
File metadata
- Download URL: langgraph_init_cli-0.1.5.tar.gz
- Upload date:
- Size: 86.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a168cf5096406f5122be8c8aa5661b42e397cf863a80db4d070ec8a1dc7b11f6
|
|
| MD5 |
0fb7cd0f8848111fa9e4d718c0b09736
|
|
| BLAKE2b-256 |
6f23985c54a76c5f521ff01f5e1d1e2157ab24f2060cf6c617321e1b6dd812df
|
File details
Details for the file langgraph_init_cli-0.1.5-py3-none-any.whl.
File metadata
- Download URL: langgraph_init_cli-0.1.5-py3-none-any.whl
- Upload date:
- Size: 144.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ece6cf9466ec0a9d57f9a2fc4d58a129bdc04656d9cedadcf5000598e793e7d7
|
|
| MD5 |
7746933667e7f2bcfdfe71f194b3b2ea
|
|
| BLAKE2b-256 |
86b8c6be9d85332a38500b1ddac0629fb17d2904a14b293777d538185a5817ab
|