Expand description
Structured Output Engine
5-layer defense system for ~99.99% JSON Schema compliance:
- Layer 0: Tool Injection (DynamicSubmitTool via
submit_toolmodule)- Handled OUTSIDE the engine, in
executor/verbs.rs(infer) andrig_agent_loop(agent). Usestool_choice: Requiredto force provider-side schema enforcement.
- Handled OUTSIDE the engine, in
- Layer 1: rig Extractor (Rust types with JsonSchema via schemars — future)
- Layer 2: Extract + Validate (extract JSON from output, validate against schema)
- Layer 3: Retry with Feedback (re-prompt with validation errors)
- Layer 4: LLM Repair (separate call to fix invalid JSON)
Layer 0 is non-blocking: if tool injection fails (native provider, timeout), execution falls through to streaming + Layers 2-4.
Each layer emits StructuredOutputAttempt events for observability.
Success emits StructuredOutputSuccess with total attempt count.
§Usage
ⓘ
use nika::runtime::StructuredOutputEngine;
use nika::ast::StructuredOutputSpec;
let spec = StructuredOutputSpec::with_file_schema("./schema.json");
let engine = StructuredOutputEngine::new(spec, event_log.clone());
// Validate raw output (Layer 2 only without callback)
let result = engine.validate("task-1", raw_output).await?;
// With inference callback for full Layer 3 & 4 support
let callback: InferCallback = Arc::new(move |prompt: String| {
let provider = provider.clone();
Box::pin(async move {
provider.infer(&prompt, None).await
.map_err(|e| NikaError::ProviderApiError { message: e.to_string() })
})
});
let engine = engine.with_infer_callback(callback);Structs§
- Structured
Output Engine - Post-processing structured output validation engine (Layers 2-4)
- Structured
Output Result - Result of structured output validation
Functions§
- validate_
structured_ output - Quick validation without the full engine (for simple cases)
Type Aliases§
- Infer
Callback - Callback type for LLM inference during retry/repair (Layers 3 & 4)