Stop a turn or record a violation
A guardrail's action decides what a failed check does to the turn:
haltstops it. The turn fails withguardrail-violation, and the run has no answer.log-onlylets it finish. The answer goes out, and the failure is recorded on the turn as a violation.
// in guardrails/answer-length/index.tsaction: { 'on-violation': 'log-only' },# in guardrails/answer_length.py@guardrail( id="my-pack.answer-length", name="Answer is short", on_violation="log-only", severity="error", config={"maxChars": 60},)A halted turn
Section titled “A halted turn”With halt, the command fails with the check's reason:
kindgi runs start --agent=my-pack.echo-agent --input='{"userMessage":"hi"}'Error [guardrail-violation]: Turn blocked by guardrail 'my-pack.answer-length': The answer is 86 characters; the limit is 60.The run is failed, and its failureMessage carries the violation:
kindgi runs get <run-id>{ "id": "5202d750-e510-483f-991a-db34c6cba950", … "flowId": "agent.turn", "status": "failed", … "failureMessage": "{\"__agent_turn_failure__\":true,\"error\":{\"code\":\"guardrail-violation\",\"message\":\"Turn blocked by guardrail 'my-pack.answer-length': The answer is 86 characters; the limit is 60.\",\"violations\":[{\"guardrailId\":\"my-pack.answer-length\",\"result\":{\"passed\":false,\"reason\":\"The answer is 86 characters; the limit is 60.\"},\"action\":\"halt\",\"severity\":\"error\",\"at\":\"2026-10-03T20:10:37.910Z\"}],\"evaluationErrors\":[]}}"}Use halt for a rule whose failure makes the answer unusable or unsafe to
show.
A recorded violation
Section titled “A recorded violation”With log-only, the turn completes, and its output lists the violation:
"status": "completed", … "output": { … "response": { "role": "agent", "actor": "my-pack.echo-agent", "content": "Tool responded: {\"echo\":\"hi\",\"echoedAt\":\"2026-10-03T20:10:57.767Z\",\"characterCount\":2}", … }, … "violations": [ { "at": "2026-10-03T20:10:57.958Z", "action": "log-only", "result": { "passed": false, "reason": "The answer is 86 characters; the limit is 60." }, "severity": "error", "guardrailId": "my-pack.answer-length" } ],Use log-only while you find out how often a new rule fails, or for a rule
your app acts on itself: read violations from the turn's result.
Severity
Section titled “Severity”severity is info, warn, error or critical. It's recorded with each
violation, and doesn't change what the action does: a log-only guardrail
can be critical.
Which agents it covers
Section titled “Which agents it covers”A guardrail checks the turns of every agent that lists it. scope narrows
that:
// in guardrails/answer-length/index.tsscope: { when: 'always', agents: ['my-pack.echo-agent'] },# in guardrails/answer_length.pyscope={"when": "always", "agents": ["my-pack.echo-agent"]},agentslists the agents the guardrail applies to. An agent that lists the guardrail but isn't in its scope isn't checked.whenisalways,runtime-onlyorci-only. Aci-onlyguardrail doesn't run in an agent's turn.