Skip to content
Blog

Sanitizing Agent Inputs: Prompt Validation Before Inference

Protect PydanticAI agents against prompt injection, jailbreaks, and malformed inputs using typed input contracts and pre-inference sanitization filters.

Published on September 11, 2026

AI Assistant

Prompt injection remains the single biggest security vulnerability in modern LLM applications (OWASP LLM01). When malicious users inject control characters, override system instructions, or embed hidden prompt instructions inside user inputs, agents can be tricked into leaking sensitive data or executing unauthorized tool calls.

Securing agents requires a Defense-in-Depth input validation pipeline that sanitizes and validates user prompts before they are sent to the model for inference.

Input Sanitization Strategy

A complete input validation pipeline performs three sequential checks on every user prompt:

  1. Structural & Character Sanitization: Stripping dangerous control sequences, zero-width characters, and excessive whitespace.
  2. Type & Length Validation: Enforcing maximum length limits and validating expected payload types (JSON, UUID, email format).
  3. Prompt Injection Classifier: Scoring the prompt against known adversarial injection signatures using lightweight local classifiers before invoking expensive LLMs.
[User Input] --> [Character Sanitizer] --> [Pydantic Contract] --> [Injection Detector] --> [LLM Engine]

Input Sanitization with PydanticAI

PydanticAI introduces type-safe agent definitions where dependencies and input parameters are strictly typed using Pydantic models.

from pydantic import BaseModel, Field, field_validator
from pydantic_ai import Agent, RunContext
import re

class UserQueryInput(BaseModel):
    query: str = Field(..., min_length=5, max_length=1000, description="User search or action query")
    user_id: str = Field(..., pattern=r"^USR-\d{6}$")

    @field_validator("query")
    @classmethod
    def sanitize_prompt_text(cls, v: str) -> str:
        # Strip system instruction override patterns and control tokens
        forbidden_patterns = [
            r"ignore previous instructions",
            r"system prompt override",
            r"you are now in developer mode",
            r"<\|im_start\|>",
            r"<\|im_end\|>"
        ]
        
        sanitized = v.strip()
        for pattern in forbidden_patterns:
            if re.search(pattern, sanitized, re.IGNORECASE):
                raise ValueError(f"Input contains prohibited prompt injection signature: '{pattern}'")
        
        # Remove null bytes and non-printable control characters
        sanitized = re.sub(r"[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]", "", sanitized)
        return sanitized

# Instantiate PydanticAI Agent with validated input context
agent = Agent(
    "gemini-1.5-flash",
    deps_type=UserQueryInput,
    system_prompt="You are an enterprise data assistant. Answer queries strictly using provided tools."
)

@agent.system_prompt
def add_user_context(ctx: RunContext[UserQueryInput]) -> str:
    return f"Active User: {ctx.deps.user_id}. Query: {ctx.deps.query}"

Running the Safe Execution Pipeline

def process_user_request(raw_user_id: str, raw_query: str):
    try:
        # 1. Pydantic validation handles sanitization and pattern matching
        validated_input = UserQueryInput(user_id=raw_user_id, query=raw_query)
        
        # 2. Execute PydanticAI Agent safely
        result = agent.run_sync(validated_input.query, deps=validated_input)
        return result.data

    except ValueError as validation_err:
        # Catch prompt injection attempts cleanly before model invocation
        return f"Request Rejected: {validation_err}"

Key Security Takeaways

  • Pre-Inference Rejection: Filtering out bad input at the application layer saves model token costs and eliminates execution exposure.
  • Never Concatenate Raw Input into System Prompts: Keep user inputs strictly separated in user message turns or validated context objects.
  • Audit Logging: Log rejected inputs and source IPs to identify active scanning or probing attempts against your agent endpoints.

To learn more about type-safe agent design, dependency injection, and model evaluation with PydanticAI, check out the PydanticAI Framework Documentation.