agenticstar-platform 3.2.0__tar.gz → 3.2.3__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.
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/PKG-INFO +165 -6
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/README.md +164 -5
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/__init__.py +1 -1
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/events/handlers.py +37 -4
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/runner.py +3 -1
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/storage/base.py +51 -7
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/storage/s3.py +21 -8
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/workflow/child.py +10 -4
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/workflow/context.py +46 -2
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/workflow/envelope.py +60 -6
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/workflow/runner.py +39 -3
- agenticstar_platform-3.2.3/agenticstar_platform/workflow/testing.py +449 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/docs/examples/workflow_reply_agent.py +42 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/pyproject.toml +1 -1
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/events/test_handler_type_routing.py +60 -3
- agenticstar_platform-3.2.3/tests/events/test_notify_token.py +101 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/runner/test_marketplace_runner_started_fence.py +21 -0
- agenticstar_platform-3.2.3/tests/storage/test_s3_credential.py +178 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/workflow/agent_fixtures.py +87 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/workflow/test_child_failure_summary.py +9 -0
- agenticstar_platform-3.2.3/tests/workflow/test_workflow_incomplete.py +322 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/workflow/test_workflow_runner.py +14 -8
- agenticstar_platform-3.2.3/tests/workflow/test_workflow_testing.py +229 -0
- agenticstar_platform-3.2.0/.gitignore +0 -270
- agenticstar_platform-3.2.0/tests/workflow/fake_runtime.py +0 -267
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/LICENSE +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/_config_utils.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/audit/ROW_HASH_SPEC.md +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/audit/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/audit/action_audit.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/audit/guardrail_alerts.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/audit/row_hash_fixture.json +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/auth/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/auth/client.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/auth/config.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/auth/exceptions.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/auth/models.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/common/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/common/context_manager.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/common/secrets.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/common/validation.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/api_manager.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/completion_report.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/config.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/config_access.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/data_access.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/execution_access.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/factory.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/manager.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/pod_runtime.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/started_fence.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/telemetry_access.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/db/wire_types.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/events/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/events/emitter.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/events/models.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/events/types.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/lab/README.md +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/lab/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/lab/__main__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/lab/checks.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/lab/docker-compose.yml +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/lab/doctor.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/lab/lab_config.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/lab/offline_embedding.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/lab/run_lab.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/lab/seed.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/memory/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/memory/semantic.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/metering/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/metering/meter.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/policy/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/policy/internal_operations.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/policy/model.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/rag/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/rag/base.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/rag/embedding.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/rag/qdrant_manager.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/runtime.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/security/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/security/aws.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/security/azure.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/security/base.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/security/content_safety_validator.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/security/factory.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/security/gcp.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/storage/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/storage/azure.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/storage/gcs.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/storage/paths.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/workflow/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/workflow/canonical.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/workflow/errors.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/workflow/files.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/workflow/runtime_client.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/workflow/schema.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/docs/agenticstar_platform.html +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/docs/examples/workflow_mock_send_agent.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/docs/index.html +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/docs/search.js +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/audit/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/audit/test_action_audit_30.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/audit/test_row_hash_fixture.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/auth/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/auth/test_auth_type_bearer_only.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/auth/test_get_user_path_encoding.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/auth/test_mcp_tokens_expiry.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/auth/test_mcp_tokens_rejected.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/db/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/db/test_api_manager_drain_and_headers.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/db/test_completion_report.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/db/test_data_access_identifier_validation.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/db/test_manager_execute_query_dispatch.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/db/test_telemetry_tools_used_contract.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/db/test_wire_param_types.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/events/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/lab/test_lab_contract.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/lab/test_lab_docker.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/memory/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/memory/test_semantic_converter_base_url.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/metering/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/metering/test_meter_cache_split.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/policy/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/policy/test_a2a_connection_rule.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/policy/test_decision_layer.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/policy/test_evaluate_decision_table.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/policy/test_policy_model.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/policy/test_scoped_forbid.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/rag/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/rag/test_embedding_dimensions.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/rag/test_qdrant_error_hierarchy.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/rag/test_qdrant_get_statistics.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/runner/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/runner/test_marketplace_runner_contract.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/runner/test_marketplace_runner_db_fallback.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/security/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/security/test_azure_connect_retry.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/security/test_azure_prompt_shield_documents.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/security/test_factory_vertex_ai_safety.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/security/test_gcp_vertex_ai_safety.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/storage/__init__.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/storage/test_azure_credential.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/test_lazy_import_contract.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/test_readme_quickstart.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/test_storage_provider_extra_contract.py +0 -0
- {agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/tests/workflow/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agenticstar-platform
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.3
|
|
4
4
|
Summary: AGENTICSTAR Platform SDK - Enterprise AI Agent Infrastructure
|
|
5
5
|
Project-URL: Homepage, https://developers.fd.agenticstar.tm.softbank.jp/
|
|
6
6
|
Project-URL: Documentation, https://developers.fd.agenticstar.tm.softbank.jp/
|
|
@@ -224,6 +224,7 @@ Environment variable contract:
|
|
|
224
224
|
| `REQUEST_SOURCE` / `AGENT_ID` | Same as above (optional) | — |
|
|
225
225
|
| `DB_HOST` / `DB_PORT` / `DB_DATABASE` / `DB_USER` / `DB_PASSWORD` | Env var settings at agent registration (`PostgreSQLConfig.from_env()` contract) | ✅ |
|
|
226
226
|
| `WEBHOOK_URL` | Env var settings at agent registration | ✅ |
|
|
227
|
+
| `ASTER_NOTIFY_TOKEN` | Injected by the Marketplace executor for each execution (SDK >= 3.2.2 sends it as `Authorization: Bearer` on the webhook notification) | — |
|
|
227
228
|
|
|
228
229
|
Terminal event rules:
|
|
229
230
|
|
|
@@ -235,7 +236,8 @@ Terminal event rules:
|
|
|
235
236
|
If you need the low-level API (to compose handlers yourself), pass
|
|
236
237
|
`create_marketplace_handler(data_access, webhook_url, user_id, conversation_id, message_id)`
|
|
237
238
|
(a composite handler for DB persistence + webhook notification; requires the `[db]` + `[webhook]`
|
|
238
|
-
extras) directly to `EventEmitter`, as before.
|
|
239
|
+
extras) directly to `EventEmitter`, as before. Without a `token_provider`, it sends the
|
|
240
|
+
`ASTER_NOTIFY_TOKEN` env var as `Authorization: Bearer` when it is set (SDK >= 3.2.2).
|
|
239
241
|
|
|
240
242
|
### 2.4 Report completion for a cycle execution (SDK >= 3.0.14, `mp-chat/1`)
|
|
241
243
|
|
|
@@ -471,6 +473,24 @@ config = AzureBlobConfig.from_dict({
|
|
|
471
473
|
client = AzureBlobStorageClient(config)
|
|
472
474
|
```
|
|
473
475
|
|
|
476
|
+
S3 without access keys (3.2.3): leave `aws_access_key_id` and `aws_secret_access_key` both out (or
|
|
477
|
+
empty). The client then passes no keys and lets boto3 find the credentials with its default
|
|
478
|
+
credential chain (for example IRSA on EKS, environment variables, `~/.aws` files, EKS Pod Identity
|
|
479
|
+
or an EC2 instance role; boto3 decides which one is used first). This is what an EKS Pod with IRSA
|
|
480
|
+
needs; do not also give that Pod `AWS_ACCESS_KEY_ID` in its env, which boto3 checks before IRSA.
|
|
481
|
+
The role needs S3 access to the bucket. Give both keys or neither: only one of them raises
|
|
482
|
+
`StorageConfigError`.
|
|
483
|
+
|
|
484
|
+
```python
|
|
485
|
+
from agenticstar_platform.storage import S3StorageClient, S3Config
|
|
486
|
+
|
|
487
|
+
config = S3Config.from_dict({
|
|
488
|
+
"bucket_name": "your-bucket",
|
|
489
|
+
"region_name": "us-east-1",
|
|
490
|
+
})
|
|
491
|
+
client = S3StorageClient(config)
|
|
492
|
+
```
|
|
493
|
+
|
|
474
494
|
### Telemetry / LLM Usage Tracking (Marketplace)
|
|
475
495
|
|
|
476
496
|
`TelemetryAccess` (under `db` module) writes records to the `ai_telemetry` table. **Unknown fields are stored in the `metadata` jsonb column automatically** — no schema migration is required to add new tracking dimensions.
|
|
@@ -687,7 +707,9 @@ What `context` provides: correlation (`execution_id` / `run_id` / `operation_key
|
|
|
687
707
|
do not start an external write without that acknowledgement), `is_cancel_requested()` /
|
|
688
708
|
`ensure_can_act()` / `deadline_remaining()`, `skip(reason)` (a step with nothing to do: `no_target` /
|
|
689
709
|
`not_applicable` / `nothing_to_do` → `skipped`), `policy_unavailable()` (the policy could not be
|
|
690
|
-
checked before any external action → `skipped/policy_unavailable`), `
|
|
710
|
+
checked before any external action → `skipped/policy_unavailable`), `incomplete(reason, comment=None)` (SDK ≥ 3.2.1:
|
|
711
|
+
the step could not be completed and running it again would not help → `incomplete/<reason>`; see below),
|
|
712
|
+
`log(message)` (written to the runner's
|
|
691
713
|
log; `run()` sends SDK logs at INFO to stderr when the process has not configured logging),
|
|
692
714
|
`gate_decision` (SDK ≥ 3.0.9: the review decision that started this run — `None` unless the run follows a
|
|
693
715
|
review; otherwise a read-only mapping `{gate_id, decision, decided_by, note, decided_at}` where `decision` is
|
|
@@ -730,11 +752,47 @@ async def run(context):
|
|
|
730
752
|
...
|
|
731
753
|
```
|
|
732
754
|
|
|
755
|
+
**Ending a step as not completed** (SDK ≥ 3.2.1). When your agent cannot complete the step and running it again would
|
|
756
|
+
give the same result — the instructions are missing, a setting is wrong — call `context.incomplete(reason, comment)` and
|
|
757
|
+
return. The platform does not retry the step automatically; it asks a person to check it and shows the reason in the
|
|
758
|
+
execution record. A platform that reads the end-of-run report (below) also shows the comment there; Marketplace 3.2.0
|
|
759
|
+
does not show the comment.
|
|
760
|
+
|
|
761
|
+
```python
|
|
762
|
+
async def run(context):
|
|
763
|
+
instructions = (context.work_dir / "instructions.md").read_text(encoding="utf-8")
|
|
764
|
+
if not instructions.strip():
|
|
765
|
+
await context.incomplete("missing_instructions",
|
|
766
|
+
comment="instructions.md is empty. Write the instructions and run the step again.")
|
|
767
|
+
return
|
|
768
|
+
...
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
- `reason` is a reason code with the same rules as `report_completion()` of cycle executions: lowercase snake_case of at
|
|
772
|
+
most 32 characters (`-` and spaces become `_`, upper case becomes lower case). Any other value (a sentence, an exception
|
|
773
|
+
string) becomes `incomplete` and a warning is logged
|
|
774
|
+
- `comment` (optional) is a short explanation for the person who checks the step. It is cut at 2,048 characters (counted
|
|
775
|
+
as UTF-16 code units, like JavaScript). Do not put secrets or personal data in it
|
|
776
|
+
- Declare once. A second call is not recorded (the first one is kept and the runner logs a warning). An exception after
|
|
777
|
+
the declaration still ends the step as `incomplete`
|
|
778
|
+
- An audit persistence failure, cancellation, the deadline, the execution being closed elsewhere, a pod stop signal and
|
|
779
|
+
a denied tool call decide the outcome before the declaration
|
|
780
|
+
- For a failure that may go away on its own (a timeout of an external service, a rate limit), raise an exception
|
|
781
|
+
instead: the platform retries `failed/agent_error` (up to its retry limit) when the contract's effect mode is
|
|
782
|
+
`read_only` or `idempotent_write` and the effects are known
|
|
783
|
+
|
|
784
|
+
The completion then carries an **end-of-run report**, `completion_report`, in the same form as the platform's own agents:
|
|
785
|
+
`{"completed": false, "reason_code": ..., "comment": ...}`. For `incomplete` the comment is yours (no `comment` key when
|
|
786
|
+
you gave none); for an exception (`failed/agent_error`) the comment is the cause chain the runner writes to stderr —
|
|
787
|
+
class names, the SDK's error code, the HTTP status and the destination host name only, never messages, URLs or tokens.
|
|
788
|
+
Other outcomes carry no report. A platform that does not read the report yet keeps the completion and drops the report.
|
|
789
|
+
|
|
733
790
|
The outcome describes how the run ended, with 7 values (`completed` / `incomplete` / `failed` /
|
|
734
791
|
`timeout` / `stopped` / `denied` / `skipped`). **Success means the agent ran to completion**: the agent
|
|
735
792
|
function returns normally → `completed/completed`, unless an audit persistence failure, a denied tool
|
|
736
|
-
call, an invalid declared output, a skip or a missing required output decides otherwise (failed writes,
|
|
737
|
-
unobserved effects or zero observations do not lower the outcome);
|
|
793
|
+
call, a declared `incomplete`, an invalid declared output, a skip or a missing required output decides otherwise (failed writes,
|
|
794
|
+
unobserved effects or zero observations do not lower the outcome); `context.incomplete(reason)` → `incomplete/<reason>`;
|
|
795
|
+
an exception → `failed/agent_error`; cancellation →
|
|
738
796
|
`stopped/cancelled`; deadline → `timeout/execution_timeout`; pod stop signal → `failed/runner_stopped`;
|
|
739
797
|
a call reported with `audit.tool_denied` → `denied`.
|
|
740
798
|
What was written is kept in `counts` / `tools` and `had_mutating_success` (true = success observed /
|
|
@@ -743,6 +801,83 @@ automatically and go to a human (effects that already happened are never undone)
|
|
|
743
801
|
source distribution: `docs/examples/workflow_reply_agent.py` (drafting a reply) /
|
|
744
802
|
`workflow_mock_send_agent.py` (a mock send).
|
|
745
803
|
|
|
804
|
+
**Testing an agent without ASTER** (SDK ≥ 3.2.1). `agenticstar_platform.workflow.testing.FakeRuntime` answers the
|
|
805
|
+
platform's runtime API in memory. Give it your contract, the step's parameters, the input files, the connection tokens,
|
|
806
|
+
the effect mode and the deadline, run one step with `arun(...)`, then read what the runner saved. With this layout:
|
|
807
|
+
|
|
808
|
+
```text
|
|
809
|
+
my_project/
|
|
810
|
+
my_agent/__init__.py (empty)
|
|
811
|
+
my_agent/main.py (your agent)
|
|
812
|
+
try_it.py (the script below)
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
```python
|
|
816
|
+
# my_agent/main.py
|
|
817
|
+
async def run(context):
|
|
818
|
+
instructions = (context.work_dir / "instructions.md").read_text(encoding="utf-8")
|
|
819
|
+
(context.output_dir / "reply.md").write_text(f"# Reply\n\n{instructions}", encoding="utf-8")
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
```python
|
|
823
|
+
# try_it.py
|
|
824
|
+
import asyncio
|
|
825
|
+
import tempfile
|
|
826
|
+
|
|
827
|
+
from agenticstar_platform.workflow import arun
|
|
828
|
+
from agenticstar_platform.workflow.testing import FakeRuntime
|
|
829
|
+
|
|
830
|
+
CONTRACT = {
|
|
831
|
+
"runtime_protocol": "mp-workflow/1", "effect_mode": "read_only",
|
|
832
|
+
"files": [{"name": "instructions", "path": "instructions.md", "format": "markdown", "required": True}],
|
|
833
|
+
"outputs": [{"name": "reply", "path": "reply.md", "format": "markdown", "required": True}],
|
|
834
|
+
"limits": {"execution_timeout_seconds": 600},
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
async def main():
|
|
839
|
+
fake = FakeRuntime(
|
|
840
|
+
contract=CONTRACT,
|
|
841
|
+
parameters={"product_code": "P-100", "language": "en"},
|
|
842
|
+
inputs={"instructions": b"Thank the customer.\n"}, # by the name of a contract file
|
|
843
|
+
connections={"crm": "test-access-token"}, # slot -> token, or (token, expires_at)
|
|
844
|
+
deadline_seconds=600,
|
|
845
|
+
)
|
|
846
|
+
with tempfile.TemporaryDirectory() as workspace:
|
|
847
|
+
result = await arun("my_agent.main:run", env=fake.runner_env(), workspace=workspace, transport=fake.transport)
|
|
848
|
+
print(result.outcome, result.outcome_reason_code) # completed completed
|
|
849
|
+
print(fake.saved_artifacts()["reply"]["content"]) # the saved output, by its name
|
|
850
|
+
print([e["event_type"] for e in fake.saved_audit_events()]) # context.manifest x2, then your audit events
|
|
851
|
+
print(fake.saved_completion()["envelope"]) # the completion_envelope
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
asyncio.run(main())
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
```bash
|
|
858
|
+
cd my_project
|
|
859
|
+
PYTHONPATH="$PWD" python try_it.py
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
- The runner starts your entrypoint in a child process whose current directory is the work directory, so `my_agent.main`
|
|
863
|
+
must be importable from `PYTHONPATH` **as an absolute path** (`PYTHONPATH="$PWD"`, not `PYTHONPATH=.`: the child would
|
|
864
|
+
look for `.` in the work directory) or installed. In a test, set `os.environ["PYTHONPATH"]` to the absolute path before
|
|
865
|
+
calling `arun`
|
|
866
|
+
- The fake copies the current behaviour of the runtime API (only declared outputs are saved, a `completed` outcome needs
|
|
867
|
+
the required outputs, writes after cancellation, the end of the run or the deadline are refused except the audit
|
|
868
|
+
records of what the agent already did (`tool.effect` / `tool.denied`), ...). It **does not check the parameters
|
|
869
|
+
against `parameters_schema` or validate the contract**: the platform checks those before a run (the admin console's
|
|
870
|
+
check before registration and the executor). Parameters are passed to your agent as given
|
|
871
|
+
- **Supported surface**: the constructor arguments, `runner_env()`, `transport`, `saved_artifacts()` /
|
|
872
|
+
`saved_audit_events()` / `saved_completion()`, `sample_contract()` / `sample_parameters()`, the constants
|
|
873
|
+
`EXECUTION_ID` / `TOKEN` / `BASE_URL`, and the attributes that simulate the platform, which you can change before or
|
|
874
|
+
during a run: `contract` (a copy of the one you passed; later requests see your changes), `cancel_requested_at` (an ISO time = cancellation
|
|
875
|
+
was requested), `run_closed`, `deadline_passed`, `gate_decision`, `start_input`, `fail_audit_types`,
|
|
876
|
+
`fail_upload_times`, `fail_completion_times`, `fail_download_times` (see the module's docstring). Everything else is
|
|
877
|
+
internal and may change
|
|
878
|
+
- Without arguments the fake uses the contract and parameters of `docs/examples/workflow_reply_agent.py`; run
|
|
879
|
+
`python docs/examples/workflow_reply_agent.py` (source distribution) to see one step end to end
|
|
880
|
+
|
|
746
881
|
### Policy Module — `agenticstar_platform.policy` (SDK ≥ 1.0.0a1)
|
|
747
882
|
|
|
748
883
|
Pure computation (no I/O, no agent framework): decide **allow / forbid** for a tool call from a two-layer policy.
|
|
@@ -993,6 +1128,30 @@ See the [developer portal](https://developers.fd.agenticstar.tm.softbank.jp/) fo
|
|
|
993
1128
|
|
|
994
1129
|
## Changelog
|
|
995
1130
|
|
|
1131
|
+
### 3.2.3 (2026-11-04) — storage: S3 without access keys (IRSA) / events: a failed run ends the chat message
|
|
1132
|
+
|
|
1133
|
+
3.2.2 was not published to PyPI; 3.2.3 includes its change (the notify token below).
|
|
1134
|
+
|
|
1135
|
+
- **`S3StorageClient` works without access keys.** Leave `aws_access_key_id` and `aws_secret_access_key` both out (or empty) and the client passes no keys and lets boto3 find the credentials with its default credential chain (for example IRSA on EKS with `AWS_ROLE_ARN` + `AWS_WEB_IDENTITY_TOKEN_FILE`, environment variables, `~/.aws` files, EKS Pod Identity or an EC2 instance role; boto3 decides the order). Before, the client raised `StorageConfigError: S3 requires aws_access_key_id and aws_secret_access_key` on an EKS runner Pod that has only IRSA. Giving only one of the two keys still raises `StorageConfigError` (it is a configuration mistake, and the client does not silently fall back to other credentials). Both keys work as before, exactly as given (a non-blank key is not stripped); an empty or whitespace-only key, including a `SecretStr`, counts as not given. With no keys the client is created even when boto3 finds no credentials; the first call then fails (for example `object_exists()` returns `False`). `S3Config` keeps its field order, so positional construction is unchanged; `S3Config.from_dict` no longer requires the two keys.
|
|
1136
|
+
- **A failed run ends the chat message.** `create_marketplace_handler` (and so `run_marketplace_agent`) now sends `COMPLETION_FAILURE` with `finish_reason: "stop"`, the same as the platform's own agent worker. The chat front ends a message only on `"stop"`; with the previous `"error"` the failure text was added but the message kept showing as in progress. The failure is told by the message text, as before. `WebhookEventHandler` used on its own keeps `"error"` by default, so a receiver of your own that tells failures by `"error"` is unchanged; the new argument `failure_finish_reason="stop"` sends what the chat front expects. If you pointed `create_marketplace_handler` at a receiver of your own that needs `"error"`, build `WebhookEventHandler` yourself instead.
|
|
1137
|
+
- docs: "Ending a step as not completed" now says that the execution record shows the reason, and that the comment is shown only by a platform that reads the end-of-run report (Marketplace 3.2.0 does not show it). In 3.2.1 and 3.2.2 that section said the record shows the comment. The SDK's behavior is unchanged.
|
|
1138
|
+
|
|
1139
|
+
### 3.2.2 (2026-10-30) — events: the webhook notification carries the execution's notify token (`ASTER_NOTIFY_TOKEN`)
|
|
1140
|
+
|
|
1141
|
+
- **`create_marketplace_handler(...)` sends `Authorization: Bearer <token>` on the webhook notification when the `ASTER_NOTIFY_TOKEN` env var is set.** The Marketplace executor issues this token for each execution and passes it to the agent Pod; the platform checks it when it receives the notification. Without a `token_provider` argument, the handler reads the env var each time it sends. When the env var is missing or empty, no `Authorization` header is sent, as before. A `token_provider` you pass is used as before, and the env var is not read. `run_marketplace_agent` uses this default, so a runner agent sends the token without code changes.
|
|
1142
|
+
- `WebhookEventHandler` used on its own does not read `ASTER_NOTIFY_TOKEN`; as before, it sends an `Authorization` header only when you give one (through its `token_provider` or `headers`).
|
|
1143
|
+
- To use it, rebuild the agent image with this SDK.
|
|
1144
|
+
|
|
1145
|
+
### 3.2.1 (2026-10-28) — workflow: end a step as not completed (`context.incomplete`) with an end-of-run report / a fake runtime for testing (`agenticstar_platform.workflow.testing`)
|
|
1146
|
+
|
|
1147
|
+
- **New `WorkflowContext.incomplete(reason, comment=None)`.** An agent that cannot complete its step, where running it again would give the same result (missing instructions, a wrong setting), ends the step as `incomplete` with `reason` as the reason code. The platform does not retry it automatically and asks a person to check it. `reason` follows the rules of `report_completion()` (lowercase snake_case of at most 32 characters; any other value becomes `incomplete` with a warning); `comment` is cut at 2,048 UTF-16 code units. The declaration comes after an audit persistence failure, cancellation, the deadline, the execution being closed elsewhere, a pod stop signal and a denied tool call, and before an exception (an exception after the declaration still ends as `incomplete`), an invalid output, a skip and a missing required output. A second declaration is not recorded. See "Ending a step as not completed" in the Workflow Runner section.
|
|
1148
|
+
- **The completion carries an end-of-run report** (`completion_report`: `completed: false`, `reason_code`, `comment`) for `incomplete` (the agent's comment) and for an agent exception, `failed/agent_error` (the redacted cause chain the child already writes to stderr since 3.1.3: class names, the SDK's error code, the HTTP status and the host name; at most 2,048 UTF-16 code units, also with `ASTER_WORKFLOW_DEBUG_TRACEBACK=1`). Other outcomes carry no report, so their completion is the same as in 3.2. A platform that does not read the report yet keeps the completion and drops the report. A `comment` that is not a string (an exception, for example) is left out with a warning, so its message never reaches the report.
|
|
1149
|
+
- **The cause chain shows an `error_code` only in the SDK's own form** (upper-case snake_case of at most 64 characters, such as `REQUEST_ERROR`), in stderr and in the report. An SDK exception that agent code created with another value no longer shows that value.
|
|
1150
|
+
- **New `agenticstar_platform.workflow.testing`**: `FakeRuntime`, an in-memory copy of the platform's runtime API for testing an agent without ASTER. It takes the contract, parameters, input files, connection tokens, effect mode, deadline and instructions as arguments, and `saved_artifacts()` / `saved_audit_events()` / `saved_completion()` read what the runner saved. It does not check the parameters or the contract (the platform checks them before a run). Like the platform, it accepts the audit records of what the agent already did (`tool.effect` / `tool.denied`) after cancellation, the end of the run or the deadline, and reports the end of the run in the context's `cancel_requested_at`. The supported surface (constructor arguments, `runner_env()`, `transport`, the `saved_*()` readers and the listed simulation attributes) is described in the module's docstring; everything else is internal. The SDK's own tests now use it. `import agenticstar_platform.workflow` does not import it.
|
|
1151
|
+
- The sample `docs/examples/workflow_reply_agent.py` ends as `incomplete/missing_instructions` when the instructions are empty, and running the file runs one step against `FakeRuntime`.
|
|
1152
|
+
- `build_envelope(...)` accepts an optional `completion_report`. Other public functions of the runner and the context are unchanged.
|
|
1153
|
+
- To use it, rebuild the agent image with this SDK.
|
|
1154
|
+
|
|
996
1155
|
### 3.2.0 (2026-10-26) — auth: the `api_key` authentication mode (`X-Internal-API-Key` header) is removed
|
|
997
1156
|
|
|
998
1157
|
The version follows the platform release (3.2.0).
|
|
@@ -1429,4 +1588,4 @@ Marketplace SDK reliability fixes (surfaced while building agents from the guide
|
|
|
1429
1588
|
|
|
1430
1589
|
## Version
|
|
1431
1590
|
|
|
1432
|
-
3.2.
|
|
1591
|
+
3.2.3
|
|
@@ -143,6 +143,7 @@ Environment variable contract:
|
|
|
143
143
|
| `REQUEST_SOURCE` / `AGENT_ID` | Same as above (optional) | — |
|
|
144
144
|
| `DB_HOST` / `DB_PORT` / `DB_DATABASE` / `DB_USER` / `DB_PASSWORD` | Env var settings at agent registration (`PostgreSQLConfig.from_env()` contract) | ✅ |
|
|
145
145
|
| `WEBHOOK_URL` | Env var settings at agent registration | ✅ |
|
|
146
|
+
| `ASTER_NOTIFY_TOKEN` | Injected by the Marketplace executor for each execution (SDK >= 3.2.2 sends it as `Authorization: Bearer` on the webhook notification) | — |
|
|
146
147
|
|
|
147
148
|
Terminal event rules:
|
|
148
149
|
|
|
@@ -154,7 +155,8 @@ Terminal event rules:
|
|
|
154
155
|
If you need the low-level API (to compose handlers yourself), pass
|
|
155
156
|
`create_marketplace_handler(data_access, webhook_url, user_id, conversation_id, message_id)`
|
|
156
157
|
(a composite handler for DB persistence + webhook notification; requires the `[db]` + `[webhook]`
|
|
157
|
-
extras) directly to `EventEmitter`, as before.
|
|
158
|
+
extras) directly to `EventEmitter`, as before. Without a `token_provider`, it sends the
|
|
159
|
+
`ASTER_NOTIFY_TOKEN` env var as `Authorization: Bearer` when it is set (SDK >= 3.2.2).
|
|
158
160
|
|
|
159
161
|
### 2.4 Report completion for a cycle execution (SDK >= 3.0.14, `mp-chat/1`)
|
|
160
162
|
|
|
@@ -390,6 +392,24 @@ config = AzureBlobConfig.from_dict({
|
|
|
390
392
|
client = AzureBlobStorageClient(config)
|
|
391
393
|
```
|
|
392
394
|
|
|
395
|
+
S3 without access keys (3.2.3): leave `aws_access_key_id` and `aws_secret_access_key` both out (or
|
|
396
|
+
empty). The client then passes no keys and lets boto3 find the credentials with its default
|
|
397
|
+
credential chain (for example IRSA on EKS, environment variables, `~/.aws` files, EKS Pod Identity
|
|
398
|
+
or an EC2 instance role; boto3 decides which one is used first). This is what an EKS Pod with IRSA
|
|
399
|
+
needs; do not also give that Pod `AWS_ACCESS_KEY_ID` in its env, which boto3 checks before IRSA.
|
|
400
|
+
The role needs S3 access to the bucket. Give both keys or neither: only one of them raises
|
|
401
|
+
`StorageConfigError`.
|
|
402
|
+
|
|
403
|
+
```python
|
|
404
|
+
from agenticstar_platform.storage import S3StorageClient, S3Config
|
|
405
|
+
|
|
406
|
+
config = S3Config.from_dict({
|
|
407
|
+
"bucket_name": "your-bucket",
|
|
408
|
+
"region_name": "us-east-1",
|
|
409
|
+
})
|
|
410
|
+
client = S3StorageClient(config)
|
|
411
|
+
```
|
|
412
|
+
|
|
393
413
|
### Telemetry / LLM Usage Tracking (Marketplace)
|
|
394
414
|
|
|
395
415
|
`TelemetryAccess` (under `db` module) writes records to the `ai_telemetry` table. **Unknown fields are stored in the `metadata` jsonb column automatically** — no schema migration is required to add new tracking dimensions.
|
|
@@ -606,7 +626,9 @@ What `context` provides: correlation (`execution_id` / `run_id` / `operation_key
|
|
|
606
626
|
do not start an external write without that acknowledgement), `is_cancel_requested()` /
|
|
607
627
|
`ensure_can_act()` / `deadline_remaining()`, `skip(reason)` (a step with nothing to do: `no_target` /
|
|
608
628
|
`not_applicable` / `nothing_to_do` → `skipped`), `policy_unavailable()` (the policy could not be
|
|
609
|
-
checked before any external action → `skipped/policy_unavailable`), `
|
|
629
|
+
checked before any external action → `skipped/policy_unavailable`), `incomplete(reason, comment=None)` (SDK ≥ 3.2.1:
|
|
630
|
+
the step could not be completed and running it again would not help → `incomplete/<reason>`; see below),
|
|
631
|
+
`log(message)` (written to the runner's
|
|
610
632
|
log; `run()` sends SDK logs at INFO to stderr when the process has not configured logging),
|
|
611
633
|
`gate_decision` (SDK ≥ 3.0.9: the review decision that started this run — `None` unless the run follows a
|
|
612
634
|
review; otherwise a read-only mapping `{gate_id, decision, decided_by, note, decided_at}` where `decision` is
|
|
@@ -649,11 +671,47 @@ async def run(context):
|
|
|
649
671
|
...
|
|
650
672
|
```
|
|
651
673
|
|
|
674
|
+
**Ending a step as not completed** (SDK ≥ 3.2.1). When your agent cannot complete the step and running it again would
|
|
675
|
+
give the same result — the instructions are missing, a setting is wrong — call `context.incomplete(reason, comment)` and
|
|
676
|
+
return. The platform does not retry the step automatically; it asks a person to check it and shows the reason in the
|
|
677
|
+
execution record. A platform that reads the end-of-run report (below) also shows the comment there; Marketplace 3.2.0
|
|
678
|
+
does not show the comment.
|
|
679
|
+
|
|
680
|
+
```python
|
|
681
|
+
async def run(context):
|
|
682
|
+
instructions = (context.work_dir / "instructions.md").read_text(encoding="utf-8")
|
|
683
|
+
if not instructions.strip():
|
|
684
|
+
await context.incomplete("missing_instructions",
|
|
685
|
+
comment="instructions.md is empty. Write the instructions and run the step again.")
|
|
686
|
+
return
|
|
687
|
+
...
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
- `reason` is a reason code with the same rules as `report_completion()` of cycle executions: lowercase snake_case of at
|
|
691
|
+
most 32 characters (`-` and spaces become `_`, upper case becomes lower case). Any other value (a sentence, an exception
|
|
692
|
+
string) becomes `incomplete` and a warning is logged
|
|
693
|
+
- `comment` (optional) is a short explanation for the person who checks the step. It is cut at 2,048 characters (counted
|
|
694
|
+
as UTF-16 code units, like JavaScript). Do not put secrets or personal data in it
|
|
695
|
+
- Declare once. A second call is not recorded (the first one is kept and the runner logs a warning). An exception after
|
|
696
|
+
the declaration still ends the step as `incomplete`
|
|
697
|
+
- An audit persistence failure, cancellation, the deadline, the execution being closed elsewhere, a pod stop signal and
|
|
698
|
+
a denied tool call decide the outcome before the declaration
|
|
699
|
+
- For a failure that may go away on its own (a timeout of an external service, a rate limit), raise an exception
|
|
700
|
+
instead: the platform retries `failed/agent_error` (up to its retry limit) when the contract's effect mode is
|
|
701
|
+
`read_only` or `idempotent_write` and the effects are known
|
|
702
|
+
|
|
703
|
+
The completion then carries an **end-of-run report**, `completion_report`, in the same form as the platform's own agents:
|
|
704
|
+
`{"completed": false, "reason_code": ..., "comment": ...}`. For `incomplete` the comment is yours (no `comment` key when
|
|
705
|
+
you gave none); for an exception (`failed/agent_error`) the comment is the cause chain the runner writes to stderr —
|
|
706
|
+
class names, the SDK's error code, the HTTP status and the destination host name only, never messages, URLs or tokens.
|
|
707
|
+
Other outcomes carry no report. A platform that does not read the report yet keeps the completion and drops the report.
|
|
708
|
+
|
|
652
709
|
The outcome describes how the run ended, with 7 values (`completed` / `incomplete` / `failed` /
|
|
653
710
|
`timeout` / `stopped` / `denied` / `skipped`). **Success means the agent ran to completion**: the agent
|
|
654
711
|
function returns normally → `completed/completed`, unless an audit persistence failure, a denied tool
|
|
655
|
-
call, an invalid declared output, a skip or a missing required output decides otherwise (failed writes,
|
|
656
|
-
unobserved effects or zero observations do not lower the outcome);
|
|
712
|
+
call, a declared `incomplete`, an invalid declared output, a skip or a missing required output decides otherwise (failed writes,
|
|
713
|
+
unobserved effects or zero observations do not lower the outcome); `context.incomplete(reason)` → `incomplete/<reason>`;
|
|
714
|
+
an exception → `failed/agent_error`; cancellation →
|
|
657
715
|
`stopped/cancelled`; deadline → `timeout/execution_timeout`; pod stop signal → `failed/runner_stopped`;
|
|
658
716
|
a call reported with `audit.tool_denied` → `denied`.
|
|
659
717
|
What was written is kept in `counts` / `tools` and `had_mutating_success` (true = success observed /
|
|
@@ -662,6 +720,83 @@ automatically and go to a human (effects that already happened are never undone)
|
|
|
662
720
|
source distribution: `docs/examples/workflow_reply_agent.py` (drafting a reply) /
|
|
663
721
|
`workflow_mock_send_agent.py` (a mock send).
|
|
664
722
|
|
|
723
|
+
**Testing an agent without ASTER** (SDK ≥ 3.2.1). `agenticstar_platform.workflow.testing.FakeRuntime` answers the
|
|
724
|
+
platform's runtime API in memory. Give it your contract, the step's parameters, the input files, the connection tokens,
|
|
725
|
+
the effect mode and the deadline, run one step with `arun(...)`, then read what the runner saved. With this layout:
|
|
726
|
+
|
|
727
|
+
```text
|
|
728
|
+
my_project/
|
|
729
|
+
my_agent/__init__.py (empty)
|
|
730
|
+
my_agent/main.py (your agent)
|
|
731
|
+
try_it.py (the script below)
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
```python
|
|
735
|
+
# my_agent/main.py
|
|
736
|
+
async def run(context):
|
|
737
|
+
instructions = (context.work_dir / "instructions.md").read_text(encoding="utf-8")
|
|
738
|
+
(context.output_dir / "reply.md").write_text(f"# Reply\n\n{instructions}", encoding="utf-8")
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
```python
|
|
742
|
+
# try_it.py
|
|
743
|
+
import asyncio
|
|
744
|
+
import tempfile
|
|
745
|
+
|
|
746
|
+
from agenticstar_platform.workflow import arun
|
|
747
|
+
from agenticstar_platform.workflow.testing import FakeRuntime
|
|
748
|
+
|
|
749
|
+
CONTRACT = {
|
|
750
|
+
"runtime_protocol": "mp-workflow/1", "effect_mode": "read_only",
|
|
751
|
+
"files": [{"name": "instructions", "path": "instructions.md", "format": "markdown", "required": True}],
|
|
752
|
+
"outputs": [{"name": "reply", "path": "reply.md", "format": "markdown", "required": True}],
|
|
753
|
+
"limits": {"execution_timeout_seconds": 600},
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
async def main():
|
|
758
|
+
fake = FakeRuntime(
|
|
759
|
+
contract=CONTRACT,
|
|
760
|
+
parameters={"product_code": "P-100", "language": "en"},
|
|
761
|
+
inputs={"instructions": b"Thank the customer.\n"}, # by the name of a contract file
|
|
762
|
+
connections={"crm": "test-access-token"}, # slot -> token, or (token, expires_at)
|
|
763
|
+
deadline_seconds=600,
|
|
764
|
+
)
|
|
765
|
+
with tempfile.TemporaryDirectory() as workspace:
|
|
766
|
+
result = await arun("my_agent.main:run", env=fake.runner_env(), workspace=workspace, transport=fake.transport)
|
|
767
|
+
print(result.outcome, result.outcome_reason_code) # completed completed
|
|
768
|
+
print(fake.saved_artifacts()["reply"]["content"]) # the saved output, by its name
|
|
769
|
+
print([e["event_type"] for e in fake.saved_audit_events()]) # context.manifest x2, then your audit events
|
|
770
|
+
print(fake.saved_completion()["envelope"]) # the completion_envelope
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
asyncio.run(main())
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
```bash
|
|
777
|
+
cd my_project
|
|
778
|
+
PYTHONPATH="$PWD" python try_it.py
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
- The runner starts your entrypoint in a child process whose current directory is the work directory, so `my_agent.main`
|
|
782
|
+
must be importable from `PYTHONPATH` **as an absolute path** (`PYTHONPATH="$PWD"`, not `PYTHONPATH=.`: the child would
|
|
783
|
+
look for `.` in the work directory) or installed. In a test, set `os.environ["PYTHONPATH"]` to the absolute path before
|
|
784
|
+
calling `arun`
|
|
785
|
+
- The fake copies the current behaviour of the runtime API (only declared outputs are saved, a `completed` outcome needs
|
|
786
|
+
the required outputs, writes after cancellation, the end of the run or the deadline are refused except the audit
|
|
787
|
+
records of what the agent already did (`tool.effect` / `tool.denied`), ...). It **does not check the parameters
|
|
788
|
+
against `parameters_schema` or validate the contract**: the platform checks those before a run (the admin console's
|
|
789
|
+
check before registration and the executor). Parameters are passed to your agent as given
|
|
790
|
+
- **Supported surface**: the constructor arguments, `runner_env()`, `transport`, `saved_artifacts()` /
|
|
791
|
+
`saved_audit_events()` / `saved_completion()`, `sample_contract()` / `sample_parameters()`, the constants
|
|
792
|
+
`EXECUTION_ID` / `TOKEN` / `BASE_URL`, and the attributes that simulate the platform, which you can change before or
|
|
793
|
+
during a run: `contract` (a copy of the one you passed; later requests see your changes), `cancel_requested_at` (an ISO time = cancellation
|
|
794
|
+
was requested), `run_closed`, `deadline_passed`, `gate_decision`, `start_input`, `fail_audit_types`,
|
|
795
|
+
`fail_upload_times`, `fail_completion_times`, `fail_download_times` (see the module's docstring). Everything else is
|
|
796
|
+
internal and may change
|
|
797
|
+
- Without arguments the fake uses the contract and parameters of `docs/examples/workflow_reply_agent.py`; run
|
|
798
|
+
`python docs/examples/workflow_reply_agent.py` (source distribution) to see one step end to end
|
|
799
|
+
|
|
665
800
|
### Policy Module — `agenticstar_platform.policy` (SDK ≥ 1.0.0a1)
|
|
666
801
|
|
|
667
802
|
Pure computation (no I/O, no agent framework): decide **allow / forbid** for a tool call from a two-layer policy.
|
|
@@ -912,6 +1047,30 @@ See the [developer portal](https://developers.fd.agenticstar.tm.softbank.jp/) fo
|
|
|
912
1047
|
|
|
913
1048
|
## Changelog
|
|
914
1049
|
|
|
1050
|
+
### 3.2.3 (2026-11-04) — storage: S3 without access keys (IRSA) / events: a failed run ends the chat message
|
|
1051
|
+
|
|
1052
|
+
3.2.2 was not published to PyPI; 3.2.3 includes its change (the notify token below).
|
|
1053
|
+
|
|
1054
|
+
- **`S3StorageClient` works without access keys.** Leave `aws_access_key_id` and `aws_secret_access_key` both out (or empty) and the client passes no keys and lets boto3 find the credentials with its default credential chain (for example IRSA on EKS with `AWS_ROLE_ARN` + `AWS_WEB_IDENTITY_TOKEN_FILE`, environment variables, `~/.aws` files, EKS Pod Identity or an EC2 instance role; boto3 decides the order). Before, the client raised `StorageConfigError: S3 requires aws_access_key_id and aws_secret_access_key` on an EKS runner Pod that has only IRSA. Giving only one of the two keys still raises `StorageConfigError` (it is a configuration mistake, and the client does not silently fall back to other credentials). Both keys work as before, exactly as given (a non-blank key is not stripped); an empty or whitespace-only key, including a `SecretStr`, counts as not given. With no keys the client is created even when boto3 finds no credentials; the first call then fails (for example `object_exists()` returns `False`). `S3Config` keeps its field order, so positional construction is unchanged; `S3Config.from_dict` no longer requires the two keys.
|
|
1055
|
+
- **A failed run ends the chat message.** `create_marketplace_handler` (and so `run_marketplace_agent`) now sends `COMPLETION_FAILURE` with `finish_reason: "stop"`, the same as the platform's own agent worker. The chat front ends a message only on `"stop"`; with the previous `"error"` the failure text was added but the message kept showing as in progress. The failure is told by the message text, as before. `WebhookEventHandler` used on its own keeps `"error"` by default, so a receiver of your own that tells failures by `"error"` is unchanged; the new argument `failure_finish_reason="stop"` sends what the chat front expects. If you pointed `create_marketplace_handler` at a receiver of your own that needs `"error"`, build `WebhookEventHandler` yourself instead.
|
|
1056
|
+
- docs: "Ending a step as not completed" now says that the execution record shows the reason, and that the comment is shown only by a platform that reads the end-of-run report (Marketplace 3.2.0 does not show it). In 3.2.1 and 3.2.2 that section said the record shows the comment. The SDK's behavior is unchanged.
|
|
1057
|
+
|
|
1058
|
+
### 3.2.2 (2026-10-30) — events: the webhook notification carries the execution's notify token (`ASTER_NOTIFY_TOKEN`)
|
|
1059
|
+
|
|
1060
|
+
- **`create_marketplace_handler(...)` sends `Authorization: Bearer <token>` on the webhook notification when the `ASTER_NOTIFY_TOKEN` env var is set.** The Marketplace executor issues this token for each execution and passes it to the agent Pod; the platform checks it when it receives the notification. Without a `token_provider` argument, the handler reads the env var each time it sends. When the env var is missing or empty, no `Authorization` header is sent, as before. A `token_provider` you pass is used as before, and the env var is not read. `run_marketplace_agent` uses this default, so a runner agent sends the token without code changes.
|
|
1061
|
+
- `WebhookEventHandler` used on its own does not read `ASTER_NOTIFY_TOKEN`; as before, it sends an `Authorization` header only when you give one (through its `token_provider` or `headers`).
|
|
1062
|
+
- To use it, rebuild the agent image with this SDK.
|
|
1063
|
+
|
|
1064
|
+
### 3.2.1 (2026-10-28) — workflow: end a step as not completed (`context.incomplete`) with an end-of-run report / a fake runtime for testing (`agenticstar_platform.workflow.testing`)
|
|
1065
|
+
|
|
1066
|
+
- **New `WorkflowContext.incomplete(reason, comment=None)`.** An agent that cannot complete its step, where running it again would give the same result (missing instructions, a wrong setting), ends the step as `incomplete` with `reason` as the reason code. The platform does not retry it automatically and asks a person to check it. `reason` follows the rules of `report_completion()` (lowercase snake_case of at most 32 characters; any other value becomes `incomplete` with a warning); `comment` is cut at 2,048 UTF-16 code units. The declaration comes after an audit persistence failure, cancellation, the deadline, the execution being closed elsewhere, a pod stop signal and a denied tool call, and before an exception (an exception after the declaration still ends as `incomplete`), an invalid output, a skip and a missing required output. A second declaration is not recorded. See "Ending a step as not completed" in the Workflow Runner section.
|
|
1067
|
+
- **The completion carries an end-of-run report** (`completion_report`: `completed: false`, `reason_code`, `comment`) for `incomplete` (the agent's comment) and for an agent exception, `failed/agent_error` (the redacted cause chain the child already writes to stderr since 3.1.3: class names, the SDK's error code, the HTTP status and the host name; at most 2,048 UTF-16 code units, also with `ASTER_WORKFLOW_DEBUG_TRACEBACK=1`). Other outcomes carry no report, so their completion is the same as in 3.2. A platform that does not read the report yet keeps the completion and drops the report. A `comment` that is not a string (an exception, for example) is left out with a warning, so its message never reaches the report.
|
|
1068
|
+
- **The cause chain shows an `error_code` only in the SDK's own form** (upper-case snake_case of at most 64 characters, such as `REQUEST_ERROR`), in stderr and in the report. An SDK exception that agent code created with another value no longer shows that value.
|
|
1069
|
+
- **New `agenticstar_platform.workflow.testing`**: `FakeRuntime`, an in-memory copy of the platform's runtime API for testing an agent without ASTER. It takes the contract, parameters, input files, connection tokens, effect mode, deadline and instructions as arguments, and `saved_artifacts()` / `saved_audit_events()` / `saved_completion()` read what the runner saved. It does not check the parameters or the contract (the platform checks them before a run). Like the platform, it accepts the audit records of what the agent already did (`tool.effect` / `tool.denied`) after cancellation, the end of the run or the deadline, and reports the end of the run in the context's `cancel_requested_at`. The supported surface (constructor arguments, `runner_env()`, `transport`, the `saved_*()` readers and the listed simulation attributes) is described in the module's docstring; everything else is internal. The SDK's own tests now use it. `import agenticstar_platform.workflow` does not import it.
|
|
1070
|
+
- The sample `docs/examples/workflow_reply_agent.py` ends as `incomplete/missing_instructions` when the instructions are empty, and running the file runs one step against `FakeRuntime`.
|
|
1071
|
+
- `build_envelope(...)` accepts an optional `completion_report`. Other public functions of the runner and the context are unchanged.
|
|
1072
|
+
- To use it, rebuild the agent image with this SDK.
|
|
1073
|
+
|
|
915
1074
|
### 3.2.0 (2026-10-26) — auth: the `api_key` authentication mode (`X-Internal-API-Key` header) is removed
|
|
916
1075
|
|
|
917
1076
|
The version follows the platform release (3.2.0).
|
|
@@ -1348,4 +1507,4 @@ Marketplace SDK reliability fixes (surfaced while building agents from the guide
|
|
|
1348
1507
|
|
|
1349
1508
|
## Version
|
|
1350
1509
|
|
|
1351
|
-
3.2.
|
|
1510
|
+
3.2.3
|
|
@@ -9,7 +9,7 @@ import importlib
|
|
|
9
9
|
import importlib.util
|
|
10
10
|
from typing import TYPE_CHECKING
|
|
11
11
|
|
|
12
|
-
__version__ = "3.2.
|
|
12
|
+
__version__ = "3.2.3"
|
|
13
13
|
|
|
14
14
|
# Common utilities are internal - not exported as public API
|
|
15
15
|
# Use agenticstar_platform.common for internal SDK development only
|
{agenticstar_platform-3.2.0 → agenticstar_platform-3.2.3}/agenticstar_platform/events/handlers.py
RENAMED
|
@@ -33,6 +33,7 @@ Example:
|
|
|
33
33
|
import asyncio
|
|
34
34
|
import json
|
|
35
35
|
import logging
|
|
36
|
+
import os
|
|
36
37
|
from typing import Any, Callable, Dict, List, Optional
|
|
37
38
|
|
|
38
39
|
from .types import EventType
|
|
@@ -249,6 +250,7 @@ class WebhookEventHandler:
|
|
|
249
250
|
chunk_type_map: Optional[Dict[EventType, str]] = None,
|
|
250
251
|
request_source: Optional[str] = None,
|
|
251
252
|
message_type_map: Optional[Dict[EventType, str]] = None,
|
|
253
|
+
failure_finish_reason: str = "error",
|
|
252
254
|
):
|
|
253
255
|
"""
|
|
254
256
|
WebhookEventHandlerを初期化
|
|
@@ -269,6 +271,10 @@ class WebhookEventHandler:
|
|
|
269
271
|
message_type_map: EventType→トップレベルtypeのカスタムマッピング
|
|
270
272
|
(オプション)。省略時は HITL系→"vnc_hitl_event"、
|
|
271
273
|
PROGRESS_MESSAGE→"progress_message" を切り替えるデフォルトを使用。
|
|
274
|
+
failure_finish_reason: COMPLETION_FAILURE の finish_reason(既定 "error"。3.2.3)。
|
|
275
|
+
AgenticStar のチャット画面(chatboardfront の監視)へ送るときは "stop" にする:
|
|
276
|
+
受信側は "stop" のときだけメッセージを終わらせ、"error" は読まない(本体の worker も
|
|
277
|
+
失敗を "stop" で送る)。create_marketplace_handler はこれを "stop" にして作る
|
|
272
278
|
|
|
273
279
|
Example:
|
|
274
280
|
>>> handler = WebhookEventHandler(
|
|
@@ -309,10 +315,10 @@ class WebhookEventHandler:
|
|
|
309
315
|
EventType.FINAL_RESULT: None,
|
|
310
316
|
}
|
|
311
317
|
|
|
312
|
-
# finish_reason
|
|
318
|
+
# finish_reasonマッピング(失敗の値は failure_finish_reason。既定 "error" は従来どおり)
|
|
313
319
|
self._finish_reason_map = {
|
|
314
320
|
EventType.COMPLETION_SUCCESS: "stop",
|
|
315
|
-
EventType.COMPLETION_FAILURE:
|
|
321
|
+
EventType.COMPLETION_FAILURE: failure_finish_reason,
|
|
316
322
|
}
|
|
317
323
|
|
|
318
324
|
logger.debug(
|
|
@@ -502,6 +508,20 @@ class CompositeEventHandler:
|
|
|
502
508
|
return None
|
|
503
509
|
|
|
504
510
|
|
|
511
|
+
# 完了の知らせ(/webhook/notify)に付ける実行ごとのトークンの env。
|
|
512
|
+
# Marketplace executor が実行ごとに発行し、会話の Pod に渡す。受信側(front の監視)が
|
|
513
|
+
# Authorization: Bearer で確かめる。
|
|
514
|
+
NOTIFY_TOKEN_ENV = "ASTER_NOTIFY_TOKEN"
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def _notify_token_from_env() -> Optional[str]:
|
|
518
|
+
"""env ASTER_NOTIFY_TOKEN から知らせのトークンを返す(無い・空なら None)
|
|
519
|
+
|
|
520
|
+
create_marketplace_handler の既定の token_provider。送るたびに env を読む。
|
|
521
|
+
"""
|
|
522
|
+
return os.environ.get(NOTIFY_TOKEN_ENV) or None
|
|
523
|
+
|
|
524
|
+
|
|
505
525
|
def create_marketplace_handler(
|
|
506
526
|
data_access: Any,
|
|
507
527
|
webhook_url: str,
|
|
@@ -522,12 +542,19 @@ def create_marketplace_handler(
|
|
|
522
542
|
user_id: ユーザーID
|
|
523
543
|
conversation_id: 会話ID
|
|
524
544
|
message_id: メッセージID
|
|
525
|
-
token_provider:
|
|
545
|
+
token_provider: 認証トークン取得関数(オプション)。
|
|
546
|
+
省略時(None)は env ASTER_NOTIFY_TOKEN を送るたびに読む既定の関数を使い、
|
|
547
|
+
値があれば Webhook に Authorization: Bearer <値> を付ける。env が無い・空なら付けない
|
|
548
|
+
(Marketplace executor が実行ごとに発行して Pod に渡すトークン。呼び出し側のコードは
|
|
549
|
+
変えなくてよい。SDK 3.2.2 から)。明示した場合はその関数だけを使い、env は読まない。
|
|
526
550
|
request_source: リクエスト発信元("internal" / "external")。
|
|
527
551
|
受信側で Progress SSE 配信 と 外部Webhook送信 の振り分けに使われる。
|
|
528
552
|
外部API経由(extapi)からの呼び出しでは "external" を指定すること。
|
|
529
553
|
通常はPod起動スクリプトで os.environ.get("REQUEST_SOURCE", "internal") を渡す。
|
|
530
554
|
|
|
555
|
+
失敗の完了(COMPLETION_FAILURE)は finish_reason "stop" で送る(3.2.3。チャット画面は "stop" で
|
|
556
|
+
メッセージを終わらせる。WebhookEventHandler の既定 "error" とは違う)。
|
|
557
|
+
|
|
531
558
|
Returns:
|
|
532
559
|
CompositeEventHandler: DB + Webhookの複合ハンドラー
|
|
533
560
|
|
|
@@ -561,8 +588,14 @@ def create_marketplace_handler(
|
|
|
561
588
|
webhook_url=webhook_url,
|
|
562
589
|
conversation_id=conversation_id,
|
|
563
590
|
message_id=message_id,
|
|
564
|
-
token_provider=
|
|
591
|
+
token_provider=(
|
|
592
|
+
token_provider if token_provider is not None else _notify_token_from_env
|
|
593
|
+
),
|
|
565
594
|
request_source=request_source,
|
|
595
|
+
# 失敗も "stop"(3.2.3): 受信側のチャット画面(chatboardfront の監視)は "stop" のときだけ
|
|
596
|
+
# メッセージを終わらせ、"error" は読まない。本体の worker も COMPLETION_FAILURE を "stop" で送る
|
|
597
|
+
# (src/subscribers/common.py の get_finish_reason)。失敗の中身は本文で伝わる
|
|
598
|
+
failure_finish_reason="stop",
|
|
566
599
|
)
|
|
567
600
|
|
|
568
601
|
return CompositeEventHandler([db_handler, webhook_handler])
|
|
@@ -67,7 +67,7 @@ from .db import DataAccess, PostgreSQLConfig, create_postgresql_manager
|
|
|
67
67
|
from .db.execution_access import ExecutionAccess
|
|
68
68
|
from .db.started_fence import StartedFenceTaken, take_started_fence
|
|
69
69
|
from .events import EventEmitter, EventType
|
|
70
|
-
from .events.handlers import create_marketplace_handler
|
|
70
|
+
from .events.handlers import NOTIFY_TOKEN_ENV, create_marketplace_handler
|
|
71
71
|
|
|
72
72
|
logger = logging.getLogger(__name__)
|
|
73
73
|
|
|
@@ -315,6 +315,8 @@ async def arun_marketplace_agent(
|
|
|
315
315
|
conversation_id=identity["CONVERSATION_ID"],
|
|
316
316
|
message_id=identity["MESSAGE_ID"],
|
|
317
317
|
request_source=request_source or env.get("REQUEST_SOURCE", "internal"),
|
|
318
|
+
# 完了の知らせの実行ごとのトークン(3.2.2)。identity・WEBHOOK_URL と同じく渡された env から読む
|
|
319
|
+
token_provider=lambda: env.get(NOTIFY_TOKEN_ENV) or None,
|
|
318
320
|
)
|
|
319
321
|
|
|
320
322
|
execution_id = identity["EXECUTION_ID"]
|