Skip to content

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.ts
export 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.

Edit the value and save; the next turn uses it. With maxChars: 300, the dev-echo answer from Write a guardrail passes:

Terminal window
kindgi runs start --agent=my-pack.echo-agent --input='{"userMessage":"hi"}'
"status": "completed",
…
"violations": [],

The registered guardrail shows the values it runs with:

Terminal window
kindgi guardrails get my-pack.answer-length
"config": {
"maxChars": 300
},

The check gets config resolved by its schema, in both SDKs:

  • Defaults are filled in. A guardrail without config runs 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 > 0

A 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 > 0

To 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.