langgraph-init-cli 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. langgraph_cli/__init__.py +5 -0
  2. langgraph_cli/cli.py +42 -0
  3. langgraph_cli/generator.py +47 -0
  4. langgraph_cli/templates/advanced/README.md +3 -0
  5. langgraph_cli/templates/advanced/langgraph.json +6 -0
  6. langgraph_cli/templates/advanced/pyproject.toml +20 -0
  7. langgraph_cli/templates/advanced/src/__init__.py +1 -0
  8. langgraph_cli/templates/advanced/src/__pycache__/__init__.cpython-313.pyc +0 -0
  9. langgraph_cli/templates/advanced/src/app/__init__.py +1 -0
  10. langgraph_cli/templates/advanced/src/app/__pycache__/__init__.cpython-313.pyc +0 -0
  11. langgraph_cli/templates/advanced/src/app/__pycache__/main.cpython-313.pyc +0 -0
  12. langgraph_cli/templates/advanced/src/app/graph/__init__.py +1 -0
  13. langgraph_cli/templates/advanced/src/app/graph/__pycache__/__init__.cpython-313.pyc +0 -0
  14. langgraph_cli/templates/advanced/src/app/graph/__pycache__/builder.cpython-313.pyc +0 -0
  15. langgraph_cli/templates/advanced/src/app/graph/__pycache__/constants.cpython-313.pyc +0 -0
  16. langgraph_cli/templates/advanced/src/app/graph/__pycache__/edges.cpython-313.pyc +0 -0
  17. langgraph_cli/templates/advanced/src/app/graph/__pycache__/registry.cpython-313.pyc +0 -0
  18. langgraph_cli/templates/advanced/src/app/graph/__pycache__/state.cpython-313.pyc +0 -0
  19. langgraph_cli/templates/advanced/src/app/graph/builder.py +18 -0
  20. langgraph_cli/templates/advanced/src/app/graph/constants.py +20 -0
  21. langgraph_cli/templates/advanced/src/app/graph/edges.py +14 -0
  22. langgraph_cli/templates/advanced/src/app/graph/registry.py +8 -0
  23. langgraph_cli/templates/advanced/src/app/graph/state.py +9 -0
  24. langgraph_cli/templates/advanced/src/app/main.py +12 -0
  25. langgraph_cli/templates/advanced/src/app/nodes/__init__.py +1 -0
  26. langgraph_cli/templates/advanced/src/app/nodes/__pycache__/__init__.cpython-313.pyc +0 -0
  27. langgraph_cli/templates/advanced/src/app/nodes/__pycache__/intent.cpython-313.pyc +0 -0
  28. langgraph_cli/templates/advanced/src/app/nodes/__pycache__/output.cpython-313.pyc +0 -0
  29. langgraph_cli/templates/advanced/src/app/nodes/__pycache__/processing.cpython-313.pyc +0 -0
  30. langgraph_cli/templates/advanced/src/app/nodes/intent.py +9 -0
  31. langgraph_cli/templates/advanced/src/app/nodes/output.py +10 -0
  32. langgraph_cli/templates/advanced/src/app/nodes/processing.py +14 -0
  33. langgraph_cli/templates/advanced/src/app/prompts/__init__.py +1 -0
  34. langgraph_cli/templates/advanced/src/app/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  35. langgraph_cli/templates/advanced/src/app/prompts/__pycache__/registry.cpython-313.pyc +0 -0
  36. langgraph_cli/templates/advanced/src/app/prompts/registry.py +12 -0
  37. langgraph_cli/templates/advanced/src/app/services/__init__.py +1 -0
  38. langgraph_cli/templates/advanced/src/app/services/__pycache__/__init__.cpython-313.pyc +0 -0
  39. langgraph_cli/templates/advanced/src/app/services/__pycache__/prompt_service.cpython-313.pyc +0 -0
  40. langgraph_cli/templates/advanced/src/app/services/prompt_service.py +6 -0
  41. langgraph_cli/templates/advanced/src/app/utils/__init__.py +1 -0
  42. langgraph_cli/templates/advanced/src/app/utils/__pycache__/__init__.cpython-313.pyc +0 -0
  43. langgraph_cli/templates/advanced/src/app/utils/__pycache__/logger.cpython-313.pyc +0 -0
  44. langgraph_cli/templates/advanced/src/app/utils/logger.py +6 -0
  45. langgraph_cli/templates/base/README.md +3 -0
  46. langgraph_cli/templates/base/langgraph.json +6 -0
  47. langgraph_cli/templates/base/pyproject.toml +20 -0
  48. langgraph_cli/templates/base/src/__init__.py +1 -0
  49. langgraph_cli/templates/base/src/__pycache__/__init__.cpython-313.pyc +0 -0
  50. langgraph_cli/templates/base/src/app/__init__.py +1 -0
  51. langgraph_cli/templates/base/src/app/__pycache__/__init__.cpython-313.pyc +0 -0
  52. langgraph_cli/templates/base/src/app/__pycache__/main.cpython-313.pyc +0 -0
  53. langgraph_cli/templates/base/src/app/__pycache__/nodes.cpython-313.pyc +0 -0
  54. langgraph_cli/templates/base/src/app/__pycache__/state.cpython-313.pyc +0 -0
  55. langgraph_cli/templates/base/src/app/main.py +27 -0
  56. langgraph_cli/templates/base/src/app/nodes.py +22 -0
  57. langgraph_cli/templates/base/src/app/state.py +7 -0
  58. langgraph_cli/templates/production/README.md +121 -0
  59. langgraph_cli/templates/production/langgraph.json +6 -0
  60. langgraph_cli/templates/production/pyproject.toml +20 -0
  61. langgraph_cli/templates/production/src/__init__.py +1 -0
  62. langgraph_cli/templates/production/src/__pycache__/__init__.cpython-313.pyc +0 -0
  63. langgraph_cli/templates/production/src/app/__init__.py +1 -0
  64. langgraph_cli/templates/production/src/app/__pycache__/__init__.cpython-313.pyc +0 -0
  65. langgraph_cli/templates/production/src/app/__pycache__/config.cpython-313.pyc +0 -0
  66. langgraph_cli/templates/production/src/app/__pycache__/main.cpython-313.pyc +0 -0
  67. langgraph_cli/templates/production/src/app/api/__init__.py +1 -0
  68. langgraph_cli/templates/production/src/app/api/__pycache__/__init__.cpython-313.pyc +0 -0
  69. langgraph_cli/templates/production/src/app/api/__pycache__/app.cpython-313.pyc +0 -0
  70. langgraph_cli/templates/production/src/app/api/__pycache__/routes.cpython-313.pyc +0 -0
  71. langgraph_cli/templates/production/src/app/api/app.py +11 -0
  72. langgraph_cli/templates/production/src/app/api/routes.py +16 -0
  73. langgraph_cli/templates/production/src/app/config.py +37 -0
  74. langgraph_cli/templates/production/src/app/evaluation/__init__.py +1 -0
  75. langgraph_cli/templates/production/src/app/evaluation/__pycache__/__init__.cpython-313.pyc +0 -0
  76. langgraph_cli/templates/production/src/app/evaluation/__pycache__/evaluator.cpython-313.pyc +0 -0
  77. langgraph_cli/templates/production/src/app/evaluation/__pycache__/scoring.cpython-313.pyc +0 -0
  78. langgraph_cli/templates/production/src/app/evaluation/evaluator.py +12 -0
  79. langgraph_cli/templates/production/src/app/evaluation/scoring.py +2 -0
  80. langgraph_cli/templates/production/src/app/graph/__init__.py +1 -0
  81. langgraph_cli/templates/production/src/app/graph/__pycache__/__init__.cpython-313.pyc +0 -0
  82. langgraph_cli/templates/production/src/app/graph/__pycache__/builder.cpython-313.pyc +0 -0
  83. langgraph_cli/templates/production/src/app/graph/__pycache__/constants.cpython-313.pyc +0 -0
  84. langgraph_cli/templates/production/src/app/graph/__pycache__/edges.cpython-313.pyc +0 -0
  85. langgraph_cli/templates/production/src/app/graph/__pycache__/registry.cpython-313.pyc +0 -0
  86. langgraph_cli/templates/production/src/app/graph/__pycache__/state.cpython-313.pyc +0 -0
  87. langgraph_cli/templates/production/src/app/graph/builder.py +20 -0
  88. langgraph_cli/templates/production/src/app/graph/constants.py +28 -0
  89. langgraph_cli/templates/production/src/app/graph/edges.py +21 -0
  90. langgraph_cli/templates/production/src/app/graph/registry.py +10 -0
  91. langgraph_cli/templates/production/src/app/graph/state.py +15 -0
  92. langgraph_cli/templates/production/src/app/main.py +27 -0
  93. langgraph_cli/templates/production/src/app/models/__init__.py +1 -0
  94. langgraph_cli/templates/production/src/app/models/__pycache__/__init__.cpython-313.pyc +0 -0
  95. langgraph_cli/templates/production/src/app/models/__pycache__/schema.cpython-313.pyc +0 -0
  96. langgraph_cli/templates/production/src/app/models/__pycache__/workflow.cpython-313.pyc +0 -0
  97. langgraph_cli/templates/production/src/app/models/schema.py +11 -0
  98. langgraph_cli/templates/production/src/app/models/workflow.py +30 -0
  99. langgraph_cli/templates/production/src/app/nodes/__init__.py +1 -0
  100. langgraph_cli/templates/production/src/app/nodes/__pycache__/__init__.cpython-313.pyc +0 -0
  101. langgraph_cli/templates/production/src/app/nodes/__pycache__/error.cpython-313.pyc +0 -0
  102. langgraph_cli/templates/production/src/app/nodes/__pycache__/intent.cpython-313.pyc +0 -0
  103. langgraph_cli/templates/production/src/app/nodes/__pycache__/output.cpython-313.pyc +0 -0
  104. langgraph_cli/templates/production/src/app/nodes/__pycache__/processing.cpython-313.pyc +0 -0
  105. langgraph_cli/templates/production/src/app/nodes/__pycache__/validation.cpython-313.pyc +0 -0
  106. langgraph_cli/templates/production/src/app/nodes/error.py +7 -0
  107. langgraph_cli/templates/production/src/app/nodes/intent.py +21 -0
  108. langgraph_cli/templates/production/src/app/nodes/output.py +13 -0
  109. langgraph_cli/templates/production/src/app/nodes/processing.py +32 -0
  110. langgraph_cli/templates/production/src/app/nodes/validation.py +22 -0
  111. langgraph_cli/templates/production/src/app/observability/__init__.py +1 -0
  112. langgraph_cli/templates/production/src/app/observability/__pycache__/__init__.cpython-313.pyc +0 -0
  113. langgraph_cli/templates/production/src/app/observability/__pycache__/langsmith.cpython-313.pyc +0 -0
  114. langgraph_cli/templates/production/src/app/observability/__pycache__/metrics.cpython-313.pyc +0 -0
  115. langgraph_cli/templates/production/src/app/observability/langsmith.py +31 -0
  116. langgraph_cli/templates/production/src/app/observability/metrics.py +15 -0
  117. langgraph_cli/templates/production/src/app/prompts/__init__.py +1 -0
  118. langgraph_cli/templates/production/src/app/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
  119. langgraph_cli/templates/production/src/app/prompts/__pycache__/registry.cpython-313.pyc +0 -0
  120. langgraph_cli/templates/production/src/app/prompts/registry.py +20 -0
  121. langgraph_cli/templates/production/src/app/prompts/versions/extraction/v1.txt +1 -0
  122. langgraph_cli/templates/production/src/app/prompts/versions/intent/v1.txt +1 -0
  123. langgraph_cli/templates/production/src/app/prompts/versions/intent/v2.txt +1 -0
  124. langgraph_cli/templates/production/src/app/prompts/versions/validation/v1.txt +1 -0
  125. langgraph_cli/templates/production/src/app/services/__init__.py +1 -0
  126. langgraph_cli/templates/production/src/app/services/__pycache__/__init__.cpython-313.pyc +0 -0
  127. langgraph_cli/templates/production/src/app/services/__pycache__/evaluation_service.cpython-313.pyc +0 -0
  128. langgraph_cli/templates/production/src/app/services/__pycache__/llm_service.cpython-313.pyc +0 -0
  129. langgraph_cli/templates/production/src/app/services/__pycache__/prompt_service.cpython-313.pyc +0 -0
  130. langgraph_cli/templates/production/src/app/services/__pycache__/tool_service.cpython-313.pyc +0 -0
  131. langgraph_cli/templates/production/src/app/services/__pycache__/versioning_service.cpython-313.pyc +0 -0
  132. langgraph_cli/templates/production/src/app/services/evaluation_service.py +19 -0
  133. langgraph_cli/templates/production/src/app/services/llm_service.py +56 -0
  134. langgraph_cli/templates/production/src/app/services/prompt_service.py +21 -0
  135. langgraph_cli/templates/production/src/app/services/tool_service.py +22 -0
  136. langgraph_cli/templates/production/src/app/services/versioning_service.py +12 -0
  137. langgraph_cli/templates/production/src/app/storage/__init__.py +1 -0
  138. langgraph_cli/templates/production/src/app/storage/__pycache__/__init__.cpython-313.pyc +0 -0
  139. langgraph_cli/templates/production/src/app/storage/__pycache__/cache.cpython-313.pyc +0 -0
  140. langgraph_cli/templates/production/src/app/storage/__pycache__/prompt_store.cpython-313.pyc +0 -0
  141. langgraph_cli/templates/production/src/app/storage/__pycache__/workflow_store.cpython-313.pyc +0 -0
  142. langgraph_cli/templates/production/src/app/storage/cache.py +12 -0
  143. langgraph_cli/templates/production/src/app/storage/prompt_store.py +11 -0
  144. langgraph_cli/templates/production/src/app/storage/workflow_store.py +13 -0
  145. langgraph_cli/templates/production/src/app/tools/__init__.py +1 -0
  146. langgraph_cli/templates/production/src/app/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  147. langgraph_cli/templates/production/src/app/tools/__pycache__/base.cpython-313.pyc +0 -0
  148. langgraph_cli/templates/production/src/app/tools/__pycache__/registry.cpython-313.pyc +0 -0
  149. langgraph_cli/templates/production/src/app/tools/api/__pycache__/http_tool.cpython-313.pyc +0 -0
  150. langgraph_cli/templates/production/src/app/tools/api/http_tool.py +12 -0
  151. langgraph_cli/templates/production/src/app/tools/base.py +15 -0
  152. langgraph_cli/templates/production/src/app/tools/db/__pycache__/query_tool.cpython-313.pyc +0 -0
  153. langgraph_cli/templates/production/src/app/tools/db/query_tool.py +12 -0
  154. langgraph_cli/templates/production/src/app/tools/rag/__pycache__/retriever_tool.cpython-313.pyc +0 -0
  155. langgraph_cli/templates/production/src/app/tools/rag/retriever_tool.py +18 -0
  156. langgraph_cli/templates/production/src/app/tools/registry.py +26 -0
  157. langgraph_cli/templates/production/src/app/tools/utils/__pycache__/calculator_tool.cpython-313.pyc +0 -0
  158. langgraph_cli/templates/production/src/app/tools/utils/calculator_tool.py +21 -0
  159. langgraph_cli/templates/production/src/app/utils/__init__.py +1 -0
  160. langgraph_cli/templates/production/src/app/utils/__pycache__/__init__.cpython-313.pyc +0 -0
  161. langgraph_cli/templates/production/src/app/utils/__pycache__/logger.cpython-313.pyc +0 -0
  162. langgraph_cli/templates/production/src/app/utils/__pycache__/parallel.cpython-313.pyc +0 -0
  163. langgraph_cli/templates/production/src/app/utils/__pycache__/tracing.cpython-313.pyc +0 -0
  164. langgraph_cli/templates/production/src/app/utils/logger.py +33 -0
  165. langgraph_cli/templates/production/src/app/utils/parallel.py +9 -0
  166. langgraph_cli/templates/production/src/app/utils/tracing.py +16 -0
  167. langgraph_init_cli-0.1.0.dist-info/METADATA +383 -0
  168. langgraph_init_cli-0.1.0.dist-info/RECORD +172 -0
  169. langgraph_init_cli-0.1.0.dist-info/WHEEL +5 -0
  170. langgraph_init_cli-0.1.0.dist-info/entry_points.txt +2 -0
  171. langgraph_init_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
  172. langgraph_init_cli-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,5 @@
