> ## Documentation Index
> Fetch the complete documentation index at: https://docs.egisai.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Enforcement matrix

> Where EgisAI physically prevents a violation versus where it can only audit after the fact, framework by framework — and why the `enforcement_status` field is recorded on every audit row.

Different agent frameworks expose tool execution at different boundaries.
Some run the agentic loop in Python, where the SDK can sit between the
model and the tool and physically prevent a dangerous dispatch. A couple
run it in a subprocess or on managed infrastructure, where the SDK can
record what happened but cannot intervene before it happens. This page is
the honest, locked contract for **what `egisai` can stop before it
happens** versus **what it can only audit after the fact**, framework by
framework.

This honesty matters for compliance. SOC 2, GDPR, HIPAA, and ISO 27001
auditors care that a control either fires preventively or is honestly
labelled as detective; conflating the two erodes audit trust. Every audit
row written by EgisAI carries an `enforcement_status` field that
distinguishes the two states, and this page is where you discover, per
framework, which state to expect.

## Two enforcement seams

Two seams matter for compliance:

1. **Tool / MCP call enforcement** — block dangerous tool dispatches
   (`deny_tool_call`, `deny_mcp_call`, `semantic_guard`) **before** the
   tool runs.
2. **Tool result enforcement** — block or mask PII
   (`pii_scan`, `deny_output_regex`, `semantic_guard`) in the tool's
   response **before** the model is shown it.

A row in the matrix below says **enforced** when the SDK can physically
prevent the failure mode in question. It says **advisory** when the SDK
observes after the fact and records the violation in the audit log but
couldn't intervene.

## The matrix

| Framework                            | Tier | Tool / MCP block          | Tool result PII block      | How it works                                                                                                                                                                                                                                                                                                                       |
| ------------------------------------ | ---- | ------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **OpenAI**                           | 1    | **enforced**              | **enforced** (next call)   | Output policy raises `PermissionError` before the response (with `tool_calls`) returns. Tool results round-trip Python; the next call's input phase scans them.                                                                                                                                                                    |
| **Anthropic**                        | 1    | **enforced**              | **enforced** (next call)   | Output policy on `Messages.create` response with `tool_use` blocks. Tool result blocks in the next call's `messages` are scanned by the input phase.                                                                                                                                                                               |
| **Google GenAI (Gemini)**            | 1    | **enforced**              | **enforced** (next call)   | `generate_content` response with `function_call` parts is policy-gated before return; tool responses scanned on next call.                                                                                                                                                                                                         |
| **Google (legacy)**                  | 1    | **enforced**              | **enforced** (next call)   | Same gate as Google GenAI; legacy `google-generativeai` package.                                                                                                                                                                                                                                                                   |
| **AWS Bedrock Converse**             | 1    | **enforced**              | **enforced** (next call)   | `Converse` / `ConverseStream` response gated; `toolUse` blocks blocked before caller dispatches; tool results scanned on next call.                                                                                                                                                                                                |
| **HTTP fallback (httpx / requests)** | 1    | **enforced**              | **enforced** (next call)   | Best-effort body parsing for unknown providers; the next request's payload text gets the same input-phase scan.                                                                                                                                                                                                                    |
| **LangChain**                        | 1    | **enforced**              | **enforced** (next call)   | Cascades to the underlying provider patch (OpenAI / Anthropic / Google).                                                                                                                                                                                                                                                           |
| **OpenAI Agents**                    | 2    | **enforced**              | **enforced** (next call)   | Identity wrap on `Runner.run`; cascades to inner OpenAI patch and the input-phase scan on tool results.                                                                                                                                                                                                                            |
| **CrewAI**                           | 2    | **enforced**              | **enforced** (next call)   | Identity wrap on `Agent.execute_task`; cascades.                                                                                                                                                                                                                                                                                   |
| **AutoGen**                          | 2    | **enforced**              | **enforced** (next call)   | Identity wrap on `AssistantAgent.run`; cascades.                                                                                                                                                                                                                                                                                   |
| **LangGraph**                        | 2    | **enforced**              | **enforced** (next call)   | Identity wrap on `Pregel.invoke`; cascades.                                                                                                                                                                                                                                                                                        |
| **LlamaIndex**                       | 2    | **enforced**              | **enforced** (next call)   | Identity wrap on `FunctionAgent.run`; cascades.                                                                                                                                                                                                                                                                                    |
| **Agno**                             | 2    | **enforced**              | **enforced** (next call)   | Identity wrap on `Agent.run` / `Agent.arun`; cascades.                                                                                                                                                                                                                                                                             |
| **smolagents**                       | 2    | **enforced**              | **enforced** (next call)   | Identity wrap on agent entry; cascades.                                                                                                                                                                                                                                                                                            |
| **Strands Agents**                   | 2    | **enforced**              | **enforced** (next call)   | Identity wrap on `Agent.__call__`; cascades.                                                                                                                                                                                                                                                                                       |
| **Pydantic AI**                      | 2    | **enforced**              | **enforced** (next call)   | Identity wrap on `Agent.run`; cascades.                                                                                                                                                                                                                                                                                            |
| **Google ADK**                       | 2    | **enforced**              | **enforced** (next call)   | Identity wrap on the ADK entry; cascades.                                                                                                                                                                                                                                                                                          |
| **Claude Agent SDK**                 | 3a   | **enforced** (PreToolUse) | **enforced** (PostToolUse) | Subprocess agent loop. The patch injects `PreToolUse` AND `PostToolUse` hooks. PreToolUse gates the dispatch; PostToolUse evaluates the tool's response and substitutes the bytes before Claude is shown the result. Older SDK versions without the hooks field fall back to advisory mode and the audit row is honestly labelled. |
| **AWS Bedrock Agents**               | 3b   | **advisory**              | **advisory**               | Action Groups execute on AWS-managed infrastructure with no equivalent of `PostToolUse`. The patch records what happened but cannot prevent the tool dispatch or substitute its result before the model sees it. Use the standalone `bedrock-runtime` Converse API or `claude_agent_sdk` for SOC 2 / GDPR-grade enforcement.       |

