Runtime loop
AvertGate runs the same loop on every tool call: cheap deterministic checks first, then the semantic model when needed.
Intercept
Agent id, session id, tool name and arguments are captured; the session's trajectory is loaded.
Request inspection (before the tool runs)
Policy, egress scan and loop breaker run in order. The policy decision is made here; if the arguments carry secrets/PII the call is stopped. Optionally the AI Guard analyses intent.
Execute
The allowed call is forwarded to the real tool and the result is received.
Response inspection (after the tool runs)
The returned result is treated as untrusted content and scanned for indirect prompt injection.
Return and record
The clean result goes back to the agent. The full event (with redacted arguments) is appended to the chained audit log.
Why two phases?
The request phase governs what the agent is about to do. The response phase inspects what comes back: tool results, retrieved documents and web content are the untrusted channel through which indirect prompt injection reaches the agent. The two cannot be collapsed into one step; an attack usually enters in the response phase and can only be neutralised at the request phase.
Order and cost
| Step | Kind | Typical time |
|---|---|---|
| Policy, egress/ingress regex, loop breaker | Deterministic, local | < 2 ms |
| AI Guard (optional) | Semantic model | ~50–100 ms (TypeSafe AI Jev) |
If a deterministic step already stops a call, the model is never called. The model is consulted only for content that passed the cheap checks and is long enough.
What happens in the request and response phases?
Every call produces one final decision and one audit event. The outcome depends on where the call stopped:
| Situation | Does the tool run? | What the agent gets | Audit record |
|---|---|---|---|
| Request phase ALLOW, response clean | Yes | The tool's result | ALLOW |
| Request phase BLOCK | No | A safe error message | BLOCK + reason + rule |
| Request phase ESCALATE, approved | Yes, after approval | The tool's result (if the response scan passes) | Final decision |
| Request phase ESCALATE, denied / timed out / Slack error | No | A safe error message | BLOCK |
| Request passed, response suspicious (injection signal) | Yes, it already ran | The result is withheld from the agent; a safe error comes back | BLOCK (reason: ingress scan) |
allow: false, constraints, require_approval). See Risk tiers.In shadow mode nothing is blocked in either phase; the outcome is only recorded as SHADOW_BLOCK / SHADOW_ESCALATE and the result reaches the agent unchanged.
Fail-closed: what happens on errors?
If an inspector fails (network, timeout, parse error) AvertGate never silently allows. Behaviour by situation (fail_closed defaults to true):
| Situation | fail_closed: true (default) | fail_closed: false | Shadow mode |
|---|---|---|---|
| Policy cannot be loaded / parsed at start | The gateway does not start (exits with an error). There is no policy-less operation. | Same | |
| Policy reload fails while running (broken file) | The active policy is kept; the reload error is logged as a warning. | Same | |
| Request inspector errors (egress scan, AI Guard layer 1 timeout) | BLOCK | The check is skipped, the call continues | SHADOW_BLOCK recorded, call continues |
| Response inspector errors (ingress scan, AI Guard layer 2) | BLOCK: the tool ran, the result is withheld | The result reaches the agent | SHADOW_BLOCK recorded, result delivered |
| Human approval: denial, timeout (default 120 s) or Slack error | BLOCK: always, regardless of this setting. | No wait, SHADOW_ESCALATE recorded | |
| Tool (upstream) errors | The agent gets a "tool execution failed" error; the event is recorded as BLOCK. | Same | |
| Connection to the dashboard is lost | Tool calls are not affected. Event shipping logs a warning and drops the failed batch; at most 500 events are buffered in memory. The local audit log keeps being written. | Same | |
Keep fail_closed: true in production. Use false only as a deliberate decision when an inspector outage is judged worse than a coverage gap.