Skip to main content
A quality gate is a named function that receives an agent’s output and returns a pass/fail verdict with an optional reason string. Gates are the core primitive in Pecta: they run on the very first evaluation with no baseline period, execute in parallel within a shared timeout budget, and stop as soon as one fails (fail-fast). Every gate runs inside your own process — there is no network call on the hot path.

How gates run

When you call engine.evaluate(), the engine starts all configured gates simultaneously using Promise.all. A shared AbortController enforces the timeout budget (default 50 ms). If any gate fails and failFast is enabled (the default), the controller aborts immediately and remaining in-flight gates receive an abort signal and return without doing further work.
The total_latency_ms reflects wall-clock time, not the sum of individual gate latencies, because gates run concurrently.

Fail-fast and timeout behaviour

Two configuration options control how the engine handles failures and slow gates:
  • failFast (default true) — as soon as one gate returns passed: false, the engine sends an abort signal to all other running gates and marks them as aborted in the result.
  • timeout (default 50 ms) — if the wall-clock budget expires before all gates complete, the engine aborts everything. Timed-out gates appear as failed in the result with reason pecta:timeout.
For RTB pipelines you can tighten the budget to 15 ms. For MCP proxy use cases, the default 50 ms gives gates enough room to do regex and schema checks comfortably.

Gate results

Each gate contributes one entry to result.gates:
The top-level EvaluationResult:
passed is true only when every gate either passes or explicitly sets skipped: true. A single passed: false gate makes the entire evaluation fail.

Built-in gates

General

RTB (under gates.rtb)

RTB gates read standard OpenRTB fields from ctx.input (the bid request) and ctx.output (the bid response). Pass tmaxMs and startedAt on the context to enable the tmaxGuard gate.

Writing a custom gate

Any object with a name string and a run function is a valid gate. Check the abort signal at the start of expensive operations.
run returns GateOutcome:
The engine merges in name and latency_ms before adding the result to EvaluationResult.gates.

Further reading