Configure a guardrail
A check's settings (a limit, a list of words, a tool's id) don't belong in
its code. The guardrail declares them as config, and the check runs with
them. The answer-length guardrail has one setting,
maxChars:
// in guardrails/answer-length/index.tsexport const check = defineCheck({ id: 'my-pack.checks.answer-length', kind: 'zero-llm', configSchema: z.object({ maxChars: z.number().int().positive().default(500) }), evaluate: async (config, trace) => { // config.maxChars: 60 here, or 500 when the declaration gives none // … },});
export default { id: 'my-pack.answer-length', // … check, config: { maxChars: 60 }, // …};configSchema describes the settings; config in the declaration gives
their values. The check's evaluate gets those values, typed from the
schema.
# in guardrails/answer_length.pyclass Config(BaseModel): max_chars: int = Field(500, alias="maxChars", gt=0)
@guardrail( id="my-pack.answer-length", # … config={"maxChars": 60},)def answer_length(config: Config, trace: RunTrace) -> CheckResult: ...The type of the check's first parameter describes the settings; config=
gives their values, keyed by their wire names, the aliases: maxChars, not
max_chars.
Change a setting
Section titled “Change a setting”Edit the value and save; the next turn uses it. With maxChars: 300, the
dev-echo answer from Write a guardrail
passes:
kindgi runs start --agent=my-pack.echo-agent --input='{"userMessage":"hi"}' "status": "completed", … "violations": [],The registered guardrail shows the values it runs with:
kindgi guardrails get my-pack.answer-length "config": { "maxChars": 300 },What the check receives
Section titled “What the check receives”The check gets config resolved by its schema, in both SDKs:
- Defaults are filled in. A guardrail without
configruns with the schema's defaults; here, a limit of 500. - A value that doesn't fit is refused before any turn runs, and the message names the setting.
Zod's .default() and a JSON Schema's default both apply. When the pack is
indexed, each guardrail's config is checked against its configSchema, so
kindgi dev reports the file and kindgi build refuses the pack. With
config: { maxChars: -5 }:
guardrails/answer-length/index.ts: guardrail my-pack.answer-length's config doesn't fit its configSchema at /maxChars: must be > 0A setting the schema requires, with no default, must be in config:
guardrails/answer-length/index.ts: guardrail my-pack.answer-length's config doesn't fit its configSchema: must have required property 'maxChars'In a deployment, a guardrail registered through the API
(kindgi guardrails register) names the pack's check with its own config.
A config that doesn't fit the check's configSchema is refused
(422 guardrail-config-invalid), and nothing is registered:
Error [invalid-request]: Guardrail "acme.strict-length" doesn't fit check "my-pack.checks.answer-length": config.maxChars must be > 0. ✗ /config/maxChars: config.maxChars must be > 0.Under kindgi dev the indexer has refused such a config already.
A guardrail registered before 0.1.5, or against a pack deployed before
0.1.5, wasn't checked. The pack service checks the config on every call, as
sent, against the indexed configSchema, so the check doesn't run, and every
turn the guardrail checks fails, whatever its action. kindgi runs start
exits 1 with:
Error [run-failed]: input-validation-failed: Check "my-pack.checks.answer-length" config failed validation at /maxChars: must be > 0To fix it, unregister it and register it again with a config that fits. A pack deployed before 0.1.5 needs one redeploy for registration to check it.
The check gets config parsed into its type:
-
Defaults are filled in. Give every field a default: a required field with no value isn't caught when the pack is indexed, and fails every turn the guardrail checks, whatever its action.
kindgi runs startexits 1 withError [run-failed]: input-validation-failed: Check "my-pack.req-cfg" config failed validation: must have required property 'maxChars'. -
Values are checked where they're declared. A value that doesn't fit is a
DefinitionError, andpython -m kindgi.pack index(andkindgi dev) reports the file:Guardrail "my-pack.answer-length": config does not fit its type: 1 validation error for ConfigmaxCharsInput should be greater than 0 [type=greater_than, input_value=-5, input_type=int] -
A key that isn't a wire name is ignored.
config={"max_chars": 60}isn't an error: the field keeps its default.