AG2 Integration with TealTiger
TealTiger ships as a built-in AG2 extension: deterministic governance guardrails for AG2 agents with no LLM in the governance path. It enforces tool allowlists and blocklists, detects PII and secrets in tool arguments, blocks prompt injection, tracks per-session cost, provides a per-agent kill switch, and emits structured TEEC audit receipts.Package: Ships with AG2 (built-in extension — no separate install)
License: Apache 2.0
Latency: Under 2ms per evaluation
Dependencies: Zero — pure AG2 + stdlib
Source: ag2/extensions/tealtiger/
PR: #3128 (merged)
This page documents the built-in AG2 extension, which is intentionally focused and dependency-free. The standalone TealTiger platform adds capabilities that are not part of the bundled extension — rate limiting, circuit breakers, content moderation, evidence export, and OpenTelemetry spans. Those are called out in Beyond the built-in extension.
Installation
TealTiger ships as a built-in AG2 extension — no separate package needed:Quick Start
TealTigerMiddleware is a middleware factory — pass the instance straight into an agent’s middleware list.
Multi-Stage Defense
TealTiger governs at two stages of the AG2 agent lifecycle:
Both stages activate from a single middleware instance — the middleware factory pattern keeps state (decisions, receipts, cost, frozen agents) alive across turns.
A
TEECReceipt is emitted for every tool evaluation, whether the call was executed or blocked. Turn-level kill switch denials record a GovernanceDecision but do not emit a receipt.Governance Modes
mode accepts a GovernanceMode member or its string name, and defaults to GovernanceMode.ENFORCE. Start in MONITOR to see what would be blocked, then promote to ENFORCE:
Policy Types
All policies are created withGovernancePolicy factory methods and evaluated deterministically over the serialized tool arguments.
Tool Allowlist
Restrict which tools the agent can call. Patterns match withfnmatch, so the full glob syntax (*, ?, [seq]) applies:
TOOL_NOT_ALLOWED and risk score 80.
Tool Blocklist
The complement of the allowlist: allow every tool except the ones you name. Reach for this when most tools are safe and you only need to carve out a dangerous few. Patterns also match withfnmatch:
TOOL_BLOCKED and risk score 80. An empty blocklist raises ValueError at construction, so a policy that blocks nothing can’t be created by mistake.
Allowlist and blocklist compose — allow read_* but still deny read_secrets. When both are configured, either policy denying the call results in a DENY (the first match in your list is the one reported):
PII Detection
Block tool calls containing PII in their arguments:
Denied with risk score 90. One reason code is appended per matched category, in the form
PII_DETECTED:ssn, PII_DETECTED:email, and so on.
Secret Detection
Block tool calls containing API keys, tokens, or credentials in their arguments:
Denied with reason code
SECRET_DETECTED and risk score 95.
Output scanning
Every policy above inspects a tool’s arguments before it runs.output_scan inspects what a tool returns — the data-leakage direction. A tool that reads a database, a file, or an external API can return an SSN or a leaked credential that would otherwise land in the model’s context on the next turn. This scans the result and redacts, blocks, or flags it first.
Defaults follow the sensible split: PII is redacted (you usually still need the surrounding result), secrets are blocked (a leaked credential should not reach the model at all). When both a PII and a secret finding occur, the more restrictive action wins.
Findings are recorded with reason codes
OUTPUT_PII_DETECTED:{category} and OUTPUT_SECRET_DETECTED, plus OUTPUT_REDACTED or OUTPUT_BLOCKED describing the action. Risk score is 90 when a secret is present, 60 for PII only. Output scanning runs after the tool executes (it governs the result), in MONITOR and ENFORCE; in OBSERVE the result passes through unmodified.
Prompt Injection Detection
Block tool calls containing adversarial prompt injection patterns in their arguments:
Denied with reason code
PROMPT_INJECTION:{technique}/{pattern_name} and risk score 95.
Enable only specific techniques, or tune the confidence threshold to reduce false positives:
0.7. An unknown technique name, an empty techniques list, or a threshold outside 0.0–1.0 raises ValueError at construction.
Policies are evaluated in the order you pass them, and evaluation stops at the first denial. Put
prompt_injection_block() before tool_allowlist(...) if you want injection attempts reported as PROMPT_INJECTION:… rather than TOOL_NOT_ALLOWED.Cost Limit
Enforce a per-session cost ceiling:cost_per_call (a middleware option, default 0.002). Once the limit is reached, further calls are denied with BUDGET_EXCEEDED and risk score 70.
Factory-Level Budget
In addition to the policy-levelcost_limit, set a factory-level budget that is always enforced before any policy runs — a spending cap no policy ordering can bypass:
budget_limit defaults to infinity.
Kill Switch
Freeze an agent immediately — this blocks its turns and all of its tool calls, regardless of policies or mode:on_turn) and the tool level (on_tool_execution):
- ENFORCE: returns a
ToolErrorEvent, blocking the turn or tool call - MONITOR: records a DENY decision but allows the action through
- OBSERVE: not evaluated (passthrough)
AGENT_FROZEN and risk score 100.
Audit Trail
Every governance decision produces a structuredGovernanceDecision:
Decision Contract Fields
TEEC Receipts
Every tool evaluation — executed or blocked — produces aTEECReceipt:
receipt_id, decision_id, agent_name, tool_name, action, execution_outcome (executed, blocked, or error), reason_codes, risk_score, policy_digest (short SHA-256 of the active policy set), and timestamp_ms.
Factory State API
The factory exposes accumulated state directly:Callbacks
React to governance decisions in real time:on_decision is called for every decision (ALLOW and DENY); on_receipt is called for every TEEC receipt.
Evaluation Order
Two checks always run first, in this order. Everything after them is your policy list, walked in declared order — the first DENY wins and short-circuits the rest:- Kill switch —
AGENT_FROZEN, risk 100 - Factory budget —
BUDGET_EXCEEDED, risk 70 - Your policies, in list order — first DENY wins
If all checks pass, the decision is
ALLOW with reason code POLICY_ALLOW and risk score 0.
Output scanning is the one check that runs after the tool executes rather than before it — it governs what the result puts back into the model’s context, so it cannot short-circuit the pre-tool order above.
Use Across Multiple Agents
One governance instance can be attached to several agents — decisions, receipts, cost, and frozen agents are shared across all of them:Complete Example: Governed Research Agent
Beyond the built-in extension
The built-in extension is deliberately small and dependency-free. The standalone TealTiger platform adds governance capabilities that are not part of the bundled AG2 extension:
If you need those, see the TealTiger platform documentation. The built-in extension and the platform share the same policy vocabulary, so configurations translate directly.
OWASP AI Security Coverage
The built-in extension addresses several OWASP Agentic Security Issues:
Broader coverage (output handling, sandboxing constraints, circuit breakers) is available through the standalone platform.
Key Properties
Architecture
The middleware follows AG2’s middleware factory pattern:TealTigerMiddleware— long-lived factory holding shared state (decisions, receipts, frozen agents, cumulative cost)- Calling the factory creates a
_TealTigerPerTurninstance for the turn, referencing the factory on_turnhandles kill switch enforcement;on_tool_executionhandles policy evaluation- Kill switch, budget, and audit state persist across turns and agents
Troubleshooting
Policies not enforcing
Policies not enforcing
Ensure
mode=GovernanceMode.ENFORCE. In MONITOR or OBSERVE mode, violations are recorded but not blocked. Check governance.decisions to confirm policies evaluated.Kill switch not working
Kill switch not working
Verify the agent name matches exactly:
governance.freeze("assistant") must match the name passed to Agent("assistant", ...). The freeze is case-sensitive with no wildcard.Cost tracking shows zero
Cost tracking shows zero
Set
cost_per_call on the middleware. Without it, the tracker cannot estimate spend (it defaults to 0.002 per call).Looking for rate limiting, circuit breakers, or evidence export
Looking for rate limiting, circuit breakers, or evidence export
Those are part of the standalone TealTiger platform, not the built-in extension. See Beyond the built-in extension.
Links
- AG2 GitHub
- Extension source
- PR #3128 (merged)
- TealTiger GitHub (Apache 2.0)
- TealTiger platform on PyPI
- Maintainer: @nagasatish007

