From 9a2e64285d47d0a333f5c12d3e6ce66cf298b27b Mon Sep 17 00:00:00 2001 From: a2a-platform Date: Mon, 13 Jul 2026 13:04:27 +0000 Subject: [PATCH] deploy --- .a2a/agent.dsl.json | 64 +++++++++++++++++++++++++++--------------- a2a.yaml | 2 +- agent.py | 68 ++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 104 insertions(+), 30 deletions(-) diff --git a/.a2a/agent.dsl.json b/.a2a/agent.dsl.json index 0784a66..2494f75 100644 --- a/.a2a/agent.dsl.json +++ b/.a2a/agent.dsl.json @@ -3,7 +3,7 @@ "language": "python", "name": "customer-integration-engineer", "description": "Guides and validates customer integrations from requirements through a tested handoff while keeping credentials and production changes under customer control.", - "version": "0.1.5", + "version": "0.1.6", "entrypoint": { "module": "agent", "class_name": "CustomerIntegrationEngineer", @@ -24,11 +24,15 @@ "max_retries": 0, "cost_class": "deterministic", "allow_scope_expansion": false, - "grant_mode": null, - "grant_allow_patterns": [], + "grant_mode": "read_write_overlay", + "grant_allow_patterns": [ + "outputs/integrations/**" + ], "grant_deny_patterns": [], - "grant_outputs_prefix": null, - "grant_write_prefixes": [], + "grant_outputs_prefix": "outputs/integrations/", + "grant_write_prefixes": [ + "outputs/integrations/" + ], "grant_ttl_seconds": null, "grant_run_timeout_seconds": null, "grant_approval_timeout_seconds": null, @@ -820,11 +824,15 @@ "max_retries": 0, "cost_class": "deterministic", "allow_scope_expansion": false, - "grant_mode": null, - "grant_allow_patterns": [], + "grant_mode": "read_write_overlay", + "grant_allow_patterns": [ + "outputs/integrations/**" + ], "grant_deny_patterns": [], - "grant_outputs_prefix": null, - "grant_write_prefixes": [], + "grant_outputs_prefix": "outputs/integrations/", + "grant_write_prefixes": [ + "outputs/integrations/" + ], "grant_ttl_seconds": null, "grant_run_timeout_seconds": null, "grant_approval_timeout_seconds": null, @@ -1637,11 +1645,15 @@ "max_retries": 0, "cost_class": "deterministic", "allow_scope_expansion": false, - "grant_mode": null, - "grant_allow_patterns": [], + "grant_mode": "read_write_overlay", + "grant_allow_patterns": [ + "outputs/integrations/**" + ], "grant_deny_patterns": [], - "grant_outputs_prefix": null, - "grant_write_prefixes": [], + "grant_outputs_prefix": "outputs/integrations/", + "grant_write_prefixes": [ + "outputs/integrations/" + ], "grant_ttl_seconds": null, "grant_run_timeout_seconds": null, "grant_approval_timeout_seconds": null, @@ -1987,11 +1999,15 @@ "max_retries": 0, "cost_class": "deterministic", "allow_scope_expansion": false, - "grant_mode": null, - "grant_allow_patterns": [], + "grant_mode": "read_write_overlay", + "grant_allow_patterns": [ + "outputs/integrations/**" + ], "grant_deny_patterns": [], - "grant_outputs_prefix": null, - "grant_write_prefixes": [], + "grant_outputs_prefix": "outputs/integrations/", + "grant_write_prefixes": [ + "outputs/integrations/" + ], "grant_ttl_seconds": null, "grant_run_timeout_seconds": null, "grant_approval_timeout_seconds": null, @@ -2496,11 +2512,15 @@ "max_retries": 0, "cost_class": "deterministic", "allow_scope_expansion": false, - "grant_mode": null, - "grant_allow_patterns": [], + "grant_mode": "read_write_overlay", + "grant_allow_patterns": [ + "outputs/integrations/**" + ], "grant_deny_patterns": [], - "grant_outputs_prefix": null, - "grant_write_prefixes": [], + "grant_outputs_prefix": "outputs/integrations/", + "grant_write_prefixes": [ + "outputs/integrations/" + ], "grant_ttl_seconds": null, "grant_run_timeout_seconds": null, "grant_approval_timeout_seconds": null, @@ -2968,7 +2988,7 @@ "source": "python-a2a-pack", "project_manifest": { "name": "customer-integration-engineer", - "version": "0.1.5", + "version": "0.1.6", "entrypoint": "agent:CustomerIntegrationEngineer" } } diff --git a/a2a.yaml b/a2a.yaml index aac123c..47f3154 100644 --- a/a2a.yaml +++ b/a2a.yaml @@ -1,5 +1,5 @@ name: customer-integration-engineer -version: 0.1.5 +version: 0.1.6 entrypoint: agent:CustomerIntegrationEngineer expose: public: false diff --git a/agent.py b/agent.py index 17a07c0..ccd296a 100644 --- a/agent.py +++ b/agent.py @@ -14,7 +14,6 @@ import ipaddress import json import re import socket -import time from datetime import UTC, datetime from typing import Any, Literal from urllib.parse import urlparse @@ -410,7 +409,7 @@ class CustomerIntegrationEngineer(A2AAgent[CustomerIntegrationEngineerConfig, No "Guides and validates customer integrations from requirements through a tested handoff while " "keeping credentials and production changes under customer control." ) - version = "0.1.5" + version = "0.1.6" config_model = CustomerIntegrationEngineerConfig auth_model = NoAuth @@ -440,7 +439,18 @@ class CustomerIntegrationEngineer(A2AAgent[CustomerIntegrationEngineerConfig, No ConsumerSetupField.config("ARGOCD_APP_REF", label="Argo CD app reference", description="Optional caller-owned Argo CD app reference.", required=False), ) - @a2a.tool(description="Capture requirements, produce architecture and field mapping artifacts", input_schema=_tool_input_schema(DesignIntegrationRequest), timeout_seconds=120, idempotent=True, max_retries=0, cost_class="deterministic") + @a2a.tool( + description="Capture requirements, produce architecture and field mapping artifacts", + input_schema=_tool_input_schema(DesignIntegrationRequest), + timeout_seconds=120, + idempotent=True, + max_retries=0, + cost_class="deterministic", + grant_mode="read_write_overlay", + grant_allow_patterns=("outputs/integrations/**",), + grant_outputs_prefix="outputs/integrations/", + grant_write_prefixes=("outputs/integrations/",), + ) async def design_integration(self, ctx: RunContext[NoAuth], request: DesignIntegrationRequest) -> DesignIntegrationResult: req = request.requirements.model_copy( update={"dry_run": _effective_dry_run(self, request.dry_run, request.requirements.dry_run)} @@ -478,7 +488,18 @@ class CustomerIntegrationEngineer(A2AAgent[CustomerIntegrationEngineerConfig, No required_setup=required_setup, ) - @a2a.tool(description="Generate a minimal workspace-contained connector scaffold with no deployment or repository mutation", input_schema=_tool_input_schema(GenerateConnectorRequest), timeout_seconds=120, idempotent=True, max_retries=0, cost_class="deterministic") + @a2a.tool( + description="Generate a minimal workspace-contained connector scaffold with no deployment or repository mutation", + input_schema=_tool_input_schema(GenerateConnectorRequest), + timeout_seconds=120, + idempotent=True, + max_retries=0, + cost_class="deterministic", + grant_mode="read_write_overlay", + grant_allow_patterns=("outputs/integrations/**",), + grant_outputs_prefix="outputs/integrations/", + grant_write_prefixes=("outputs/integrations/",), + ) async def generate_connector(self, ctx: RunContext[NoAuth], request: GenerateConnectorRequest) -> GenerateConnectorResult: req = request.requirements.model_copy( update={"dry_run": _effective_dry_run(self, request.dry_run, request.requirements.dry_run)} @@ -532,7 +553,18 @@ class CustomerIntegrationEngineer(A2AAgent[CustomerIntegrationEngineerConfig, No blocked_actions=blocked_actions, ) - @a2a.tool(description="Validate OpenAPI, JSON Schema, and webhook contracts with deterministic fixtures", input_schema=_tool_input_schema(ValidateContractRequest), timeout_seconds=120, idempotent=True, max_retries=0, cost_class="deterministic") + @a2a.tool( + description="Validate OpenAPI, JSON Schema, and webhook contracts with deterministic fixtures", + input_schema=_tool_input_schema(ValidateContractRequest), + timeout_seconds=120, + idempotent=True, + max_retries=0, + cost_class="deterministic", + grant_mode="read_write_overlay", + grant_allow_patterns=("outputs/integrations/**",), + grant_outputs_prefix="outputs/integrations/", + grant_write_prefixes=("outputs/integrations/",), + ) async def validate_contract(self, ctx: RunContext[NoAuth], request: ValidateContractRequest) -> ValidateContractResult: dry_run = _effective_dry_run(self, request.dry_run) audit = [_audit("contract_validation_started", request.integration_id, {"contracts": len(request.contracts), "dry_run": dry_run})] @@ -564,7 +596,18 @@ class CustomerIntegrationEngineer(A2AAgent[CustomerIntegrationEngineerConfig, No drift_detected=drift, ) - @a2a.tool(description="Run dry-run or allowlisted acceptance checks using endpoint metadata and secret references", input_schema=_tool_input_schema(RunAcceptanceRequest), timeout_seconds=180, idempotent=True, max_retries=0, cost_class="deterministic") + @a2a.tool( + description="Run dry-run or allowlisted acceptance checks using endpoint metadata and secret references", + input_schema=_tool_input_schema(RunAcceptanceRequest), + timeout_seconds=180, + idempotent=True, + max_retries=0, + cost_class="deterministic", + grant_mode="read_write_overlay", + grant_allow_patterns=("outputs/integrations/**",), + grant_outputs_prefix="outputs/integrations/", + grant_write_prefixes=("outputs/integrations/",), + ) async def run_acceptance(self, ctx: RunContext[NoAuth], request: RunAcceptanceRequest) -> RunAcceptanceResult: dry_run = _effective_dry_run(self, request.dry_run) live_network_block = _live_network_unavailable_reason(self) @@ -635,7 +678,18 @@ class CustomerIntegrationEngineer(A2AAgent[CustomerIntegrationEngineerConfig, No network_calls_made=network_calls, ) - @a2a.tool(description="Prepare rollout, rollback, monitoring, and operator handoff documentation with approval-gated delivery planning", input_schema=_tool_input_schema(PrepareHandoffRequest), timeout_seconds=120, idempotent=True, max_retries=0, cost_class="deterministic") + @a2a.tool( + description="Prepare rollout, rollback, monitoring, and operator handoff documentation with approval-gated delivery planning", + input_schema=_tool_input_schema(PrepareHandoffRequest), + timeout_seconds=120, + idempotent=True, + max_retries=0, + cost_class="deterministic", + grant_mode="read_write_overlay", + grant_allow_patterns=("outputs/integrations/**",), + grant_outputs_prefix="outputs/integrations/", + grant_write_prefixes=("outputs/integrations/",), + ) async def prepare_handoff(self, ctx: RunContext[NoAuth], request: PrepareHandoffRequest) -> PrepareHandoffResult: dry_run = _effective_dry_run(self, request.dry_run) audit = [_audit("handoff_started", request.integration_id, {"dry_run": dry_run, "delivery_actions": len(request.delivery_actions)})]