harness-rs-loop
The ReAct agent loop for harness-rs: think → call tools → observe → self-correct, repeat until the model stops or the iteration budget runs out. Also home to subagent isolation and session record/replay.
What the loop does each iteration
- Applies
Guides (system context) — once at the start. - Sends the
Context(with available tools) to theModel. - Dispatches every returned tool call through the
ToolRegistry. - Runs
Sensors after each action — auto-fix patches are applied to theWorlddirectly; blocking signals are fed back to the model to retry. Hooks wrap each step (PreToolUse / PostToolUse / TaskCompleted).- When the model stops asking for tools, acceptance checks decide whether
the work is actually done (a run that narrates a plan and stops looks
exactly like one that did the job); a failed verdict goes back to the model
and the loop continues. Otherwise stops at
max_iters.
Guards (each one measured, see the workspace README's ablation)
- Stuck detection (
StuckPolicy) — repeated identical tool-call rounds get a "change your approach" nudge, then a cleanOutcome::Stuck. - Result ceiling with spill (
ToolResultPolicy) — a single tool result larger thanmax_bytes(default 24 KiB) is saved in full to.harness/spill/inside the workspace; the context gets a 4 KiB preview plus the path, and the model retrieves slices with its ownread_file/grep. Nothing is lost.spill: falsefalls back to destructive truncation. - Per-call tool deadline (
with_tool_timeout, default 120s) — a hung call becomes an error result the model can route around, not a hung run. - Acceptance (
with_acceptance) — cheap deterministic "is it done?" checks (e.g.FilesExist) consulted beforeOutcome::Done.
Usage
use ;
use OpenAiCompat;
use default_world;
use Task;
use ;
use Arc;
let model = with_key;
let mut world = default_world;
let outcome = new
.with_tool
.with_tool
.run_with_max_iters
.await?;
match outcome
Outcome is #[non_exhaustive] — always destructure with a trailing ...
Subagents
Run an isolated child agent with its own tools and budget, returning a single
report to the parent — the basis for harness-rs-orchestrator and
harness-rs-scheduler:
use ;
let spec = new.with_max_iters.with_tool;
let report = new.run.await?;
println!;
Record & replay
Every run can emit a JSONL session log; read_session + SessionStats /
format_event_* reconstruct it (the harness trace CLI command reads these).
License
MIT OR Apache-2.0.