Download all docs
modifiers

Validation

Defines JSON Schema input and output rules that are enforced at the request phase — before an actor or frontend element runs — rejecting non-conforming data with a structured HTTP 422 so malformed requests fail early and consistently.

Working with it

Opening a Validation launches a code editor — its dedicated working surface.

How it appears

The same element type rendered as a definition, a circle instance, and a live workspace card.

Vl
type

Validation

Validate and sanitize input data

modifiersmodifierdefinition

When to use / not

When to use

  • Enforcing the shape of requests to an element before any logic runs — required fields, types, bounds — with a portable JSON Schema.
  • Returning consistent, structured 422 errors across endpoints instead of ad-hoc per-handler validation.
  • Hardening an exposed surface: rejecting oversized payloads and unexpected field injection at the door.

When not to use

  • Defining a reusable data shape for storage or $ref — that is data/schema; validation enforces rules on a request, schema describes a type.
  • Filtering or transforming content (e.g. profanity) rather than rejecting it — see modifiers/filter-words.

Topology

Attaches to another element as a modifier, shaping that element's behaviour rather than running on its own.

Properties

schemaobject
JSON Schema for input validation
sanitizationobject
Input sanitization options
coercionobject
Type coercion settings
defaultsobject
Default values for missing fields
error_handlingobject
Error handling configuration

Capabilities

Defined for this element
  • Evaluate
  • Observe

Operations

  • attachPOST
  • deleteDELETE
  • detachPOST
  • disablePOST
  • enablePOST
  • evaluatePOST
  • getGET
  • get_attached_modifiersGET
  • intentionGET
  • list_attachmentsGET
  • readme_updatePOST
  • schemaGET
  • updatePATCH
  • validatePOST

Ports

Inputs

  • input_schemaconfig
  • output_schemaconfig
  • sanitizeconfig
  • coerceconfig

Composition

Attaches
Referenced by

Errors / when it fails

At least one of input_schema or output_schema must be defined
Fails unless: input_schema is not None or output_schema is not None

Validation rules

  • Non-strict validation - additional properties are allowed
  • Validation failures only warn - invalid data may proceed

Validation (validation)

Category: modifiers | Form: | Symbol: Vl

Validate and sanitize input data

Validates and sanitizes input data before it reaches attached elements. Cascade strategy: restrictive — when inherited and local validation configs conflict, the stricter rules win. Evaluation order 300 (runs late, after most other middleware). Applies to actors and frontend. Fails with HTTP 422 (Unprocessable Entity) when validation fails. Spec defines a JSON Schema that input must match. The validate operation returns valid (bool), errors (array of path/message/code), and sanitized data. The schema operation returns the current JSON Schema definition. Use validation for input shape/type checking; use auth-policy for access control. Common mistake: validation runs at evaluation_order 300.

Guide

Overview

A Validation modifier defines input and output schema rules that are enforced on requests before they reach an actor or frontend element. Validation runs at the request phase, before any actor logic executes, and returns HTTP 422 with structured errors when data does not conform.

Why Validation Exists

  • Early Rejection: Reject malformed requests before expensive processing
  • Consistent Errors: Standardized error format across all endpoints
  • Schema Enforcement: JSON Schema-based rules that are readable and portable
  • Security: Prevent oversized payloads and unexpected field injection

Configuration

Basic Example

element_type: validation
slug: user-input-validation
name: User Input Validation

spec:
  input:
    type: object
    required:
      - email
      - name
    properties:
      email:
        type: string
        format: email
      name:
        type: string
        minLength: 1
        maxLength: 100
      age:
        type: integer
        minimum: 0
        maximum: 150

Output Validation

spec:
  output:
    type: object
    properties:
      id:
        type: string
        format: uuid
      created_at:
        type: string
        format: date-time

Additional Options

spec:
  input:
    type: object
    properties:
      payload:
        type: object

  # Reject requests with extra fields not in schema
  additional_properties: false

  # Maximum request body size
  max_body_bytes: 1048576  # 1 MB

Inheritance

When multiple validation modifiers are attached at different scopes (circle, project, element), the most restrictive rules win. A child element cannot relax a constraint set by a parent.

Error Response

When validation fails, the response is HTTP 422 with a structured error body:

{
  "error": "validation_failed",
  "message": "Request did not pass validation",
  "details": [
    {
      "field": "email",
      "message": "must be a valid email address"
    }
  ]
}

Files

  • README.md - Documentation
  • .triform/definition.yaml - Element type definition
  • .triform/properties.yaml - Configurable properties
  • .triform/contract.yaml - Bonds and capabilities
  • .triform/ops.yaml - Operations

Runtime Behavior

PropertyValue
Cascaderestrictive — strictest schema wins across scopes
Eval Order300
Phaserequest
Fail ActionHTTP 422 (Unprocessable Entity) with field-level error details
Applies Toactors, frontend

Relationships

  • Attaches to: circle

Capabilities

  • json-schema: JSON Schema validation
  • sanitize: Input sanitization
  • coerce: Type coercion
  • detailed-errors: Detailed validation errors

