VotalAI · LLM Shield — Security Operations

Where an agent gets stopped, and what to do when it does

One request from an AI agent, and every gate it passes through. Read left to right: the agent is untrusted, the model and tools sit behind the gates, and nothing reaches them except through Shield. Each gate names the audit signal it produces, so an alert can be traced back to the control that fired it.

Verified against the deployed data plane, 2026-07-28.

The request path five gates, in order

1 · Who is calling
Identity
Establishes the agent and the role before anything else runs.
Agent credentialSigned agent token, SPIFFE SVID, or an OIDC service account.
Role today is assertedRead from X-User-Role unless role binding is on. The audit records role_source so you can see which.
2 · What was said
Input guardrails
Runs before the model sees the prompt.
Prompt injection, exfiltration, toxicityModel-based detection with a confidence score.
Tenant custom policiesYour own rules in plain language, evaluated per request.
Blocked ⇒guardrail=adversarial_detection or custom_policy_input
3 · What it wants to do
Tool authorization
Every tool call, before execution.
Agent AND role must allowRegistry intersection — neither alone is enough.
Arguments, not just namesData policies inspect recipients, amounts, scope.
Control planeKillswitch · circuit breaker · workflow limits · human approval.
Blocked ⇒guardrail=rbac_guard · tool_allowlist · tool_call_validation
4 · What came back
Output guardrails
Runs on the reply and on tool output.
PII, credentials, card dataBlocked or redacted before it reaches the user.
Secret vaultPlaceholders in the model path; the real value appears only at a bound destination.
Blocked ⇒guardrail=custom_policy_output
5 · What was recorded
Audit
The record you investigate from.
Decision logAgent, role, tool, verdict, and the guardrail that fired.
Provenancerole_source · agent_source · token_binding · acting_for
Tamper-evident chainHash chain with signed checkpoints. Off by default.

What to alert on and what each one means

PrioritySignalWhat it meansFirst action
P1 role_source=header on a privileged role A caller named its own role. With binding off this is normal and unverifiable — which is the point. Confirm binding mode. If prefer, this caller is sending no verified token.
P1 token_binding=failed A bound credential arrived without a valid proof. This is the stolen-token signature. Revoke the token by jti, then find where it leaked — logs, traces, a tool response.
P1 Same agent_key, sudden new tool An agent doing something it has never done. Often prompt injection rather than compromise. Killswitch the tool for that tenant; read the prompts in that session_id.
P2 guardrail=custom_policy_input spike Repeated attempts against one of your own policies. Probing, or a broken integration. Group by agent_key. One agent means a bug; many means an attack.
P2 [monitor] would block on the MCP gateway The control plane would have denied this, but is in observe mode. Count them for a week, then set SHIELD_MCP_CONTROL_PLANE=enforce.
P2 Registry allows, enforcement denies A data policy is vetoing a permission the console grants. The console is not the whole picture. Reconcile the tool policy with the agent registry; the stricter layer wins.
P3 delegation_verified=false with a header present An on-behalf-of token was presented and rejected. Check issuer allowlist and audience — usually a misconfigured client, not an attack.

Failure modes what happens when a part is down

If this failsBehaviourWhy
Shield unreachable from the appTraffic is refused The LangChain middleware is fail-closed by default. A timeout is not an approval.
Redis downReplay and rate limits degrade; config falls back to defaults "Cannot read config" must not mean "deny everything" — but replay protection is genuinely unavailable.
Model backend slowGuarded calls take ~25s; the client may time out Custom policies are model-evaluated. Budget for it in client timeouts.
An agent bypasses ShieldEvery gate above is skipped This is the assumption the whole design rests on. See below.
The one control that makes the rest true: the model, the tools, the secrets and the egress must be reachable only through Shield — private networking, no direct credentials in the agent, no alternate route. Every gate on this page is bypassed by a client that can reach a resource directly. If you verify one thing quarterly, verify that.

Run examples/langchain/verify_deployment.py after each deploy: it exercises gates 2 through 4 against the live data plane and reports the identity posture, with a non-zero exit code so it can gate a release.