Skip to content

Releases: vstorm-co/pydantic-ai-shields

0.3.0

28 Mar 02:53
4b70e4f

Choose a tag to compare

[0.3.0] - 2026-03-28

Changed

  • Renamed to pydantic-ai-shields — the package is now focused exclusively on guardrail capabilities built on
    pydantic-ai's native capabilities API. The old middleware layer (MiddlewareAgent, AgentMiddleware, etc.) has been
    removed — pydantic-ai v1.71+ provides this natively.

Added

  • 5 infrastructure capabilities:
    • CostTracking — token usage tracking, USD cost calculation via genai-prices, budget enforcement
    • ToolGuard — block tools via prepare_tools or require approval via before_tool_execute
    • InputGuard — block/check user input with pluggable guard function (sync or async)
    • OutputGuard — block/check model output with pluggable guard function (sync or async)
    • AsyncGuardrail — run guardrail concurrently with LLM call, 3 timing modes
  • 5 built-in content shields (zero external dependencies):
    • PromptInjection — detect prompt injection / jailbreak across 6 categories with 3 sensitivity levels
    • PiiDetector — detect PII (email, phone, SSN, credit card, IP) with block or log action
    • SecretRedaction — block API keys, tokens, credentials in model output (OpenAI, Anthropic, AWS, GitHub,
      Slack, JWT, private keys)
    • BlockedKeywords — block forbidden keywords/phrases with case, whole-word, and regex modes
    • NoRefusals — block LLM refusals with 10 built-in patterns and partial refusal support

Removed

  • All legacy middleware modules: MiddlewareAgent, AgentMiddleware, MiddlewareToolset, MiddlewareChain,
    MiddlewareContext, ConditionalMiddleware, ParallelMiddleware, AsyncGuardrailMiddleware,
    CostTrackingMiddleware, decorators, config loaders, pipeline spec, builder
  • All legacy examples and documentation

0.2.4

19 Mar 15:24
398719f

Choose a tag to compare

[0.2.4] - 2026-03-19

Fixed

  • MiddlewareAgent missing description property — pydantic-ai added description as an abstract property on AbstractAgent, causing MiddlewareAgent instantiation to fail with reportAbstractUsage. Delegates to the wrapped agent with a fallback for older pydantic-ai versions.

0.2.3

12 Mar 02:01
3d6351f

Choose a tag to compare

[0.2.3] - 2026-03-11

