Files
lda-wf/docs/schema_validation.md
T
lda Verified 95ec73d518 even MORE code review
stateful to not deadhang, graph context -> output, more explicit state errors, other misc changes idfk any of those good thing theyre fixed tho
2026-05-26 02:33:41 +07:00

4.3 KiB

Schema Validation Boundary

wf_core uses SchemaRef to carry JSON-schema-like shapes on workflow input, node input, node output, and workflow output. Runtime payload validation is delegated to the existing jsonschema library.

Current Behavior

wf_core.runtime.ops.schemas.validate_payload_against_schema currently:

  • converts SchemaRef into a JSON Schema dictionary
  • asks jsonschema to validate the schema itself
  • asks jsonschema to validate the payload
  • wraps validation failures in WorkflowExecutionError

This means normal JSON Schema checks such as object shape, required fields, property types, nested required fields, arrays, and item types are enforced by the library.

It still does not solve:

  • semantic compatibility between Pydantic-generated schemas and every possible external JSON Schema dialect
  • typed Python object creation from arbitrary JSON Schema
  • workflow state merge behavior beyond declared exact-path metadata
  • deep node-local map-path validation beyond statically knowable schema roots
  • better domain-specific error payloads beyond WorkflowExecutionError

This means schema fields are contracts for authoring, planning, documentation, and mapping validation. Runtime state merge behavior is separate metadata on declared exact state paths; undeclared paths still use replace.

Final workflow output has two projection modes:

  • If Workflow.output contains bindings, those bindings build the public output payload from graph paths such as state.result.message.
  • If Workflow.output is empty, legacy projection copies same-named top-level state keys listed in workflow.output_schema.properties.

Prefer explicit Workflow.output bindings for new workflows. The same-named state projection exists for compatibility with older plans.

The projected payload is then validated against workflow.output_schema.

Why This Matters

Node and workflow boundaries can now reject wrong primitive/container types when the schema declares them. This matters before workflows are generated by an LLM or backed by arbitrary MCP tools.

Authoring Footguns

Prefer explicit entry arrays at LLM-facing boundaries

dict[str, SomeModel] is often pleasant in Python but weak as a human- or LLM-facing schema. It commonly appears as a generic object with arbitrary keys, and many clients communicate or render it much less clearly than an explicit list shape.

Prefer:

class Entry(BaseModel):
    key: str
    value: SomeModel


entries: list[Entry]

over:

entries: dict[str, SomeModel]

when the schema is meant for MCP tools, LLM planning, or durable workflow authoring contracts. Internal Python state can still use dictionaries when that is the right runtime shape.

Do not assume all JSON Schema consumers handle references equally

Pydantic-generated schemas may use $defs and local $ref references for nested models. The runtime delegates validation to jsonschema, which supports that structure, but display layers and downstream consumers may vary in how well they present or reason about referenced shapes.

wf_authoring resolves the local Pydantic $ref -> $defs pattern only for its own state-field projection. That helper is not a general-purpose JSON Schema flattener, and arbitrary external schemas should not be assumed to share the same shape.

Intended Seam

The schema adapter lives behind:

wf_core.runtime.ops.schemas.validate_payload_against_schema

Callers should not choose or invoke the validation backend directly. The runtime keeps one small validation interface and hides the validation backend.

Future Requirements

  • Validate workflow input, node input, node output, and final workflow output with the same semantics.
  • Return errors that name the failing boundary and path.
  • Keep schema validation separate from graph structure validation.
  • Keep wf_authoring free to generate schemas from Pydantic models without making the core runtime depend on authoring internals.
  • Add targeted tests as externally sourced schemas grow more complex.

Non-Goals For Now

  • Do not add ad hoc type checks throughout runtime state operations.
  • Do not let each node wrapper invent separate validation behavior.
  • Do not conflate graph validation with payload validation.
  • Do not hand-write a general JSON Schema implementation.