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
Metadata
Release files for langgraph-init-cli 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| langgraph_init_cli-0.1.5.tar.gz | 86.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| langgraph_init_cli-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 230.8 kB
Release files / langgraph_init_cli-0.1.5.tar.gz
| Download URL | langgraph_init_cli-0.1.5.tar.gz |
|---|---|
| Size | 86.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a168cf5096406f5122be8c8aa5661b42e397cf863a80db4d070ec8a1dc7b11f6
|
|
BLAKE2b-256 checksum How to use checksums |
6f23985c54a76c5f521ff01f5e1d1e2157ab24f2060cf6c617321e1b6dd812df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|
Release files / langgraph_init_cli-0.1.5-py3-none-any.whl
| Download URL | langgraph_init_cli-0.1.5-py3-none-any.whl |
|---|---|
| Size | 144.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ece6cf9466ec0a9d57f9a2fc4d58a129bdc04656d9cedadcf5000598e793e7d7
|
|
BLAKE2b-256 checksum How to use checksums |
86b8c6be9d85332a38500b1ddac0629fb17d2904a14b293777d538185a5817ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|