Fixed

  • MiddlewareAgent.iter() now calls after_run and on_error middleware — previously only before_run was invoked, making middleware unusable for post-processing (e.g. audit logging, cost tracking) when using iter() / run_stream(). after_run is called in reverse order after iteration completes, on_error is called when an exception propagates out of the async with block. (#17)

0.2.2

26 Feb 23:53
785a49c

Choose a tag to compare

[0.2.2] - 2026-02-26

Changed

  • Replaced pydantic-ai dependency with pydantic-ai-slim — reduces dependency bloat and avoids pulling unnecessary model provider SDKs. All pydantic_ai.* imports work identically with the slim package (#14)

0.2.1

15 Feb 23:05
f87cb29

Choose a tag to compare

[0.2.1] - 2025-02-15

Added

  • Cost Tracking MiddlewareCostTrackingMiddleware for automatic token usage and USD cost monitoring
    • Tracks cumulative input/output tokens and USD costs across agent runs
    • USD cost calculation via genai-prices library (supports "provider:model" format)
    • budget_limit_usd — enforces cost budget limits, raises BudgetExceededError when exceeded
    • on_cost_update callback with CostInfo dataclass (supports sync and async)
    • reset() method to clear accumulators
    • create_cost_tracking_middleware() factory function
  • BudgetExceededError exception for budget limit enforcement
  • run_usage metadata — MiddlewareAgent now stores result.usage() in context metadata after each run, enabling cost tracking and other usage-aware middleware

Changed

  • before_model_request hook — now invoked via pydantic-ai's history processor mechanism instead of manual message interception. This ensures the hook fires for every model request in both run() and iter() modes.
  • Toolset wrappingMiddlewareAgent now always wraps all toolsets (agent's own + explicitly passed) using agent.override(toolsets=...), preventing duplicate tool registration.
  • ToolBlocked handlingMiddlewareToolset now catches ToolBlocked exceptions in before_tool_call and returns a descriptive string instead of raising, avoiding message ordering issues with pydantic-ai retries.

Dependencies

  • Added genai-prices>=0.0.49 as a required dependency (for cost calculation)

0.2.0

13 Feb 00:30

Choose a tag to compare

[0.2.0] - 2025-02-12

Added

  • Middleware Chains - MiddlewareChain for grouping middleware into reusable, ordered units
    • Fluent API: add(), insert(), remove(), replace(), pop(), clear(), copy()
    • Chain composition: chains flatten when added to other chains
    • Operator support: + and += for combining chains
    • Iteration support: len(), [], in, iteration
  • Conditional Middleware - ConditionalMiddleware for branching execution based on runtime conditions
    • Route to different middleware based on predicate functions
    • Supports single middleware or middleware pipelines for each branch
    • Predicate receives ScopedContext for context-aware decisions
    • when(condition, then, otherwise) helper for fluent syntax
  • Pipeline Spec Builder - PipelineSpec for building middleware pipelines as portable config dictionaries
    • Fluent builder API: add_type(), add_chain(), add_parallel(), add_when()
    • Export to files: dump(format="json"|"yaml"), save(path) with auto-detection from extension
    • Direct compilation: compile(compiler) delegates to compiler
    • Helper functions: type_node(), chain_node(), parallel_node(), when_node()
  • Config Loaders - Functions to load middleware pipelines from JSON/YAML
    • load_middleware_config_text(text, registry, predicates) - parse from string
    • load_middleware_config_path(path, registry, predicates) - parse from file
    • Auto-detection of format from file extension or content
    • Registration helpers: register_middleware(), register_predicate() decorators
  • Pipeline Compiler - MiddlewarePipelineCompiler for compiling config dictionaries into middleware
    • MiddlewareRegistry for storing middleware factories and predicates
    • Built-in node handlers: type, chain, parallel, when
    • Extensible via register_node_handler() for custom node types
    • Convenience wrappers: build_middleware(), build_middleware_list()
  • Context Sharing System - Share data between middleware hooks with access control
    • MiddlewareContext class for managing shared state across hooks
    • ScopedContext class for enforcing access control based on hook execution order
    • HookType enum defining hook execution order: BEFORE_RUN(1)BEFORE_MODEL_REQUEST(2)BEFORE_TOOL_CALL(3)ON_TOOL_ERROR(4)AFTER_TOOL_CALL(5)AFTER_RUN(6)ON_ERROR(7)
    • Immutable config for read-only global settings
    • Mutable metadata for shared state
    • Namespaced hook storage with strict access control
    • Hooks can only write to their own namespace
    • Hooks can only read from earlier or same-phase hooks
    • Enable context by passing a MiddlewareContext instance to MiddlewareAgent
  • Parallel Execution - ParallelMiddleware for running multiple middleware concurrently
    • AggregationStrategy enum: ALL_MUST_PASS, FIRST_SUCCESS, RACE, COLLECT_ALL
    • Early cancellation: remaining tasks are cancelled when result is determined
    • Configurable timeout support
  • Async Guardrails - AsyncGuardrailMiddleware for concurrent guardrail + LLM execution
    • GuardrailTiming enum: BLOCKING, CONCURRENT, ASYNC_POST
    • cancel_on_failure option to short-circuit LLM calls when guardrail fails
    • Background task management for async post-processing
  • Tool Name Filtering - Scope middleware to specific tools
    • tool_names: set[str] | None class attribute on AgentMiddleware (default None = all tools)
    • _should_handle_tool(tool_name) helper method
    • Filtering in MiddlewareToolset, MiddlewareChain, and composite middleware
    • tools parameter on @before_tool_call, @after_tool_call, @on_tool_error decorators
  • on_tool_error Hook - Handle tool execution failures with tool-specific context
    • on_tool_error(tool_name, tool_args, error, deps, ctx) method on AgentMiddleware
    • Returns Exception | None — return a different exception or None to re-raise original
    • New HookType.ON_TOOL_ERROR enum value
    • Integrated in MiddlewareToolset, MiddlewareChain, ParallelMiddleware, ConditionalMiddleware, AsyncGuardrailMiddleware
    • @on_tool_error decorator with optional tools parameter
  • Hook Timeout - Per-middleware timeout enforcement
    • timeout: float | None class attribute on AgentMiddleware (default None = no timeout)
    • call_with_timeout() utility wrapping asyncio.wait_for()
    • Enforced in MiddlewareToolset and MiddlewareAgent for all hooks
  • Permission Decision Protocol - Structured ALLOW/DENY/ASK decisions for tool authorization
    • ToolDecision enum: ALLOW, DENY, ASK
    • ToolPermissionResult dataclass with decision, reason, and optional modified_args
    • before_tool_call return type extended: dict[str, Any] | ToolPermissionResult
    • PermissionHandler callback type for ASK decisions: async (tool_name, tool_args, reason) -> bool
    • permission_handler parameter on MiddlewareAgent and MiddlewareToolset
  • New exceptions:
    • ParallelExecutionFailed - When parallel execution fails
    • GuardrailTimeout - When guardrail times out
    • AggregationFailed - When result aggregation fails
    • MiddlewareConfigError - When config loading or compilation fails
    • MiddlewareTimeout - When a middleware hook exceeds its timeout
  • Project restructured to src/ layout

Changed

  • BREAKING: All hook signatures now include ctx: ScopedContext | None = None as the last keyword argument
    • before_run(prompt, deps, ctx)
    • after_run(prompt, output, deps, ctx)
    • before_model_request(messages, deps, ctx)
    • before_tool_call(tool_name, tool_args, deps, ctx) — return type extended to dict | ToolPermissionResult
    • on_tool_error(tool_name, tool_args, error, deps, ctx)NEW
    • after_tool_call(tool_name, tool_args, tool_result, deps, ctx)
    • on_error(error, deps, ctx)
  • __version__ now uses importlib.metadata instead of a hardcoded string
  • Bumped minimum pydantic-ai-slim dependency from >=0.1.0 to >=1.38

Fixed

  • Replaced private pydantic-ai API usage with public alternatives (#11 by @pedroallenrevez)
    • from pydantic_ai._run_context import RunContextfrom pydantic_ai import RunContext
    • AgentRunResult(output=..., _output_tool_name=..., ...)dataclasses.replace(result, output=output)
    • Removed dependency on pydantic_ai._utils.UNSET/Unset by simplifying override() to use **kwargs pass-through

0.1.0

29 Dec 00:33

Choose a tag to compare

0.1.0 - 2024-12-29

Added

  • Initial release
  • AgentMiddleware base class with lifecycle hooks:
    • before_run - Called before agent runs
    • after_run - Called after agent finishes
    • before_model_request - Called before each model request
    • before_tool_call - Called before tool execution
    • after_tool_call - Called after tool execution
    • on_error - Called when errors occur
  • MiddlewareAgent - Wrapper agent that applies middleware
  • MiddlewareToolset - Toolset wrapper for tool call interception
  • Decorator-based middleware creation:
    • @before_run
    • @after_run
    • @before_model_request
    • @before_tool_call
    • @after_tool_call
    • @on_error
  • Custom exceptions:
    • MiddlewareError - Base exception
    • InputBlocked - Block input
    • ToolBlocked - Block tool calls
    • OutputBlocked - Block output
  • Full type safety with generics
  • 100% test coverage
  • Documentation with MkDocs