Use a built-in check
Kindgi has seven built-in checks for common rules: words an answer must or mustn't contain, a pattern it must match, citations, and which tools a turn may call, how many and in what order. A guardrail can name one instead of shipping a check you write yourself.
Name a built-in
Section titled “Name a built-in”In a TypeScript pack, the guardrail names the built-in as its check, gives
its config, and ships no check implementation:
export default { id: 'my-pack.no-guarantees', name: 'Never promise a guarantee', kind: 'zero-llm', check: 'forbidden-substring', config: { patterns: ['guaranteed', 'we promise'] }, action: { 'on-violation': 'halt' }, severity: 'error',};Put it on an agent by its id, as with any guardrail
(Put it on an agent). With
halt, an answer containing "guaranteed" stops the turn
(A halted turn). The failure gives the
check's reason. For a must-cite guardrail on an answer without a citation:
Error [guardrail-violation]: Turn blocked by guardrail 'acme.cite-or-halt': expected >= 1 citations, found 0A Python, Java or Scala pack can't name a built-in yet: a guardrail there is
always defined with its own check (Python's @guardrail decorates a check
function). Write the rule as your own check; the table below says what each
built-in checks.
The built-in checks
Section titled “The built-in checks”A tool list holds tool ids, as <pack>.<tool>. A setting in bold is
required.
| Check | Fails when | config |
|---|---|---|
must-cite |
the answer is empty, or has fewer than minCitations matches of sourcePattern |
minCitations: a whole number, 1 or more (1 by default); sourcePattern: a regular expression (by default, citations in square brackets, such as [ord_1003]) |
never-call-tool |
the turn called any tool in tools |
tools: a list of one or more tool ids |
max-tool-calls |
the turn made more than max tool calls |
max: a whole number, 0 or more (10 by default) |
output-matches |
the answer doesn't match pattern, or, with negate: true, it does |
pattern: a regular expression; flags: regular-expression flags (d, g, i, m, s, u, v, y), such as "i"; negate: true or false |
tool-order |
the tools in sequence weren't called in that order (other calls may come between) |
sequence: a list of one or more tool ids |
required-substring |
the answer is empty, or lacks any of patterns |
patterns: a list of one or more plain-text strings; caseSensitive (false by default) |
forbidden-substring |
the answer contains any of patterns |
patterns: a list of one or more plain-text strings; caseSensitive (false by default) |
A config the check doesn't take is refused: a required setting left out, a
setting of the wrong type, one the check doesn't know, or a regular expression
that doesn't compile. Registering such a guardrail answers
422 guardrail-config-invalid, with each problem in details.issues, and
deploying a pack with one fails with deployment-validation-failed. If one
reaches a turn anyway, its check can't run, so with halt the turn stops
(When the check can't run).
Your own check under a built-in's name
Section titled “Your own check under a built-in's name”The built-in ids are reserved. A pack that ships its own check under one, such
as a defineCheck({ id: 'must-cite', … }), is refused when you build it
(reserved-check-id; in Python, DefinitionError). Give your check a name of
its own, such as my-pack.checks.must-cite, or, to use the built-in, name it
and drop your implementation.
A pack built with a CLI from before 0.1.5 wasn't checked for this, and a current CLI marks a guardrail that only names a built-in. So from runtime 0.1.6, a guardrail that names a built-in, comes with its pack's code, and lacks that mark gets one warning in the runtime's log each time the runtime loads the guardrail. The built-in runs either way. If the guardrail only names the built-in, rebuild the pack with a current CLI and the warning goes. If its module is your own check, rename that check as above: the built-in has been running in its place.