simple-agents-healing 0.2.31

Response healing system for SimpleAgents - BAML-inspired JSON parsing and coercion
Documentation

simple-agents-healing

Response healing system for SimpleAgents - BAML-inspired JSON parsing and type coercion.

Overview

This crate implements a sophisticated JSON healing system that handles malformed LLM outputs. Instead of failing on broken JSON, it tracks all transformations via a flag system and provides confidence scores, making LLM integrations robust in production.

Features

🔧 Three-Phase Parsing

  1. Strip & Fix: Quick string transformations

    • Remove markdown code fences (`````json ... ```)
    • Fix trailing commas ({...,}{...})
    • Normalize quotes ('...'"...")
    • Remove BOM and control characters
    • Fix unquoted keys (optional with regex-support feature)
  2. Standard Parse: Fast path using serde_json

    • If JSON is valid after Strip & Fix, use standard parser
    • Optimal performance for slightly malformed inputs
  3. Lenient Parse: State machine for deeply broken JSON

    • Character-by-character parsing
    • Auto-close unclosed structures
    • Handle incomplete streaming responses
    • Truncate to last valid object/array

📊 Confidence Scoring

Every parse result includes a confidence score (0.0-1.0):

  • 1.0: Perfect JSON, no healing needed
  • 0.95-0.99: Minor fixes (markdown, trailing commas)
  • 0.85-0.94: Quote normalization or simple fixes
  • 0.70-0.84: Type coercion or truncation
  • <0.70: Significant healing required

🏷️ Transparency via Flags

All transformations are tracked with CoercionFlag:

  • StrippedMarkdown - Removed code fences
  • FixedTrailingComma - Removed trailing commas
  • FixedQuotes - Normalized single quotes to double
  • FixedUnquotedKeys - Added quotes to object keys
  • FixedControlCharacters - Removed control characters
  • RemovedBom - Removed byte order mark
  • TruncatedJson - Truncated incomplete JSON

Usage

Basic Example

use simple_agents_healing::prelude::*;

let parser = JsonishParser::new();

// Parse markdown-wrapped JSON
let malformed = r#"```json
{"name": "Alice", "age": 30,}
```"#;

let result = parser.parse(malformed)?;

// Access parsed value
assert_eq!(result.value["name"], "Alice");
assert_eq!(result.value["age"], 30);

// Check confidence and flags
assert!(result.confidence > 0.85);
assert!(result.flags.contains(&CoercionFlag::StrippedMarkdown));
assert!(result.flags.contains(&CoercionFlag::FixedTrailingComma));

Custom Configuration

use simple_agents_healing::prelude::*;

let config = ParserConfig {
    strip_markdown: true,
    fix_trailing_commas: true,
    fix_quotes: true,
    fix_unquoted_keys: false,
    fix_control_chars: true,
    remove_bom: true,
    min_confidence: 0.8,  // Reject results below 0.8
};

let parser = JsonishParser::with_config(config);
let result = parser.parse(input)?;

Confidence Thresholds

use simple_agents_healing::prelude::*;

let strict_config = ParserConfig {
    min_confidence: 0.95,
    ..Default::default()
};

let parser = JsonishParser::with_config(strict_config);

match parser.parse(input) {
    Ok(result) => {
        println!("High confidence: {}", result.confidence);
    }
    Err(SimpleAgentsError::Healing(HealingError::LowConfidence { .. })) => {
        println!("Confidence too low, requires review");
    }
    Err(e) => {
        println!("Parse failed: {}", e);
    }
}

Examples

Run the included examples:

# Basic healing demonstration
cargo run --example basic_healing

Testing

# Run all tests
cargo test -p simple-agents-healing

# Run with coverage
cargo test -p simple-agents-healing --all-features

# Run clippy
cargo clippy -p simple-agents-healing -- -D warnings

Architecture

Parser Components

Input String
    ↓
┌─────────────────────┐
│  Strip & Fix Phase  │ ← Remove markdown, fix commas, quotes
└─────────────────────┘
    ↓
┌─────────────────────┐
│   Standard Parse    │ ← Try serde_json (fast path)
└─────────────────────┘
    ↓ (if fails)
┌─────────────────────┐
│   Lenient Parse     │ ← State machine for broken JSON
└─────────────────────┘
    ↓
CoercionResult<Value>

Flag System

Every transformation is tracked:

pub enum CoercionFlag {
    StrippedMarkdown,
    FixedTrailingComma,
    FixedQuotes,
    FixedUnquotedKeys,
    FixedControlCharacters,
    RemovedBom,
    TruncatedJson,
    // More flags for coercion engine (future)
}

Confidence Calculation

confidence = 1.0
             * (markdown_stripped ? 0.95 : 1.0)
             * (trailing_comma_fixed ? 0.95 : 1.0)
             * (quotes_fixed ? 0.90 : 1.0)
             * (unquoted_keys_fixed ? 0.85 : 1.0)
             * (truncated ? 0.70 : 1.0)

Future Features

Week 6 (Planned)

  • Coercion Engine: Type coercion with schema validation

    • String → Number coercion
    • Fuzzy field matching (case-insensitive, snake_case ↔ camelCase)
    • Union resolution with best-match selection
    • Default value injection
  • Streaming Parser: Incremental parsing

    • Partial value extraction from incomplete buffers
    • Progressive emission during streaming
    • Annotation support (stream.not_null, stream.done)

Performance

  • Fast path: Standard serde_json for valid JSON after Strip & Fix
  • Zero allocations: In-place string transformations where possible
  • Minimal overhead: Flags are small enums, confidence is a single f32

Safety

  • No unsafe code: 100% safe Rust
  • No panics: All errors are Result types
  • Send + Sync: Parser can be shared across threads

Credits

Inspired by BAML's Jsonish parser and coercion system.

License

MIT OR Apache-2.0