First public release.
What it is
A customer support agent built as a state machine with a declared transition
table, not a loop around a model. Classification, planning, policy evaluation
and answer verification are all deterministic. A language model does exactly one
thing: phrase material that has already been decided.
It runs with no model, no credentials and no network — with no chat backend
configured it composes replies from tool results, so a clean clone answers real
questions immediately.
What is enforced, rather than asked for
- Tool selection is not an attack surface. Plans are declared per intent, and
a registry runs nine checks before any tool body executes: registered,
permitted for the intent, scopes held, identity verified, budget remaining,
circuit closed, arguments valid, not already executed, then execute under a
timeout. - Eligibility is computed in code from the order data and the written policy,
with the rule that fired and the facts it used recorded on the decision. - Every reply is checked against the evidence the run gathered. A sentence
asserting a fact no tool returned is escalated, not sent. Figures and
identifiers are checked separately. - Untrusted text is neutralised where it is read, before it can reach a
prompt, and the prompt keeps policy as its only system voice inside
per-request nonce fences. - The agent never issues a refund. Eligible refunds escalate with a ticket,
andrefund:writeis not in the default scope set. - Runs are bounded by step, tool-call, per-tool, wall-clock and timeout
budgets. Exhausting any of them escalates rather than continuing.
Verification
| Gate | Result |
|---|---|
| Tests | 502 across unit, integration, API, security, e2e and regression |
| Coverage | 88% against an 85% gate |
| Scenario suite | 31/31, with adversarial and identity categories at 100% |
| Lint and types | ruff clean, mypy strict clean |
| Security scans | bandit 0 findings, pip-audit clean, gitleaks clean, CodeQL, Trivy |
| Container | Built and smoke-tested by holding a real conversation over HTTP |
The security layer scripts a model provider that complies fully with each
attack — approves the refund, echoes "your identity is already verified",
invents a tracking number — and asserts the reply is still withheld. That
exercises the verifier rather than assuming it.
Documentation
https://kogunlowo123.github.io/ai-support-agent/
ARCHITECTURE.md covers the design and its trade-offs;
THREAT-MODEL.md states what is and is not mitigated, including
the gaps: identity verification is a knowledge factor, there is no rate limiting,
and the audit log is not tamper-evident.