Software Engineeringunpacked

LLM guardrails for Claude agents: which rules belong in code, and how to build them

LLM guardrails are the checks around a model that keep its inputs, its actions and its outputs inside your rules. Some guardrails are guidance in the prompt, and Claude follows them very well, but not with a guarantee. Any rule where one miss costs money, trust or safety belongs in code that runs on every call: a screen on what comes in, a hook that can block a tool call, and permissions that limit what the agent can touch at all.

What LLM guardrails are

A model decides what to say and which tool to call. Guardrails decide what's allowed. They sit at four points:

Where Guardrail Kind
What comes in Screen user input with a small, fast model; validate known injection patterns Code
What the agent reads Third-party content only in tool results, marked as untrusted Structure + prompt
What the agent does Hooks that check each tool call; permission rules; least privilege Code
What comes out A JSON schema for the output, validated before use; a person reviews the risky cases Code + people

The prompt still matters: it shapes tone, scope and how Claude refuses. But a prompt is guidance. Code is enforcement.

The rule: code for anything that must always hold

The exam guide for the Claude Certified Architect certification puts it plainly: when compliance has to be deterministic, such as identity verification before financial operations, "prompt instructions alone have a non-zero failure rate".

A simple test decides where a rule goes. If breaking it once costs money, trust or safety, enforce it in code. A refund limit, a verification step before account changes, a folder the agent must never write to: code. A friendly tone, a preferred answer format, which topics to stay on: prompt.

Example: a refund limit the agent can't skip

Take a bike-rental support agent built on the Claude Agent SDK, with a refund tool on its backend MCP server. Rule: refunds over $100 need a person.

```python from claude_agent_sdk import ClaudeAgentOptions, HookMatcher

REASON = "Refunds over $100 need a person. Hand off with a summary."

async def refund_limit(input_data, tool_use_id, context): if input_data["tool_input"].get("amount", 0) > 100: return {"hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": REASON, }} return {} # allow

options = ClaudeAgentOptions(hooks={ "PreToolUse": [HookMatcher(matcher="mcp__cogwheel-backend__issue_refund", hooks=[refund_limit])], }) ```

Three details make it work:

A second gate makes a prerequisite: a PostToolUse hook watches the customer lookup and records, for the session, that the customer was verified. The refund hook then denies any refund for an unverified session, whatever the chat says.

Why hooks hold when prompts don't

In the Agent SDK, when Claude asks for a tool, hooks run first: before deny rules, ask rules, the permission mode and allow rules. The permissions docs add that "a hook deny applies even in bypassPermissions mode". When several hooks disagree, deny wins. And hooks run in your application process, outside Claude's context window, so nothing in the conversation can argue with them.

Claude Code works the same way: Claude Code hooks can block a command or an edit, and permission rules are enforced by Claude Code, not by the model.

Guardrails against prompt injection

Anthropic's guide on jailbreaks and prompt injection separates two threats: a user who attacks your application directly, and instructions hidden in content the agent reads, such as an email, a web page or a tool result. Its main defenses:

  1. Screen input with a lightweight model and a structured output, such as {"is_harmful": true}.
  2. Put untrusted content only in tool results, say where it came from, and state in the system prompt that it is data, not instructions.
  3. JSON-encode third-party strings, so injected text can't break out of its quotes into an instruction.
  4. Limit access. Least privilege, sandboxed tools and narrow permissions keep a successful injection small.
  5. Screen tool outputs with a small model before Claude acts on them, and red-team the agent with poisoned documents before launch.

Don't stop at "no"

A guardrail that blocks without a next step frustrates customers and staff. Pair each hard gate with a path forward: the deny reason tells Claude to hand off to a human, and the hand-off carries a structured summary (customer, booking, amount asked, root cause, recommended action), because the person picking it up can't read the chat.

Guardrails on the Claude Certified Architect exam

Domain 1 of the CCAR-F exam tests this in task 1.4 (programmatic enforcement versus prompt guidance, prerequisite gates, structured handoffs) and task 1.5 (hooks that block a refund above a threshold and redirect to a human). The usual wrong answer is a stronger sentence in the system prompt where the scenario needs a guarantee. See also AI agent architecture for where guardrails sit among the other building blocks.

More in all articles.

Sources: Hooks (Agent SDK); Configure permissions (Agent SDK); Connect to external tools with MCP; Mitigate jailbreaks and prompt injections, read on 22 October 2026; Claude Certified Architect Foundations exam guide v1.0, task statements 1.4 and 1.5.

FAQ

What are LLM guardrails?

Checks around a language model that keep it within your rules: screening what goes in, limiting and checking what it does with tools, validating what comes out, and monitoring the results. They range from prompt instructions to hard gates in code.

Are prompt instructions enough as guardrails?

Not for rules that must always hold. The Claude Certified Architect exam guide notes that prompt instructions alone have a non-zero failure rate when compliance must be deterministic, such as identity checks before financial operations. Use code for those.

How do I block a tool call in the Claude Agent SDK?

Register a PreToolUse hook with a matcher for the tool. Inside it, check the tool input and return a permission decision of deny with a reason. The reason is shown to Claude, so it can change course, for example by handing off to a person.

How do guardrails protect against prompt injection?

Deliver third-party content only in tool results, say where it came from, tell Claude in the system prompt that such content is data and not instructions, give the agent the least access it needs, and screen tool outputs with a small model before Claude acts on them.