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,124 @@
|
|
|
1
|
+
# LangChain models: `init_chat_model` and provider switching
|
|
2
|
+
|
|
3
|
+
The agent never names a provider in code. `app/app_utils/model.py` reads the environment and calls
|
|
4
|
+
`init_chat_model`; the same function builds the judge from `JUDGE_*`.
|
|
5
|
+
|
|
6
|
+
## Provider table
|
|
7
|
+
|
|
8
|
+
| `MODEL_PROVIDER` | LangChain provider | Key variable | Extra variables | Notes |
|
|
9
|
+
|---|---|---|---|---|
|
|
10
|
+
| `openai` | `openai` | `OPENAI_API_KEY` | | default under `-y` |
|
|
11
|
+
| `anthropic` | `anthropic` | `ANTHROPIC_API_KEY` | | |
|
|
12
|
+
| `gemini` | `google_genai` | `GOOGLE_API_KEY` | | the AI Studio API-key path only |
|
|
13
|
+
| `openai-compatible` | `openai` with `base_url` | `MODEL_API_KEY` (sent as the OpenAI key) | `OPENAI_BASE_URL` | Ollama, vLLM, TGI, OpenRouter, any OpenAI-compatible server |
|
|
14
|
+
| `fake` | the template's deterministic `FakeChatModel` (`app/app_utils/model.py`) | none | | tests and CI only; never offered by `create`; replies depend only on the input (greeting, a request mentioning a bound tool -> a call of it, judge prompt -> JSON verdict) |
|
|
15
|
+
|
|
16
|
+
Default model names per provider are recorded by `create` in `.env` and the manifest
|
|
17
|
+
(`create_params.model`). They are placeholders to verify at release time; do not replace them
|
|
18
|
+
from memory.
|
|
19
|
+
|
|
20
|
+
## `get_model()` shape (as `app/app_utils/model.py` implements it)
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from langchain.chat_models import init_chat_model # imported lazily, inside build_model
|
|
24
|
+
|
|
25
|
+
PROVIDER_TO_LANGCHAIN = {
|
|
26
|
+
"openai": "openai",
|
|
27
|
+
"anthropic": "anthropic",
|
|
28
|
+
"gemini": "google_genai",
|
|
29
|
+
"openai-compatible": "openai",
|
|
30
|
+
}
|
|
31
|
+
PROVIDER_KEY_VARS = {
|
|
32
|
+
"openai": "OPENAI_API_KEY",
|
|
33
|
+
"anthropic": "ANTHROPIC_API_KEY",
|
|
34
|
+
"gemini": "GOOGLE_API_KEY",
|
|
35
|
+
"openai-compatible": "MODEL_API_KEY",
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def model_settings(*, judge=False) -> dict:
|
|
40
|
+
# MODEL_PROVIDER (default "openai"), MODEL_NAME, OPENAI_BASE_URL, the provider's key variable;
|
|
41
|
+
# with judge=True each is overridden by JUDGE_MODEL_PROVIDER / JUDGE_MODEL_NAME / JUDGE_BASE_URL /
|
|
42
|
+
# JUDGE_API_KEY when set. Read at CALL time, so tests and the eval judge runner can set them late.
|
|
43
|
+
...
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def build_model(provider, name, *, base_url=None, api_key=None, **kwargs):
|
|
47
|
+
if provider == "fake":
|
|
48
|
+
return FakeChatModel(**kwargs)
|
|
49
|
+
# unknown provider -> ValueError; empty MODEL_NAME -> ValueError;
|
|
50
|
+
# openai-compatible without OPENAI_BASE_URL -> ValueError
|
|
51
|
+
return init_chat_model(
|
|
52
|
+
name, model_provider=PROVIDER_TO_LANGCHAIN[provider], api_key=..., base_url=..., **kwargs
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def get_model(**kwargs): # the agent's model
|
|
57
|
+
return build_model(**model_settings(), **kwargs)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_judge_model(**kwargs): # the judge; JUDGE_* with the agent's values as defaults
|
|
61
|
+
return build_model(**model_settings(judge=True), **kwargs)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def model_label(*, judge=False) -> str: # "<provider>/<model>", recorded in run records and traces
|
|
65
|
+
...
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`get_judge_model()` takes no provider or model arguments; `eval grade --judge-provider/--judge-model`
|
|
69
|
+
reach it through `JUDGE_MODEL_PROVIDER` / `JUDGE_MODEL_NAME` in the judge runner's environment.
|
|
70
|
+
|
|
71
|
+
## OpenAI-API models: reasoning effort and the Responses API
|
|
72
|
+
|
|
73
|
+
For `openai` and `openai-compatible` only (set for another provider, the app refuses to start):
|
|
74
|
+
|
|
75
|
+
| Variable | Values | Effect |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| `MODEL_REASONING_EFFORT` | `none`, `minimal`, `low`, `medium`, `high`, `xhigh`; unset = the model's default | `reasoning_effort` on Chat Completions, `reasoning.effort` on the Responses API |
|
|
78
|
+
| `MODEL_USE_RESPONSES_API` | `true`, `false`; unset = langchain-openai chooses | `true`: every request to `/v1/responses`; `false`: `/v1/chat/completions` |
|
|
79
|
+
|
|
80
|
+
`build_model` passes them to `init_chat_model` as `reasoning_effort` and `use_responses_api`
|
|
81
|
+
(an explicit argument wins). Unset, langchain-openai uses Chat Completions except for the
|
|
82
|
+
models its own list says need the Responses API. A model that refuses function tools with a
|
|
83
|
+
reasoning effort on Chat Completions fails its first call with a 400 naming `/v1/responses`:
|
|
84
|
+
set `MODEL_USE_RESPONSES_API=true` (or `MODEL_REASONING_EFFORT=none`). Keep it `false` or unset
|
|
85
|
+
for an OpenAI-compatible server without `/v1/responses`. The judge reads
|
|
86
|
+
`JUDGE_REASONING_EFFORT` / `JUDGE_USE_RESPONSES_API`, defaulting to the agent's when the judge
|
|
87
|
+
is an OpenAI-API model too. Tools, streaming and token usage work on both APIs.
|
|
88
|
+
|
|
89
|
+
## Switching providers
|
|
90
|
+
|
|
91
|
+
Edit `.env` (locally) and the chart `env:` plus the Secret (deployed):
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# hosted -> on-network vLLM
|
|
95
|
+
MODEL_PROVIDER=openai-compatible
|
|
96
|
+
MODEL_NAME=Qwen/Qwen2.5-14B-Instruct
|
|
97
|
+
OPENAI_BASE_URL=http://vllm.models.svc:8000/v1
|
|
98
|
+
MODEL_API_KEY=none
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then update the manifest's `secrets.keys` if the provider key variable changed (the allow-list
|
|
102
|
+
names the variable `secrets apply` exports), and re-run `secrets apply` and `deploy --restart`.
|
|
103
|
+
`scaffold enhance` can rewrite `create_params.model_provider` and the allow-list for you.
|
|
104
|
+
|
|
105
|
+
## Tool calling on open models
|
|
106
|
+
|
|
107
|
+
`create_agent` and `ToolNode` depend on native function calling. Use Llama 3.1+, Qwen 2.5+, or
|
|
108
|
+
Mistral families served with tool-call parsing enabled (vLLM: `--enable-auto-tool-choice
|
|
109
|
+
--tool-call-parser <parser>`; Ollama: a model tagged with tools). Small or older models loop or
|
|
110
|
+
emit malformed calls; the eval gate (`expect.tool_calls`) catches this.
|
|
111
|
+
|
|
112
|
+
## Judge model
|
|
113
|
+
|
|
114
|
+
The judge is a chat model like any other, built from `JUDGE_MODEL_PROVIDER`, `JUDGE_MODEL_NAME`,
|
|
115
|
+
`JUDGE_BASE_URL`, and `JUDGE_API_KEY`, defaulting to the agent's configuration. In the
|
|
116
|
+
disconnected profile it points at an on-network OpenAI-compatible server, possibly the same one.
|
|
117
|
+
`eval_config.yaml` `judge: {provider, model}` overrides the environment for a run.
|
|
118
|
+
|
|
119
|
+
## Egress
|
|
120
|
+
|
|
121
|
+
Selecting a hosted provider sends prompts, tool results, and any context the agent assembles to
|
|
122
|
+
that provider. That is a policy decision the consuming project makes explicitly (and publishes a
|
|
123
|
+
privacy notice for) before connecting a hosted model. Local hosting alone does not make data local
|
|
124
|
+
if traces or evals are exported elsewhere; see `/graph-agents-cli-observability`.
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# LangGraph patterns used by the template
|
|
2
|
+
|
|
3
|
+
Patterns below are the ones the template and its tests rely on. For anything else, fetch the
|
|
4
|
+
upstream LangGraph docs; do not guess API names from memory.
|
|
5
|
+
|
|
6
|
+
## `create_agent` (default)
|
|
7
|
+
|
|
8
|
+
```python
|
|
9
|
+
from langchain.agents import create_agent
|
|
10
|
+
from app.app_utils.model import get_model
|
|
11
|
+
from app.tools import TOOLS
|
|
12
|
+
|
|
13
|
+
graph = create_agent(model=get_model(), tools=TOOLS, system_prompt=SYSTEM_PROMPT)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
A ReAct loop: model -> tool calls -> tool node -> model until no tool call remains. State is
|
|
17
|
+
`MessagesState` (`{"messages": [...]}`). Unbound; the app binds the checkpointer.
|
|
18
|
+
|
|
19
|
+
## Explicit `StateGraph`
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from typing import Annotated, TypedDict
|
|
23
|
+
from langchain_core.messages import AnyMessage
|
|
24
|
+
from langgraph.graph import StateGraph, START, END, MessagesState, add_messages
|
|
25
|
+
from langgraph.prebuilt import ToolNode, tools_condition
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class State(MessagesState):
|
|
29
|
+
site_id: str | None # extra keys beside messages
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def call_model(state: State):
|
|
33
|
+
model = get_model().bind_tools(TOOLS)
|
|
34
|
+
return {"messages": [model.invoke([SystemMessage(SYSTEM_PROMPT), *state["messages"]])]}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
builder = StateGraph(State)
|
|
38
|
+
builder.add_node("model", call_model)
|
|
39
|
+
builder.add_node("tools", ToolNode(TOOLS))
|
|
40
|
+
builder.add_edge(START, "model")
|
|
41
|
+
builder.add_conditional_edges("model", tools_condition, {"tools": "tools", END: END})
|
|
42
|
+
builder.add_edge("tools", "model")
|
|
43
|
+
|
|
44
|
+
graph = builder.compile() # still unbound
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Use an explicit graph for fixed stages (classify -> retrieve -> answer), branching by state, or a
|
|
48
|
+
human-approval node. Keep the export `graph`.
|
|
49
|
+
|
|
50
|
+
## Tools
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from langchain_core.tools import tool
|
|
54
|
+
|
|
55
|
+
API_CALLS = [
|
|
56
|
+
{"api": "sites", "method": "GET", "operation_id": "getSite", "path": "/sites/{site_id}"},
|
|
57
|
+
{"api": "sites", "method": "PATCH", "operation_id": "renameSite", "path": "/sites/{site_id}"},
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@tool
|
|
62
|
+
async def get_site(site_id: str) -> str:
|
|
63
|
+
"""Return the site record for SITE_ID."""
|
|
64
|
+
...
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- The docstring is the model's description of the tool; write it for the model.
|
|
68
|
+
- Typed parameters become the schema; keep them simple (str, int, bool, small models).
|
|
69
|
+
- Return strings or JSON-serialisable data; long payloads bloat the context and the trace.
|
|
70
|
+
- Tools that call an external API use `get_client("<api>")` from `app_utils.api_client` and
|
|
71
|
+
declare `API_CALLS`.
|
|
72
|
+
- Tools that need the caller's identity read it from the run context the app sets
|
|
73
|
+
(`runtime: ToolRuntime[Any]` parameter, `runtime.context`: `principal_id`, `roles`,
|
|
74
|
+
`attributes`; or `current_caller(runtime.context)` from `app_utils.api_client`); never from a
|
|
75
|
+
global. Parameterise `ToolRuntime`: the bare form makes pydantic warn with the run context
|
|
76
|
+
(which may hold credentials) on every call.
|
|
77
|
+
- Tool results are untrusted data: write tools act only on ids the user named
|
|
78
|
+
(`require_user_mentioned`) and on the caller's own records (`require_owner`); see section 2a
|
|
79
|
+
of the skill.
|
|
80
|
+
|
|
81
|
+
## Checkpointers and `thread_id`
|
|
82
|
+
|
|
83
|
+
The app (not `agent.py`) does:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
# app/app_utils/checkpointer.py
|
|
87
|
+
def get_checkpointer():
|
|
88
|
+
if os.environ.get("CHECKPOINTER", "memory") == "postgres":
|
|
89
|
+
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
|
|
90
|
+
|
|
91
|
+
saver = AsyncPostgresSaver.from_conn_string(os.environ["POSTGRES_DSN"])
|
|
92
|
+
await saver.setup()
|
|
93
|
+
return saver
|
|
94
|
+
from langgraph.checkpoint.memory import InMemorySaver
|
|
95
|
+
|
|
96
|
+
return InMemorySaver()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# app/fast_api_app.py
|
|
100
|
+
runnable = graph.with_config(...) # or graph rebuilt with checkpointer=get_checkpointer()
|
|
101
|
+
config = {"configurable": {"thread_id": thread_id, "principal": principal}}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- `thread_id` selects the checkpoint namespace; each `/chat` call on the same id continues the
|
|
105
|
+
conversation.
|
|
106
|
+
- Under `memory`, state lives only in the process. Under `postgres`, it survives restarts and is
|
|
107
|
+
shared across replicas.
|
|
108
|
+
- Under `langgraph-server`, the server creates and persists threads from `DATABASE_URI`; the app's
|
|
109
|
+
`/chat` route uses the server's thread.
|
|
110
|
+
|
|
111
|
+
## Streaming
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
async for event in runnable.astream_events(
|
|
115
|
+
{"messages": [HumanMessage(text)]}, config, version="v2"
|
|
116
|
+
):
|
|
117
|
+
kind = event["event"]
|
|
118
|
+
if kind == "on_chat_model_stream":
|
|
119
|
+
yield sse("message.delta", {"text": event["data"]["chunk"].content})
|
|
120
|
+
elif kind == "on_tool_start":
|
|
121
|
+
yield sse(
|
|
122
|
+
"tool.call",
|
|
123
|
+
{"id": event["run_id"], "name": event["name"], "args": event["data"].get("input")},
|
|
124
|
+
)
|
|
125
|
+
elif kind == "on_tool_end":
|
|
126
|
+
yield sse(
|
|
127
|
+
"tool.result",
|
|
128
|
+
{
|
|
129
|
+
"id": event["run_id"],
|
|
130
|
+
"name": event["name"],
|
|
131
|
+
"result": str(event["data"].get("output")),
|
|
132
|
+
"is_error": False,
|
|
133
|
+
},
|
|
134
|
+
)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The app applies `TRACE_CAPTURE` before emitting `args` and `result` to a non-owner. Nodes should
|
|
138
|
+
not `print` or log prompt text; the telemetry layer handles capture.
|
|
139
|
+
|
|
140
|
+
## Human-in-the-loop (interrupts)
|
|
141
|
+
|
|
142
|
+
For API calls, use the policy's approval gate: `graph-agents-cli api approval NAME ...` makes the
|
|
143
|
+
API client itself call `interrupt()` before a gated call, `/chat` ends with `message.end` status
|
|
144
|
+
`awaiting_approval`, and `POST /threads/{thread_id}/approvals/{approval_id}` resumes the run (see
|
|
145
|
+
SKILL.md section 5). Nothing in the graph changes.
|
|
146
|
+
|
|
147
|
+
The general LangGraph pattern is below for reference. **The scaffolded chat API does not expose
|
|
148
|
+
your own interrupts:** there is no status for a graph paused elsewhere and no `metadata.resume`
|
|
149
|
+
request convention, so a node that calls `interrupt()` outside the API client stalls the `/chat`
|
|
150
|
+
stream. Use such interrupts only under `playground --graph` (LangGraph Studio).
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from langgraph.types import interrupt, Command
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def confirm_action(state: State):
|
|
157
|
+
decision = interrupt(
|
|
158
|
+
{"question": "Approve closing incident?", "incident_id": state["incident_id"]}
|
|
159
|
+
)
|
|
160
|
+
if decision != "approve":
|
|
161
|
+
return {"messages": [AIMessage("Cancelled.")]}
|
|
162
|
+
return {"approved": True}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
- Requires a checkpointer (any); the thread pauses at the interrupt and is resumed with
|
|
166
|
+
`graph.invoke(Command(resume="approve"), config)` on the same `thread_id`. On resume the
|
|
167
|
+
interrupted node runs again from its start (`interrupt()` then returns the resume value), so
|
|
168
|
+
the code before it must be safe to repeat.
|
|
169
|
+
- Not wired to `/chat` outside the API client's approval gate: the app does not report such a
|
|
170
|
+
paused graph and does not translate a request `metadata.resume` into `Command(resume=...)`. Adding that is a scaffolding change to
|
|
171
|
+
`app/app_utils/chat.py` and `fast_api_app.py`, which `upgrade` 3-way merges; ask before doing it.
|
|
172
|
+
- `interrupt_before=["tools"]` at compile time pauses before every tool call; same caveat.
|
|
173
|
+
|
|
174
|
+
## Subgraphs
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
sub = StateGraph(SubState)
|
|
178
|
+
...
|
|
179
|
+
sub_graph = sub.compile() # unbound
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def run_sub(state: State):
|
|
183
|
+
result = sub_graph.invoke({"query": state["messages"][-1].content})
|
|
184
|
+
return {"messages": [AIMessage(result["answer"])]}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
builder.add_node(
|
|
188
|
+
"research", run_sub
|
|
189
|
+
) # or builder.add_node("research", sub_graph) when schemas share keys
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Subgraphs inherit the parent's checkpointer and `thread_id`; interrupts inside a subgraph surface
|
|
193
|
+
through the parent.
|
|
194
|
+
|
|
195
|
+
## Testing with the `fake` provider
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
# tests/unit/conftest.py
|
|
199
|
+
import pytest
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@pytest.fixture(autouse=True)
|
|
203
|
+
def fake_model(monkeypatch):
|
|
204
|
+
monkeypatch.setenv("MODEL_PROVIDER", "fake")
|
|
205
|
+
monkeypatch.setenv("MODEL_NAME", "fake")
|
|
206
|
+
monkeypatch.setenv("CHECKPOINTER", "memory")
|
|
207
|
+
monkeypatch.setenv("AUTH_POLICY", "shared-bearer")
|
|
208
|
+
monkeypatch.setenv("API_KEY", "test-key")
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
`get_model()` returns the template's deterministic `FakeChatModel` (`app/app_utils/model.py`):
|
|
212
|
+
`hi` -> `Hello! How can I help you today?`; a request that mentions a bound tool (its name, or a
|
|
213
|
+
distinctive word of it: `What is the weather in Paris?` with `get_weather` bound) -> a call of that
|
|
214
|
+
tool with every required argument filled (text arguments get the request's subject, `Paris`), then
|
|
215
|
+
`Here is what I found: <tool result>`; a prompt mentioning "score" and "json" -> the JSON judge
|
|
216
|
+
verdict `{"score": 5, ...}`; anything else -> `I am a fake model. I can use these tools: ... You
|
|
217
|
+
said: <text>`. There is no scripted-response list or `FAKE_MODEL_RESPONSES` variable. The
|
|
218
|
+
template's `tests/conftest.py` keeps `.env` and the shell's app settings out of the tests and
|
|
219
|
+
offers `use_test_tools(tool, ...)`, which serves the graph with test-only tools, so plumbing tests
|
|
220
|
+
never depend on the project's own tools. Use it to test:
|
|
221
|
+
|
|
222
|
+
- the SSE mapping (`/chat` returns `message.start`, deltas, `tool.call`/`tool.result`,
|
|
223
|
+
`message.end`);
|
|
224
|
+
- tool routing (with a test-only tool) and the middleware turning `ApiPolicyError` / `ApiCallError`
|
|
225
|
+
into a tool error;
|
|
226
|
+
- policy enforcement (401 without the bearer, 403 on a foreign thread under a per-user policy
|
|
227
|
+
such as `jwt` or an implemented `custom`).
|
|
228
|
+
|
|
229
|
+
Never test model behaviour here; that is `graph-agents-cli eval`.
|
|
230
|
+
|
|
231
|
+
## Prompts and graph modules
|
|
232
|
+
|
|
233
|
+
`app/prompts/**` and `app/graph/**` are reserved agent-code directories: `upgrade` never touches
|
|
234
|
+
them. Put system prompts in `app/prompts/` as Python constants or text files loaded at import;
|
|
235
|
+
put a large explicit graph in `app/graph/` and import it from `agent.py`.
|