graph-agents-cli 0.3.1__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 (291) hide show
  1. graph_agents_cli/__init__.py +26 -0
  2. graph_agents_cli/_api_policy.py +2145 -0
  3. graph_agents_cli/_approvals.py +400 -0
  4. graph_agents_cli/_build.py +186 -0
  5. graph_agents_cli/_build_info.json +7 -0
  6. graph_agents_cli/_chat_client.py +462 -0
  7. graph_agents_cli/_click.py +157 -0
  8. graph_agents_cli/_defaults.py +139 -0
  9. graph_agents_cli/_experiments.py +64 -0
  10. graph_agents_cli/_http.py +192 -0
  11. graph_agents_cli/_output.py +83 -0
  12. graph_agents_cli/_project.py +462 -0
  13. graph_agents_cli/_remote.py +220 -0
  14. graph_agents_cli/_response_schema.py +264 -0
  15. graph_agents_cli/_runner.py +319 -0
  16. graph_agents_cli/_skills_check.py +274 -0
  17. graph_agents_cli/_tools.py +189 -0
  18. graph_agents_cli/_trust.py +66 -0
  19. graph_agents_cli/api/__init__.py +15 -0
  20. graph_agents_cli/api/_changes.py +506 -0
  21. graph_agents_cli/api/_files.py +658 -0
  22. graph_agents_cli/api/cmd_api.py +2480 -0
  23. graph_agents_cli/deploy/__init__.py +15 -0
  24. graph_agents_cli/deploy/_config.py +171 -0
  25. graph_agents_cli/deploy/_image.py +128 -0
  26. graph_agents_cli/deploy/_kube.py +286 -0
  27. graph_agents_cli/deploy/_modes.py +234 -0
  28. graph_agents_cli/deploy/_preflight.py +370 -0
  29. graph_agents_cli/deploy/_values.py +168 -0
  30. graph_agents_cli/deploy/cmd_deploy.py +1866 -0
  31. graph_agents_cli/deploy/gitops.py +562 -0
  32. graph_agents_cli/deploy/local_load.py +273 -0
  33. graph_agents_cli/dev/__init__.py +13 -0
  34. graph_agents_cli/dev/cmd_build.py +131 -0
  35. graph_agents_cli/dev/cmd_install.py +78 -0
  36. graph_agents_cli/dev/cmd_lint.py +119 -0
  37. graph_agents_cli/dev/cmd_playground.py +297 -0
  38. graph_agents_cli/dev/policy_check.py +1287 -0
  39. graph_agents_cli/eval/__init__.py +22 -0
  40. graph_agents_cli/eval/_client.py +670 -0
  41. graph_agents_cli/eval/_common.py +177 -0
  42. graph_agents_cli/eval/_judge.py +168 -0
  43. graph_agents_cli/eval/_judge_runner.py +238 -0
  44. graph_agents_cli/eval/_paths.py +212 -0
  45. graph_agents_cli/eval/checks.py +581 -0
  46. graph_agents_cli/eval/cmd_analyze.py +278 -0
  47. graph_agents_cli/eval/cmd_compare.py +284 -0
  48. graph_agents_cli/eval/cmd_eval_group.py +80 -0
  49. graph_agents_cli/eval/cmd_generate.py +558 -0
  50. graph_agents_cli/eval/cmd_grade.py +466 -0
  51. graph_agents_cli/eval/cmd_metric.py +156 -0
  52. graph_agents_cli/eval/cmd_run.py +370 -0
  53. graph_agents_cli/eval/cmd_submit.py +400 -0
  54. graph_agents_cli/eval/config.py +435 -0
  55. graph_agents_cli/eval/dataset.py +350 -0
  56. graph_agents_cli/eval/gate.py +420 -0
  57. graph_agents_cli/eval/transcript.py +192 -0
  58. graph_agents_cli/extension/__init__.py +13 -0
  59. graph_agents_cli/extension/_compat.py +86 -0
  60. graph_agents_cli/extension/_loader.py +293 -0
  61. graph_agents_cli/extension/_manifest.py +135 -0
  62. graph_agents_cli/extension/_overrides.py +195 -0
  63. graph_agents_cli/extension/_paths.py +91 -0
  64. graph_agents_cli/extension/_refs.py +193 -0
  65. graph_agents_cli/extension/_resolver.py +453 -0
  66. graph_agents_cli/extension/_schema.py +106 -0
  67. graph_agents_cli/extension/_spec.py +253 -0
  68. graph_agents_cli/extension/_sync.py +102 -0
  69. graph_agents_cli/extension/_trust.py +58 -0
  70. graph_agents_cli/extension/cmd_extension_add.py +259 -0
  71. graph_agents_cli/extension/cmd_extension_group.py +57 -0
  72. graph_agents_cli/extension/cmd_extension_list.py +56 -0
  73. graph_agents_cli/extension/cmd_extension_remove.py +61 -0
  74. graph_agents_cli/extension/cmd_extension_update.py +195 -0
  75. graph_agents_cli/info/__init__.py +13 -0
  76. graph_agents_cli/info/cmd_info.py +222 -0
  77. graph_agents_cli/infra/__init__.py +15 -0
  78. graph_agents_cli/infra/checks.py +1169 -0
  79. graph_agents_cli/infra/cmd_infra.py +103 -0
  80. graph_agents_cli/main.py +591 -0
  81. graph_agents_cli/peer/__init__.py +15 -0
  82. graph_agents_cli/peer/_generate.py +254 -0
  83. graph_agents_cli/peer/cmd_peer.py +1151 -0
  84. graph_agents_cli/run/__init__.py +13 -0
  85. graph_agents_cli/run/_local_server.py +1157 -0
  86. graph_agents_cli/run/_signals.py +141 -0
  87. graph_agents_cli/run/cmd_approvals.py +530 -0
  88. graph_agents_cli/run/cmd_run.py +1421 -0
  89. graph_agents_cli/scaffold/__init__.py +19 -0
  90. graph_agents_cli/scaffold/agents/README.md +24 -0
  91. graph_agents_cli/scaffold/agents/empty_py/.template/templateconfig.yaml +22 -0
  92. graph_agents_cli/scaffold/agents/langgraph/.env.example +292 -0
  93. graph_agents_cli/scaffold/agents/langgraph/.template/templateconfig.yaml +28 -0
  94. graph_agents_cli/scaffold/agents/langgraph/Dockerfile +59 -0
  95. graph_agents_cli/scaffold/agents/langgraph/Dockerfile.langgraph-server +59 -0
  96. graph_agents_cli/scaffold/agents/langgraph/README.md +571 -0
  97. graph_agents_cli/scaffold/agents/langgraph/api-policy.yaml +60 -0
  98. graph_agents_cli/scaffold/agents/langgraph/app/__init__.py +20 -0
  99. graph_agents_cli/scaffold/agents/langgraph/app/agent.py +174 -0
  100. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/__init__.py +15 -0
  101. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/a2a.py +2162 -0
  102. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/a2a_client.py +1167 -0
  103. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/api_client.py +4220 -0
  104. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/approvals.py +1349 -0
  105. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/auth.py +1986 -0
  106. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/chat.py +2962 -0
  107. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/checkpointer.py +432 -0
  108. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/content.py +569 -0
  109. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/db.py +580 -0
  110. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/limits.py +203 -0
  111. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/metrics.py +231 -0
  112. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/middleware.py +361 -0
  113. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/model.py +611 -0
  114. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/playground.py +230 -0
  115. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/run_locks.py +459 -0
  116. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/structured.py +755 -0
  117. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/telemetry.py +681 -0
  118. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/threads.py +493 -0
  119. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/token_exchange.py +959 -0
  120. graph_agents_cli/scaffold/agents/langgraph/app/fast_api_app.py +770 -0
  121. graph_agents_cli/scaffold/agents/langgraph/app/policies/__init__.py +55 -0
  122. graph_agents_cli/scaffold/agents/langgraph/app/policies/custom.py +97 -0
  123. graph_agents_cli/scaffold/agents/langgraph/app/tools/__init__.py +46 -0
  124. graph_agents_cli/scaffold/agents/langgraph/app/tools/example_api.py +92 -0
  125. graph_agents_cli/scaffold/agents/langgraph/app/tools/weather.py +33 -0
  126. graph_agents_cli/scaffold/agents/langgraph/langgraph.json +14 -0
  127. graph_agents_cli/scaffold/agents/langgraph/pyproject.toml +78 -0
  128. graph_agents_cli/scaffold/agents/langgraph/tests/conftest.py +376 -0
  129. graph_agents_cli/scaffold/agents/langgraph/tests/eval/datasets/basic-dataset.json +53 -0
  130. graph_agents_cli/scaffold/agents/langgraph/tests/eval/eval_config.yaml +32 -0
  131. graph_agents_cli/scaffold/agents/langgraph/tests/integration/approval_graph.py +137 -0
  132. graph_agents_cli/scaffold/agents/langgraph/tests/integration/fake_issuer.py +216 -0
  133. graph_agents_cli/scaffold/agents/langgraph/tests/integration/fake_openai.py +357 -0
  134. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_a2a_outcomes.py +569 -0
  135. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_a2a_relay.py +479 -0
  136. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_api_surface.py +812 -0
  137. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_approvals.py +1367 -0
  138. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_approvals_server.py +794 -0
  139. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_cross_actor.py +497 -0
  140. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_cross_actor_server.py +247 -0
  141. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_history_repair.py +278 -0
  142. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_model_apis.py +242 -0
  143. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_postgres.py +637 -0
  144. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_resilience_postgres.py +770 -0
  145. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_runtime_guardrails.py +854 -0
  146. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_server_e2e.py +340 -0
  147. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_server_runtime.py +989 -0
  148. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_structured_answers.py +584 -0
  149. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_structured_server.py +222 -0
  150. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_token_exchange_issuer.py +650 -0
  151. graph_agents_cli/scaffold/agents/langgraph/tests/load_test/.results/.placeholder +0 -0
  152. graph_agents_cli/scaffold/agents/langgraph/tests/load_test/README.md +22 -0
  153. graph_agents_cli/scaffold/agents/langgraph/tests/load_test/conftest.py +21 -0
  154. graph_agents_cli/scaffold/agents/langgraph/tests/load_test/load_test.py +81 -0
  155. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_a2a_client.py +824 -0
  156. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_a2a_scoping.py +724 -0
  157. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_client.py +1214 -0
  158. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_client_hardening.py +716 -0
  159. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_policy_rpc.py +767 -0
  160. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_approval_ledger.py +1536 -0
  161. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_fake_model.py +115 -0
  162. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_jwt_policy.py +991 -0
  163. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_limits.py +310 -0
  164. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_logging.py +148 -0
  165. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_logging_hardening.py +271 -0
  166. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_policy.py +378 -0
  167. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_resilience.py +610 -0
  168. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_server_auth.py +702 -0
  169. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_structured.py +673 -0
  170. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_telemetry.py +404 -0
  171. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_thread_listing.py +255 -0
  172. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_threads.py +268 -0
  173. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_token_exchange.py +1320 -0
  174. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_untrusted_content.py +393 -0
  175. graph_agents_cli/scaffold/agents/langgraph/uv-fastapi.lock +2084 -0
  176. graph_agents_cli/scaffold/agents/langgraph/uv-langgraph-server.lock +2106 -0
  177. graph_agents_cli/scaffold/agents/langgraph/{{cookiecutter.agent_guidance_filename}} +129 -0
  178. graph_agents_cli/scaffold/base_templates/_shared/graph-agents-cli-manifest.yaml +36 -0
  179. graph_agents_cli/scaffold/base_templates/python/.dockerignore +32 -0
  180. graph_agents_cli/scaffold/base_templates/python/.github/CODEOWNERS +30 -0
  181. graph_agents_cli/scaffold/base_templates/python/.github/agent.env +7 -0
  182. graph_agents_cli/scaffold/base_templates/python/.github/workflows/pr_checks.yaml +214 -0
  183. graph_agents_cli/scaffold/base_templates/python/.gitignore +209 -0
  184. graph_agents_cli/scaffold/base_templates/python/tests/unit/test_dummy.py +23 -0
  185. graph_agents_cli/scaffold/base_templates/python/{{cookiecutter.agent_guidance_filename}} +35 -0
  186. graph_agents_cli/scaffold/cmd_scaffold_group.py +49 -0
  187. graph_agents_cli/scaffold/commands/__init__.py +13 -0
  188. graph_agents_cli/scaffold/commands/create.py +1424 -0
  189. graph_agents_cli/scaffold/commands/enhance.py +1652 -0
  190. graph_agents_cli/scaffold/commands/upgrade.py +570 -0
  191. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/agent.env +12 -0
  192. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/workflows/promote-to-prod.yaml +371 -0
  193. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/workflows/staging.yaml +450 -0
  194. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-dev.yaml +43 -0
  195. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-prod.yaml +41 -0
  196. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-staging.yaml +43 -0
  197. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/.helmignore +14 -0
  198. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/Chart.yaml +21 -0
  199. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/examples/networkpolicy.yaml +103 -0
  200. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/NOTES.txt +48 -0
  201. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/_helpers.tpl +189 -0
  202. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/certificate.yaml +15 -0
  203. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/configmap.yaml +10 -0
  204. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/deployment.yaml +199 -0
  205. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/hpa.yaml +22 -0
  206. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/httproute.yaml +30 -0
  207. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/ingress.yaml +39 -0
  208. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/networkpolicy.yaml +48 -0
  209. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/pdb.yaml +13 -0
  210. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/postgresql-secret.yaml +37 -0
  211. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/service.yaml +15 -0
  212. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/serviceaccount.yaml +13 -0
  213. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/servicemonitor.yaml +42 -0
  214. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-dev.yaml +22 -0
  215. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-prod.yaml +45 -0
  216. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-staging.yaml +29 -0
  217. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values.yaml +396 -0
  218. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/tests/integration/test_chart.py +269 -0
  219. graph_agents_cli/scaffold/deployment_targets/none/README.md +5 -0
  220. graph_agents_cli/scaffold/deployment_targets/none/python/README.md +6 -0
  221. graph_agents_cli/scaffold/utils/__init__.py +13 -0
  222. graph_agents_cli/scaffold/utils/backup.py +212 -0
  223. graph_agents_cli/scaffold/utils/build_record.py +257 -0
  224. graph_agents_cli/scaffold/utils/cli_options.py +184 -0
  225. graph_agents_cli/scaffold/utils/fs.py +83 -0
  226. graph_agents_cli/scaffold/utils/generate_locks.py +214 -0
  227. graph_agents_cli/scaffold/utils/generation_metadata.py +88 -0
  228. graph_agents_cli/scaffold/utils/keyedit.py +768 -0
  229. graph_agents_cli/scaffold/utils/keymerge.py +537 -0
  230. graph_agents_cli/scaffold/utils/language.py +138 -0
  231. graph_agents_cli/scaffold/utils/lock_utils.py +94 -0
  232. graph_agents_cli/scaffold/utils/logging.py +77 -0
  233. graph_agents_cli/scaffold/utils/manifest.py +292 -0
  234. graph_agents_cli/scaffold/utils/merge.py +970 -0
  235. graph_agents_cli/scaffold/utils/merge3.py +216 -0
  236. graph_agents_cli/scaffold/utils/openapi_seed.py +199 -0
  237. graph_agents_cli/scaffold/utils/remote_template.py +376 -0
  238. graph_agents_cli/scaffold/utils/template.py +1352 -0
  239. graph_agents_cli/scaffold/utils/upgrade.py +894 -0
  240. graph_agents_cli/scaffold/utils/version.py +438 -0
  241. graph_agents_cli/secrets/__init__.py +15 -0
  242. graph_agents_cli/secrets/_apply.py +954 -0
  243. graph_agents_cli/secrets/_required.py +188 -0
  244. graph_agents_cli/secrets/cmd_secrets.py +211 -0
  245. graph_agents_cli/setup/__init__.py +13 -0
  246. graph_agents_cli/setup/_antigravity.py +221 -0
  247. graph_agents_cli/setup/cmd_auth.py +1030 -0
  248. graph_agents_cli/setup/cmd_dev_token.py +513 -0
  249. graph_agents_cli/setup/cmd_setup.py +428 -0
  250. graph_agents_cli/setup/cmd_update.py +140 -0
  251. graph_agents_cli/skills/__init__.py +13 -0
  252. graph_agents_cli/skills/_bundle.py +65 -0
  253. graph_agents_cli/skills/data/README.md +19 -0
  254. graph_agents_cli/skills/data/graph-agents-cli-deploy/SKILL.md +357 -0
  255. graph_agents_cli/skills/data/graph-agents-cli-deploy/references/github-settings.md +113 -0
  256. graph_agents_cli/skills/data/graph-agents-cli-deploy/references/gitops.md +137 -0
  257. graph_agents_cli/skills/data/graph-agents-cli-deploy/references/kubernetes.md +315 -0
  258. graph_agents_cli/skills/data/graph-agents-cli-deploy/references/secrets.md +160 -0
  259. graph_agents_cli/skills/data/graph-agents-cli-eval/SKILL.md +303 -0
  260. graph_agents_cli/skills/data/graph-agents-cli-eval/references/dataset_schema.md +282 -0
  261. graph_agents_cli/skills/data/graph-agents-cli-eval/references/metrics-guide.md +143 -0
  262. graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/SKILL.md +659 -0
  263. graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/langchain-models.md +124 -0
  264. graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/langgraph.md +235 -0
  265. graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/template-contract.md +477 -0
  266. graph_agents_cli/skills/data/graph-agents-cli-observability/SKILL.md +231 -0
  267. graph_agents_cli/skills/data/graph-agents-cli-observability/references/langsmith.md +46 -0
  268. graph_agents_cli/skills/data/graph-agents-cli-observability/references/otel.md +59 -0
  269. graph_agents_cli/skills/data/graph-agents-cli-scaffold/SKILL.md +414 -0
  270. graph_agents_cli/skills/data/graph-agents-cli-scaffold/references/flags.md +134 -0
  271. graph_agents_cli/skills/data/graph-agents-cli-workflow/SKILL.md +478 -0
  272. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/brainstorming.md +118 -0
  273. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/commands.md +419 -0
  274. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/extension.md +156 -0
  275. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/internals.md +67 -0
  276. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/spec-template.md +56 -0
  277. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/terminology.md +119 -0
  278. graph_agents_cli/system/__init__.py +15 -0
  279. graph_agents_cli/system/_apply.py +519 -0
  280. graph_agents_cli/system/_checks.py +1023 -0
  281. graph_agents_cli/system/_deploy.py +215 -0
  282. graph_agents_cli/system/_model.py +363 -0
  283. graph_agents_cli/system/_system.py +664 -0
  284. graph_agents_cli/system/_views.py +208 -0
  285. graph_agents_cli/system/cmd_system.py +423 -0
  286. graph_agents_cli-0.3.1.dist-info/METADATA +162 -0
  287. graph_agents_cli-0.3.1.dist-info/RECORD +291 -0
  288. graph_agents_cli-0.3.1.dist-info/WHEEL +4 -0
  289. graph_agents_cli-0.3.1.dist-info/entry_points.txt +2 -0
  290. graph_agents_cli-0.3.1.dist-info/licenses/LICENSE +201 -0
  291. graph_agents_cli-0.3.1.dist-info/licenses/NOTICE +19 -0
@@ -0,0 +1,19 @@
1
+ # Copyright 2026 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Scaffold package — project scaffolding, enhancement, and CI/CD setup.
16
+
17
+ Provides the core logic for creating, enhancing, and upgrading
18
+ agent projects.
19
+ """
@@ -0,0 +1,24 @@
1
+ # Agent templates
2
+
3
+ Bundled templates that `graph-agents-cli create --agent <name>` renders on top of
4
+ `base_templates/` and `deployment_targets/`:
5
+
6
+ | Template | Purpose |
7
+ |---|---|
8
+ | `langgraph` | The LangGraph agent: `app/agent.py` exports `graph`, `app/fast_api_app.py` exports `app` (chat SSE API, A2A, health, dev playground), auth policy adapter (shared-bearer, jwt, custom), policy-enforcing API client (`api-policy.yaml`), tests, evals, two runtime locks, both Dockerfiles. Targets: `kubernetes`, `none`. |
9
+ | `empty_py` | Hidden, framework-neutral base a framework template builds on. Ships no agent, dependencies or lock. |
10
+
11
+ Layering (see `utils/template.py`): `base_templates/_shared` -> `base_templates/python`
12
+ -> `deployment_targets/<target>/{_shared,python}` -> the agent template (its `app/`,
13
+ `tests/`, `deployment/` and every other top-level item). Cookiecutter renders
14
+ everything except Helm `templates/`, `*.tpl`, `.github/workflows/*` and `*.lock`,
15
+ which are copied verbatim; project-specific values for those go through rendered
16
+ files (`Chart.yaml`, `values*.yaml`, `.github/agent.env`). The variables a template
17
+ may use are defined by the scaffold configuration and template tests.
18
+
19
+ Regenerate the `langgraph` template's `uv-fastapi.lock` and `uv-langgraph-server.lock`
20
+ after changing its `pyproject.toml` (render it per runtime, `uv lock`, replace the
21
+ project name with `{{cookiecutter.project_name}}`); `tests/template/` renders and
22
+ installs the template to prove the locks match.
23
+
24
+ Remote templates (`--agent org/repo/path@ref`) follow the same layout.
@@ -0,0 +1,22 @@
1
+ # Copyright 2026 Google LLC
2
+ # Modifications Copyright 2026 graph-agents-cli contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ description: "Empty project scaffold (no agent or framework) - the base a framework template builds on"
17
+ hidden: true
18
+ example_question: "Hello!"
19
+ settings:
20
+ language: "python"
21
+ deployment_targets: ["kubernetes", "none"]
22
+ tags: ["empty"]
@@ -0,0 +1,292 @@
1
+ # {{cookiecutter.project_name}}: local development configuration.
2
+ # Copy to .env (git-ignored). `graph-agents-cli deploy --env <env>` and
3
+ # `graph-agents-cli secrets apply --env <env>` read .env.<env> (only dev falls
4
+ # back to this .env, so local keys never reach staging or prod) and export ONLY
5
+ # the keys listed under `secrets.keys` in graph-agents-cli-manifest.yaml into
6
+ # the environment's Kubernetes Secret.
7
+ # Everything else below is non-secret configuration that the Helm chart sets
8
+ # from deployment/helm/{{cookiecutter.project_name}}/values*.yaml.
9
+
10
+ # --- Application ------------------------------------------------------------
11
+ # Exactly `dev` enables GET /playground, /docs and the dev-only relaxations;
12
+ # any other value (prod, staging, DEV, unset) is a deployed environment.
13
+ APP_ENV=dev
14
+ # Port the server listens on (uvicorn under fastapi, the server under langgraph-server).
15
+ PORT=8000
16
+
17
+ # --- Agent model (LangChain init_chat_model) --------------------------------
18
+ # openai | anthropic | gemini | openai-compatible (fake is test-only)
19
+ MODEL_PROVIDER={{cookiecutter.model_provider}}
20
+ MODEL_NAME={{cookiecutter.model}}
21
+ {% if cookiecutter.model_provider == 'openai-compatible' -%}
22
+ # Base URL of the OpenAI-compatible endpoint (Ollama, vLLM, TGI, ...).
23
+ OPENAI_BASE_URL=http://localhost:11434/v1
24
+ {% else -%}
25
+ # Only for MODEL_PROVIDER=openai-compatible (Ollama, vLLM, TGI, ...).
26
+ # OPENAI_BASE_URL=http://localhost:11434/v1
27
+ {% endif -%}
28
+ # Provider key (Secret). openai -> OPENAI_API_KEY, anthropic -> ANTHROPIC_API_KEY,
29
+ # gemini -> GOOGLE_API_KEY (AI Studio), openai-compatible -> MODEL_API_KEY.
30
+ {{cookiecutter.provider_key_var}}=
31
+ # OpenAI-API models only (openai, openai-compatible; set for another provider,
32
+ # startup refuses). Reasoning effort: none | minimal | low | medium | high |
33
+ # xhigh (unset: the model's default). The API: true = the Responses API
34
+ # (/v1/responses), false = Chat Completions; unset lets langchain-openai choose
35
+ # (Chat Completions but for the models it knows need the Responses API). A model
36
+ # that refuses function tools with a reasoning effort on Chat Completions needs
37
+ # MODEL_USE_RESPONSES_API=true (or MODEL_REASONING_EFFORT=none); a server with no
38
+ # /v1/responses needs false or unset.
39
+ # MODEL_REASONING_EFFORT=
40
+ # MODEL_USE_RESPONSES_API=
41
+
42
+ # Structured answers: only with {{cookiecutter.agent_directory}}/response_schema.json (the JSON
43
+ # shape of the final answer; without it the agent answers in text). auto (the
44
+ # provider's own structured output where the model has it and its client can send
45
+ # the schema, else a final_answer tool the model must call) | provider | tool.
46
+ # RESPONSE_FORMAT_STRATEGY=auto
47
+
48
+ # --- Judge model (evals; defaults to the agent's provider, model and key) ---
49
+ # JUDGE_MODEL_PROVIDER=
50
+ # JUDGE_MODEL_NAME={{cookiecutter.default_judge_model}}
51
+ # JUDGE_BASE_URL=
52
+ # JUDGE_API_KEY=
53
+ # Unset: the agent's, when the judge is an OpenAI-API model too.
54
+ # JUDGE_REASONING_EFFORT=
55
+ # JUDGE_USE_RESPONSES_API=
56
+
57
+ # --- Persistence -------------------------------------------------------------
58
+ {% if cookiecutter.runtime == 'fastapi' -%}
59
+ # memory | postgres. memory needs no database (state is lost on restart); the
60
+ # chart sets postgres and supplies POSTGRES_DSN from the subchart or the Secret.
61
+ CHECKPOINTER=memory
62
+ # POSTGRES_DSN=postgresql://agent:agent@localhost:5432/agent
63
+ # Connection pool per process (shared by the checkpointer and the app tables).
64
+ # Connections are health-checked on checkout, so a database restart heals itself.
65
+ # DB_POOL_MIN_SIZE=1
66
+ # DB_POOL_MAX_SIZE=10
67
+ {% else -%}
68
+ # LangGraph Server owns persistence. `graph-agents-cli run` and `playground`
69
+ # use `langgraph dev` (in-memory) locally; the chart sets these in the cluster.
70
+ # DATABASE_URI=postgresql://agent:agent@localhost:5432/agent
71
+ # REDIS_URI=redis://localhost:6379
72
+ {% endif -%}
73
+
74
+ # --- Authentication (app/app_utils/auth.py) ---------------------------------
75
+ # shared-bearer | jwt | custom
76
+ AUTH_POLICY={{cookiecutter.auth_policy}}
77
+ # shared-bearer: clients send `Authorization: Bearer <API_KEY>`. Generate one:
78
+ # python -c "import secrets; print(secrets.token_hex(32))"
79
+ # `graph-agents-cli login --write-env` generates it here; `graph-agents-cli
80
+ # secrets apply` generates one per environment when neither the env file nor the
81
+ # cluster has one (and writes it to that env file; the live key is never
82
+ # replaced without --rotate-api-key).
83
+ API_KEY=
84
+ {% if cookiecutter.auth_policy == 'jwt' -%}
85
+ # jwt: per-user principals from a verified OIDC/JWT bearer token. Outside
86
+ # APP_ENV=dev the issuer and the audience are required and any configuration
87
+ # problem stops startup (under dev a missing issuer or audience is only a
88
+ # warning and a problem answers 503).
89
+ # Keys: a JWKS URL (https outside dev unless its host is loopback), or one PEM
90
+ # public key or certificate (escaped \n newlines accepted), not both.
91
+ # Local runs without an identity provider: `graph-agents-cli auth dev-token --sub
92
+ # <user>` fills AUTH_JWT_PUBLIC_KEY, AUTH_JWT_ISSUER and AUTH_JWT_AUDIENCE below
93
+ # with a dev key (APP_ENV=dev only) and prints a token. Never deploy that key.
94
+ AUTH_JWT_JWKS_URL=
95
+ # AUTH_JWT_PUBLIC_KEY=
96
+ AUTH_JWT_ISSUER=
97
+ AUTH_JWT_AUDIENCE=
98
+ # Accepted algorithms (never `none`; HS* only with AUTH_JWT_ALLOW_HS=true and AUTH_JWT_SECRET).
99
+ # AUTH_JWT_ALGORITHMS=RS256,ES256
100
+ # Shared-secret (HS256/384/512) tokens: opt in, and put a secret of at least 32
101
+ # bytes in the Secret (the CLI adds AUTH_JWT_SECRET to the allow-list then).
102
+ # AUTH_JWT_ALLOW_HS=false
103
+ # AUTH_JWT_SECRET=
104
+ # A plain-http JWKS URL outside dev, for a trusted in-cluster issuer only.
105
+ # AUTH_JWT_JWKS_ALLOW_HTTP=false
106
+ # Claim holding the principal id, and the claim (dotted path allowed, e.g.
107
+ # realm_access.roles) holding the roles.
108
+ # AUTH_JWT_PRINCIPAL_CLAIM=sub
109
+ # AUTH_JWT_ROLES_CLAIM=roles
110
+ # AUTH_JWT_LEEWAY_S=60
111
+ # AUTH_JWT_JWKS_CACHE_S=300
112
+ # Agents calling for a user: a token carrying the RFC 8693 actor claim (`act`) is
113
+ # the user's (its `sub`) presented by that agent. Empty turns this off (every
114
+ # token is the user's own, as in 0.2).
115
+ # AUTH_JWT_ACTOR_CLAIM=act
116
+ # The client claim (`azp`; `client_id` when absent; Okta uses `cid`), and the
117
+ # clients people sign in with: when set, a token with no `act` from any other
118
+ # client is treated as that client presenting the user's token (`client:<azp>`).
119
+ # AUTH_JWT_CLIENT_CLAIM=azp
120
+ # AUTH_JWT_DIRECT_CLIENTS=
121
+ {% else -%}
122
+ # jwt (AUTH_POLICY=jwt): AUTH_JWT_JWKS_URL or AUTH_JWT_PUBLIC_KEY, AUTH_JWT_ISSUER,
123
+ # AUTH_JWT_AUDIENCE; see the project README.
124
+ {% endif -%}
125
+ # Comma-separated roles allowed to read other principals' threads (and list,
126
+ # never decide, their approvals).
127
+ AUTH_READ_ACROSS_ROLES=
128
+ # Comma-separated roles allowed to manage assistants, crons and the store under
129
+ # langgraph-server (empty = nobody).
130
+ AUTH_ADMIN_ROLES=
131
+ # Agents that may call this one for a user (the actor ids, comma-separated; * for
132
+ # any). Empty refuses every delegated request (403) until the agent is listed.
133
+ AUTH_ALLOWED_ACTORS=
134
+ # Roles a delegated request keeps (empty: an agent acting for a user holds none of
135
+ # the user's roles), and how many agents may stand between the user and this one.
136
+ # AUTH_DELEGATED_ROLES=
137
+ # AUTH_MAX_DELEGATION_DEPTH=3
138
+ # When an agent asks for a user, require_user_mentioned needs the record id in the
139
+ # user's own words that agent forwarded (origin), always refuses (refuse), or counts
140
+ # the agent's request as the user's words (request, the 0.2 behaviour: an opt-out).
141
+ # A2A_DELEGATED_MENTIONS=origin
142
+ # Tell the model, in one system note, that an agent wrote the request (off: fence only).
143
+ # A2A_CALLER_NOTE=on
144
+ # Calling other agents (A2A peers, `graph-agents-cli peer add`): send them the user's
145
+ # own words when their card reads them (off: never), at most this many characters
146
+ # (also the most read from an agent calling this one), how long a peer's checked
147
+ # agent card is reused, and the most of a peer's reply the model reads.
148
+ # A2A_FORWARD_ORIGIN=auto
149
+ # A2A_ORIGIN_MAX_CHARS=4000
150
+ # A2A_CARD_TTL_S=300
151
+ # A2A_REPLY_MAX_CHARS=6000
152
+ # langgraph-server runtime with LANGGRAPH_SERVER_URL set: the request headers
153
+ # passed on to the server's auth handler (the headers your policy reads).
154
+ # Empty forwards nothing.
155
+ # AUTH_FORWARD_HEADERS=authorization,cookie
156
+
157
+ # --- Outbound APIs (app/app_utils/api_client.py, api-policy.yaml) ----------
158
+ {% if cookiecutter.has_api_policy -%}
159
+ {% for api in cookiecutter.apis -%}
160
+ # {{ api.name }} (auth: {{ api.auth }})
161
+ {{ api.base_url_env }}=http://localhost:9000
162
+ {% if api.auth == 'bearer' -%}
163
+ {{ api.token_env }}=
164
+ {% endif -%}
165
+ {% endfor -%}
166
+ {% if cookiecutter.apis | selectattr('auth', 'equalto', 'exchange') | list -%}
167
+ # Token exchange (RFC 8693) for the auth: exchange APIs: the issuer's token endpoint
168
+ # and this agent's client there. Put the client secret in .env (it is in secrets.keys).
169
+ # Optional: client authentication (or client_secret_post), the subject token type
170
+ # sent, the exchange's deadline, how long an exchanged token is reused (at most
171
+ # 300 s), how long a refusal or a failing issuer is left alone, tokens kept per
172
+ # process, and a plain-http token URL outside dev (a trusted in-cluster issuer only).
173
+ # TOKEN_EXCHANGE_CLIENT_AUTH=client_secret_basic
174
+ # TOKEN_EXCHANGE_SUBJECT_TOKEN_TYPE=urn:ietf:params:oauth:token-type:access_token
175
+ # TOKEN_EXCHANGE_TIMEOUT_MS=2000
176
+ # TOKEN_EXCHANGE_MAX_TTL_S=300
177
+ # TOKEN_EXCHANGE_FAILURE_TTL_S=10
178
+ # TOKEN_EXCHANGE_CACHE_MAX=10000
179
+ # TOKEN_EXCHANGE_ALLOW_HTTP=false
180
+ # TOKEN_EXCHANGE_CLIENT_SECRET=
181
+ TOKEN_EXCHANGE_URL=
182
+ TOKEN_EXCHANGE_CLIENT_ID=
183
+ {% endif -%}
184
+ {% else -%}
185
+ # No api-policy.yaml is declared, so every outbound API call is refused. Declare
186
+ # the APIs tools may call with `graph-agents-cli api add` (see README.md).
187
+ {% endif -%}
188
+ # Path of the policy file; defaults to ./api-policy.yaml.
189
+ # API_POLICY_PATH=api-policy.yaml
190
+ # Human approval: an API's `approval` block in api-policy.yaml holds the calls it
191
+ # gates until a person approves them (nothing to set here). Approvals live in the
192
+ # app's database ({% if cookiecutter.runtime == 'langgraph-server' %}table agent_approvals in DATABASE_URI{% else %}table approvals under CHECKPOINTER=postgres{% endif %};
193
+ # in process memory otherwise) and expire after the policy's timeout_s.
194
+ # `role:<name>` approvers need a per-user AUTH_POLICY (jwt or custom): under
195
+ # shared-bearer every caller is the one principal `shared`, the requester itself.
196
+
197
+ # --- Run guardrails and request limits (app/app_utils/limits.py) ------------
198
+ # A value that does not parse stops the app at startup. Defaults shown.
199
+ # Wall-clock limit of one run, in seconds; the run is cancelled (status timeout).
200
+ # RUN_TIMEOUT_S=300
201
+ # Per model request: timeout in seconds (0 = the provider SDK default) and retries.
202
+ # MODEL_TIMEOUT_S=60
203
+ # MODEL_MAX_RETRIES=2
204
+ # Graph steps per run: two to answer, plus two per tool call made after the
205
+ # previous one returned (50 fits 24 sequential calls). A run that reaches it
206
+ # ends with a reply saying so (message.end status step_limit).
207
+ # RECURSION_LIMIT=50
208
+ # Request body cap in bytes (413 above it) and /chat metadata caps (422 above
209
+ # them: at most N keys; keys and string values at most N characters).
210
+ # MAX_REQUEST_BYTES=1048576
211
+ # MAX_METADATA_KEYS=16
212
+ # MAX_METADATA_VALUE_CHARS=256
213
+ # Longest user message, in characters, on /chat (422 above it) and A2A (an
214
+ # invalid-params error): one cap for every surface that reaches the model.
215
+ # MAX_MESSAGE_CHARS=32000
216
+ # Seconds without an event before the SSE stream sends a ": keep-alive" comment.
217
+ # SSE_HEARTBEAT_S=15
218
+ # Delete threads (checkpoints and run records) idle for more than N days,
219
+ # checked hourly by every replica (best effort). 0 keeps everything.
220
+ # RETENTION_DAYS=0
221
+
222
+ # --- Logging, metrics and CORS -----------------------------------------------
223
+ # DEBUG | INFO | WARNING | ERROR | CRITICAL
224
+ # LOG_LEVEL=INFO
225
+ # json | text (default: text under APP_ENV=dev, json otherwise). Records carry
226
+ # the request id (X-Request-ID), run id, thread id and hashed principal. Access
227
+ # lines keep the path without its query string; outbound API calls are logged
228
+ # by API, method, operation id and path template (httpx's own URL lines are
229
+ # off); Python warnings become records too. LOG_LEVEL=DEBUG also turns on
230
+ # third-party debug logs, which can hold message content: use it locally.
231
+ # LOG_FORMAT=json
232
+ # GET /metrics serves Prometheus text; unauthenticated like /health and /ready
233
+ # unless METRICS_TOKEN is set, so keep it off the public ingress either way.
234
+ # METRICS_ENABLED=true
235
+ # Optional secret: when set, GET /metrics answers only requests that send
236
+ # `Authorization: Bearer <METRICS_TOKEN>` (configure your scraper with it{% if cookiecutter.deployment_target == 'kubernetes' %}:
237
+ # the chart's ServiceMonitor sends it with metrics.serviceMonitor.bearerToken.enabled{% endif %});
238
+ # /health and /ready stay open for the probes. Generate one:
239
+ # python -c "import secrets; print(secrets.token_hex(32))"
240
+ # METRICS_TOKEN=
241
+ # Optional secret: when set, the hashed principal id in logs, traces and run
242
+ # records is HMAC-SHA256(PRINCIPAL_HASH_SALT, id) instead of a plain sha256, so
243
+ # nobody holding them can confirm a guessed id (an email address, say) by
244
+ # hashing it. Keep it stable: changing it changes every hash, and new ones
245
+ # no longer match older logs and run records.
246
+ # PRINCIPAL_HASH_SALT=
247
+ # Comma-separated browser origins allowed to call the API; empty = no CORS.
248
+ # (LangGraph Server reads the same variable: `langgraph dev` allows every
249
+ # origin while it is unset; the server image starts with none.)
250
+ # CORS_ALLOW_ORIGINS=https://app.example.com
251
+
252
+ # --- Tracing (off unless TRACING_ENABLED=true) ------------------------------
253
+ TRACING_ENABLED=false
254
+ # metadata: structure, timing, token counts, tool names, error types, hashed
255
+ # principal id; no prompt/completion text, tool args/results, messages,
256
+ # or the client's /chat metadata.
257
+ # full: everything, including prompts, completions, tool I/O, error messages
258
+ # and the client's /chat metadata (under client_metadata).
259
+ # Sending full content to a hosted destination is an egress decision.
260
+ TRACE_CAPTURE=metadata
261
+ # With LANGSMITH_API_KEY set, traces go to LangSmith; otherwise to OTLP.
262
+ # LANGSMITH_API_KEY=
263
+ LANGSMITH_PROJECT={{cookiecutter.project_name}}
264
+ # LANGSMITH_ENDPOINT=https://api.smith.langchain.com
265
+ # OTLP/HTTP collector, used when TRACING_ENABLED=true and no LangSmith key is set.
266
+ # OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
267
+ # Correlation across agents (peers, the default): every call of another agent
268
+ # (`protocol: a2a`, whatever its auth) or of an `auth: forward` or
269
+ # `auth: exchange` API carries this request's X-Request-ID and, under OTLP
270
+ # tracing, its W3C trace context (traceparent, tracestate); other APIs never
271
+ # receive them. An incoming traceparent continues the caller's trace on the A2A
272
+ # routes (/a2a/...) only. all: every API, and every path (behind a tracing
273
+ # gateway). off (or false): neither. true reads as peers.
274
+ # PROPAGATE_TRACE_HEADERS=peers
275
+
276
+ # --- A2A ---------------------------------------------------------------------
277
+ # Public base URL advertised in the agent card (defaults to http://HOST:PORT).
278
+ # APP_URL=http://localhost:8000
279
+ # What the agent card (and its chat skill) says the agent does, and the
280
+ # version it advertises (AGENT_VERSION is also the OpenAPI and trace version).
281
+ # A2A_DESCRIPTION=Answers questions about orders and their delivery status.
282
+ # AGENT_VERSION=0.1.0
283
+ # A2A tasks live in the app's database ({% if cookiecutter.runtime == 'langgraph-server' %}table agent_a2a_tasks in DATABASE_URI{% else %}table a2a_tasks under CHECKPOINTER=postgres{% endif %}:
284
+ # every replica sees them, restarts keep them; in process memory otherwise) and
285
+ # are dropped this many seconds after their last update (0: when their thread
286
+ # is deleted; in memory, at restart).
287
+ # A2A_TASK_TTL_S=3600
288
+
289
+ # --- Client side (not read by the app) ---------------------------------------
290
+ # `graph-agents-cli run --url ...` and `eval generate --url ...` send this as the
291
+ # bearer key when --header is not given.
292
+ # GRAPH_AGENTS_CLI_API_KEY=
@@ -0,0 +1,28 @@
1
+ # Copyright 2026 Google LLC
2
+ # Modifications Copyright 2026 graph-agents-cli contributors
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ # Read by the CLI when the template is selected; never copied into the
17
+ # generated project, because the overlay skips .template/.
18
+ name: "langgraph"
19
+ description: "LangGraph ReAct agent served over a chat SSE API and A2A, with a FastAPI or LangGraph Server runtime, Postgres persistence, and a Helm chart"
20
+ # empty_py leaves out any agent layer, so this template supplies its own
21
+ # agent, server, tests, dependency locks and deployment files.
22
+ base_template: "empty_py"
23
+ example_question: "What's the weather in San Francisco?"
24
+ settings:
25
+ language: "python"
26
+ deployment_targets: ["kubernetes", "none"]
27
+ agent_directory: "app"
28
+ tags: ["langgraph", "a2a"]
@@ -0,0 +1,59 @@
1
+ # FastAPI runtime image (base: the official python:3.12-slim line, pinned to an
2
+ # exact release). Two stages: the builder installs the dependencies from the
3
+ # committed uv.lock with a pinned uv; the final image holds only the
4
+ # virtualenv and the app (no uv), runs as uid/gid 1000 and writes nothing
5
+ # outside /tmp, so it runs with a read-only root filesystem.
6
+ #
7
+ # The tags below are exact releases. For fully reproducible builds pin them by
8
+ # digest as well, e.g. `python:3.12.14-slim-bookworm@sha256:<digest>`
9
+ # (`docker buildx imagetools inspect <image>` prints the digest); bump them
10
+ # deliberately, e.g. for security updates of the base image.
11
+ ARG PYTHON_IMAGE=python:3.12.14-slim-bookworm
12
+ ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.12.18
13
+
14
+ FROM ${UV_IMAGE} AS uv
15
+
16
+ FROM ${PYTHON_IMAGE} AS builder
17
+
18
+ ENV UV_COMPILE_BYTECODE=1 \
19
+ UV_LINK_MODE=copy \
20
+ UV_PYTHON_DOWNLOADS=never
21
+
22
+ WORKDIR /app
23
+
24
+ # Dependencies first so the layer is cached until the lock changes.
25
+ COPY pyproject.toml uv.lock ./
26
+ RUN --mount=from=uv,source=/uv,target=/bin/uv \
27
+ --mount=type=cache,target=/root/.cache/uv \
28
+ uv sync --frozen --no-dev --no-install-project
29
+
30
+ COPY {{cookiecutter.agent_directory}} ./{{cookiecutter.agent_directory}}
31
+ RUN --mount=from=uv,source=/uv,target=/bin/uv \
32
+ --mount=type=cache,target=/root/.cache/uv \
33
+ uv sync --frozen --no-dev \
34
+ && python -m compileall -q {{cookiecutter.agent_directory}}
35
+
36
+ FROM ${PYTHON_IMAGE}
37
+
38
+ ENV PYTHONUNBUFFERED=1 \
39
+ PYTHONDONTWRITEBYTECODE=1 \
40
+ HOME=/tmp \
41
+ PATH="/app/.venv/bin:$PATH" \
42
+ HOST=0.0.0.0 \
43
+ PORT=8000
44
+
45
+ WORKDIR /app
46
+ COPY --from=builder /app /app
47
+
48
+ # The outbound API policy travels with the image: without it the API client
49
+ # refuses every call. The glob copies api-policy.yaml when the project has one
50
+ # and nothing otherwise (pyproject.toml is repeated only so the COPY always has
51
+ # a source). --chmod makes it readable by uid 1000 whatever its mode in the
52
+ # working tree (an unreadable policy also refuses every call).
53
+ COPY --chmod=0644 pyproject.toml api-policy.yam[l] ./
54
+
55
+ USER 1000:1000
56
+
57
+ EXPOSE 8000
58
+
59
+ CMD ["sh", "-c", "exec uvicorn {{cookiecutter.agent_directory}}.fast_api_app:app --host ${HOST:-0.0.0.0} --port ${PORT:-8000}"]
@@ -0,0 +1,59 @@
1
+ # LangGraph Server runtime image. Mirrors the shape of `langgraph dockerfile`
2
+ # output, with two differences: the dependencies are installed at the exact
3
+ # versions of uv.lock (not resolved again), and the server runs as uid/gid 1000.
4
+ #
5
+ # The base image is pinned to the langgraph-api release in uv.lock
6
+ # (langchain/langgraph-api:<version>-py3.12): bump both together. For fully
7
+ # reproducible builds pin it by digest as well
8
+ # (`...:0.14.4-py3.12@sha256:<digest>`; `docker buildx imagetools inspect
9
+ # <image>` prints it). Mirror it for a disconnected registry and change the
10
+ # FROM line accordingly.
11
+ FROM langchain/langgraph-api:0.14.4-py3.12
12
+
13
+ # The whole project (minus .dockerignore) is the dependency, so api-policy.yaml,
14
+ # the outbound API policy the API client enforces, is in the image when the
15
+ # project has one (made readable by uid 1000 below, whatever its mode in the
16
+ # working tree: an unreadable policy refuses every call).
17
+ ADD . /deps/{{cookiecutter.project_name}}
18
+
19
+ # `uv export` writes the locked versions (with hashes); they are installed
20
+ # without resolving again, and must agree with the base image's constraints, so
21
+ # a lock that conflicts with the server fails the build instead of the server.
22
+ # The lock must also pin the base image's own langgraph-api release (the build
23
+ # stops with the tag to use otherwise). The base image ships uv; nothing is
24
+ # added to it.
25
+ RUN cd /deps/{{cookiecutter.project_name}} \
26
+ && if [ -f api-policy.yaml ]; then chmod a+r api-policy.yaml; fi \
27
+ && base_api="$(python -c "import importlib.metadata as m; print(m.version('langgraph-api'))")" \
28
+ && uv export --quiet --frozen --no-dev --no-emit-project --no-header -o /tmp/requirements.txt \
29
+ && uv pip install --system --no-cache --compile-bytecode --no-deps \
30
+ -c /api/constraints.txt -r /tmp/requirements.txt \
31
+ && uv pip install --system --no-cache --compile-bytecode --no-deps \
32
+ -e /deps/{{cookiecutter.project_name}} \
33
+ && rm /tmp/requirements.txt \
34
+ && lock_api="$(python -c "import importlib.metadata as m; print(m.version('langgraph-api'))")" \
35
+ && if [ "$base_api" != "$lock_api" ]; then \
36
+ echo "uv.lock pins langgraph-api $lock_api but the base image is $base_api:" \
37
+ "use FROM langchain/langgraph-api:$lock_api-py3.12" >&2; \
38
+ exit 1; \
39
+ fi
40
+
41
+ # The graph, the custom routes (/chat, /threads, /health, /ready, /metrics,
42
+ # /playground, A2A) and the auth handler, as langgraph.json declares them.
43
+ # `disable_meta` turns off the server's unauthenticated meta routes (/docs,
44
+ # /openapi.json, /info, /metrics); the app's own /metrics takes over.
45
+ ENV LANGSERVE_GRAPHS='{"agent": "/deps/{{cookiecutter.project_name}}/{{cookiecutter.agent_directory}}/agent.py:graph"}'
46
+ ENV LANGGRAPH_HTTP='{"app": "/deps/{{cookiecutter.project_name}}/{{cookiecutter.agent_directory}}/fast_api_app.py:app", "disable_meta": true}'
47
+ ENV LANGGRAPH_AUTH='{"path": "/deps/{{cookiecutter.project_name}}/{{cookiecutter.agent_directory}}/app_utils/auth.py:auth"}'
48
+ # LANGGRAPH_SERVER tells fast_api_app.py it is mounted inside the server (no
49
+ # checkpointer binding). The server allows every CORS origin when
50
+ # CORS_ALLOW_ORIGINS is unset; the image starts from none, like the fastapi
51
+ # runtime: list your browser origins in CORS_ALLOW_ORIGINS (comma-separated).
52
+ ENV LANGGRAPH_SERVER=1 \
53
+ CORS_ALLOW_ORIGINS="" \
54
+ PYTHONDONTWRITEBYTECODE=1 \
55
+ HOME=/tmp
56
+
57
+ WORKDIR /deps/{{cookiecutter.project_name}}
58
+
59
+ USER 1000:1000