Skip to main content

foundry-agt

AGT 4.1 in-process message-policy and tool-governance middleware for Microsoft Agent Framework (MAF) agents on Foundry. Loads YAML policies (default / PII-deny, inbound message text only) into a PolicyEvaluator; AuditTrailMiddleware and GovernancePolicyMiddleware are always in the canonical policy path. CapabilityGuardMiddleware — the deterministic per-tool-call allow/deny gate — is added only when allowed_tools or denied_tools is configured. Exposes a tamper-evident AuditLog with integrity verification and CloudEvents export. `agt verify` is a toolkit self-assessment, not a certification. USE FOR: agent action/tool governance, AGT, agent-governance-toolkit, MAF middleware, capability allow/deny, policy enforcement, audit trail, deterministic tool gating, agt verify, agt doctor. DO NOT USE FOR: Foundry agent deployment (use foundry-hosted-agents), message/content moderation (use Azure AI Content Safety), eval scoring (use foundry-evals), telemetry pipeline wiring (use foundry-observability).

Jump to install

Source facts

Repository
aiappsgbb/awesome-gbb
Last source activity
September 5, 2026 at 12:18
Detected SKILL.md language
English
Stars
6
Forks
3

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
10 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
foundry-agt
description
AGT 4.1 in-process message-policy and tool-governance middleware for Microsoft Agent Framework (MAF) agents on Foundry. Loads YAML policies (default / PII-deny, inbound message text only) into a PolicyEvaluator; AuditTrailMiddleware and GovernancePolicyMiddleware are always in the canonical policy path. CapabilityGuardMiddleware — the deterministic per-tool-call allow/deny gate — is added only when allowed_tools or denied_tools is configured. Exposes a tamper-evident AuditLog with integrity verification and CloudEvents export. `agt verify` is a toolkit self-assessment, not a certification. USE FOR: agent action/tool governance, AGT, agent-governance-toolkit, MAF middleware, capability allow/deny, policy enforcement, audit trail, deterministic tool gating, agt verify, agt doctor. DO NOT USE FOR: Foundry agent deployment (use foundry-hosted-agents), message/content moderation (use Azure AI Content Safety), eval scoring (use foundry-evals), telemetry pipeline wiring (use foundry-observability).
metadata
{"version":"2.0.1"}
# foundry-agt — Microsoft Agent Governance Toolkit, in-process (Path A) > **Status:** AGT 4.1.0 (Public Preview, MIT) + selective Microsoft Agent > Framework (MAF) packages. Exact pinned versions, the released-source > SHA, and the executable validation script are the single source of > truth in [`references/upstream-pin.md`](references/upstream-pin.md) — > re-run its `validation.script` before trusting any re-pin (AGENTS.md > § 9). > > AGT 4.1 is Public Preview. `agt verify` is toolkit self-assessment, > not certification, an independent audit, or a guarantee that a > workload meets every organizational or regulatory control. --- ## Why action governance matters A system-prompt instruction like "never call `delete_account`" is a *request to the model*, not an enforcement point — a jailbroken or mis-routed turn can still emit the tool call. AGT moves that check out of the model and into **middleware that runs before the tool function executes**: `CapabilityGuardMiddleware` inspects the real `FunctionInvocationContext` for every tool invocation and decides allow/deny deterministically, in-process, before `call_next()` (the actual tool body) ever runs. A denied call raises `MiddlewareTermination` and the tool body never executes at all — this is proven locally by [`references/python/contract_probe.py`](references/python/contract_probe.py), not just asserted from upstream documentation. --- ## Scope & ownership For the complete per-agent adoption and release-evidence workflow, see [`foundry-agentops`](../foundry-agentops/SKILL.md). This skill remains authoritative for AGT policy authoring and in-process runtime governance; AgentOps aggregates evidence and never replaces those enforcement controls. | Concern | Owner | Notes | |---|---|---| | Action / tool-call plane — may the agent invoke this named tool at all? | **This skill (AGT)** | Deterministic, in-process, pre-execution by tool name. Argument validation remains the caller's / tool-body's responsibility. | | Message / token content — is this text safe to send or show? | [Azure AI Content Safety](https://learn.microsoft.com/azure/ai-services/content-safety/) | A different plane entirely; pair with AGT, don't substitute for it. | | Edge auth, rate limiting, product policy | APIM / gateway — see [`citadel-spoke-onboarding`](../citadel-spoke-onboarding/SKILL.md) | Gates the HTTP edge; AGT gates inside the tool loop. | | Network isolation (VNet, private endpoints) | [`foundry-vnet-deploy`](../foundry-vnet-deploy/SKILL.md) | Network plane, not policy plane. | | Quality / task-adherence evaluation | [`foundry-evals`](../foundry-evals/SKILL.md) | AGT governs the safety of actions, not answer quality. | | Telemetry plumbing (App Insights, OTel exporters) | [`foundry-observability`](../foundry-observability/SKILL.md) | AGT **emits** CloudEvents; this skill owns the pipe they flow through. | Any workload with both chat content and side-effecting tools needs Content Safety **and** AGT — never treat one as a stand-in for the other. --- ## When to use this skill - A Foundry hosted or custom agent, built on Microsoft Agent Framework, that calls one or more **side-effecting** tools (write / send / delete / transfer — not just read-only lookups). - You need a deterministic, pre-execution allow/deny decision that holds even when the model tries to route around it. - You need tamper-evident evidence, independent of what the model's own transcript claims: `AuditTrailMiddleware` always writes a hash-chained agent-invocation start/complete entry into `AuditLog` for every run. `CapabilityGuardMiddleware`, when explicitly configured with `allowed_tools` / `denied_tools`, additionally writes a tool-invoked or tool-blocked entry to the same `AuditLog` for every gated tool call — that per-tool coverage is not automatic. ## When NOT to use this skill - **Pure offline eval / batch scoring.** No runtime tool calls fire — use [`foundry-evals`](../foundry-evals/SKILL.md) instead. - **Content moderation only** (toxicity, self-harm, jailbreak detection at the message level). That's [Azure AI Content Safety](https://learn.microsoft.com/azure/ai-services/content-safety/)'s job, not AGT's. - **Read-only, single-tool agents** (e.g. a chat agent that only calls `web_search`). There's no destructive-action surface to gate yet; the policy/middleware ceremony isn't worth it until a second, write-capable tool shows up. - **You need a GA, SLA-backed governance product today.** AGT is **Public Preview** — production-quality and Microsoft-signed, but breaking changes remain possible before GA. --- ## Upstream sources - Repo: <https://github.com/microsoft/agent-governance-toolkit> - Release tag pinned here: <https://github.com/microsoft/agent-governance-toolkit/releases/tag/v4.1.0> - Docs site: <https://microsoft.github.io/agent-governance-toolkit> - `agent-governance-toolkit` on PyPI: <https://pypi.org/project/agent-governance-toolkit/> - `agent-framework-core` on PyPI: <https://pypi.org/project/agent-framework-core/> - `agent-framework-foundry` on PyPI: <https://pypi.org/project/agent-framework-foundry/> - `agent-framework-openai` on PyPI: <https://pypi.org/project/agent-framework-openai/> This skill is a thin wrapper — it does not re-document upstream. Follow a link rather than trust a paraphrase, and read [`references/upstream-pin.md`](references/upstream-pin.md) for the exact, live-re-verified API surface. --- ## Install (selective, bounded) Pin the specific sub-packages this skill actually imports — not the broad `agent-framework` meta-package: ```bash pip install \ "agent-governance-toolkit[full]~=4.1.0" \ "agent-framework-core~=1.13.0" \ "agent-framework-foundry~=1.10.4" \ "agent-framework-openai~=1.12.0" \ "azure-identity~=1.25.3" ``` --- ## Wiring snippet > **MUST:** Copy verbatim from > [`references/maf-middleware-snippet.py`](references/maf-middleware-snippet.py). > Do NOT redefine `build_governed_agent(...)` inline — the validator > enforces single-source-of-truth. That file is the canonical MAF > middleware wiring, re-verified live against AGT 4.1.0 + Agent > Framework Core 1.13.0. Drop `build_governed_agent(...)` into your hosted-agent module and pass it the chat client your project constructs (see "Foundry composition" below). ### Middleware factory stack `create_governance_middleware(...)` assembles two always-on middleware in this skill's canonical snippet and proved path, which passes `enable_rogue_detection=False`; a third middleware is conditional on caller-configured capability gating. `contract_probe.py::build_factory_stack` proves middleware-type *membership* for a configured stack — it does not assert ordering; `contract_probe.py::check_snippet_import` is the probe that proves the factory's `AuditTrail -> GovernancePolicy -> CapabilityGuard` order is preserved end-to-end through `build_governed_agent(...)`, alongside `allowed_tools=None` / `denied_tools=None` default (no-guard) semantics passthrough. 1. **`AuditTrailMiddleware`** *(always)* — hash-chains one agent-invocation start entry and one agent-invocation complete entry into `AuditLog` per run; it hooks the agent invocation, not individual tool calls. 2. **`GovernancePolicyMiddleware`** *(always)* — evaluates the loaded YAML policy set against a flat `{agent, message, timestamp, stream, message_count}` context built from the *message text*; ALLOW / DENY per message. It has no visibility into `tool_name` or `tool_args` — see "Policy YAML" below for what that means for policy authoring. 3. **`CapabilityGuardMiddleware`** *(conditional)* — the factory adds this middleware to the stack only when `allowed_tools` or `denied_tools` is not `None`; explicit allow/deny lists on `tool_name` are, in that configuration, the deterministic tool-action gate (not YAML policy). When configured, it also hash-chains a tool-invoked or tool-blocked entry into the same `AuditLog` for every gated tool call — in addition to the allow/deny gate itself. Both `allowed_tools=None` and `denied_tools=None` (the snippet's default) mean **no capability guard at all**: with no `CapabilityGuardMiddleware` in the stack, every tool call is allowed (nothing is left to deny it), and none of them get a tool-invoked or tool-blocked entry in `AuditLog` — tools still execute normally through the runtime's own dispatch, they are simply not guard-audited at the tool level. `AuditTrailMiddleware`'s agent-invocation start/complete entries still fire regardless, since that middleware is always present. Passing `allowed_tools=[]` is not the same as `None`: an empty list is not `None`, so it turns the guard on, and an empty allowlist matches no tool — deny-all. The canonical snippet, [`references/maf-middleware-snippet.py`](references/maf-middleware-snippet.py), passes `allowed_tools` / `denied_tools` straight through to the factory — never coerced with `or []` — so it preserves whichever of these the caller actually asked for. AGT 4.1's factory default for `enable_rogue_detection` is `True`; omitting the flag adds `RogueDetectionMiddleware` as a third unconditional member (fourth when a tool list is also configured — see the upstream pin's four-case table in [`references/upstream-pin.md`](references/upstream-pin.md)). The canonical snippet intentionally overrides this to `False` until the caller has established a capability profile to compare against. ### Policy YAML Two starter policies ship in [`references/policies/`](references/policies/): | File | Purpose | |---|---| | `default.yaml` | Conservative default — blocks destructive SQL / shell-exec patterns, caps message length | | `pii-deny.yaml` | Regex PII guardrail (SSN, credit card, IBAN) on **inbound message text only** | `pii-deny.yaml`'s `block-us-ssn` rule accepts hyphen, space, dot, or no separator at all between digit groups. That last, unseparated form is indistinguishable from any other standalone 9-digit number (order/invoice IDs). An ordinary hyphenated ZIP+4 also matches because the first separator is optional and the second accepts its hyphen, so it can false-positive/false-deny on either. This is not cosmetic: a deny terminates the message path (`GovernancePolicyMiddleware.process` raises `MiddlewareTermination` before the agent ever sees it), and `load_policies(...)` loads every file in the default policy directory — including pii-deny.yaml — so this rule is active by default the moment you load the starter policies. Tune or drop `block-us-ssn` before production and pair it with a real classifier / Azure AI Content Safety rather than relying on this regex alone. `GovernancePolicyMiddleware`'s evaluation context is the flat `{agent, message, timestamp, stream, message_count}` dict described above — it is built from the inbound *message text*, never from `tool_name` or `tool_args`. A policy rule with a `field: tool_name` or `field: tool_args.<key>` condition, or a `field: response` condition targeting the assistant's outgoing reply, can never match against the real middleware in this release; such rules are permanently inert regardless of how they read in YAML. Deterministic tool-action gating (which tool may or may not run) is `CapabilityGuardMiddleware`'s explicit `allowed_tools` / `denied_tools` lists — not a YAML policy field. See "Deterministic capability allow/deny hook" below. Load every policy file in the directory at once: ```python from agent_os.policies import PolicyEvaluator evaluator = PolicyEvaluator() evaluator.load_policies("skills/foundry-agt/references/policies") ``` `load_policies(...)` is the only loader this skill exercises and pins — [`references/python/contract_probe.py`](references/python/contract_probe.py) proves this exact call against the two starter policies above. --- ## Deterministic capability allow/deny hook `CapabilityGuardMiddleware.process(context, call_next)` receives the real `FunctionInvocationContext` for the invoked `FunctionTool`: - **Allowed** tool → `process` calls `call_next()` exactly once; the tool body executes. - **Denied** tool → `process` raises `MiddlewareTermination` *before* `call_next()` runs; the tool body never executes. This is not prose — it's exercised by [`references/python/contract_probe.py`](references/python/contract_probe.py)'s `check_capability_hook`, which asserts the allowed function runs exactly once and the denied function runs zero times against the real, installed middleware class. --- ## Audit trail `AuditLog.log(...)` appends a hash-chained entry for every governed action, allowed or denied. `audit_log.verify_integrity()` recomputes the chain and confirms nothing was altered after the fact — this is **self-assessment evidence for your own audit trail**, not a third-party certification of anything upstream or downstream. `audit_log.export_cloudevents()` emits an OTel-compatible CloudEvents list; wire it into the App Insights pipeline [`foundry-observability`](../foundry-observability/SKILL.md) already provisions rather than inventing parallel telemetry plumbing. --- ## Foundry composition Construct a real `FoundryChatClient` and pass it straight into the snippet's factory: ```python from agent_framework.foundry import FoundryChatClient from azure.identity.aio import DefaultAzureCredential chat_client = FoundryChatClient( project_endpoint="https://<project>.services.ai.azure.com/api/projects/<project-name>", model="<model-deployment-name>", credential=DefaultAzureCredential(), ) agent = build_governed_agent( name="my-governed-agent", instructions="...", chat_client=chat_client, policy_dir="skills/foundry-agt/references/policies", allowed_tools=["web_search"], denied_tools=["delete_account"], ) ``` The exact `FoundryChatClient` constructor signature and the `Agent.run(...)` response shape this composes with are exercised live by [`references/python/contract_probe.py`](references/python/contract_probe.py) (`check_stub_foundry_construction`, `check_stub_response_shape`) against a stub credential — no network call required to validate the shape. --- ## Local validation Run the pinned validation flow rather than trusting this prose: ```bash python3 skills/foundry-agt/references/python/contract_probe.py ``` or run the equivalent `validation.script` in [`references/upstream-pin.md`](references/upstream-pin.md), which first pins a throwaway venv to the exact package set above. A clean run ends in `CONTRACT_PROBE=PASS`, with every intermediate marker (`STUB_FOUNDRY_CONSTRUCTION=PASS`, `CAPABILITY_HOOK=PASS`, …) printed along the way. Two `agt` CLI quirks are **cosmetic** and should only be treated as informational *after* `contract_probe.py` passes cleanly: - `agt doctor` undercounts installed packages — it still checks pre-4.1.0-split distribution names. - `agt verify` self-reports a stale internal `Toolkit:` schema version, independent of the installed package version. Full detail: [`references/upstream-pin.md`](references/upstream-pin.md) KI-002 / KI-003. `agt verify` itself is a **toolkit self-assessment** — a useful local signal, not an external check. --- ## Using the canonical capability detector When you need a programmatic read of a repo's AGT posture (version pinned, intervention points present, policy YAML discovered, audit fields in a verifier JSON, CI action SHA-pinned), call the canonical helper: Copy `references/python/capability_detector.py` verbatim into your consumer repo and put its containing directory on `PYTHONPATH` (or your equivalent package path) before importing it — the module ships as a standalone file, not an installable package: ```python from capability_detector import detect caps = detect(repo_root=".") # caps["version_detected"] → str | None # caps["detection_confidence"] → 0.0..1.0
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub