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.
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
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
validateoperation returns valid (bool), errors (array of path/message/code), and sanitized data. Theschemaoperation 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
| Property | Value |
|---|---|
| Cascade | restrictive — strictest schema wins across scopes |
| Eval Order | 300 |
| Phase | request |
| Fail Action | HTTP 422 (Unprocessable Entity) with field-level error details |
| Applies To | actors, frontend |
Relationships
- Attaches to: circle
Capabilities
- json-schema: JSON Schema validation
- sanitize: Input sanitization
- coerce: Type coercion
- detailed-errors: Detailed validation errors
Properties
| Property | Type | Default | Description |
|---|---|---|---|
schema | object | — | JSON Schema for input validation |
sanitization | object | — | Input sanitization options |
coercion | object | — | Type coercion settings |
defaults | object | — | Default values for missing fields |
error_handling | object | — | Error 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, andintentionare all independently optional.specMUST 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
| Code | Class | Retryable | Description |
|---|---|---|---|
VALIDATION_INPUT_FAILED | validation | no | Input validation failed |
VALIDATION_OUTPUT_FAILED | validation | no | Output validation failed |
VALIDATION_SCHEMA_INVALID | validation | no | Schema 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