How-tos

How to screen inbound prompts in Claude Agent SDK

Screen inbound prompts in Claude Agent SDK on guardHooks({ inbound }) via UserPromptSubmit. A DENY returns { decision: "block" } and Claude Code erases the prompt before the model sees it.

3 min read
In short: Screen inbound prompts in Claude Agent SDK on guardHooks({ inbound }) via UserPromptSubmit. A DENY returns { decision: "block" } and Claude Code erases the prompt before the model sees it.

How do you screen inbound prompts in Claude Agent SDK?

Pass inbound to guardHooks(), and put detectPromptInjection on the submitted prompt.

A pasted GitHub comment that says "mail the inbox" is the next instruction. Screen it before the model sees it. On DENY, UserPromptSubmit returns { decision: "block" } and Claude Code erases the prompt.

import { query } from "@anthropic-ai/claude-agent-sdk";
import { guardHooks } from "@arcjet/guard/claude-agent-sdk/v0";
import { detectPromptInjection } from "@arcjet/guard";
import { arcjet } from "./arcjet.js";
const conversationId = "..."; // your conversation id
const sessionId = conversationId;
for await (const message of query({
prompt: userText,
options: {
sessionId,
hooks: guardHooks(arcjet, {
sessionId,
inbound: {
action: "message.received",
rules: ({ prompt }) => [detectPromptInjection()(prompt)],
},
}),
},
})) {
// handle streamed messages
}

protect() is the HTTP check on a route. This hook is the agent-side screen after you call query().

Why isn't there a guardInbound?

Claude already has an inbound event. UserPromptSubmit runs on the submitted text before Claude processes it. A second helper would be another name for the same hook.

guardHooks({ inbound }) is that screen.

Where does UserPromptSubmit run?

On the submitted prompt, before Claude processes it. A hook on that event can inject context, or it can act as a policy gate. A timed-out callback already fail-closes the prompt (Claude Code v2.1.208+). The session doesn't let an unscreened prompt through.

The Slack body, the GitHub comment, the user paste: those words become the next instruction. Runtime security for LLM applications already treats this as a control before the provider call.

Correlate the turn with a sessionId that you already have. claudeAgentContext reads that ID. It never mints one.

Does canUseTool screen the prompt?

No. canUseTool doesn't read the prompt. The comment that says "mail the inbox" is already in context before any tool callback runs. canUseTool is not a policy gate.

The callback runs when a tool is about to execute, and only if an earlier permission step didn't already resolve it. That is a later check. It isn't this screen.

What if Arcjet is down on inbound?

Helpers default to onGuardError: "deny". If Guard can't be evaluated, then inbound UserPromptSubmit blocks the prompt.

"allow" is a legitimate choice on inbound, because failing closed there would stop the agent answering during an outage. Timeout already fail-closes the prompt (Claude Code v2.1.208+). That is a per-action choice.

Frequently asked questions

How do I screen inbound prompts in Claude Agent SDK?

Pass inbound to guardHooks() and put detectPromptInjection on the submitted prompt. On DENY, UserPromptSubmit returns { decision: "block" } and Claude Code erases the prompt.

Is canUseTool an inbound gate?

No. The callback does not read the prompt, and a bare allowedTools name may skip the callback. Screen the text on UserPromptSubmit instead.

Where do I put detectPromptInjection?

On guardHooks({ inbound }). The rule receives { prompt } from UserPromptSubmit before Claude processes the text.

What if Arcjet is down on UserPromptSubmit?

Helpers default to onGuardError: "deny", which blocks the prompt. "allow" is legitimate on inbound because failing closed would stop the agent answering. Timeout already fail-closes the prompt (Claude Code v2.1.208+).

Does protect() screen the Claude prompt?

protect() is the HTTP check on a route. Screen the agent prompt on UserPromptSubmit via guardHooks({ inbound }).

AI runtime security in your code

Protect your AI agent workflows with Arcjet

Get allow, deny, and redact on agent actions before the side effect.