stateful to not deadhang, graph context -> output, more explicit state errors, other misc changes idfk any of those good thing theyre fixed tho
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
SchemaRefinto a JSON Schema dictionary - asks
jsonschemato validate the schema itself - asks
jsonschemato 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.outputcontains bindings, those bindings build the public output payload from graph paths such asstate.result.message. - If
Workflow.outputis empty, legacy projection copies same-named top-level state keys listed inworkflow.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_authoringfree 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.