Transform Hooks
When a block produces structured output (like JSON), you often want to assert on a specific field rather than the entire output string. Transform hooks let you extract a sub-field before the assertion runs.
Add a transform to an assertion
Section titled “Add a transform to an assertion”Set the transform field on any assertion config. The transform runs before the assertion evaluator sees the output:
blocks: classify: type: llm soul_ref: classifier assertions: - type: contains-any value: ["positive", "negative", "neutral"] transform: "json_path:$.sentiment"Without the transform, the contains-any assertion would check the entire LLM output string. With transform: "json_path:$.sentiment", it checks only the extracted value of the sentiment field.
json_path transform
Section titled “json_path transform”The only supported transform type is json_path. The syntax is:
json_path:<JSONPath expression>The engine:
- Parses the block output as JSON (using
json.loads) - Evaluates the JSONPath expression (using the
jsonpath_nglibrary) - Extracts the first match
- Converts the result to a string if it is not already one
- Passes the extracted string to the assertion evaluator
Supported JSONPath syntax
Section titled “Supported JSONPath syntax”Runsight uses the jsonpath_ng library. Common patterns:
| Expression | Selects |
|---|---|
$.field | Top-level field |
$.nested.field | Nested field |
$.items[0] | First array element |
$.items[*].name | name field from every array element (first match used) |
$..field | Recursive descent — finds field at any depth |
Examples
Section titled “Examples”Check a sentiment label in a JSON response
Section titled “Check a sentiment label in a JSON response”blocks: analyze: type: llm soul_ref: analyst assertions: - type: contains-any value: ["bullish", "bearish", "neutral"] transform: "json_path:$.outlook"If the block output is {"outlook": "bullish", "confidence": 0.92}, the assertion receives "bullish" and passes.
Validate a nested score
Section titled “Validate a nested score”blocks: scorer: type: llm soul_ref: evaluator assertions: - type: regex value: "^[1-5]$" transform: "json_path:$.rating"If the block output is {"rating": 4, "explanation": "Good quality"}, the transform extracts 4, converts it to the string "4", and the regex assertion checks it.
Combine with negation
Section titled “Combine with negation”Transforms work with negated assertion types:
assertions: - type: not-contains value: "error" transform: "json_path:$.status"Error handling
Section titled “Error handling”The transform returns a failing GradingResult (score 0.0, passed false) in these cases:
| Condition | Reason message |
|---|---|
| Output is not valid JSON | "Transform json_path failed: output is not valid JSON" |
| JSONPath expression matches nothing | "Transform json_path: path '<path>' not found in output" |
Unknown transform format (no : separator) | "Unknown transform format: '<value>'" |
Unknown transform type (not json_path) | "Unknown transform type: '<type>'" |
When a transform fails, the assertion itself does not run. The failing GradingResult from the transform is used directly.