Skip to main content
TealTiger uses a deterministic evaluation pipeline. Same input + same policy = same decision, every time. There is no LLM in the governance path — no probabilistic scoring, no prompt-dependent behavior. This makes every governance decision auditable, reproducible, and testable. This page is the definitive reference for how TealEngine v1.2 evaluates a request from the moment it arrives to the final 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: TealTiger Policy Evaluation Logic Flowchart — shows the full decision pipeline from request arrival through mode check, module resolution, parallel dispatch, failure handling, result merge, mode override, TEEC validation, and final decision Each diamond is a branching decision. Each rounded rectangle is a processing step. Red paths lead to 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.
The 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.
Start with REPORT_ONLY in production, then graduate to MONITOR, then ENFORCE. This is the same phased rollout pattern used by AWS IAM’s permission boundaries and Google Cloud’s Organization Policy dry-run mode.

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 a secrets key, TealSecrets is never initialized or invoked.
If a policy references a module that isn’t registered, the engine throws TealConfigError immediately — fail-fast, no silent skips:
This is a configuration error, not a runtime governance decision. It means your deployment is misconfigured. The engine throws rather than silently skipping the module — silent skips would create a false sense of security.

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 calls init() with the module’s policy config. Once initialized, a module stays initialized for the engine’s lifetime.
This means the first evaluation that activates a new module may be slightly slower due to initialization overhead. Subsequent evaluations reuse the initialized module.

Step 5: Parallel Dispatch

All resolved modules are dispatched simultaneously using Promise.allSettled (TypeScript) or asyncio.gather (Python). This is the key architectural difference from v1.1, which ran modules sequentially.
Each module receives the same request, ModuleContext, and full policy. Modules are independent — they don’t see each other’s results.
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.
Why parallel? In v1.1, if you had 4 modules each taking 50ms, total latency was 200ms. In v1.2, total latency is ~50ms (the slowest module). For latency-sensitive applications (chat, code completion), this matters.

Step 6: Failure Handling

After all modules settle, the engine separates successful results from failures. What happens next depends on the failurePolicy 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.
FAIL_OPEN: The failed module is ignored, and evaluation continues with successful modules only.
FAIL_OPEN should only be used in development or MONITOR mode environments. In production with ENFORCE mode, always use FAIL_CLOSED. A module that can’t evaluate is a module that can’t protect you.

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)
When two modules return actions with the same severity (e.g., 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 in metadata for analysis.
  • ENFORCE: The merged action is the final action — no override.
MONITOR mode is your shadow-testing tool. Deploy it for a week, review the decisions in your audit log, then flip to ENFORCE when you’re confident in the policy.

Step 9: TEEC Validation

The final Decision is validated against the TEEC registry (Typed Evidence & Evidence Contracts). This checks:
  • Are all reason_codes registered TEEC reason codes?
  • Is the event_type a valid TEEC event type?
  • Is the action a registered TEEC decision action?
Validation is non-blocking — invalid fields produce warnings in 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 complete Decision object is returned with all fields populated:
The metadata object includes:
  • evaluation_time_ms — How long the evaluation took
  • modules_evaluated — Which modules ran successfully
  • modules_failed — Which modules failed (if any)
  • teec_warnings — TEEC validation warnings (if any)

Key Principles

Principle 1: Explicit Deny Overrides Everything

Like AWS IAM, a DENY 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 with FAIL_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. Every Decision 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:
Request:
What each module returns: 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:
Request:
What each module returns: 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:
Request:
What each module returns: 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 in MONITOR mode. The action is overridden to ALLOW, but the violation is fully logged. Policy:
Engine configuration:
Request:
What TealSecrets returns: Merge result: DENY (severity 100) Mode override: MONITOR → override to ALLOW Final Decision:
Use MONITOR mode to build a baseline of what TealTiger would block before enabling enforcement. Review the audit log for false positives and tune your policy accordingly.

Example 5: Module Failure (Fail-Closed)

A module throws an unexpected error during evaluation. With the default FAIL_CLOSED policy, the engine returns DENY. Policy:
Engine configuration:
Request:
What happens: TealSecrets throws an internal error (e.g., pattern file corrupted). TealRegistry returns 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.