agentledger-runtime 1.5.4

Runtime reliability layer for Agent Harness stacks
Documentation
use agentledger::{
    OmpLedgerBridge, OmpModelCall, OmpSession, OmpStateChange, OmpToolExecution, OmpToolProposal,
    OmpTurn, Runtime, State, Value,
};

fn state(items: &[(&str, Value)]) -> State {
    items
        .iter()
        .map(|(key, value)| ((*key).to_string(), value.clone()))
        .collect()
}

fn main() -> agentledger::Result<()> {
    let runtime = Runtime::new();
    let mut bridge = OmpLedgerBridge::new(runtime, "omp-demo");
    let run_id = bridge.record_session_started(OmpSession {
        session_id: "omp-session-1".to_string(),
        initial_state: state(&[("task", "review contract".into())]),
        metadata: state(&[("runtime", "synthetic-omp".into())]),
        ..Default::default()
    })?;
    bridge.record_turn_started(OmpTurn {
        session_id: "omp-session-1".to_string(),
        turn_id: "turn-1".to_string(),
        agent_role: "OMPPlanner".to_string(),
        metadata: state(&[("phase", "planning".into())]),
        ..Default::default()
    })?;
    bridge.record_model_call(OmpModelCall {
        session_id: "omp-session-1".to_string(),
        turn_id: "turn-1".to_string(),
        provider: "openai-compatible-gateway".to_string(),
        model: "legal-router".to_string(),
        request: state(&[(
            "messages",
            Value::Array(vec![Value::Object(state(&[
                ("role", "user".into()),
                ("content", "find payment clause".into()),
            ]))]),
        )]),
        response: state(&[(
            "tool_calls",
            Value::Array(vec![Value::Object(state(&[
                ("name", "contract.search".into()),
                (
                    "arguments",
                    Value::Object(state(&[("clause", "payment".into())])),
                ),
            ]))]),
        )]),
        usage: state(&[
            ("input_tokens", Value::Number(12.0)),
            ("output_tokens", Value::Number(7.0)),
            ("total_tokens", Value::Number(19.0)),
        ]),
        total_usd: 0.003,
        ..Default::default()
    })?;
    bridge.record_tool_proposal(OmpToolProposal {
        session_id: "omp-session-1".to_string(),
        turn_id: "turn-1".to_string(),
        tool_name: "contract.search".to_string(),
        arguments: state(&[("clause", "payment".into())]),
        provider: Some("openai-compatible-gateway".to_string()),
        model: Some("legal-router".to_string()),
        reason: Some("model proposed a contract search".to_string()),
        ..Default::default()
    })?;
    bridge.record_tool_execution(OmpToolExecution {
        session_id: "omp-session-1".to_string(),
        turn_id: "turn-1".to_string(),
        tool_name: "contract.search".to_string(),
        arguments: state(&[("clause", "payment".into())]),
        result: Some(Value::Object(state(&[
            ("matches", Value::Array(vec!["Section 9.2".into()])),
            ("external_id", "search-001".into()),
        ]))),
        ledger_status: Some("SUCCEEDED".to_string()),
        ..Default::default()
    })?;
    bridge.record_state_change(OmpStateChange {
        session_id: "omp-session-1".to_string(),
        turn_id: Some("turn-1".to_string()),
        reason: "persist normalized runtime-adjacent state".to_string(),
        patch: state(&[("memory_version", Value::Number(1.0))]),
        before_snapshot: Some(Value::Object(state(&[("memory_version", Value::Number(0.0))]))),
        after_snapshot: Some(Value::Object(state(&[("memory_version", Value::Number(1.0))]))),
        diff: Some(Value::Object(state(&[(
            "memory_version",
            Value::Array(vec![Value::Number(0.0), Value::Number(1.0)]),
        )]))),
        ..Default::default()
    })?;
    bridge.record_turn_completed(OmpTurn {
        session_id: "omp-session-1".to_string(),
        turn_id: "turn-1".to_string(),
        state_patch: state(&[("last_tool", "contract.search".into())]),
        ..Default::default()
    })?;

    let events = bridge
        .runtime
        .store
        .events(&run_id)
        .iter()
        .map(|event| event.event_type.clone())
        .collect::<Vec<_>>();
    let final_state = bridge.runtime.store.final_state(&run_id)?;
    let rendered_events = format!("{:?}", events);
    let memory_version = match final_state.get("memory_version") {
        Some(Value::Number(value)) => *value,
        _ => 0.0,
    };
    let last_tool = match final_state.get("last_tool") {
        Some(Value::String(value)) => value.as_str(),
        _ => "",
    };
    println!(
        concat!(
            "{{\n",
            "  \"run_id\": \"{}\",\n",
            "  \"events\": {},\n",
            "  \"tool_ledger_count\": {},\n",
            "  \"final_state_memory_version\": {},\n",
            "  \"final_state_last_tool\": \"{}\"\n",
            "}}"
        ),
        run_id,
        rendered_events,
        bridge.runtime.store.ledger(&run_id).len(),
        memory_version,
        last_tool
    );
    Ok(())
}