CEL Environment
A single cel_context() function builds the CEL evaluation context used by both validation rules and property formulas. Defined in the executor crate, it provides three parameters to every CEL expression.
cel_context()
Section titled “cel_context()”pub fn cel_context<'a, M: Serialize>( metadata: &'a M, props: &'a HashMap<String, PropertyValue>, value: Option<&'a PropertyValue>,) -> Context<'a> { ... }Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
metadata | &M where M: Serialize | This component’s metadata. Always local, never parent’s. |
props | &HashMap<String, PropertyValue> | All property values including unset ones as null. Every property is present. |
value | Option<&PropertyValue> | Current property’s value. Useful in per-property expressions. |
metadata
Section titled “metadata”The metadata parameter is the local component’s metadata — for a whiteboard component, this is WhiteboardMetadata (canvas dimensions, etc.), never the parent lesson plan’s metadata. Metadata types implement Serialize, and the cel crate’s TryIntoValue blanket impl handles conversion automatically.
All property values for the current component, including properties that have no value set (represented as null). This ensures CEL expressions can reference any property by key without worrying about missing keys.
The current property’s value when evaluating a per-property expression (validation rule or formula). Set to None when evaluating component-level or modality-level expressions that are not tied to a specific property.
Usage in validation
Section titled “Usage in validation”The Validate trait takes a CEL evaluator closure rather than depending on the executor crate directly. The closure is built from cel_context() at the call site:
// At the call site (e.g., session or bridge code):let eval_cel = |expr: &str| -> Result<bool, String> { let ctx = cel_context(&metadata, &props, Some(&value)); evaluate_bool(expr, &ctx)};
// Passed to Validate::validate():let errors = property.validate(&eval_cel);This indirection keeps modality_core free of executor dependencies.
Usage in formulas
Section titled “Usage in formulas”Property formulas use the same cel_context() shape. A formula is a CEL expression that computes a derived property value from other properties and metadata. The context is identical to validation — same metadata, props, and value parameters.
ValidationRule types
Section titled “ValidationRule types”Three rule types interact with the CEL environment differently:
Expression
Section titled “Expression”A CEL expression that must evaluate to true. Hard gate at done time.
ValidationRule::Expression("size(value) <= 500".to_string())Evaluated synchronously via cel_context(). If the expression returns false or errors, a ValidationError is produced. The agent must fix the value and call done again.
Guideline
Section titled “Guideline”Natural language guidance included in the preamble. Never evaluated programmatically.
ValidationRule::Guideline("Use age-appropriate vocabulary for the target grade level".to_string())Included in the agent’s system prompt via Describe. The agent follows these while generating. They never interact with the CEL environment.
Function
Section titled “Function”A Rust-native predicate. Hard gate at done time.
ValidationRule::Function(|v| matches!(v, PropertyValue::Text(t) if !t.is_empty()))Evaluated synchronously but outside CEL. Not describable to AI, so used only for structural invariants the agent cannot violate (e.g., type constraints that the schema already enforces).
What was removed
Section titled “What was removed”The following were removed from the CEL context as part of the architecture simplification:
ModalityContext— theme/education level are now metadata fields per modalityskills— skill IDs live on metadata; full data is accessed via tool callssections— structural data accessed through modality stateModalitySession— each modality owns state viaSession<M, I>
Related
Section titled “Related”- Properties Overview — PropertySchema, PropertyType, PropertyValue
- Validation —
Validatetrait that consumes the CEL evaluator - Subagents — validation loop that triggers CEL evaluation at
donetime - Bridge — dispatch path that connects tool calls to state mutations