Skip to main content
Every built-in gate in Pecta is an object that satisfies the Gate interface. You can implement the same interface yourself to add checks that are specific to your domain — for example, enforcing a proprietary response schema, calling an internal moderation API, or checking that a bid came from an allowlisted seat. Custom gates compose with built-in gates in createEngine the same way built-in gates do. The engine handles parallelism, the timeout budget, fail-fast signalling, and result assembly automatically.

The Gate interface

name is the string recorded in result.gates and used for duplicate detection. It must be unique across all gates in an engine.

The GateRun signature

run receives the full evaluation context and an AbortSignal from the engine’s shared AbortController. It can return a GateOutcome synchronously or as a Promise.

The GateOutcome type

The engine fills in name and latency_ms automatically. You do not need to set them in your run function.

A complete custom gate

This gate verifies that the output’s bid_id field appears in an in-memory allowlist. It checks signal.aborted before doing any work, which is the correct pattern for gates that might do expensive I/O:

Using an async gate

When your gate needs to call an external service, return a Promise. The engine awaits it and applies the timeout budget the same way as synchronous gates:
Forward the signal to any fetch or other cancellable API call inside your gate. If you do not, a network request will keep running even after the engine’s timeout fires, and the Promise will not resolve until the network responds — causing the engine to wait beyond its timeout budget.

Passing your gate to createEngine

Custom gates go in the same gates array as built-in gates:

What the engine fills in automatically

You only return GateOutcome from run. The engine wraps it into a full GateResult before adding it to result.gates:

Skipping conditionally

Return { passed: true, skipped: true } when your gate cannot or should not evaluate this particular context. Skipped results appear in result.gates but do not cause result.passed to be false:
The GateRun type is exported from @pecta/core alongside Gate, GateOutcome, and EvaluationContext. Import all the types you need directly from the package — you do not need to import from sub-paths.