Build1 publisher3 min readPublished
llm-sentinel runs its ten deterministic scanners on tool output as well as user prompts
The dev.to post announcing llm-sentinel says llm-guard is archived. The replacement is ten pattern-matching scanners with a score threshold each, benchmarked on 133 hand-written cases its author calls a smoke test.
The Engineer · Build desk

What happened
- A dev.to post headlined "llm-guard is archived. I built a deterministic replacement." introduces llm-sentinel as that replacement for LLM input filtering.
- Version 1 ships ten scanners covering prompt injection, secrets, PII, toxicity, gibberish, banned topics, code execution, URL allowlists, token limits and user-supplied regex.
- Policy is composed in code by chaining scanners onto a vault that carries a default score threshold, which an individual scanner can override when it is registered.
- The post instructs users to scan model and tool output as well as user input, on the grounds that untrusted text no longer arrives only from the person typing.
- The bundled benchmark corpora, 133 labelled cases spread across all ten scanners, return 1.00 precision and 1.00 recall for every scanner, and the suite is runnable locally.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- decision Teams pinned to llm-guard now choose between a library of patterns they can read line by line and keeping a model-based classifier alive themselves.
- exposure Third-party tool results come under policy: a fetched README or an API response has to clear a check before the agent acts on the text it carries.
- cost Context-free matching bills the operator in false positives, and the agents most likely to pay are the ones whose tools legitimately return source code or discuss policed topics.
- constraint Until the unicode normalization pass exists, this cannot be the only control on input that may arrive in another language or with homoglyphs substituted in.
Per-scanner thresholds are the part of this design I would copy. The example vault is constructed with `default_threshold=0.5` and then registers `SecretsScanner` at `0.7` [4]. A secrets match therefore needs a stronger signal to block than a prompt-injection match does, on the same scale, in the same pass. That is the right way round for a check whose own documentation says the entropy heuristic flags some non-secrets [13]. Findings come back with the scanner name, a score and the matched spans [5], so moving a threshold is a decision you can make from last week's logs.
The mode in that snippet is `fail_fast`, and the vault is assembled by chaining `.add()` calls [4]. I would expect registration order to decide which finding stops the pass when two scanners would both fire, which matters if you care which of the two your log line names.
The output argument is the reason to look at this at all. "Scan model output too, not just user input," the post says, because "the threat model changed the day agents started executing tool output" [6]. It is the same call in the other direction, `vault.scan(model_output)` [18]. The scanner built for that direction is `code_execution`, which matches `os.system`, `subprocess`, `eval`/`exec` and `pickle.loads` in untrusted tool output [7]. The post's worked example is a compromised API response that thanks you for using it and then suggests running `os.system` [19].
A matcher for those four names has an obvious failure mode on agents that read code. Ordinary Python contains `subprocess` and `eval`; a docs page about serialisation contains `pickle.loads`. The post concedes the equivalent problem for its wordlist scanners, which have no sense of context and "will flag legitimate discussion of the thing they police" [15]. If your tools return repository contents, budget for tuning that scanner or scoping it to the tools whose output should never contain code.
The author reaches the benchmark's weakness first. "A 1.00 on 133 cases is a smoke test proving the patterns fire on the obvious cases. It is not a safety certification," the post says [10]. Spread across ten scanners, that is about 13 cases each [20]. For the score to mean anything on your traffic, your attackers would have to write like the corpus: English, unobfuscated, phrased the way these patterns expect. The post says novel phrasings, non-English attacks and heavy obfuscation with zero-width characters or homoglyphs get through the prompt-injection scanner, and a unicode normalization pass is on the roadmap [12].
Integration is two optional adapters: a FastAPI middleware that blocks with a status code you set, and a LangChain wrapper around a runnable [17]. PII coverage is email, phone number, US SSN and Luhn-validated card, with names, addresses and non-US identifiers out of scope [14]. Redaction "removes matched characters, not meaning", and the post says to pair it with blocking [16]. The post does not give a date for llm-guard's archival or say who archived it [22]. Each scanner's limitations are documented in its docstring [21].
What to watch
- Whether the unicode normalization pass ships, since homoglyph and zero-width obfuscation currently gets past the prompt-injection scanner.
- Whether community-sourced corpora replace the 133 hand-written cases, and what precision and recall do once they land.
- Whether llm-guard's archived repository picks up new maintainers or an active fork.