1
+ """LangGraph project scaffolding CLI."""
2
+
3
+ __all__ = ["__version__"]
4
+
5
+ __version__ = "0.1.0"
langgraph_cli/cli.py ADDED
@@ -0,0 +1,42 @@
1
+ from pathlib import Path
2
+
3
+ import typer
4
+
5
+ from langgraph_cli.generator import TEMPLATE_NAMES, scaffold_project
6
+
7
+ app = typer.Typer(
8
+ add_completion=False,
9
+ help="Scaffold LangGraph projects with modular templates.",
10
+ )
11
+
12
+
13
+ @app.command()
14
+ def main(
15
+ project_name: str = typer.Argument(..., help="Directory name for the new project."),
16
+ template: str = typer.Option(
17
+ "base",
18
+ "--template",
19
+ "-t",
20
+ help="Project template to use.",
21
+ case_sensitive=False,
22
+ ),
23
+ ) -> None:
24
+ normalized = template.lower()
25
+ if normalized not in TEMPLATE_NAMES:
26
+ typer.secho(
27
+ f"Unsupported template '{template}'. Choose from: {', '.join(TEMPLATE_NAMES)}.",
28
+ fg=typer.colors.RED,
29
+ err=True,
30
+ )
31
+ raise typer.Exit(code=1)
32
+
33
+ target_path = Path(project_name).resolve()
34
+ scaffold_project(project_name=project_name, template_name=normalized, target_dir=target_path)
35
+ typer.secho(
36
+ f"Created {normalized} LangGraph project at {target_path}",
37
+ fg=typer.colors.GREEN,
38
+ )
39
+
40
+
41
+ if __name__ == "__main__":
42
+ app()
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ import shutil
4
+ from importlib import resources
5
+ from pathlib import Path
6
+
7
+ TEMPLATE_NAMES = ("base", "advanced", "production")
8
+ TOKEN_MAP_KEY = "{{PROJECT_NAME}}"
9
+
10
+
11
+ def _template_root() -> Path:
12
+ return Path(str(resources.files("langgraph_cli").joinpath("templates")))
13
+
14
+
15
+ def _replace_tokens(content: str, project_name: str) -> str:
16
+ return content.replace(TOKEN_MAP_KEY, project_name)
17
+
18
+
19
+ def scaffold_project(project_name: str, template_name: str, target_dir: Path) -> Path:
20
+ source_dir = _template_root() / template_name
21
+ if not source_dir.exists():
22
+ raise FileNotFoundError(f"Template '{template_name}' does not exist.")
23
+
24
+ if target_dir.exists() and any(target_dir.iterdir()):
25
+ raise FileExistsError(f"Target directory '{target_dir}' already exists and is not empty.")
26
+
27
+ target_dir.mkdir(parents=True, exist_ok=True)
28
+
29
+ for source_path in source_dir.rglob("*"):
30
+ if "__pycache__" in source_path.parts or source_path.suffix == ".pyc":
31
+ continue
32
+ relative_path = source_path.relative_to(source_dir)
33
+ destination = target_dir / relative_path
34
+
35
+ if source_path.is_dir():
36
+ destination.mkdir(parents=True, exist_ok=True)
37
+ continue
38
+
39
+ destination.parent.mkdir(parents=True, exist_ok=True)
40
+ if source_path.suffix in {".png", ".jpg", ".jpeg", ".gif", ".ico"}:
41
+ shutil.copy2(source_path, destination)
42
+ continue
43
+
44
+ rendered = _replace_tokens(source_path.read_text(encoding="utf-8"), project_name=project_name)
45
+ destination.write_text(rendered, encoding="utf-8")
46
+
47
+ return target_dir
@@ -0,0 +1,3 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ Advanced LangGraph scaffold generated by `langgraph-init`.
@@ -0,0 +1,6 @@
1
+ {
2
+ "dependencies": ["."],
3
+ "graphs": {
4
+ "{{PROJECT_NAME}}": "src.app.main:run"
5
+ }
6
+ }
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "{{PROJECT_NAME}}"
7
+ version = "0.1.0"
8
+ description = "Advanced LangGraph scaffold for {{PROJECT_NAME}}"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = [
12
+ "langgraph>=0.2.0",
13
+ "langchain>=0.3.0",
14
+ "langsmith>=0.1.0",
15
+ "python-dotenv>=1.0.0",
16
+ "typer>=0.12.0",
17
+ ]
18
+
19
+ [tool.setuptools.packages.find]
20
+ include = ["src*"]
@@ -0,0 +1 @@
1
+ """Project source package."""
@@ -0,0 +1 @@
1
+ """Advanced app package."""
@@ -0,0 +1 @@
1
+ """Graph package."""
@@ -0,0 +1,18 @@
1
+ from langgraph.graph import END, START, StateGraph
2
+
3
+ from src.app.graph.constants import Names
4
+ from src.app.graph.edges import EDGE_MAP, route_after_process
5
+ from src.app.graph.registry import NODE_REGISTRY
6
+ from src.app.graph.state import WorkflowState
7
+
8
+
9
+ def build_graph():
10
+ graph = StateGraph(WorkflowState)
11
+ for name, node in NODE_REGISTRY.items():
12
+ graph.add_node(name, node)
13
+
14
+ graph.add_edge(START, Names.INTENT)
15
+ graph.add_edge(Names.INTENT, Names.PROCESS)
16
+ graph.add_conditional_edges(Names.PROCESS, route_after_process, EDGE_MAP)
17
+ graph.add_edge(Names.OUTPUT, END)
18
+ return graph.compile()
@@ -0,0 +1,20 @@
1
+ from src.app.nodes.intent import intent_node
2
+ from src.app.nodes.output import output_node
3
+ from src.app.nodes.processing import processing_node
4
+
5
+
6
+ class Names:
7
+ INTENT = "intent"
8
+ PROCESS = "process"
9
+ OUTPUT = "output"
10
+
11
+
12
+ class Tags:
13
+ CONTINUE = "continue"
14
+ COMPLETE = "complete"
15
+
16
+
17
+ class Nodes:
18
+ INTENT = intent_node
19
+ PROCESS = processing_node
20
+ OUTPUT = output_node
@@ -0,0 +1,14 @@
1
+ from src.app.graph.constants import Names, Tags
2
+ from src.app.graph.state import WorkflowState
3
+
4
+
5
+ def route_after_process(state: WorkflowState) -> str:
6
+ if state.get("validation_passed"):
7
+ return Tags.COMPLETE
8
+ return Tags.CONTINUE
9
+
10
+
11
+ EDGE_MAP = {
12
+ Tags.COMPLETE: Names.OUTPUT,
13
+ Tags.CONTINUE: Names.PROCESS,
14
+ }
@@ -0,0 +1,8 @@
1
+ from src.app.graph.constants import Names, Nodes
2
+
3
+
4
+ NODE_REGISTRY = {
5
+ Names.INTENT: Nodes.INTENT,
6
+ Names.PROCESS: Nodes.PROCESS,
7
+ Names.OUTPUT: Nodes.OUTPUT,
8
+ }
@@ -0,0 +1,9 @@
1
+ from typing import TypedDict
2
+
3
+
4
+ class WorkflowState(TypedDict, total=False):
5
+ input_text: str
6
+ intent: str
7
+ extracted_value: str
8
+ output: str
9
+ validation_passed: bool
@@ -0,0 +1,12 @@
1
+ from src.app.graph.builder import build_graph
2
+
3
+
4
+ def run():
5
+ app = build_graph()
6
+ result = app.invoke({"input_text": "Calculate 2 + 2 and confirm it is valid."})
7
+ print(result["output"])
8
+ return result
9
+
10
+
11
+ if __name__ == "__main__":
12
+ run()
@@ -0,0 +1 @@
1
+ """Nodes package."""
@@ -0,0 +1,9 @@
1
+ from src.app.graph.state import WorkflowState
2
+
3
+
4
+ def intent_node(state: WorkflowState) -> WorkflowState:
5
+ text = state.get("input_text", "").lower()
6
+ intent = "answer"
7
+ if any(token in text for token in ("calculate", "+", "-", "*", "/")):
8
+ intent = "math"
9
+ return {"intent": intent}
@@ -0,0 +1,10 @@
1
+ from src.app.graph.state import WorkflowState
2
+
3
+
4
+ def output_node(state: WorkflowState) -> WorkflowState:
5
+ return {
6
+ "output": (
7
+ f"Intent={state.get('intent', 'unknown')}; "
8
+ f"Extracted={state.get('extracted_value', 'none')}"
9
+ )
10
+ }
@@ -0,0 +1,14 @@
1
+ import re
2
+
3
+ from src.app.graph.state import WorkflowState
4
+ from src.app.prompts.registry import PromptRegistry
5
+ from src.app.services.prompt_service import PromptService
6
+
7
+
8
+ def processing_node(state: WorkflowState) -> WorkflowState:
9
+ prompt = PromptService(PromptRegistry()).get_prompt("processing")
10
+ text = state.get("input_text", "")
11
+ numbers = re.findall(r"\d+", text)
12
+ extracted = ", ".join(numbers) if numbers else prompt
13
+ validation_passed = bool(extracted)
14
+ return {"extracted_value": extracted, "validation_passed": validation_passed}
@@ -0,0 +1 @@
1
+ """Prompts package."""
@@ -0,0 +1,12 @@
1
+ class PromptRegistry:
2
+ def __init__(self) -> None:
3
+ self._prompts = {
4
+ "processing": {
5
+ "v1": "Extract relevant entities from the request.",
6
+ }
7
+ }
8
+ self._defaults = {"processing": "v1"}
9
+
10
+ def get(self, task: str, version: str | None = None) -> str:
11
+ selected_version = version or self._defaults[task]
12
+ return self._prompts[task][selected_version]
@@ -0,0 +1 @@
1
+ """Services package."""
@@ -0,0 +1,6 @@
1
+ class PromptService:
2
+ def __init__(self, registry):
3
+ self.registry = registry
4
+
5
+ def get_prompt(self, task: str, version: str | None = None) -> str:
6
+ return self.registry.get(task, version=version)
@@ -0,0 +1 @@
1
+ """Utility package."""
@@ -0,0 +1,6 @@
1
+ import logging
2
+
3
+
4
+ def get_logger(name: str) -> logging.Logger:
5
+ logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s %(message)s")
6
+ return logging.getLogger(name)
@@ -0,0 +1,3 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ Base LangGraph scaffold generated by `langgraph-init`.
@@ -0,0 +1,6 @@
1
+ {
2
+ "dependencies": ["."],
3
+ "graphs": {
4
+ "{{PROJECT_NAME}}": "src.app.main:run"
5
+ }
6
+ }
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "{{PROJECT_NAME}}"
7
+ version = "0.1.0"
8
+ description = "Base LangGraph scaffold for {{PROJECT_NAME}}"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = [
12
+ "langgraph>=0.2.0",
13
+ "langchain>=0.3.0",
14
+ "langsmith>=0.1.0",
15
+ "python-dotenv>=1.0.0",
16
+ "typer>=0.12.0",
17
+ ]
18
+
19
+ [tool.setuptools.packages.find]
20
+ include = ["src*"]
@@ -0,0 +1 @@
1
+ """Project source package."""
@@ -0,0 +1 @@
1
+ """Base app package."""
@@ -0,0 +1,27 @@
1
+ from langgraph.graph import END, START, StateGraph
2
+
3
+ from src.app.nodes import draft_node, intake_node, output_node
4
+ from src.app.state import AppState
5
+
6
+
7
+ def build_graph():
8
+ graph = StateGraph(AppState)
9
+ graph.add_node("intake", intake_node)
10
+ graph.add_node("draft", draft_node)
11
+ graph.add_node("output", output_node)
12
+ graph.add_edge(START, "intake")
13
+ graph.add_edge("intake", "draft")
14
+ graph.add_edge("draft", "output")
15
+ graph.add_edge("output", END)
16
+ return graph.compile()
17
+
18
+
19
+ def run() -> AppState:
20
+ app = build_graph()
21
+ result = app.invoke({"user_input": "Support request for order status"})
22
+ print(result["response"])
23
+ return result
24
+
25
+
26
+ if __name__ == "__main__":
27
+ run()
@@ -0,0 +1,22 @@
1
+ from src.app.state import AppState
2
+
3
+
4
+ def intake_node(state: AppState) -> AppState:
5
+ text = state.get("user_input", "").strip()
6
+ topic = "general"
7
+ lowered = text.lower()
8
+ if "billing" in lowered:
9
+ topic = "billing"
10
+ elif "support" in lowered:
11
+ topic = "support"
12
+ return {"topic": topic}
13
+
14
+
15
+ def draft_node(state: AppState) -> AppState:
16
+ topic = state.get("topic", "general")
17
+ text = state.get("user_input", "")
18
+ return {"response": f"[{topic}] {text}"}
19
+
20
+
21
+ def output_node(state: AppState) -> AppState:
22
+ return {"response": state.get("response", "No response generated.")}
@@ -0,0 +1,7 @@
1
+ from typing import TypedDict
2
+
3
+
4
+ class AppState(TypedDict, total=False):
5
+ user_input: str
6
+ topic: str
7
+ response: str
@@ -0,0 +1,121 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ Production-grade LangGraph scaffold generated by `langgraph-init`.
4
+
5
+ ## Overview
6
+
7
+ This project is a modular LangGraph application designed to serve as a strong starting point for agentic workflows in production-style environments. It includes graph orchestration, node isolation, service boundaries, prompt versioning, evaluation, structured logging, LangSmith integration hooks, and an extensible tool system.
8
+
9
+ ## Project Layout
10
+
11
+ ```text
12
+ src/app/
13
+ ├── main.py
14
+ ├── config.py
15
+ ├── graph/
16
+ ├── nodes/
17
+ ├── services/
18
+ ├── tools/
19
+ ├── prompts/
20
+ ├── models/
21
+ ├── storage/
22
+ ├── utils/
23
+ ├── observability/
24
+ ├── evaluation/
25
+ └── api/
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ Install dependencies:
31
+
32
+ ```bash
33
+ pip install -e .
34
+ ```
35
+
36
+ Run the sample workflow:
37
+
38
+ ```bash
39
+ python -m src.app.main
40
+ ```
41
+
42
+ ## How It Works
43
+
44
+ The application compiles a `StateGraph` in `src/app/graph/builder.py`.
45
+
46
+ Execution flow:
47
+
48
+ 1. `intent` classifies the request
49
+ 2. `processing` extracts structured data and calls tools
50
+ 3. `validation` scores the extraction
51
+ 4. `output` returns the final response when validation passes
52
+ 5. `error` returns a failure response when retries are exhausted
53
+
54
+ Validation uses conditional routing, so unsuccessful validation can retry processing before terminating.
55
+
56
+ ## Graph Conventions
57
+
58
+ The graph layer uses three abstractions:
59
+
60
+ - `Names`: stable node names used when building the graph
61
+ - `Nodes`: callable implementations
62
+ - `Tags`: conditional routing labels
63
+
64
+ This keeps graph orchestration readable and easy to extend.
65
+
66
+ ## Prompts
67
+
68
+ Prompt files live in `src/app/prompts/versions/` and are loaded by task/version.
69
+
70
+ Features:
71
+
72
+ - Default version selection from config
73
+ - Version-specific lookup
74
+ - Fallback to `v1`
75
+ - Prompt access tracking
76
+
77
+ ## Tools
78
+
79
+ The scaffold includes a built-in registry and several deterministic tools:
80
+
81
+ - `calculator`
82
+ - `query`
83
+ - `http`
84
+ - `retriever`
85
+
86
+ Add new tools by implementing `BaseTool` and registering them in `src/app/tools/registry.py`.
87
+
88
+ ## Evaluation
89
+
90
+ The evaluation layer currently measures:
91
+
92
+ - Field coverage
93
+ - Confidence score
94
+ - Validation pass/fail
95
+
96
+ This makes it easy to swap in richer metrics later.
97
+
98
+ ## Observability
99
+
100
+ Observability support includes:
101
+
102
+ - Structured JSON logging
103
+ - Basic metrics counters
104
+ - LangSmith environment wiring
105
+ - Trace decorators for service methods
106
+
107
+ To enable LangSmith tracing, copy `.env.example` to `.env` and set the required values.
108
+
109
+ ## API Surface
110
+
111
+ A lightweight API-facing wrapper is included under `src/app/api/` so the graph can be invoked through another interface later without changing the core graph design.
112
+
113
+ ## Next Steps
114
+
115
+ Recommended follow-up work:
116
+
117
+ - Connect a real LLM provider
118
+ - Add persistent storage backends
119
+ - Add domain-specific tools
120
+ - Add tests for graph transitions and service behavior
121
+ - Expand prompt sets and versions
@@ -0,0 +1,6 @@
1
+ {
2
+ "dependencies": ["."],
3
+ "graphs": {
4
+ "{{PROJECT_NAME}}": "src.app.main:run"
5
+ }
6
+ }
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "{{PROJECT_NAME}}"
7
+ version = "0.1.0"
8
+ description = "Production LangGraph scaffold for {{PROJECT_NAME}}"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = [
12
+ "langgraph>=0.2.0",
13
+ "langchain>=0.3.0",
14
+ "langsmith>=0.1.0",
15
+ "python-dotenv>=1.0.0",
16
+ "typer>=0.12.0",
17
+ ]
18
+
19
+ [tool.setuptools.packages.find]
20
+ include = ["src*"]
@@ -0,0 +1 @@
1
+ """Project source package."""
@@ -0,0 +1 @@
1
+ """Production app package."""
@@ -0,0 +1 @@
1
+ """API package."""