agentframe-py 0.1.0__tar.gz → 0.3.0__tar.gz
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.
- agentframe_py-0.3.0/.github/workflows/base-image.yml +62 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/AGENTS.md +167 -35
- agentframe_py-0.3.0/CHANGELOG.md +506 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/PKG-INFO +198 -77
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/README.md +189 -76
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/README.md +11 -3
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/api/README.md +18 -14
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/api/agents.md +14 -9
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/api/authorization.md +369 -19
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/api/configuration.md +10 -7
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/api/decorators.md +1 -1
- agentframe_py-0.3.0/docs/api/discovery.md +1110 -0
- agentframe_py-0.3.0/docs/api/evaluation.md +964 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/api/hosting.md +212 -34
- agentframe_py-0.3.0/docs/api/orchestration.md +1059 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/api/runtime.md +84 -7
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/design/base-classes.md +3 -5
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/design/discovery.md +188 -109
- agentframe_py-0.3.0/docs/design/evaluation.md +530 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/design/mcp-skills.md +1 -1
- agentframe_py-0.3.0/docs/design/orchestration.md +662 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/design/prompt-safeguarding.md +13 -2
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/design/tracing.md +31 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/guides/agent-examples.md +76 -21
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/guides/annotations.md +1 -1
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/guides/authorization.md +173 -5
- agentframe_py-0.3.0/docs/guides/development.md +225 -0
- agentframe_py-0.3.0/docs/guides/evaluation.md +365 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/guides/limits.md +93 -6
- agentframe_py-0.3.0/docs/guides/orchestration.md +295 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/guides/releasing.md +6 -5
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/roadmap.md +155 -30
- agentframe_py-0.3.0/examples/evaluation.py +90 -0
- agentframe_py-0.3.0/examples/multi_agent/__init__.py +1 -0
- agentframe_py-0.3.0/examples/multi_agent/agentframe.yaml +13 -0
- agentframe_py-0.3.0/examples/multi_agent/planner.py +286 -0
- agentframe_py-0.3.0/examples/multi_agent/planner_evaluation.py +175 -0
- agentframe_py-0.3.0/examples/multi_agent/research.py +108 -0
- agentframe_py-0.3.0/examples/multi_agent/writer.py +56 -0
- agentframe_py-0.3.0/examples/plan_approval.py +143 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/examples/smoke.py +152 -3
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/pyproject.toml +12 -2
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/__init__.py +58 -3
- agentframe_py-0.3.0/src/agentframe/__main__.py +5 -0
- agentframe_py-0.3.0/src/agentframe/authoring/context.py +458 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/authoring/definitions.py +20 -7
- agentframe_py-0.3.0/src/agentframe/cli.py +587 -0
- agentframe_py-0.3.0/src/agentframe/compose.py +230 -0
- agentframe_py-0.3.0/src/agentframe/dev.py +180 -0
- agentframe_py-0.3.0/src/agentframe/dev_server.py +302 -0
- agentframe_py-0.3.0/src/agentframe/discovery/__init__.py +1 -0
- agentframe_py-0.3.0/src/agentframe/discovery/cards.py +189 -0
- agentframe_py-0.3.0/src/agentframe/discovery/directory.py +467 -0
- agentframe_py-0.3.0/src/agentframe/discovery/foundry.py +232 -0
- agentframe_py-0.3.0/src/agentframe/discovery/identity.py +344 -0
- agentframe_py-0.3.0/src/agentframe/discovery/registry.py +291 -0
- agentframe_py-0.3.0/src/agentframe/discovery/remote.py +950 -0
- agentframe_py-0.3.0/src/agentframe/discovery/transport.py +82 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/errors.py +58 -0
- agentframe_py-0.3.0/src/agentframe/evaluation/__init__.py +41 -0
- agentframe_py-0.3.0/src/agentframe/evaluation/budget.py +62 -0
- agentframe_py-0.3.0/src/agentframe/evaluation/cases.py +179 -0
- agentframe_py-0.3.0/src/agentframe/evaluation/harness.py +379 -0
- agentframe_py-0.3.0/src/agentframe/evaluation/judge.py +257 -0
- agentframe_py-0.3.0/src/agentframe/evaluation/report.py +765 -0
- agentframe_py-0.3.0/src/agentframe/evaluation/scoring.py +190 -0
- agentframe_py-0.3.0/src/agentframe/evaluation/targets.py +450 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/a2a_executor.py +175 -47
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/app.py +150 -28
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/card.py +9 -6
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/host.py +48 -8
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/lifecycle.py +10 -5
- agentframe_py-0.3.0/src/agentframe/hosting/skill_call.py +222 -0
- agentframe_py-0.3.0/src/agentframe/hosting/task_store.py +61 -0
- agentframe_py-0.3.0/src/agentframe/orchestration/__init__.py +1 -0
- agentframe_py-0.3.0/src/agentframe/orchestration/card_text.py +113 -0
- agentframe_py-0.3.0/src/agentframe/orchestration/catalog.py +671 -0
- agentframe_py-0.3.0/src/agentframe/orchestration/execution.py +506 -0
- agentframe_py-0.3.0/src/agentframe/orchestration/plan.py +462 -0
- agentframe_py-0.3.0/src/agentframe/orchestration/planning.py +242 -0
- agentframe_py-0.3.0/src/agentframe/orchestration/remote_tools.py +275 -0
- agentframe_py-0.3.0/src/agentframe/project.py +127 -0
- agentframe_py-0.3.0/src/agentframe/runtime/correlation.py +147 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/runtime/generation.py +82 -24
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/runtime/limits.py +7 -0
- agentframe_py-0.3.0/src/agentframe/runtime/remotes.py +198 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/runtime/runtime.py +137 -8
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/runtime/tools.py +16 -6
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/security/authentication.py +7 -1
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/security/authorization.py +2 -1
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/security/entra.py +109 -7
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/security/execution_policy.py +71 -4
- agentframe_py-0.3.0/tests/integration/test_agentframe_dev.py +219 -0
- agentframe_py-0.3.0/tests/integration/test_compose_containers.py +131 -0
- agentframe_py-0.3.0/tests/integration/test_directory_localhost.py +56 -0
- agentframe_py-0.3.0/tests/integration/test_evaluation_a2a.py +292 -0
- agentframe_py-0.3.0/tests/integration/test_evaluation_interop.py +120 -0
- agentframe_py-0.3.0/tests/integration/test_evaluation_release.py +147 -0
- agentframe_py-0.3.0/tests/integration/test_foundry_agents.py +194 -0
- agentframe_py-0.3.0/tests/integration/test_multi_agent_interop.py +308 -0
- agentframe_py-0.3.0/tests/integration/test_multi_agent_release.py +240 -0
- agentframe_py-0.3.0/tests/integration/test_on_behalf_of.py +390 -0
- agentframe_py-0.3.0/tests/integration/test_orchestration_release.py +493 -0
- agentframe_py-0.3.0/tests/integration/test_plan_approval.py +196 -0
- agentframe_py-0.3.0/tests/integration/test_providers.py +902 -0
- agentframe_py-0.3.0/tests/integration/test_remote_agents.py +327 -0
- agentframe_py-0.3.0/tests/integration/test_remote_budgets.py +399 -0
- agentframe_py-0.3.0/tests/integration/test_remote_context.py +362 -0
- agentframe_py-0.3.0/tests/integration/test_remote_correlation.py +419 -0
- agentframe_py-0.3.0/tests/integration/test_remote_identity.py +190 -0
- agentframe_py-0.3.0/tests/integration/test_remote_tools_hosted.py +373 -0
- agentframe_py-0.3.0/tests/integration/test_run_plan_hosted.py +1057 -0
- agentframe_py-0.3.0/tests/integration/test_skill_catalog_hosted.py +122 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/support/a2a_client.py +23 -13
- agentframe_py-0.3.0/tests/support/a2a_peer.py +131 -0
- agentframe_py-0.3.0/tests/support/agent_processes.py +130 -0
- agentframe_py-0.3.0/tests/support/dev_targets.py +69 -0
- agentframe_py-0.3.0/tests/support/eval_targets.py +56 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/support/fake_entra.py +74 -1
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/support/local_server.py +5 -2
- agentframe_py-0.3.0/tests/support/peer_process.py +16 -0
- agentframe_py-0.3.0/tests/support/release_targets.py +333 -0
- agentframe_py-0.3.0/tests/unit/discovery/test_directory.py +548 -0
- agentframe_py-0.3.0/tests/unit/discovery/test_directory_find.py +220 -0
- agentframe_py-0.3.0/tests/unit/discovery/test_foundry_registry.py +414 -0
- agentframe_py-0.3.0/tests/unit/discovery/test_outbound_identity.py +148 -0
- agentframe_py-0.3.0/tests/unit/discovery/test_registry.py +294 -0
- agentframe_py-0.3.0/tests/unit/discovery/test_remote.py +1135 -0
- agentframe_py-0.3.0/tests/unit/evaluation/test_a2a_target.py +73 -0
- agentframe_py-0.3.0/tests/unit/evaluation/test_cases.py +137 -0
- agentframe_py-0.3.0/tests/unit/evaluation/test_controls.py +423 -0
- agentframe_py-0.3.0/tests/unit/evaluation/test_evaluation.py +443 -0
- agentframe_py-0.3.0/tests/unit/evaluation/test_judge.py +365 -0
- agentframe_py-0.3.0/tests/unit/evaluation/test_report.py +574 -0
- agentframe_py-0.3.0/tests/unit/evaluation/test_scorers.py +205 -0
- agentframe_py-0.3.0/tests/unit/golden/Dockerfile +9 -0
- agentframe_py-0.3.0/tests/unit/golden/compose.yaml +68 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_admission.py +2 -1
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_app.py +29 -1
- agentframe_py-0.3.0/tests/unit/hosting/test_caller_context.py +458 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_card.py +8 -1
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_shutdown.py +32 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_task_operations.py +1 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/models/test_foundry.py +33 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/models/test_ollama.py +32 -0
- agentframe_py-0.3.0/tests/unit/orchestration/test_default_remote.py +331 -0
- agentframe_py-0.3.0/tests/unit/orchestration/test_plan.py +459 -0
- agentframe_py-0.3.0/tests/unit/orchestration/test_planning.py +448 -0
- agentframe_py-0.3.0/tests/unit/orchestration/test_remote_tools.py +512 -0
- agentframe_py-0.3.0/tests/unit/orchestration/test_skill_catalog.py +612 -0
- agentframe_py-0.3.0/tests/unit/runtime/test_correlation.py +106 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/runtime/test_options.py +2 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/security/test_entra.py +61 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/security/test_execution_policy.py +59 -0
- agentframe_py-0.3.0/tests/unit/test_compose.py +188 -0
- agentframe_py-0.3.0/tests/unit/test_dev.py +135 -0
- agentframe_py-0.3.0/tests/unit/test_eval_cli.py +150 -0
- agentframe_py-0.3.0/tests/unit/test_package.py +36 -0
- agentframe_py-0.3.0/tests/unit/test_project.py +62 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/uv.lock +63 -1
- agentframe_py-0.1.0/CHANGELOG.md +0 -48
- agentframe_py-0.1.0/docs/api/discovery.md +0 -760
- agentframe_py-0.1.0/docs/guides/development.md +0 -117
- agentframe_py-0.1.0/src/agentframe/authoring/context.py +0 -123
- agentframe_py-0.1.0/src/agentframe/cli.py +0 -293
- agentframe_py-0.1.0/tests/integration/test_providers.py +0 -481
- agentframe_py-0.1.0/tests/unit/test_package.py +0 -19
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/.github/actions/check-wheel/action.yml +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/.github/workflows/ci.yml +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/.github/workflows/foundry.yml +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/.github/workflows/release.yml +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/.gitignore +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/.pre-commit-config.yaml +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/.python-version +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/LICENSE +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/api/models.md +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/api/streaming.md +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/docs/design/streaming.md +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/examples/__init__.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/examples/assistant.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/examples/echo.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/examples/orders.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/examples/routed_assistant.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/authoring/__init__.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/authoring/agent.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/authoring/decorators.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/authoring/services.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/__init__.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/admission.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/dedup.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/draining_server.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/model_router.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/request_size.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/hosting/routing.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/models/__init__.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/models/base.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/models/foundry.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/models/ollama.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/models/strict_schema.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/py.typed +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/runtime/__init__.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/runtime/options.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/runtime/usage.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/security/__init__.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/security/principal.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/src/agentframe/testing.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/conftest.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/integration/test_entra_interoperability.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/integration/test_example.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/integration/test_graceful_shutdown.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/integration/test_hardening.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/integration/test_interoperability.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/integration/test_routing_example.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/integration/test_smoke.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/integration/test_structured_example.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/integration/test_success_criterion.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/integration/test_tools_example.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/support/cli_targets.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/authoring/test_decorators.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/authoring/test_services.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/authoring/test_tool_registration.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/authoring/test_tools.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_a2a_binding.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_a2a_executor.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_dedup.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_limits_ceiling.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_model_router.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_routing.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/hosting/test_size_limits.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/models/test_models.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/models/test_strict_schema.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/runtime/test_generation.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/runtime/test_limits.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/runtime/test_retries.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/runtime/test_runtime.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/runtime/test_structured_output.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/runtime/test_tool_loop.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/runtime/test_tool_replay.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/runtime/test_validation.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/security/test_authentication.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/security/test_authorization.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/security/test_tool_authorization.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/test_cli.py +0 -0
- {agentframe_py-0.1.0 → agentframe_py-0.3.0}/tests/unit/test_testing.py +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Weekly check that the python:3.13-slim digest pinned by `agentframe compose`
|
|
2
|
+
# (src/agentframe/compose.py, tests/unit/golden/Dockerfile and
|
|
3
|
+
# docs/guides/development.md) is still the tag's current digest. When it is
|
|
4
|
+
# not, it opens one issue and fails, so a maintainer refreshes the pin
|
|
5
|
+
# deliberately; it never writes to the repository.
|
|
6
|
+
name: Base image digest
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
schedule:
|
|
10
|
+
- cron: "0 6 * * 1"
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
check:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
issues: write
|
|
22
|
+
env:
|
|
23
|
+
IMAGE: python
|
|
24
|
+
TAG: 3.13-slim
|
|
25
|
+
ISSUE_TITLE: Refresh the pinned python:3.13-slim digest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v7
|
|
28
|
+
- name: Compare the pinned and current digests
|
|
29
|
+
env:
|
|
30
|
+
GH_TOKEN: ${{ github.token }}
|
|
31
|
+
run: |
|
|
32
|
+
set -euo pipefail
|
|
33
|
+
pinned=$(sed -n 's/^FROM .*@//p' tests/unit/golden/Dockerfile)
|
|
34
|
+
token=$(curl -fsS "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/${IMAGE}:pull" | jq -r .token)
|
|
35
|
+
current=$(curl -fsSI \
|
|
36
|
+
-H "Authorization: Bearer ${token}" \
|
|
37
|
+
-H "Accept: application/vnd.oci.image.index.v1+json" \
|
|
38
|
+
-H "Accept: application/vnd.docker.distribution.manifest.list.v2+json" \
|
|
39
|
+
"https://registry-1.docker.io/v2/library/${IMAGE}/manifests/${TAG}" \
|
|
40
|
+
| tr -d '\r' | sed -n 's/^docker-content-digest: //Ip')
|
|
41
|
+
if [[ ! "${current}" =~ ^sha256:[0-9a-f]{64}$ ]]; then
|
|
42
|
+
echo "::error::Could not read the current ${IMAGE}:${TAG} digest."
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
echo "Pinned: ${pinned}"
|
|
46
|
+
echo "Current: ${current}"
|
|
47
|
+
if [[ "${pinned}" == "${current}" ]]; then
|
|
48
|
+
exit 0
|
|
49
|
+
fi
|
|
50
|
+
open=$(gh issue list --state open --search "\"${ISSUE_TITLE}\" in:title" --json number --jq length)
|
|
51
|
+
if [[ "${open}" == "0" ]]; then
|
|
52
|
+
gh issue create --title "${ISSUE_TITLE}" --body "$(cat <<EOF
|
|
53
|
+
\`${IMAGE}:${TAG}\` now resolves to \`${current}\`; \`agentframe compose\` pins \`${pinned}\`.
|
|
54
|
+
|
|
55
|
+
After testing the new image, update the digest in \`src/agentframe/compose.py\` (\`BASE_IMAGE\`), \`tests/unit/golden/Dockerfile\` and \`docs/guides/development.md\`. See the Containers section of the development guide.
|
|
56
|
+
|
|
57
|
+
Opened by the [Base image digest workflow](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}).
|
|
58
|
+
EOF
|
|
59
|
+
)"
|
|
60
|
+
fi
|
|
61
|
+
echo "::error::${IMAGE}:${TAG} moved to ${current}; refresh the pinned digest."
|
|
62
|
+
exit 1
|
|
@@ -12,13 +12,17 @@ release (M8+), not an optional add-on or a hosting platform.
|
|
|
12
12
|
|
|
13
13
|
This repository contains the M0 development tooling, M1 model-free
|
|
14
14
|
authoring/local `Runtime`, M2 native A2A hosting, M3 Ollama/Foundry text
|
|
15
|
-
generation, M4 typed structured outputs, M5 bounded tool calling
|
|
16
|
-
opt-in model routing alongside design documentation.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
generation, M4 typed structured outputs, M5 bounded tool calling, M6 built-in
|
|
16
|
+
opt-in model routing and M7 hardening alongside design documentation. Version
|
|
17
|
+
0.1.0, the first usable single-agent release, and version 0.2.0, the M8+
|
|
18
|
+
multi-agent release (#83-#97), are published on PyPI as `agentframe-py`
|
|
19
|
+
(import `agentframe`). Pre-1.0 there is no stable API. M9 evaluation (#164, #152-#163)
|
|
20
|
+
and M10 model-planned orchestration (#177, #166-#176) are complete and form
|
|
21
|
+
version 0.3.0; later features (MCP, telemetry, streaming) are not implemented. Keep design API examples beyond
|
|
22
|
+
the implemented surface labeled as unimplemented; explicitly approved
|
|
23
|
+
names/defaults are decisions, not still-unresolved recommendations. Do not
|
|
24
|
+
scaffold implementation or add dependencies merely to make design snippets
|
|
25
|
+
executable.
|
|
22
26
|
|
|
23
27
|
## Code quality and readability
|
|
24
28
|
|
|
@@ -85,23 +89,27 @@ Folders stay one level deep. Put new code in the group that owns the concept:
|
|
|
85
89
|
| Path | Contents |
|
|
86
90
|
| --- | --- |
|
|
87
91
|
| `src/agentframe/__init__.py` | Public API re-exports; every public name is importable from `agentframe`. |
|
|
88
|
-
| `src/agentframe/` (root) | `errors.py`, `testing.py` (`ScriptedModel`), `cli.py` (`agentframe run`). |
|
|
92
|
+
| `src/agentframe/` (root) | `errors.py`, `testing.py` (`ScriptedModel`), `cli.py` (`agentframe run` / `dev` / `compose` / `eval`), `project.py` (`agentframe.yaml`), `dev.py` (`dev_settings()`), `dev_server.py` (`agentframe dev` supervisor), `compose.py` (`agentframe compose` generator). |
|
|
89
93
|
| `src/agentframe/authoring/` | `Agent`, `@agent` / `@skill`, definitions, `RunContext`, `Inject` / `Services`. |
|
|
90
94
|
| `src/agentframe/runtime/` | `Runtime`, generation, `RunLimits`, `RunOptions`, `Usage`. |
|
|
91
95
|
| `src/agentframe/models/` | `base.py` model protocol and settings; provider adapters `ollama.py`, `foundry.py`; `strict_schema.py` (OpenAI strict JSON-schema converter). |
|
|
92
96
|
| `src/agentframe/hosting/` | `AgentApp`, `HostConfig`, Agent Card, A2A executor, routing. |
|
|
93
97
|
| `src/agentframe/security/` | `Principal`, authentication, authorization. |
|
|
98
|
+
| `src/agentframe/orchestration/` | `RemoteSkill`, `SkillCatalog`, bounding of untrusted card text, `RemoteTool` (remote entries as model tools, with per-entry permissions and tool checks), `Plan` / `PlanStep` with static checks and reference substitution (`plan.py`), the `ctx.plan` planning call (`planning.py`) and the plan executor behind `ctx.run_plan` (`execution.py`, `PlanResult`, `StepResult`) (M10). |
|
|
99
|
+
| `src/agentframe/discovery/` | `AgentRegistry`, `AgentReference`, `AgentQuery`, file and environment registries (M8+). |
|
|
100
|
+
| `src/agentframe/evaluation/` | Evaluation harness (M9): `cases.py` (`Case`, `load_cases`), `targets.py` (`Target`, `TargetResult`, `LocalSkill`, `A2ATarget`), `scoring.py` (`Score`, scorer calls, built-ins `equals`, `contains`, `valid`), `judge.py` (`Judge`, the rubric scorer's model-backed run and its budget holds), `report.py` (`CaseResult`, `EvalReport`, versioned JSON, `require`), `budget.py` (`TokenBudget`, evaluation-wide token holds), `harness.py` (`Evaluation`). Imported as `agentframe.evaluation`, not re-exported from `agentframe`, so its `__init__.py` re-exports its own public names. |
|
|
94
101
|
| `tests/unit/<group>/` | Unit tests mirroring the source groups; root-module tests in `tests/unit/`. |
|
|
95
102
|
| `tests/integration/` | Interoperability, real providers, success criterion, README example. |
|
|
96
|
-
| `tests/support/` | Shared helpers, on pytest's `pythonpath` (`from local_server import ...`). |
|
|
97
|
-
| `examples/` | Runnable examples, each with `create_app()
|
|
103
|
+
| `tests/support/` | Shared helpers, on pytest's `pythonpath` (`from local_server import ...`); `agent_processes.py` starts agents (`agentframe run`) and the plain A2A peer (`peer_process.py`) as separate processes for release tests. |
|
|
104
|
+
| `examples/` | Runnable examples, each with `create_app()` (`evaluation.py` has `create_evaluation()` instead; `multi_agent/planner_evaluation.py` has `create_planner_evaluation(model, runtime)`); `smoke.py` checks them all against the installed wheel in CI. `multi_agent/` holds the research, writer and planner agents (hand-written `plan`, model-planned `propose` / `planned`, M10). |
|
|
98
105
|
| `docs/roadmap.md` | Product boundaries, decisions and milestones. |
|
|
99
106
|
| `docs/guides/` | How to use AgentFrame and how its behavior works. |
|
|
100
107
|
| `docs/design/` | Rationale and proposed designs. |
|
|
101
108
|
| `docs/api/` | Public surface reference. |
|
|
102
109
|
|
|
103
110
|
Keep subpackage `__init__.py` files to a short docstring; add public exports to
|
|
104
|
-
the top-level `__init__.py` only
|
|
111
|
+
the top-level `__init__.py` only (except `agentframe.evaluation`, which
|
|
112
|
+
`import agentframe` must not load). Import internal modules by full path, for
|
|
105
113
|
example `from agentframe.runtime.limits import RunLimits`. Keep test basenames
|
|
106
114
|
unique, since test folders are not packages.
|
|
107
115
|
|
|
@@ -114,7 +122,20 @@ clear error for an unknown model/deployment, a hosted structured call through
|
|
|
114
122
|
the official A2A client, a validated typed `output=` result and the example's
|
|
115
123
|
`summarize` skill returning a typed data part over A2A, a one-tool round trip
|
|
116
124
|
run locally and through `examples/orders.py` over A2A (skipped if the model
|
|
117
|
-
lacks tool support), a
|
|
125
|
+
lacks tool support), a model calling a localhost agent's skill as a remote
|
|
126
|
+
tool (M10 #167, checking only that the entry was called; skipped without tool
|
|
127
|
+
support), a rubric `Judge` grading one model-free case in an `Evaluation`
|
|
128
|
+
by majority of `votes=3` (M9 #160, #161), `examples/evaluation.py`'s answers
|
|
129
|
+
graded by a rubric judge (M9 #163; xfails for Ollama when the small judge
|
|
130
|
+
fails correct answers), a model planning one unambiguous
|
|
131
|
+
two-step goal over two localhost agents' cards with `ctx.plan` (M10 #170,
|
|
132
|
+
checking only the entries and the dependency; `llama3.2:3b` often writes
|
|
133
|
+
an invalid or different plan, an Ollama xfail), the `examples/multi_agent` planner planning and running its
|
|
134
|
+
post with the real model and the planner evaluation with `report.require`
|
|
135
|
+
(M10 #176, `-k real_planner`; specialists use stand-in models; for Ollama only
|
|
136
|
+
model-quality outcomes xfail: an invalid or empty plan, a plan the example's
|
|
137
|
+
checks refuse, or more than half the evaluation's plans erroring that way;
|
|
138
|
+
any other failure fails), a Foundry one-tool round trip that replays encrypted
|
|
118
139
|
reasoning items and one unambiguous free-text request routed by
|
|
119
140
|
`examples/routed_assistant.py` over A2A (checking only the selected skill and
|
|
120
141
|
that its argument is present, since routing is nondeterministic). They are marked
|
|
@@ -145,6 +166,20 @@ AGENTFRAME_TEST_FOUNDRY=1 AGENTFRAME_FOUNDRY_ENDPOINT=<base-url> \
|
|
|
145
166
|
|
|
146
167
|
An enabled provider with a missing required variable fails rather than skips.
|
|
147
168
|
|
|
169
|
+
`tests/integration/test_foundry_agents.py` has opt-in `foundry` tests for
|
|
170
|
+
`FoundryAgentRegistry` (#86): it lists a real project with one A2A-enabled
|
|
171
|
+
agent and fetches that agent's card, read-only. It runs only with
|
|
172
|
+
`AGENTFRAME_TEST_FOUNDRY_AGENTS=1`, `AGENTFRAME_FOUNDRY_PROJECT_ENDPOINT`
|
|
173
|
+
(`https://<account>.services.ai.azure.com/api/projects/<project>`) and
|
|
174
|
+
`AGENTFRAME_FOUNDRY_A2A_AGENT` (the agent's name), after `az login`. Setup and
|
|
175
|
+
roles are in `docs/api/discovery.md#foundryagentregistry`. The same agent is the
|
|
176
|
+
real non-AgentFrame server for #94: one test `ask`s it once, another checks
|
|
177
|
+
`call` is refused before sending. In CI, `test_multi_agent_interop.py` proves
|
|
178
|
+
both directions against a plain SDK peer (`tests/support/a2a_peer.py`). For
|
|
179
|
+
#159 the same file evaluates the agent with one `A2ATarget` `ask` case and
|
|
180
|
+
checks a `skill=` case is refused before sending; `test_evaluation_interop.py`
|
|
181
|
+
does the same against the plain SDK peer in CI.
|
|
182
|
+
|
|
148
183
|
`tests/integration/test_entra_interoperability.py` has one opt-in `entra` test
|
|
149
184
|
using a real token from `az account get-access-token`, enabled with
|
|
150
185
|
`AGENTFRAME_TEST_ENTRA=1`, `AGENTFRAME_ENTRA_TENANT_ID` and
|
|
@@ -248,6 +283,20 @@ downgrade to prompts. Implemented wire format (M2 #5): activate the card's
|
|
|
248
283
|
skill-call URI via `A2A-Extensions` (echoed in the response), skill ID in message
|
|
249
284
|
metadata `agentframe.skill`, exactly one JSON-object data part; malformed ->
|
|
250
285
|
JSON-RPC InvalidParams, no task. Not a standard A2A `skill` field.
|
|
286
|
+
Implemented (#89): the same URI carries caller context; an activated message
|
|
287
|
+
without `agentframe.skill` is free text. Cards list `params.context`
|
|
288
|
+
(`deadline_ms`, `hops`, `max_total_tokens` since #90); senders send only
|
|
289
|
+
listed fields (0.1.0 lists none).
|
|
290
|
+
Receiver timeout = min(own, `agentframe.deadline_ms`); `RunContext.hops`;
|
|
291
|
+
`RunLimits.max_remote_hops=5`: caller fails before sending, deeper request
|
|
292
|
+
REJECTED with base `LimitExceededError` message; depth is cooperative.
|
|
293
|
+
Implemented (#91): context fields `root_invocation_id`/`parent_invocation_id`
|
|
294
|
+
(lowercase UUID strings; invalid -> ignored, new root, never echoed or an
|
|
295
|
+
error). Hosted runs log `Run started`/`Run completed` (INFO) with `extra`
|
|
296
|
+
`agent`, `invocation_id`, `root_invocation_id`, `parent_invocation_id`; no
|
|
297
|
+
log format set; root not exposed on `RunContext`. Valid W3C `traceparent`
|
|
298
|
+
(version 00) plus valid `tracestate` forwarded unchanged as headers to every
|
|
299
|
+
peer, invalid dropped; no spans or trace IDs created. Never authentication.
|
|
251
300
|
Free-text/extension-unaware callers use custom or opt-in model routing plus
|
|
252
301
|
validated extraction. Ambiguity/missing arguments asks back through
|
|
253
302
|
`TASK_STATE_INPUT_REQUIRED`, never guesses; the caller answers in the same task,
|
|
@@ -400,9 +449,11 @@ call specialists over A2A, not a workflow/graph engine.
|
|
|
400
449
|
`AgentRegistry` is a small read-only abstract base with proposed async
|
|
401
450
|
`get(agent_id) -> AgentReference` and `list(query: AgentQuery) ->
|
|
402
451
|
list[AgentReference]`; pagination is unresolved. Environment/file adapters read
|
|
403
|
-
explicit sources. `
|
|
404
|
-
|
|
405
|
-
|
|
452
|
+
explicit sources. Implemented (#83): `AgentReference(name, card_url)` (the Agent
|
|
453
|
+
Card URL), `AgentQuery(names=...)`; `FileAgentRegistry("agents.yaml")` reads a
|
|
454
|
+
YAML `name`/`url` list on each call (1 MiB, `safe_load`, PyYAML core dep);
|
|
455
|
+
`EnvironmentAgentRegistry("AGENTFRAME_AGENTS")` reads comma-separated
|
|
456
|
+
`name=url` pairs. Config problems and unknown names raise `DefinitionError`.
|
|
406
457
|
`FoundryAgentRegistry` uses the chosen Foundry project agents API through
|
|
407
458
|
`azure-ai-projects` 2.x (2.10.0 observed), project endpoint
|
|
408
459
|
`https://{account}.services.ai.azure.com/api/projects/{project}`. Incoming A2A
|
|
@@ -416,15 +467,28 @@ Foundry A2A connections are a possible additional reference source, not decided.
|
|
|
416
467
|
Model deployments are not agent endpoints; no AgentFrame-to-Foundry deployment
|
|
417
468
|
or tested registry integration is claimed.
|
|
418
469
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
refresh
|
|
470
|
+
Implemented (#84): `AgentDirectory(sources=[...], card_ttl_seconds=300,
|
|
471
|
+
allow_stale=False, allow_http_hosts=(), http_client=None,
|
|
472
|
+
max_reply_bytes=8 MiB)` (#150: `Remote` replies streamed, over it -> safe
|
|
473
|
+
`RemoteAgentError`) owns SDK card
|
|
474
|
+
fetch/validation/cache/refresh via an internal fetcher (no public
|
|
475
|
+
`AgentCardResolver`/`CardCacheConfig`). Sources read on every `get`; cards
|
|
476
|
+
cached per card URL, refetched when stale; failed refresh raises unless
|
|
477
|
+
`allow_stale=True` (`DiscoveredAgent.stale`, warning). https only except
|
|
478
|
+
loopback/`allow_http_hosts`, no redirects, 10 s, 1 MiB, interface URL same
|
|
479
|
+
origin as the registry `card_url`; no caller credentials. Remote failures
|
|
480
|
+
raise `RemoteAgentError`; duplicate names across sources `DefinitionError`.
|
|
481
|
+
No construction I/O or background tasks; closes only its own client.
|
|
424
482
|
Compose `AgentDirectory(sources=[...])`, inject via `AgentApp(directory=...)`,
|
|
425
|
-
and validate configured `Remote["name"]` bindings at startup.
|
|
483
|
+
and validate configured `Remote[Literal["name"]]` bindings at startup.
|
|
426
484
|
`directory.find(skill="find_sources")` / `find(tags=["research"])` returns
|
|
427
485
|
matching native cards from bounded validated enrichment, not assumed reference fields.
|
|
486
|
+
Implemented (#85): `find(*, skill=None, tags=())`, at least one filter; skill
|
|
487
|
+
ID and all-of tags must match on the same card skill; every source listed,
|
|
488
|
+
cards resolved through the cache, at most 8 fetches at a time; any source/card
|
|
489
|
+
failure raises (honouring `allow_stale`); source order; no pagination (small
|
|
490
|
+
curated sources). Found cards are not callable; orchestrators call configured
|
|
491
|
+
remotes, dynamic invocation is deferred.
|
|
428
492
|
Inject directories as application dependencies;
|
|
429
493
|
caller-owned resources stay caller-owned unless explicitly transferred. No
|
|
430
494
|
registration writes, deploy/start/stop/delete, leases/federation, or A2A task
|
|
@@ -440,11 +504,47 @@ references/cards/source files; enforce application-selected outbound auth and
|
|
|
440
504
|
destination/redirect policy, bounded reads/deadlines/cancellation and safe
|
|
441
505
|
telemetry. Discovery does not delegate or auto-expose skills as tools. A separate
|
|
442
506
|
`RemoteAgentClient` may remain underlying/explicit client with construction open.
|
|
443
|
-
Author skills use `Remote["name"]` (excluded from external schemas),
|
|
507
|
+
Author skills use `Remote[Literal["name"]]` (excluded from external schemas),
|
|
444
508
|
`call("skill", ..., output=list[Source], max_total_tokens=...)` for structured
|
|
445
509
|
A2A, or `ask(text)` for any compatible peer. Both wait within caller deadline;
|
|
446
510
|
remote input-required raises `ClarificationNeededError` with question, no
|
|
447
|
-
automatic back-and-forth.
|
|
511
|
+
automatic back-and-forth. Implemented (#87): `class Remote[N: str]` read from the
|
|
512
|
+
`Literal` (alias `type Research = Remote[Literal["research-agent"]]`; string form
|
|
513
|
+
fails mypy), `Runtime(directory=)`/`AgentApp(directory=)` (app-owned; no
|
|
514
|
+
directory -> construction `DefinitionError`), `Runtime.validate_remotes` at
|
|
515
|
+
startup, bound per run inside its deadline. `ask` sends via the SDK
|
|
516
|
+
`JsonRpcTransport` with the directory client to `interface_url` only,
|
|
517
|
+
`return_immediately` then `GetTask` polling (0.25 s -> 1 s), per-request
|
|
518
|
+
`A2A-Version`/timeout headers; deadline or cancellation sends best-effort
|
|
519
|
+
`CancelTask`.
|
|
520
|
+
Implemented (#88): `call(skill, /, *, output=None, **arguments)` checks the
|
|
521
|
+
card declares the skill-call extension and skill (else `RemoteAgentError`, no
|
|
522
|
+
send, no `ask` fallback), sends the M2 wire format with per-request
|
|
523
|
+
`A2A-Extensions`, reuses `ask`'s wait/cancel, decodes text or `{"value": ...}`
|
|
524
|
+
and validates `output` (`OutputValidationError`, no remote data).
|
|
525
|
+
Implemented (#90): `ask`/`call` take `max_total_tokens=` (default: all the run
|
|
526
|
+
has left), held atomically in the run's `RunAccounting` before sending and sent
|
|
527
|
+
as `agentframe.max_total_tokens` only to peers listing it in `params.context`
|
|
528
|
+
(older receivers reject unknown keys). Receiver uses min(own, incoming). The
|
|
529
|
+
task's usage snapshot `total_tokens` replaces the hold, even if higher;
|
|
530
|
+
non-advertising peers hold nothing and make usage unknown (`None`). Over the
|
|
531
|
+
remaining budget -> `TokenLimitExceededError` before sending (default-ceiling
|
|
532
|
+
message says to pass `max_total_tokens` per call for fan-out).
|
|
533
|
+
Implemented (#92): `remotes={name: Service(credential=...)}` on
|
|
534
|
+
`Runtime`/`AgentApp` (same rule as `services=`); `OutboundCredential` protocol
|
|
535
|
+
`async headers()` + `satisfies(scheme)`, built-ins `APIKeyCredential(key,
|
|
536
|
+
header="X-API-Key")`, `EntraAppCredential(credential, scope=...)`. Headers per
|
|
537
|
+
request (send, polls, cancel) to `interface_url` only; no redirects. Startup:
|
|
538
|
+
card security must be met by the entry, else `DefinitionError`; open cards need
|
|
539
|
+
none. Implemented (#93): `OnBehalfOf(scope=...)` entries; credential on
|
|
540
|
+
inbound `EntraIDAuth(client_id=audience, client_credential=secret|cert bytes|
|
|
541
|
+
assertion func)`; delegated tokens (`scp`, not `idtyp=app`) kept privately as
|
|
542
|
+
`VerifiedCaller.user_assertion`; one azure `OnBehalfOfCredential` per run.
|
|
543
|
+
Non-Entra host/no credential -> startup `DefinitionError`; no user (app-only,
|
|
544
|
+
local run) -> `PermissionDeniedError`; failed exchange -> `AuthenticationError`;
|
|
545
|
+
never a `Service` fallback. Opt-in `entra` OBO test uses two registrations.
|
|
546
|
+
`ClarificationNeededError(question, task_id, context_id)` fails a hosted
|
|
547
|
+
orchestrator task. See `docs/design/discovery.md` and `docs/api/discovery.md`.
|
|
448
548
|
|
|
449
549
|
Plan cross-hop verified identity/delegation without authority amplification,
|
|
450
550
|
permissions, deadlines, remaining token allowance and trace/correlation;
|
|
@@ -460,18 +560,41 @@ reservations. Default max 5 remote hops, excess fails. These controls use the
|
|
|
460
560
|
same A2A extension; detailed config/wire/usage trust remains open, not base
|
|
461
561
|
protocol fields or hard billing guarantees.
|
|
462
562
|
No orchestration helpers in the first multi-agent release: plain await,
|
|
463
|
-
asyncio.TaskGroup and directory.find.
|
|
563
|
+
asyncio.TaskGroup and directory.find. M10 (0.3.0) adds opt-in remote skills as model
|
|
564
|
+
tools and checked plans (`docs/guides/orchestration.md`); plain await stays
|
|
565
|
+
the default. Later optional `Remote[ResearchAgent]`
|
|
464
566
|
typed proxy always uses structured selection, never prompt routing. Prove two or more
|
|
465
567
|
independently deployed AgentFrame agents, an orchestrator discovering/calling a
|
|
466
568
|
specialist with propagated context, and non-AgentFrame A2A client/server interop.
|
|
467
569
|
Development support starts with running N agents locally, then container
|
|
468
570
|
packaging; Foundry/Kubernetes templates are later. M2 `agentframe run module:create_app`
|
|
469
571
|
serves the app's own configured `AgentApp` (`--dev module:Class` is localhost-only
|
|
470
|
-
anonymous; Uvicorn is the `server` extra).
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
572
|
+
anonymous; Uvicorn is the `server` extra). Implemented (#95): `agentframe dev`
|
|
573
|
+
reads agentframe.yaml (`agents: {name: {app: module:create_app, port}}`,
|
|
574
|
+
`project.py`), starts each as `python -m agentframe run` on 127.0.0.1 in file
|
|
575
|
+
order after the previous `/ready`, writes `.agentframe/agents.yaml` (name/url
|
|
576
|
+
only, self-gitignored), generates one random key per agent per session (an
|
|
577
|
+
agent calls others with its own key, verified as its name), passes keys only
|
|
578
|
+
via child env (`AGENTFRAME_DEV`, `AGENTFRAME_PUBLIC_URL`,
|
|
579
|
+
`AGENTFRAME_DEV_REGISTRY`, `AGENTFRAME_DEV_API_KEYS`,
|
|
580
|
+
`AGENTFRAME_DEV_REMOTE_KEYS`), never disk/logs; optional
|
|
581
|
+
`AGENTFRAME_DEV_CLIENT_KEY` is caller `developer`. Factories call
|
|
582
|
+
`dev_settings()` (refuses without `AGENTFRAME_DEV=1`; directory has its own
|
|
583
|
+
http client; reads `AGENTFRAME_ALLOW_HTTP_HOSTS`). Output prefixed
|
|
584
|
+
`[agent-name]`, agents log INFO; failures stop all and exit 1; Ctrl+C sends
|
|
585
|
+
one SIGTERM (children in own session), kills after 35 s; a client key with
|
|
586
|
+
`,`/`=` is refused. Implemented (#96): `agentframe compose [--config]
|
|
587
|
+
[--force]` (`compose.py`) writes development `compose.yaml` (one service per
|
|
588
|
+
agent, `agentframe run APP --host 0.0.0.0 --port P`, `127.0.0.1:P:P`, `/ready`
|
|
589
|
+
healthcheck, depends on earlier agents healthy; env = dev contract with
|
|
590
|
+
`AGENTFRAME_PUBLIC_URL=http://name:P`, `AGENTFRAME_AGENTS` (read by
|
|
591
|
+
`dev_settings()` as an `EnvironmentAgentRegistry`), `AGENTFRAME_DEV=1`,
|
|
592
|
+
`AGENTFRAME_ALLOW_HTTP_HOSTS`=service names; keys only
|
|
593
|
+
`${NAME_API_KEY:?...}`/`${AGENTFRAME_DEV_CLIENT_KEY:?...}` from user `.env`)
|
|
594
|
+
and, only if missing, a `Dockerfile` (digest-pinned `python:3.13-slim`,
|
|
595
|
+
`dist/*.whl`, `USER 10001:10001`); `--force` overwrites only `compose.yaml`.
|
|
596
|
+
Golden files in `tests/unit/golden/`; opt-in `docker` test
|
|
597
|
+
(`AGENTFRAME_TEST_DOCKER=1`, skipped without a running Docker).
|
|
475
598
|
No hosting platform is implied. See `docs/guides/development.md`.
|
|
476
599
|
|
|
477
600
|
### Initial release boundaries
|
|
@@ -504,11 +627,19 @@ A2A failures use safe failed/rejected states as appropriate; no raw provider
|
|
|
504
627
|
exception, stack trace or secret goes to callers. Log diagnostics with redaction:
|
|
505
628
|
failed runs log ID, class and safe message; skill/tool/router tracebacks stay in
|
|
506
629
|
operator logs with the ID, so authors keep secrets out of exception messages.
|
|
507
|
-
`tests/integration/test_hardening.py` is the M7 end-to-end acceptance suite
|
|
630
|
+
`tests/integration/test_hardening.py` is the M7 end-to-end acceptance suite;
|
|
631
|
+
`tests/integration/test_multi_agent_release.py` is M8+'s, running
|
|
632
|
+
`examples/multi_agent` as separate `agentframe run` processes;
|
|
633
|
+
`tests/integration/test_orchestration_release.py` is M10's (#176), running its
|
|
634
|
+
research, writer and planner agents, the plain SDK peer and a registry-wide
|
|
635
|
+
coordinator (`tests/support/release_targets.py`) as separate processes with a
|
|
636
|
+
scripted planning model, plus the planner evaluation.
|
|
508
637
|
Network host examples must include clearly labeled application-supplied
|
|
509
638
|
development authentication/authorization placeholders where appropriate;
|
|
510
639
|
loopback/omission is not access policy or a production-safe default.
|
|
511
|
-
M8+ adds `
|
|
640
|
+
M8+ adds `RemoteAgentError` (#84; failures caused by another agent, optional
|
|
641
|
+
`task_id`/`task_state`) and `ClarificationNeededError` under
|
|
642
|
+
`AgentFrameError`; local client
|
|
512
643
|
input-required question is not a failed remote task or durable resumption.
|
|
513
644
|
|
|
514
645
|
Use explicit model selection, finite execution limits, validated inputs/outputs,
|
|
@@ -570,11 +701,12 @@ remain open; tracing/accounting/enforcement work independently. See
|
|
|
570
701
|
|
|
571
702
|
Read `README.md` and `docs/README.md` first. Keep `docs/roadmap.md`, the
|
|
572
703
|
guides (`docs/guides/annotations.md`, `agent-examples.md`, `limits.md`,
|
|
573
|
-
`authorization.md`, `development.md`) and the design docs
|
|
704
|
+
`authorization.md`, `development.md`, `evaluation.md`, `orchestration.md`) and the design docs
|
|
574
705
|
(`docs/design/base-classes.md`, `tracing.md`, `mcp-skills.md`,
|
|
575
|
-
`prompt-safeguarding.md`, `discovery.md`, `streaming.md`
|
|
576
|
-
discovery/streaming API pages and
|
|
577
|
-
confirmed product direction and
|
|
706
|
+
`prompt-safeguarding.md`, `discovery.md`, `streaming.md`, `evaluation.md`,
|
|
707
|
+
`orchestration.md`) consistent, including discovery/streaming API pages and
|
|
708
|
+
navigation. Preserve the distinction between confirmed product direction and
|
|
709
|
+
illustrative API details.
|
|
578
710
|
|
|
579
711
|
Maintain `docs/api/README.md` and its linked surface reference pages alongside
|
|
580
712
|
those design documents. Give every proposed decorator, class, and known public
|