Decision object returned to your application.
This documents the v1.2 evaluation pipeline (
TealEngineV12). The v1.1 TealEngine uses a simpler sequential pipeline. See the migration guide for differences.Evaluation Flowchart
The following diagram shows the complete decision path for every request that enters TealEngine v1.2:DENY outcomes. Green paths lead to ALLOW outcomes. The teal path is the normal evaluation flow.
Step-by-Step Evaluation
Step 1: Request Arrives
Every evaluation starts with a request object and a ModuleContext. The request contains the data being governed (model, messages, tool calls, etc.). The context carries metadata that ties the evaluation to your system.correlation_id is required — it ties the entire evaluation chain together across your system. The engine uses it in the final Decision, in audit logs, and in TEEC evidence envelopes. If you’re using OpenTelemetry, this maps to your trace ID.
Step 2: Check Policy Mode
The first thing the engine checks is the policy mode. TealTiger supports three modes that control how strictly the pipeline enforces decisions:
If the mode is
REPORT_ONLY, the engine skips the entire evaluation pipeline, logs the request, and returns ALLOW immediately. This is useful for onboarding — deploy TealTiger in production without affecting any traffic, and review what would have been evaluated.
Step 3: Resolve Required Modules
The engine inspects the policy object for top-level keys that match registered module names. Only modules referenced by the policy are activated — if your policy doesn’t include asecrets key, TealSecrets is never initialized or invoked.
TealConfigError immediately — fail-fast, no silent skips:
Step 4: Lazy Initialization
Modules are initialized on first use, not at engine construction. When a module is needed for the first time, the engine callsinit() with the module’s policy config. Once initialized, a module stays initialized for the engine’s lifetime.
Step 5: Parallel Dispatch
All resolved modules are dispatched simultaneously usingPromise.allSettled (TypeScript) or asyncio.gather (Python). This is the key architectural difference from v1.1, which ran modules sequentially.
Promise.allSettled (not Promise.all) is used deliberately. If one module throws, the others still complete. The engine handles failures in the next step rather than aborting the entire evaluation.Step 6: Failure Handling
After all modules settle, the engine separates successful results from failures. What happens next depends on thefailurePolicy configuration:
FAIL_CLOSED (default): If any module threw an error, the entire evaluation returns DENY with reason "Module(s) failed". Failed module names appear in metadata.modules_failed.
Step 7: Result Merge — “Most Restrictive Wins”
All successful module results are merged using action severity ranking. The action with the highest severity becomes the final action. All reason codes from all modules are combined (union). All findings (e.g.,SecretFinding) are combined.
Merge Example
Three modules evaluate the same request:
Merged result:
- Action:
REDACT(severity 70 — highest) - Reason codes:
['SECRET_DETECTED', 'POLICY_COMPLIANT'](union from all modules) - Event type: from the winning module (
secret.detection)
DENY and DENY_WRITE), the engine uses the action from the module that appears first in the evaluation order. Both modules’ reason codes are still combined.
Step 8: Mode Override
After merging, the engine checks the mode one more time:- MONITOR: The merged action is logged but overridden to
ALLOW. The original action is preserved inmetadatafor analysis. - ENFORCE: The merged action is the final action — no override.
Step 9: TEEC Validation
The finalDecision is validated against the TEEC registry (Typed Evidence & Evidence Contracts). This checks:
- Are all
reason_codesregistered TEEC reason codes? - Is the
event_typea valid TEEC event type? - Is the
actiona registered TEEC decision action?
metadata.teec_warnings. The decision is returned regardless of validation result.
TEEC validation is intentionally non-blocking so that custom modules with custom reason codes don’t break the evaluation pipeline. The warnings give you visibility without disrupting governance.
Step 10: Return Decision
The completeDecision object is returned with all fields populated:
metadata object includes:
evaluation_time_ms— How long the evaluation tookmodules_evaluated— Which modules ran successfullymodules_failed— Which modules failed (if any)teec_warnings— TEEC validation warnings (if any)
Key Principles
Principle 1: Explicit Deny Overrides Everything
Like AWS IAM, aDENY from any module overrides ALLOW from all others. There is no way to “un-deny” a request. This is a security-first design choice — you can’t accidentally allow something that any governance dimension flags.
Principle 2: No LLM in the Governance Path
The evaluation pipeline is pure deterministic logic. No model inference, no probabilistic decisions. Pattern matching, severity ranking, and boolean logic — that’s it. This is what makes TealTiger’s decisions reconstructable and auditable.Principle 3: Fail-Closed by Default
If the governance system itself fails (a module throws an exception), the default is to deny. This prevents a broken guardrail from becoming an open door. You can override this withFAIL_OPEN, but it’s not recommended for production.
Principle 4: Evidence by Default
Every evaluation produces a structured evidence envelope (TEEC). You don’t opt into evidence — you opt out of it. EveryDecision includes correlation IDs, timestamps, reason codes, component versions, and module metadata.
Examples
Example 1: Simple ALLOW
A request passes all governance modules. No violations detected. Policy:
Merge result:
ALLOW (both severity 0)
Final Decision:
Example 2: Single Module DENY
TealSecrets detects an AWS access key in the message content. TealRegistry allows the model. Policy:
Merge result:
DENY (severity 100 overrides severity 0)
Final Decision:
Example 3: REQUIRE_APPROVAL
A cost governance module detects that the request’s estimated cost exceeds a threshold. Policy:
Merge result:
REQUIRE_APPROVAL (severity 80 > severity 0)
Final Decision:
Example 4: MONITOR Mode
The same secret-detection DENY from Example 2, but the engine is inMONITOR mode. The action is overridden to ALLOW, but the violation is fully logged.
Policy:
Merge result:
DENY (severity 100)
Mode override: MONITOR → override to ALLOW
Final Decision:
Example 5: Module Failure (Fail-Closed)
A module throws an unexpected error during evaluation. With the defaultFAIL_CLOSED policy, the engine returns DENY.
Policy:
ALLOW.
Failure policy:
FAIL_CLOSED → entire evaluation returns DENY
Final Decision:
Fail-closed means “when in doubt, deny.” This is the same principle behind AWS IAM’s implicit deny — if the system can’t determine whether to allow, it denies.
Comparison with AWS IAM
TealTiger’s policy evaluation shares several design principles with AWS IAM, adapted for AI agent governance:
The key difference: TealTiger evaluates modules in parallel, while AWS IAM evaluates policy types sequentially. This is possible because TealTiger modules are independent — they don’t depend on each other’s results. The merge step handles conflicts after all modules complete.
Related Documentation
- Module System — How modules are registered, initialized, and dispatched
- TEEC — Typed Evidence & Evidence Contracts — The evidence schema behind every decision
- Decision Lifecycle — From request to audit log
- Decision Model — The
Decisionobject in detail - Policy Modes —
ENFORCE,MONITOR,REPORT_ONLYdeep dive - TealEngineV12 API Reference — Full API documentation

