fharness 1.0.0

Harness library for the fiddlesticks agent harness framework
Documentation

Agent Harness API

fharness is the top-level orchestration layer for long-running agent workflows in Fiddlesticks.

It currently supports:

  • initializer flow
  • task agent incremental loop
  • runtime wiring + run-level policy
  • reliability + guardrails for production usage

fharness composes lower layers (fmemory, fchat, ftooling, fprovider) into a structured multi-run harness.

Responsibilities

  • Run initializer setup for a session (manifest + feature list + progress + checkpoint)
  • Run incremental task iterations one feature at a time
  • Enforce clean handoff by recording explicit run outcomes
  • Coordinate health checks, execution, validation, and persistence updates

fharness does not:

  • Implement provider transports (fprovider)
  • Implement turn orchestration internals (fchat)
  • Implement tool runtimes (ftooling)
  • Implement persistence internals (fmemory)

Add dependency

[dependencies]

fharness = { path = "../fharness" }

fmemory = { path = "../fmemory" }

fchat = { path = "../fchat" }

Core types

  • Harness: orchestrator for initializer and task iterations
  • HarnessBuilder: runtime wiring for provider/chat/tooling/memory
  • InitializerRequest / InitializerResult
  • TaskIterationRequest / TaskIterationResult
  • RuntimeRunRequest / RuntimeRunOutcome
  • HealthChecker (NoopHealthChecker default)
  • OutcomeValidator (AcceptAllValidator default)
  • FeatureSelector (FirstPendingFeatureSelector default)
  • HarnessError / HarnessErrorKind

Initializer flow

run_initializer(...):

  1. Validates objective and feature list rules
  2. Builds/versions SessionManifest
  3. Uses initialize_session_if_missing(...) for idempotent initialization
  4. Persists initial progress + run checkpoint

If no feature list is provided, Harness generates a starter skeleton via starter_feature_list(...).

use std::sync::Arc;

use fharness::{Harness, InitializerRequest};
use fmemory::{InMemoryMemoryBackend, MemoryBackend};

let memory: Arc<dyn MemoryBackend> = Arc::new(InMemoryMemoryBackend::new());
let harness = Harness::new(memory);

let request = InitializerRequest::new("session-1", "run-init-1", "Build incremental harness");
let _result = harness.run_initializer(request).await?;

Task-Iteration incremental loop

run_task_iteration(...) executes one bounded run:

  1. Get bearings
    • loads manifest/progress/features from fmemory
    • runs health check using manifest init_plan
  2. Picks one highest-priority failing feature (passes == false)
  3. Delegates execution to fchat (run_turn or stream_turn)
  4. Validates outcome via OutcomeValidator
  5. Updates artifacts:
    • marks feature passing only when validated
    • appends progress entry
    • records completed checkpoint with status/note

Integrated runtime and policy ownership

HarnessBuilder wires lower-layer runtime dependencies directly:

  • provider (fprovider)
  • chat service (fchat) with transcript storage from fmemory
  • tool runtime (ftooling)
  • memory backend (fmemory)

fchat stays responsible for turn orchestration. fharness owns run-level policy:

  • phase selection (initializer vs task-iteration)
  • feature selection strategy (FeatureSelector)
  • validation gate before marking feature pass (OutcomeValidator)

Reliability + guardrails

Harness run policy now supports reliability constraints:

  • mode (strict_incremental, bounded_batch, unlimited_batch)
  • max_turns_per_run
  • max_features_per_run (used by strict/bounded modes)
  • retry_budget
  • fail-fast conditions (health check, chat, validation)

Mode semantics:

  • strict_incremental: exactly one feature per run (max_features_per_run must be 1)
  • bounded_batch: process up to max_features_per_run features in one run
  • unlimited_batch: process features until completion gate or turn/retry constraints stop progress

Completion guardrail:

  • harness does not declare done early
  • completion requires all required features in feature_list to have passes = true
use std::sync::Arc;

use fharness::{Harness, RuntimeRunRequest, RuntimeRunOutcome};
use fmemory::{InMemoryMemoryBackend, MemoryBackend};

let memory: Arc<dyn MemoryBackend> = Arc::new(InMemoryMemoryBackend::new());
let harness = Harness::builder(memory)
    .provider(provider)
    .tool_runtime(tool_runtime)
    .build()?;

match harness.run(RuntimeRunRequest::new(session, "run-1", "Build feature loop")).await? {
    RuntimeRunOutcome::Initializer(_) => {
        // session bootstrapped
    }
    RuntimeRunOutcome::TaskIteration(result) => {
        // one task iteration completed
        assert!(result.validated);
    }
}
use std::sync::Arc;

use fharness::{Harness, TaskIterationRequest};

let harness = Harness::new(memory).with_chat(chat_service);
let request = TaskIterationRequest::new(session, "run-task-1");
let _result = harness.run_task_iteration(request).await?;

Extensibility hooks

  • HealthChecker
    • run startup/baseline checks before task-iteration work
  • OutcomeValidator
    • enforce real validation gates before marking features as passing

Use with_health_checker(...) and with_validator(...) to override defaults.

Clean handoff guarantees

Every task-iteration run records terminal outcome artifacts:

  • run checkpoint with explicit status (Succeeded/Failed) and note
  • progress entry summarizing what happened

This avoids ambiguous handoff state across context windows.

Error model

HarnessErrorKind variants:

  • InvalidRequest
  • Memory
  • Chat
  • Validation
  • HealthCheck
  • NotReady