The shield

Quis ut Deus

Who is like God? It is what the name Michael means, and what is written on his shield.

Ours is one binary that stands on your machine. Every prompt is judged before it leaves; every secret is restored when the answer comes back. Open source. Judged locally. Works offline.

Michael's shield of hammered bronze and gold, set with a beryl and inscribed QUIS UT DEUS above a sunburst, photographed in raking light on black.

At that time shall Michael stand up, the great prince which standeth for the children of thy people.Daniel 12:1

How it works

Out judged. Back restored.

The same engine as the hosted gate, in one binary on your machine, and in WebAssembly and Python for the integrations. Prompts never leave your machine to be judged.

  1. I

    Judged on the way out

    What you type is judged as yours. Tool results, files and fetched pages are judged as documents: an instruction hidden in one is censored, and the rest still reaches the model. A clean prompt passes through the gates exactly as you typed it.

  2. II

    Renamed, consistently

    Secrets, personal data and the terms you list become placeholders like SECRET_1. The same value keeps the same name all session, so the model can still reason about it.

  3. III

    Restored on the way back

    Placeholders in the reply, streamed or not, prose and tool-call arguments alike, are swapped back to the originals. Thinking blocks are never touched.

Only your newest message can be rejected. If a rejected message comes back in the conversation history, it is replaced with [withheld by Archangel Michael], so one bad prompt cannot poison the rest.

Quickstart

Wherever you prompt.

The quis command, and the AAM integrations that carry the shield into your tools. None has shipped yet; each is marked until it does.

Coding agents

Coming soon

Claude Code, Codex and pi. quis run starts a loopback proxy for the tool’s lifetime, points the tool at it, and ends the session when the tool exits.

Terminal
quis run -- claudequis run -- codex# or pipe one prompt through itcat incident.md | quis pipe -- claude -p "Summarize this"

On exit it reports counts, never values:

judged 42 prompts · 3 secrets obfuscated (SECRET ×2, EMAIL ×1) · 1 injection censored in a tool result · nothing written to disk

Open WebUI + LiteLLM

Coming soon

A Python package with a LiteLLM guardrail that judges before the call and restores after it, streaming included, and a single-file Open WebUI filter that does the same per chat.

Python
pip install archangel_aam

AI SDK and Circuitry

Coming soon

Language-model middleware for the Vercel AI SDK, and an adapter for Circuitry. Wrap the model once; every call is judged and every reply restored.

TypeScript
import { withArchangel } from '@archangel/aam-ai-sdk';import { loadConfig, loadEngine } from '@archangel/aam/node';const engine = await loadEngine();const config = await loadConfig();const model = withArchangel(base, {  aam: { engine, config },});

The browser extension

Coming soon

For ChatGPT and claude.ai, Chrome first. It judges each message as you send it, with the engine running inside the extension, blocks a rejected one with a notice, and restores placeholders in the reply you read.

One session per tab, in that tab’s memory; the part that runs the engine keeps nothing. Reload the tab and restore for that conversation reports “unavailable” rather than store anything.

Configuration

One file, every tool.

The command and every integration read the same configuration. List the terms the model should never see (codenames, clients) and they are renamed like any secret. Nothing is ever written back into it.

~/.config/quis/config.yaml
policies:  user: aam.user  document: aam.documentfail_mode: closedcustom_terms:  - { value: "Project Falcon", category: CODENAME }  - { value: "Acme Corp", category: ORG }

What it never keeps

Your secrets stay in memory.

The map from SECRET_1 back to your key is the most dangerous thing the shield holds. It is treated that way.

  • Memory only

    Maps, originals and raw prompts live in process memory for the session. Never on disk, in logs, crash reports, telemetry or browser storage.

  • Counts, not values

    Logs and summaries carry counts, signal names and categories. Never the values themselves.

  • No new traffic

    Nothing goes anywhere except the model request you were already making, and the hosted gate if you turn it on.

  • Fails closed

    If the engine errors, your newest message is rejected and anything else it could not judge is withheld, rather than sent unjudged, unless you choose fail_mode: open.

Hybrid mode

Judged twice. Your secrets seen once: by you.

On a paid plan, the shield judges locally first, so secrets and personal data are obfuscated on your machine. Only then does the already-obfuscated text go to the hosted gate, with the model you are about to call, for up-to-date, model-specific protection from our own attack research and testing. The hosted service never sees the raw secrets.

Coming soon

See plans

Plainly

What it will not do.

  • It does not moderate the model’s answers. It restores your own placeholders and nothing more.
  • A placeholder the model mangles (Secret_1, SECRET-1) is not restored.
  • System prompts are not judged unless you ask: vendor system prompts look like instructions, because they are.
  • Website changes can break the browser extension until it is updated.