From 3b901303fa95a122bead322f43938f402ba3602d Mon Sep 17 00:00:00 2001 From: Marvin-Cypher Date: Mon, 1 Jun 2026 18:39:25 -0700 Subject: [PATCH] feat: add agent-governance-toolkit template --- templates/config.json | 24 +- templates/icons/agent-governance-toolkit.svg | 48 +++ .../agent-governance-toolkit/README.md | 128 +++++++ .../docker-compose.yml | 358 ++++++++++++++++++ 4 files changed, 557 insertions(+), 1 deletion(-) create mode 100644 templates/icons/agent-governance-toolkit.svg create mode 100644 templates/prebuilt/agent-governance-toolkit/README.md create mode 100644 templates/prebuilt/agent-governance-toolkit/docker-compose.yml diff --git a/templates/config.json b/templates/config.json index 75b9a2f5..3fab7a35 100644 --- a/templates/config.json +++ b/templates/config.json @@ -4782,5 +4782,27 @@ "diskSize": 10 }, "tags": ["Media & Design", "AI Agents", "Developer Tools"] -} +}, +{ + "id": "agent-governance-toolkit", + "name": "microsoft/agent-governance-toolkit", + "description": "AI Agent Governance Toolkit — Policy enforcement, zero-trust identity, execution sandboxing, and reliability engineering for autonomous AI agents. Covers 10/10 OWASP Agentic Top 10.", + "repo": "https://github.com/Phala-Network/phala-cloud/tree/main/templates/prebuilt/agent-governance-toolkit", + "author": "microsoft", + "icon": "agent-governance-toolkit.svg", + "envs": [ + { + "key": "AGT_PACKAGE_VERSION", + "required": false, + "default": "3.7.0", + "description": "Published agent-governance-toolkit Python package version installed by the verifier at container startup." + } + ], + "defaultResource": { + "vCPU": 1, + "memory": 2048, + "diskSize": 20 + }, + "tags": ["AI Agents", "Developer Tools"] + } ] diff --git a/templates/icons/agent-governance-toolkit.svg b/templates/icons/agent-governance-toolkit.svg new file mode 100644 index 00000000..8844ef1e --- /dev/null +++ b/templates/icons/agent-governance-toolkit.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/prebuilt/agent-governance-toolkit/README.md b/templates/prebuilt/agent-governance-toolkit/README.md new file mode 100644 index 00000000..a6a9604b --- /dev/null +++ b/templates/prebuilt/agent-governance-toolkit/README.md @@ -0,0 +1,128 @@ +# microsoft/agent-governance-toolkit + +Deploy a CPU-safe Agent Governance Toolkit package verifier on Phala Cloud. + +## Metadata + +- Template id: `agent-governance-toolkit` +- Display name: `microsoft/agent-governance-toolkit` +- Category: AI Agents & Developer Tools +- Upstream repository: https://github.com/microsoft/agent-governance-toolkit +- Upstream documentation: https://microsoft.github.io/agent-governance-toolkit/ +- Python package: `agent-governance-toolkit[full]` +- Default package version: `3.7.0` +- Icon source: upstream project icon, `docs/assets/agent-governance-toolkit.svg` +- Upstream author: Microsoft, via the `microsoft/agent-governance-toolkit` GitHub repository + +## Overview + +Agent Governance Toolkit is Microsoft's public-preview toolkit for policy enforcement, zero-trust identity, execution sandboxing, auditability, compliance verification, and reliability controls for autonomous AI agents. The upstream README describes a Python-first quickstart with `pip install agent-governance-toolkit[full]`, `govern(...)` wrappers around tools, and CLI checks such as `agt verify` for OWASP Agentic Security Initiative coverage. + +This Phala Cloud template is a no-credential verifier, not a production agent service. It installs the real published Python package, imports `agentmesh.governance`, `agent_os.policies`, and `agent_compliance.cli.agt`, then exposes a deterministic HTTP smoke API. + +The `/demo` endpoint uses the real AGT `govern()` wrapper around a local Python tool, evaluates a YAML policy, allows a safe `read_file` action, blocks a destructive `delete_file` action, and returns compact audit hash-chain metadata. It does not call an LLM provider, download model weights, open browser authentication flows, require GPU access, or use external credentials. + +The upstream repository also includes a `docker-compose.yml`, but it is a development/test compose file with a local build context and bind-mounted workspace. This template avoids that shape so it is deployable on Phala Cloud. + +## Services + +- `app`: Internal Python HTTP server on port `8000`. At startup it installs `agent-governance-toolkit[full]` with `uv pip` and runs the deterministic verifier. +- `proxy`: Caddy reverse proxy listening on public port `8080` and forwarding to `app:8000`. + +## Environment Variables + +No credentials are required. + +| Variable | Required | Default | Description | +| --- | --- | --- | --- | +| `AGT_PACKAGE_VERSION` | No | `3.7.0` | Published `agent-governance-toolkit` version installed by the verifier at container startup. | + +## Deploy On Phala Cloud + +1. Deploy the `agent-governance-toolkit` template. +2. Keep the default CPU-only resources for this verifier. +3. Leave `AGT_PACKAGE_VERSION` at `3.7.0` unless you intentionally want to test another published package version. +4. Open `https:///healthz` after startup completes. + +The first startup downloads Python wheels from PyPI. The verifier path is local and deterministic after dependencies are installed. + +## Endpoints + +- `GET /healthz`: Reports package version, import checks, expected symbols, Python/runtime metadata, and no-LLM flags. +- `GET /demo`: Runs the deterministic AGT `govern()` policy enforcement demo and returns allow, deny, and audit integrity results. +- `GET /v1/models`: Returns an OpenAI-style metadata list for the local policy verifier. It is not a hosted model endpoint. +- `GET /upstream`: Returns upstream repository, documentation, package, icon attribution, runtime shape, and endpoint metadata. +- `GET /`: Returns a compact service index. + +Example: + +```bash +curl -fsS https:///healthz +curl -fsS https:///demo +curl -fsS https:///v1/models +curl -fsS https:///upstream +``` + +Expected `/demo` fields include: + +```json +{ + "ok": true, + "llm_provider_calls": false, + "model_downloaded": false, + "model_loaded": false, + "demo": { + "denied_call": { + "blocked": true, + "matched_rule": "block-destructive-actions" + }, + "audit": { + "entry_count": 2, + "integrity_ok": true + } + } +} +``` + +## Local Smoke Verification + +Run from the parent worktree: + +```bash +docker compose -f templates/prebuilt/agent-governance-toolkit/docker-compose.yml config >/tmp/agt-compose.out +docker compose -f templates/prebuilt/agent-governance-toolkit/docker-compose.yml up -d +curl -fsS http://localhost:8080/healthz +curl -fsS http://localhost:8080/demo +curl -fsS http://localhost:8080/v1/models +curl -fsS http://localhost:8080/upstream +docker compose -f templates/prebuilt/agent-governance-toolkit/docker-compose.yml down +``` + +If local port `8080` is already in use, temporarily change only the host side of the proxy mapping, for example `18080:80`, then use `http://localhost:18080/healthz`. + +Template validation commands from the parent worktree: + +```bash +python3 templates/validate.py +git diff --check origin/main...HEAD +docker compose -f templates/prebuilt/agent-governance-toolkit/docker-compose.yml config >/dev/null +``` + +## Production Notes + +- This template verifies package installation and core governance primitives. It does not run a full production agent, sidecar fleet, dashboard, or managed policy service. +- Add authentication, authorization, rate limiting, request logging, and network restrictions before exposing governance results for private workloads. +- Real deployments should wrap actual framework tools or agent actions with AGT policy checks, configure identity/trust material, and store audit logs in durable infrastructure. +- Do not put provider API keys, bearer tokens, private keys, OTPs, or passwords in the compose file. Use Phala Cloud secret handling for production credentials. +- The default verifier is unauthenticated and should remain a smoke endpoint unless adapted behind an authenticated gateway. +- The demo does not invoke model providers, download model weights, request GPU access, use privileged mode, mount host paths, use `env_file`, access the Docker socket, or use host networking. +- The upstream project is public preview. Pin `AGT_PACKAGE_VERSION` for reproducible deployments and test policy behavior before changing versions. + +## Upstream Attribution + +This template installs and imports the real Agent Governance Toolkit Python package from Microsoft: + +- Repository: https://github.com/microsoft/agent-governance-toolkit +- Documentation: https://microsoft.github.io/agent-governance-toolkit/ +- Package index: https://pypi.org/project/agent-governance-toolkit/ +- Icon: https://github.com/microsoft/agent-governance-toolkit/blob/main/docs/assets/agent-governance-toolkit.svg diff --git a/templates/prebuilt/agent-governance-toolkit/docker-compose.yml b/templates/prebuilt/agent-governance-toolkit/docker-compose.yml new file mode 100644 index 00000000..eb076414 --- /dev/null +++ b/templates/prebuilt/agent-governance-toolkit/docker-compose.yml @@ -0,0 +1,358 @@ +services: + app: + image: ghcr.io/astral-sh/uv:python3.12-bookworm-slim + restart: unless-stopped + init: true + expose: + - "8000" + environment: + AGT_PACKAGE_VERSION: ${AGT_PACKAGE_VERSION:-3.7.0} + APP_PORT: "8000" + PIP_DISABLE_PIP_VERSION_CHECK: "1" + PIP_NO_CACHE_DIR: "1" + PIP_ROOT_USER_ACTION: ignore + PYTHONDONTWRITEBYTECODE: "1" + PYTHONUNBUFFERED: "1" + UV_SYSTEM_PYTHON: "1" + configs: + - source: agt_demo_app + target: /opt/agt-demo/main.py + command: + - /bin/sh + - -lc + - | + set -eu + uv pip install --system --no-cache "agent-governance-toolkit[full]==$${AGT_PACKAGE_VERSION}" + exec python /opt/agt-demo/main.py + healthcheck: + test: + [ + "CMD-SHELL", + "python -c \"import os, sys, urllib.request; port = os.environ.get('APP_PORT', '8000'); response = urllib.request.urlopen(f'http://127.0.0.1:{port}/healthz', timeout=5); sys.exit(0 if response.status == 200 else 1)\"", + ] + interval: 30s + timeout: 10s + retries: 10 + start_period: 300s + networks: + - internal + + proxy: + image: caddy:2.8 + restart: unless-stopped + ports: + - "8080:80" + configs: + - source: caddy_config + target: /etc/caddy/Caddyfile + depends_on: + app: + condition: service_healthy + networks: + - internal + +configs: + caddy_config: + content: | + :80 { + encode zstd gzip + header { + X-Content-Type-Options "nosniff" + Referrer-Policy "no-referrer" + -Server + } + reverse_proxy app:8000 + } + + agt_demo_app: + content: | + import importlib + import importlib.metadata + import json + import os + import platform + import sys + import time + from http import HTTPStatus + from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer + from urllib.parse import urlparse + + + SERVICE = "agent-governance-toolkit-demo" + UPSTREAM = "https://github.com/microsoft/agent-governance-toolkit" + DOCUMENTATION = "https://microsoft.github.io/agent-governance-toolkit/" + PACKAGE_NAME = "agent-governance-toolkit" + REQUESTED_VERSION = os.environ.get("AGT_PACKAGE_VERSION", "3.7.0") + STARTED_AT = time.time() + ENDPOINTS = ["/healthz", "/demo", "/v1/models", "/upstream"] + + POLICY_YAML = """ + apiVersion: governance.toolkit/v1 + name: phala-agt-template-demo + default_action: allow + rules: + - name: block-destructive-actions + condition: "action.type in ['delete_file', 'drop_table', 'shell_exec']" + action: deny + description: "Destructive actions are blocked by deterministic policy" + priority: 100 + - name: require-review-for-email + condition: "action.type == 'send_email'" + action: require_approval + approvers: ["security-team"] + description: "Outbound email requires human approval in production" + priority: 50 + """ + + + def import_checks(): + status = { + "package": PACKAGE_NAME, + "requested_version": REQUESTED_VERSION, + "distribution_version": None, + "modules": {}, + "symbols": {}, + "ok": False, + "error": None, + } + try: + status["distribution_version"] = importlib.metadata.version(PACKAGE_NAME) + governance = importlib.import_module("agentmesh.governance") + policies = importlib.import_module("agent_os.policies") + cli = importlib.import_module("agent_compliance.cli.agt") + status["modules"] = { + "agentmesh.governance": True, + "agent_os.policies": True, + "agent_compliance.cli.agt": True, + } + status["symbols"] = { + "govern": hasattr(governance, "govern"), + "GovernanceDenied": hasattr(governance, "GovernanceDenied"), + "AuditLog": hasattr(governance, "AuditLog"), + "PolicyEvaluator": hasattr(policies, "PolicyEvaluator"), + "agt_verify_command": hasattr(cli, "verify"), + } + status["ok"] = all(status["modules"].values()) and all(status["symbols"].values()) + except Exception as exc: + status["error"] = f"{type(exc).__name__}: {exc}" + return status + + + IMPORT_STATUS = import_checks() + + + def governed_tool(action: str, resource: str, payload: dict | None = None): + return { + "status": "executed", + "action": action, + "resource": resource, + "payload": payload or {}, + } + + + def compact_audit_entry(entry): + data = getattr(entry, "data", {}) or {} + return { + "entry_id": getattr(entry, "entry_id", None), + "event_type": getattr(entry, "event_type", None), + "action": getattr(entry, "action", None), + "outcome": getattr(entry, "outcome", None), + "policy_decision": getattr(entry, "policy_decision", None), + "rule": data.get("rule") or getattr(entry, "matched_rule", None), + "reason": data.get("reason"), + "entry_hash": getattr(entry, "entry_hash", None), + "previous_hash": getattr(entry, "previous_hash", None), + } + + + def run_governance_demo(): + if not IMPORT_STATUS["ok"]: + raise RuntimeError(IMPORT_STATUS["error"] or "AGT imports are unavailable") + + from agentmesh.governance import GovernanceDenied, govern + + safe_tool = govern( + governed_tool, + policy=POLICY_YAML, + agent_id="did:phala:agt-demo", + audit=True, + ) + + allowed = safe_tool( + action="read_file", + resource="policy.yaml", + payload={"classification": "public"}, + ) + + denied = None + try: + safe_tool( + action="delete_file", + resource="/workspace/customer-data.db", + payload={"classification": "restricted"}, + ) + except GovernanceDenied as exc: + denied = { + "blocked": True, + "exception": type(exc).__name__, + "matched_rule": exc.decision.matched_rule, + "reason": exc.decision.reason, + } + + audit_entries = [] + integrity_ok = None + integrity_error = None + if safe_tool.audit_log is not None: + audit_entries = [compact_audit_entry(entry) for entry in safe_tool.audit_log.query()] + integrity_ok, integrity_error = safe_tool.audit_log.verify_integrity() + + return { + "policy": { + "name": "phala-agt-template-demo", + "default_action": "allow", + "rules": ["block-destructive-actions", "require-review-for-email"], + }, + "allowed_call": allowed, + "denied_call": denied, + "audit": { + "entry_count": len(audit_entries), + "integrity_ok": integrity_ok, + "integrity_error": integrity_error, + "entries": audit_entries, + }, + } + + + def base_payload(): + return { + "service": SERVICE, + "upstream": UPSTREAM, + "documentation": DOCUMENTATION, + "python": sys.version.split()[0], + "platform": platform.platform(), + "uptime_seconds": round(time.time() - STARTED_AT, 3), + "credentials_required": False, + "llm_provider_calls": False, + "model_downloaded": False, + "model_loaded": False, + "package": IMPORT_STATUS, + } + + + def response_body(path): + if path == "/healthz": + payload = base_payload() + payload["status"] = "ok" if IMPORT_STATUS["ok"] else "unhealthy" + return ( + HTTPStatus.OK if IMPORT_STATUS["ok"] else HTTPStatus.SERVICE_UNAVAILABLE, + payload, + ) + + if path == "/demo": + payload = base_payload() + payload.update( + { + "ok": IMPORT_STATUS["ok"], + "check": "AGT govern() policy enforcement with audit hash-chain verification", + } + ) + if not IMPORT_STATUS["ok"]: + return HTTPStatus.SERVICE_UNAVAILABLE, payload + try: + payload["demo"] = run_governance_demo() + except Exception as exc: + payload["ok"] = False + payload["error"] = f"{type(exc).__name__}: {exc}" + return HTTPStatus.INTERNAL_SERVER_ERROR, payload + return HTTPStatus.OK, payload + + if path == "/v1/models": + return HTTPStatus.OK, { + "object": "list", + "data": [ + { + "id": "agent-governance-toolkit/local-policy-verifier", + "object": "model", + "created": 0, + "owned_by": "microsoft", + "description": ( + "OpenAI-style metadata endpoint for the local deterministic " + "AGT verifier. No LLM is hosted or called." + ), + } + ], + "llm_provider_calls": False, + "model_loaded": False, + } + + if path == "/upstream": + return HTTPStatus.OK, { + "upstream": UPSTREAM, + "documentation": DOCUMENTATION, + "package_index": "https://pypi.org/project/agent-governance-toolkit/", + "icon_source": ( + "https://github.com/microsoft/agent-governance-toolkit/blob/main/" + "docs/assets/agent-governance-toolkit.svg" + ), + "default_demo_package": f"agent-governance-toolkit[full]=={REQUESTED_VERSION}", + "runtime_shape": "CPU-safe deterministic HTTP verifier", + "endpoints": ENDPOINTS, + } + + if path == "/": + payload = base_payload() + payload["endpoints"] = ENDPOINTS + return HTTPStatus.OK, payload + + return HTTPStatus.NOT_FOUND, { + "error": "not_found", + "endpoints": ENDPOINTS, + } + + + class Handler(BaseHTTPRequestHandler): + server_version = "agt-demo" + + def log_message(self, fmt, *args): + print( + json.dumps( + { + "ts": time.time(), + "client": self.client_address[0], + "request": self.requestline, + "message": fmt % args, + } + ), + flush=True, + ) + + def do_GET(self): + path = urlparse(self.path).path.rstrip("/") or "/" + status, payload = response_body(path) + body = json.dumps(payload, indent=2, sort_keys=True).encode("utf-8") + self.send_response(status) + self.send_header("Content-Type", "application/json; charset=utf-8") + self.send_header("Cache-Control", "no-store") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + + if __name__ == "__main__": + port = int(os.environ.get("APP_PORT", "8000")) + print( + json.dumps( + { + "event": "startup", + "port": port, + "package": IMPORT_STATUS, + "llm_provider_calls": False, + } + ), + flush=True, + ) + ThreadingHTTPServer(("0.0.0.0", port), Handler).serve_forever() + +networks: + internal: + driver: bridge