Normandy.Agents.ValidationMiddleware (normandy v0.6.2)

View Source

Validation middleware for BaseAgent input/output schemas.

Provides automatic validation of agent inputs and outputs using Normandy schemas, ensuring type safety and constraint enforcement throughout the agent lifecycle.

Features

  • Input Validation: Validates user inputs before processing
  • Output Validation: Validates LLM responses before returning
  • Clear Error Messages: Path-based validation errors
  • Optional Enforcement: Can be disabled for backward compatibility

Usage

# Validate input
case ValidationMiddleware.validate_input(config, user_input) do
  {:ok, validated_input} -> # proceed
  {:error, errors} -> # handle validation failure
end

# Validate output
case ValidationMiddleware.validate_output(config, response) do
  {:ok, validated_response} -> # proceed
  {:error, errors} -> # handle validation failure
end

Summary

Functions

Validates and returns a sanitized error message for display.

Formats validation errors into user-friendly messages.

Validates user input against the agent's input schema.

Validates LLM output against the agent's output schema.

Checks if validation is enabled for the agent configuration.

Functions

error_message(errors)

@spec error_message(list()) :: String.t()

Validates and returns a sanitized error message for display.

Converts validation error list into a human-readable string.

Examples

iex> errors = [
...>   %{path: [:name], message: "is required", constraint: :required},
...>   %{path: [:age], message: "must be at least 0", constraint: :minimum}
...> ]
iex> ValidationMiddleware.error_message(errors)
"Validation failed:\n  - name: is required\n  - age: must be at least 0"

format_validation_errors(context, errors)

@spec format_validation_errors(String.t(), list()) :: list()

Formats validation errors into user-friendly messages.

Examples

iex> errors = [%{path: [:name], message: "is required", constraint: :required}]
iex> ValidationMiddleware.format_validation_errors("Input", errors)
[%{
  type: "Input validation error",
  path: [:name],
  message: "is required",
  constraint: :required
}]

validate_input(base_agent_config, input)

@spec validate_input(Normandy.Agents.BaseAgentConfig.t(), map() | struct() | nil) ::
  {:ok, struct() | term()} | {:error, list()} | {:ok, nil}

Validates user input against the agent's input schema.

Returns {:ok, validated_struct} on success or {:error, errors} on failure. If no input schema is defined or validation is disabled, returns the input unchanged.

Examples

iex> config = %BaseAgentConfig{input_schema: %MyInputSchema{}}
iex> ValidationMiddleware.validate_input(config, %{query: "test"})
{:ok, %MyInputSchema{query: "test"}}

iex> ValidationMiddleware.validate_input(config, %{invalid: "data"})
{:error, [%{path: [:query], message: "is required", constraint: :required}]}

validate_output(base_agent_config, output)

@spec validate_output(Normandy.Agents.BaseAgentConfig.t(), struct() | map() | nil) ::
  {:ok, struct()} | {:error, list()} | {:ok, nil}

Validates LLM output against the agent's output schema.

Returns {:ok, validated_struct} on success or {:error, errors} on failure. If no output schema is defined or validation is disabled, returns the output unchanged.

Examples

iex> config = %BaseAgentConfig{output_schema: %MyOutputSchema{}}
iex> ValidationMiddleware.validate_output(config, %{result: "success"})
{:ok, %MyOutputSchema{result: "success"}}

iex> ValidationMiddleware.validate_output(config, %{invalid: "data"})
{:error, [%{path: [:result], message: "is required", constraint: :required}]}

validation_enabled?(arg1)

@spec validation_enabled?(Normandy.Agents.BaseAgentConfig.t()) :: boolean()

Checks if validation is enabled for the agent configuration.

Validation is considered enabled if the agent has schemas with validation support.

Examples

iex> config = %BaseAgentConfig{input_schema: %MySchema{}}
iex> ValidationMiddleware.validation_enabled?(config)
true