## What you can rely on

For every row above **except Bedrock Agents**:

* A `deny_tool_call`, `deny_mcp_call`, or `semantic_guard` verdict on a
  tool call physically stops the tool from running.
* A `pii_scan`, `deny_output_regex`, or `semantic_guard` verdict on a
  tool result either masks the result in place (`action = "sanitize"`)
  or refuses it (`action = "block"`) before the model is shown it. For
  Tier 1 and Tier 2 frameworks this happens on the next round trip's
  input phase; for the Claude Agent SDK it happens at the `PostToolUse`
  hook so the model never sees the raw bytes for one turn.
* Input-side policies (`pii_scan`, `deny_regex`, `allow_model`,
  `max_prompt_chars`, `semantic_guard` on the prompt) always run
  before the model is called.
* Sanitization rewrites the prompt locally before it reaches the
  provider — the raw value never crosses the SDK boundary.
* Audit rows distinguish `enforcement_status = "enforced"` (the SDK
  actually prevented the action) from `enforcement_status = "advisory"`
  (the SDK observed after the fact). SOC 2 / GDPR auditors can query
  both states with a single SQL clause.

For Bedrock Agents specifically, see the SDK's public
[`SECURITY.md`](https://github.com/EgisLabs/egisai-sdk/blob/main/SECURITY.md)
for the architectural limitation. The limitation is publicly documented
so customers can risk-assess accordingly and pick a different framework
for workflows that require pre-execution gating.

## Aggregated OUTPUT replay (Claude Agent SDK)

For the Claude Agent SDK only, there is a third evaluation pass that runs
on the **aggregated assistant stream** at `ResultMessage`. When that
evaluation replays structured `tool_calls` that the CLI subprocess
already executed, a `verdict = "block"` stamps
`enforcement_status = "advisory"` on the enclosing `model_call` row —
MCP / tool bytes were already replayed before Python aggregated them.
**Text-only** violations still stamp `enforced` when hooks are wired.

Applications using `on_block = "raise"` continue to see `PermissionError`
in their code path; the audit flag distinguishes *subprocess timing
truth* from *caller withhold*. The distinction is purely for SOC 2 / GDPR
evidence — your code's behavior is unchanged.

## Why this is published

A governance product that quietly papers over its limits is worse than
one that names them. The Bedrock Agents row above will fail every "what
controls would have stopped this" question an auditor asks; we publish
the matrix so a customer evaluating EgisAI for a Bedrock Agents workload
knows up front to pick a different runtime for pre-execution gating, and
so an auditor reviewing a Bedrock Agents audit row can see immediately
that the `advisory` label is by design and not a regression.

Every other framework on this list **does** physically prevent the
failure modes listed above. If you ever see a tool call that ran despite
a matching `deny_tool_call` policy on any framework except Bedrock
Agents, or a tool result that reached the model despite a matching
`pii_scan` or `deny_output_regex` policy on any framework except Bedrock
Agents, that is a Critical-severity bypass and we want to know within
hours — see the vulnerability disclosure section of the
[security page](https://egisai.co/security#vuln).

## What's next

<CardGroup cols={2}>
  <Card title="Audit-event schema" icon="file-code" href="/api-reference/audit-event-schema">
    The `enforcement_status` field on every audit row.
  </Card>

  <Card title="Verdicts" icon="gavel" href="/concepts/verdicts">
    Allow, sanitize, and block — what each one means in detail.
  </Card>

  <Card title="Two-phase governance" icon="diagram-project" href="/concepts/two-phase-governance">
    The request / response split the matrix interacts with.
  </Card>

  <Card title="Trust Center" icon="building-shield" href="https://trust.egisai.co/">
    Live certifications, security posture, and downloadable evidence.
  </Card>
</CardGroup>
