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.
- graph_agents_cli/__init__.py +26 -0
- graph_agents_cli/_api_policy.py +2145 -0
- graph_agents_cli/_approvals.py +400 -0
- graph_agents_cli/_build.py +186 -0
- graph_agents_cli/_build_info.json +7 -0
- graph_agents_cli/_chat_client.py +462 -0
- graph_agents_cli/_click.py +157 -0
- graph_agents_cli/_defaults.py +139 -0
- graph_agents_cli/_experiments.py +64 -0
- graph_agents_cli/_http.py +192 -0
- graph_agents_cli/_output.py +83 -0
- graph_agents_cli/_project.py +462 -0
- graph_agents_cli/_remote.py +220 -0
- graph_agents_cli/_response_schema.py +264 -0
- graph_agents_cli/_runner.py +319 -0
- graph_agents_cli/_skills_check.py +274 -0
- graph_agents_cli/_tools.py +189 -0
- graph_agents_cli/_trust.py +66 -0
- graph_agents_cli/api/__init__.py +15 -0
- graph_agents_cli/api/_changes.py +506 -0
- graph_agents_cli/api/_files.py +658 -0
- graph_agents_cli/api/cmd_api.py +2480 -0
- graph_agents_cli/deploy/__init__.py +15 -0
- graph_agents_cli/deploy/_config.py +171 -0
- graph_agents_cli/deploy/_image.py +128 -0
- graph_agents_cli/deploy/_kube.py +286 -0
- graph_agents_cli/deploy/_modes.py +234 -0
- graph_agents_cli/deploy/_preflight.py +370 -0
- graph_agents_cli/deploy/_values.py +168 -0
- graph_agents_cli/deploy/cmd_deploy.py +1866 -0
- graph_agents_cli/deploy/gitops.py +562 -0
- graph_agents_cli/deploy/local_load.py +273 -0
- graph_agents_cli/dev/__init__.py +13 -0
- graph_agents_cli/dev/cmd_build.py +131 -0
- graph_agents_cli/dev/cmd_install.py +78 -0
- graph_agents_cli/dev/cmd_lint.py +119 -0
- graph_agents_cli/dev/cmd_playground.py +297 -0
- graph_agents_cli/dev/policy_check.py +1287 -0
- graph_agents_cli/eval/__init__.py +22 -0
- graph_agents_cli/eval/_client.py +670 -0
- graph_agents_cli/eval/_common.py +177 -0
- graph_agents_cli/eval/_judge.py +168 -0
- graph_agents_cli/eval/_judge_runner.py +238 -0
- graph_agents_cli/eval/_paths.py +212 -0
- graph_agents_cli/eval/checks.py +581 -0
- graph_agents_cli/eval/cmd_analyze.py +278 -0
- graph_agents_cli/eval/cmd_compare.py +284 -0
- graph_agents_cli/eval/cmd_eval_group.py +80 -0
- graph_agents_cli/eval/cmd_generate.py +558 -0
- graph_agents_cli/eval/cmd_grade.py +466 -0
- graph_agents_cli/eval/cmd_metric.py +156 -0
- graph_agents_cli/eval/cmd_run.py +370 -0
- graph_agents_cli/eval/cmd_submit.py +400 -0
- graph_agents_cli/eval/config.py +435 -0
- graph_agents_cli/eval/dataset.py +350 -0
- graph_agents_cli/eval/gate.py +420 -0
- graph_agents_cli/eval/transcript.py +192 -0
- graph_agents_cli/extension/__init__.py +13 -0
- graph_agents_cli/extension/_compat.py +86 -0
- graph_agents_cli/extension/_loader.py +293 -0
- graph_agents_cli/extension/_manifest.py +135 -0
- graph_agents_cli/extension/_overrides.py +195 -0
- graph_agents_cli/extension/_paths.py +91 -0
- graph_agents_cli/extension/_refs.py +193 -0
- graph_agents_cli/extension/_resolver.py +453 -0
- graph_agents_cli/extension/_schema.py +106 -0
- graph_agents_cli/extension/_spec.py +253 -0
- graph_agents_cli/extension/_sync.py +102 -0
- graph_agents_cli/extension/_trust.py +58 -0
- graph_agents_cli/extension/cmd_extension_add.py +259 -0
- graph_agents_cli/extension/cmd_extension_group.py +57 -0
- graph_agents_cli/extension/cmd_extension_list.py +56 -0
- graph_agents_cli/extension/cmd_extension_remove.py +61 -0
- graph_agents_cli/extension/cmd_extension_update.py +195 -0
- graph_agents_cli/info/__init__.py +13 -0
- graph_agents_cli/info/cmd_info.py +222 -0
- graph_agents_cli/infra/__init__.py +15 -0
- graph_agents_cli/infra/checks.py +1169 -0
- graph_agents_cli/infra/cmd_infra.py +103 -0
- graph_agents_cli/main.py +591 -0
- graph_agents_cli/peer/__init__.py +15 -0
- graph_agents_cli/peer/_generate.py +254 -0
- graph_agents_cli/peer/cmd_peer.py +1151 -0
- graph_agents_cli/run/__init__.py +13 -0
- graph_agents_cli/run/_local_server.py +1157 -0
- graph_agents_cli/run/_signals.py +141 -0
- graph_agents_cli/run/cmd_approvals.py +530 -0
- graph_agents_cli/run/cmd_run.py +1421 -0
- graph_agents_cli/scaffold/__init__.py +19 -0
- graph_agents_cli/scaffold/agents/README.md +24 -0
- graph_agents_cli/scaffold/agents/empty_py/.template/templateconfig.yaml +22 -0
- graph_agents_cli/scaffold/agents/langgraph/.env.example +292 -0
- graph_agents_cli/scaffold/agents/langgraph/.template/templateconfig.yaml +28 -0
- graph_agents_cli/scaffold/agents/langgraph/Dockerfile +59 -0
- graph_agents_cli/scaffold/agents/langgraph/Dockerfile.langgraph-server +59 -0
- graph_agents_cli/scaffold/agents/langgraph/README.md +571 -0
- graph_agents_cli/scaffold/agents/langgraph/api-policy.yaml +60 -0
- graph_agents_cli/scaffold/agents/langgraph/app/__init__.py +20 -0
- graph_agents_cli/scaffold/agents/langgraph/app/agent.py +174 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/__init__.py +15 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/a2a.py +2162 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/a2a_client.py +1167 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/api_client.py +4220 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/approvals.py +1349 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/auth.py +1986 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/chat.py +2962 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/checkpointer.py +432 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/content.py +569 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/db.py +580 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/limits.py +203 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/metrics.py +231 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/middleware.py +361 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/model.py +611 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/playground.py +230 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/run_locks.py +459 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/structured.py +755 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/telemetry.py +681 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/threads.py +493 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/token_exchange.py +959 -0
- graph_agents_cli/scaffold/agents/langgraph/app/fast_api_app.py +770 -0
- graph_agents_cli/scaffold/agents/langgraph/app/policies/__init__.py +55 -0
- graph_agents_cli/scaffold/agents/langgraph/app/policies/custom.py +97 -0
- graph_agents_cli/scaffold/agents/langgraph/app/tools/__init__.py +46 -0
- graph_agents_cli/scaffold/agents/langgraph/app/tools/example_api.py +92 -0
- graph_agents_cli/scaffold/agents/langgraph/app/tools/weather.py +33 -0
- graph_agents_cli/scaffold/agents/langgraph/langgraph.json +14 -0
- graph_agents_cli/scaffold/agents/langgraph/pyproject.toml +78 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/conftest.py +376 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/eval/datasets/basic-dataset.json +53 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/eval/eval_config.yaml +32 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/approval_graph.py +137 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/fake_issuer.py +216 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/fake_openai.py +357 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_a2a_outcomes.py +569 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_a2a_relay.py +479 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_api_surface.py +812 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_approvals.py +1367 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_approvals_server.py +794 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_cross_actor.py +497 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_cross_actor_server.py +247 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_history_repair.py +278 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_model_apis.py +242 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_postgres.py +637 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_resilience_postgres.py +770 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_runtime_guardrails.py +854 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_server_e2e.py +340 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_server_runtime.py +989 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_structured_answers.py +584 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_structured_server.py +222 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_token_exchange_issuer.py +650 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/load_test/.results/.placeholder +0 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/load_test/README.md +22 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/load_test/conftest.py +21 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/load_test/load_test.py +81 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_a2a_client.py +824 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_a2a_scoping.py +724 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_client.py +1214 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_client_hardening.py +716 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_policy_rpc.py +767 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_approval_ledger.py +1536 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_fake_model.py +115 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_jwt_policy.py +991 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_limits.py +310 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_logging.py +148 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_logging_hardening.py +271 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_policy.py +378 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_resilience.py +610 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_server_auth.py +702 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_structured.py +673 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_telemetry.py +404 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_thread_listing.py +255 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_threads.py +268 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_token_exchange.py +1320 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_untrusted_content.py +393 -0
- graph_agents_cli/scaffold/agents/langgraph/uv-fastapi.lock +2084 -0
- graph_agents_cli/scaffold/agents/langgraph/uv-langgraph-server.lock +2106 -0
- graph_agents_cli/scaffold/agents/langgraph/{{cookiecutter.agent_guidance_filename}} +129 -0
- graph_agents_cli/scaffold/base_templates/_shared/graph-agents-cli-manifest.yaml +36 -0
- graph_agents_cli/scaffold/base_templates/python/.dockerignore +32 -0
- graph_agents_cli/scaffold/base_templates/python/.github/CODEOWNERS +30 -0
- graph_agents_cli/scaffold/base_templates/python/.github/agent.env +7 -0
- graph_agents_cli/scaffold/base_templates/python/.github/workflows/pr_checks.yaml +214 -0
- graph_agents_cli/scaffold/base_templates/python/.gitignore +209 -0
- graph_agents_cli/scaffold/base_templates/python/tests/unit/test_dummy.py +23 -0
- graph_agents_cli/scaffold/base_templates/python/{{cookiecutter.agent_guidance_filename}} +35 -0
- graph_agents_cli/scaffold/cmd_scaffold_group.py +49 -0
- graph_agents_cli/scaffold/commands/__init__.py +13 -0
- graph_agents_cli/scaffold/commands/create.py +1424 -0
- graph_agents_cli/scaffold/commands/enhance.py +1652 -0
- graph_agents_cli/scaffold/commands/upgrade.py +570 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/agent.env +12 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/workflows/promote-to-prod.yaml +371 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/workflows/staging.yaml +450 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-dev.yaml +43 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-prod.yaml +41 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-staging.yaml +43 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/.helmignore +14 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/Chart.yaml +21 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/examples/networkpolicy.yaml +103 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/NOTES.txt +48 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/_helpers.tpl +189 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/certificate.yaml +15 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/configmap.yaml +10 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/deployment.yaml +199 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/hpa.yaml +22 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/httproute.yaml +30 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/ingress.yaml +39 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/networkpolicy.yaml +48 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/pdb.yaml +13 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/postgresql-secret.yaml +37 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/service.yaml +15 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/serviceaccount.yaml +13 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/servicemonitor.yaml +42 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-dev.yaml +22 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-prod.yaml +45 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-staging.yaml +29 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values.yaml +396 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/tests/integration/test_chart.py +269 -0
- graph_agents_cli/scaffold/deployment_targets/none/README.md +5 -0
- graph_agents_cli/scaffold/deployment_targets/none/python/README.md +6 -0
- graph_agents_cli/scaffold/utils/__init__.py +13 -0
- graph_agents_cli/scaffold/utils/backup.py +212 -0
- graph_agents_cli/scaffold/utils/build_record.py +257 -0
- graph_agents_cli/scaffold/utils/cli_options.py +184 -0
- graph_agents_cli/scaffold/utils/fs.py +83 -0
- graph_agents_cli/scaffold/utils/generate_locks.py +214 -0
- graph_agents_cli/scaffold/utils/generation_metadata.py +88 -0
- graph_agents_cli/scaffold/utils/keyedit.py +768 -0
- graph_agents_cli/scaffold/utils/keymerge.py +537 -0
- graph_agents_cli/scaffold/utils/language.py +138 -0
- graph_agents_cli/scaffold/utils/lock_utils.py +94 -0
- graph_agents_cli/scaffold/utils/logging.py +77 -0
- graph_agents_cli/scaffold/utils/manifest.py +292 -0
- graph_agents_cli/scaffold/utils/merge.py +970 -0
- graph_agents_cli/scaffold/utils/merge3.py +216 -0
- graph_agents_cli/scaffold/utils/openapi_seed.py +199 -0
- graph_agents_cli/scaffold/utils/remote_template.py +376 -0
- graph_agents_cli/scaffold/utils/template.py +1352 -0
- graph_agents_cli/scaffold/utils/upgrade.py +894 -0
- graph_agents_cli/scaffold/utils/version.py +438 -0
- graph_agents_cli/secrets/__init__.py +15 -0
- graph_agents_cli/secrets/_apply.py +954 -0
- graph_agents_cli/secrets/_required.py +188 -0
- graph_agents_cli/secrets/cmd_secrets.py +211 -0
- graph_agents_cli/setup/__init__.py +13 -0
- graph_agents_cli/setup/_antigravity.py +221 -0
- graph_agents_cli/setup/cmd_auth.py +1030 -0
- graph_agents_cli/setup/cmd_dev_token.py +513 -0
- graph_agents_cli/setup/cmd_setup.py +428 -0
- graph_agents_cli/setup/cmd_update.py +140 -0
- graph_agents_cli/skills/__init__.py +13 -0
- graph_agents_cli/skills/_bundle.py +65 -0
- graph_agents_cli/skills/data/README.md +19 -0
- graph_agents_cli/skills/data/graph-agents-cli-deploy/SKILL.md +357 -0
- graph_agents_cli/skills/data/graph-agents-cli-deploy/references/github-settings.md +113 -0
- graph_agents_cli/skills/data/graph-agents-cli-deploy/references/gitops.md +137 -0
- graph_agents_cli/skills/data/graph-agents-cli-deploy/references/kubernetes.md +315 -0
- graph_agents_cli/skills/data/graph-agents-cli-deploy/references/secrets.md +160 -0
- graph_agents_cli/skills/data/graph-agents-cli-eval/SKILL.md +303 -0
- graph_agents_cli/skills/data/graph-agents-cli-eval/references/dataset_schema.md +282 -0
- graph_agents_cli/skills/data/graph-agents-cli-eval/references/metrics-guide.md +143 -0
- graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/SKILL.md +659 -0
- graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/langchain-models.md +124 -0
- graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/langgraph.md +235 -0
- graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/template-contract.md +477 -0
- graph_agents_cli/skills/data/graph-agents-cli-observability/SKILL.md +231 -0
- graph_agents_cli/skills/data/graph-agents-cli-observability/references/langsmith.md +46 -0
- graph_agents_cli/skills/data/graph-agents-cli-observability/references/otel.md +59 -0
- graph_agents_cli/skills/data/graph-agents-cli-scaffold/SKILL.md +414 -0
- graph_agents_cli/skills/data/graph-agents-cli-scaffold/references/flags.md +134 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/SKILL.md +478 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/brainstorming.md +118 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/commands.md +419 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/extension.md +156 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/internals.md +67 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/spec-template.md +56 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/terminology.md +119 -0
- graph_agents_cli/system/__init__.py +15 -0
- graph_agents_cli/system/_apply.py +519 -0
- graph_agents_cli/system/_checks.py +1023 -0
- graph_agents_cli/system/_deploy.py +215 -0
- graph_agents_cli/system/_model.py +363 -0
- graph_agents_cli/system/_system.py +664 -0
- graph_agents_cli/system/_views.py +208 -0
- graph_agents_cli/system/cmd_system.py +423 -0
- graph_agents_cli-0.3.1.dist-info/METADATA +162 -0
- graph_agents_cli-0.3.1.dist-info/RECORD +291 -0
- graph_agents_cli-0.3.1.dist-info/WHEEL +4 -0
- graph_agents_cli-0.3.1.dist-info/entry_points.txt +2 -0
- graph_agents_cli-0.3.1.dist-info/licenses/LICENSE +201 -0
- 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
|