Properties

PropertyTypeDefaultDescription
schemaobjectJSON Schema for input validation
sanitizationobjectInput sanitization options
coercionobjectType coercion settings
defaultsobjectDefault values for missing fields
error_handlingobjectError handling configuration

Operations

attach

Post /ops/attach | Auth: Read

Attach this modifier to a target element

Attaches this modifier to a target element. The target_id must be a UUID of an existing element that supports this modifier type (check applies_to in definition.yaml). Priority controls evaluation order when multiple modifiers of the same type are attached — lower priority runs first. The attachment is stored in element_modifiers table. Cascade resolution runs at bond-time to merge this modifier into the target’s resolved config. Common mistake: attaching to an incompatible element type — check topology rules first.

delete

Delete /ops/delete | Auth: Admin

Delete element (soft delete)

Soft delete — sets state to ‘deleted’ but retains the record. Cannot delete elements that have children (has_no_bond precondition) or active runs. Requires admin auth and confirmation.

detach

Post /ops/detach | Auth: Read

Detach this modifier from a target element

Removes this modifier from a target element. Requires the target_id. Pervasive modifiers (audit, policy) can only be detached at the level they were originally attached — inherited pervasive modifiers cannot be detached by child elements. After detach, cascade resolution re-runs to remove this modifier’s effect from the resolved config.

disable

Post /ops/disable | Auth: Admin

Disable element (hides and prevents use)

Idempotent — safe to call on already-disabled elements. Optionally pass a reason string. Disabled elements cannot be invoked or executed. Inverse of enable.

enable

Post /ops/enable | Auth: Admin

Enable element (makes usable and visible)

Idempotent — safe to call on already-enabled elements. Transitions element to ready/enabled state. Cannot enable deleted elements. Inverse of disable.

evaluate

Post /ops/evaluate | Auth: Read

Evaluate modifier against current context

Evaluates this modifier against a context and optional target_id. Returns applies (bool), result (modifier-specific), and message. For modifiers without custom evaluation logic, returns a default pass result. Auth-policy returns allowed/denied. This is the explicit evaluation endpoint — during normal request flow, modifiers are evaluated automatically by the cascade resolver as middleware.

get

Get /ops/get | Auth: Read

Get element details

Element is already resolved by the routing layer — this returns the cached element, not a fresh DB query. Use the path /api/{circle}/{slug} to address elements.

get_attached_modifiers

Get /ops/attached/{target_id} | Auth: Read

Get all modifiers attached to a target element

Lists all modifiers attached to a specific target element, including modifier_id, type, subcategory, and priority. Useful for debugging cascade resolution or understanding which policies apply to an element before invoking it.

intention

Get /ops/intention | Auth: Read

Get element intention with full inheritance chain

Returns three levels: direct (this element’s intention), inherited (from category and root), and resolved (final merged intention). Useful for understanding an element’s purpose in context of its hierarchy.

list_attachments

Get /ops/targets | Auth: Read

List all elements this modifier is attached to

Returns all target elements where this modifier is currently applied. Shows target_id, target_type, priority, and cascade_policy.

readme_update

Post /ops/readme_update | Auth: Write

Update element README.md content

Creates or overwrites README.md in the element’s git repo. Commits to the draft branch. Content must be provided as a markdown string.

schema

Get /ops/schema | Auth: Read

Get the validation schema

Returns the JSON Schema definition that this validation modifier enforces. Use to inspect expected input format before calling validate, or to generate client-side validation.

update

Patch /ops/update | Auth: Write

Update element

Partial update — send only the fields you want to change. spec, name, and intention are all independently optional. spec MUST be a JSON object when present; deep-merged into the existing spec by default. Empty {"spec":{}} preserves existing spec content but still records a new version (no-op for content, not for version state). To clear/replace the entire spec wholesale send {"spec":{...},"deep":false}. List-typed spec fields use replace semantics (the patch list replaces the existing list, no array merging). Coordinates Git + DB writes. Slug cannot be changed after creation.

validate

Post /ops/validate | Auth: Read

Validate data against this rule’s schema

Validates the input payload directly against this element’s JSON Schema. Returns valid (bool), errors (array with path, message, code for each violation), and sanitized (cleaned data if valid). Pass the data fields at the top level — no wrapper needed. Idempotent — use for pre-flight validation before submitting to an actor. During normal request flow, validation runs automatically as middleware at evaluation_order 300.

Error Codes

CodeClassRetryableDescription
VALIDATION_INPUT_FAILEDvalidationnoInput validation failed
VALIDATION_OUTPUT_FAILEDvalidationnoOutput validation failed
VALIDATION_SCHEMA_INVALIDvalidationnoSchema is invalid

Lifecycle / runtime

Defined for this element

Execution model: sync

Observability

Defined for this element

Metrics

  • evaluation_count
  • rejection_count

Events

  • validation.evaluated
  • validation.rejected

Pricing / cost

Platform default

Operation costs

  • create: free
  • update: free
  • delete: free
  • get: free
  • list: free
  • invoke: 10000 micro-AU
  • tool_use: free