agent-harness-rs
Agent loop harness for building LLM-powered coding agents. Provides a complete runtime with tool execution, context management, MCP support, and e2b sandbox integration.
Features
- Agent loop — OpenAI-compatible streaming model client with retry, reconnect, and compaction
- Local tools —
bash,read,write,edit,glob,grepwith approval gate (feature = "local-tools", default) - Sandbox tools — Generic
SandboxExecutortrait for any remote sandbox - E2b integration —
E2bToolRuntimevia Connect Protocol to envd (feature = "e2b") - Context persistence — JSONL-based context store with incremental append and compaction rewrite
- MCP support — HTTP and stdio MCP server integration via
CompositeToolRuntime - Model limits catalog — async
models.devfetch with disk cache, backoff retry, and offline fallback for context-window / output-token resolution
Quick start
[]
= "0.2"
# For e2b sandbox support:
= { = "0.2", = ["e2b"] }
use ;
use Arc;
use PathBuf;
// Local tool runtime (runs bash/read/write on your machine)
let tools = new;
let model = new;
let harness = new;
let mut rx = harness.run_turn.await?;
while let Some = rx.recv.await
E2b sandbox
use ;
let tools = connect.await?;
let harness = new;
Model limits catalog
Context-window and output-token limits are resolved per model from
models.dev (the public model registry opencode
also uses), with a best-effort strategy that never blocks the agent loop:
- In-memory table populated by a fire-and-forget background fetch.
On the first
resolve_limits()call a fetch is spawned; while it is in flight (typically during early LLM warm-up) callers get the fallback value, and pick up the real value on the next turn. - Disk cache at
<cache_dir>/agent-harness-rs/models.json(5 min TTL, atomic tempfile +renamewrite) so a network blip mid-session still serves real values. - Offline fallback table — the legacy hand-encoded claude/gpt/ o-series/minimax/deepseek mappings, so behavior never regresses.
- Conservative default
{ context: 128_000, output: 8_192 }.
The fetch retries 3× with exponential backoff (+ jitter) and a 10 s per-request timeout; on final failure it logs and falls back silently.
use ;
// Optional: warm the cache before the first turn. Safe to skip — the
// first resolve_limits() triggers it lazily.
prefetch_model_limits;
// Fast, non-async, never blocks.
let limits = resolve_limits;
// limits.context — used for compaction thresholds
// limits.output — model's per-completion output cap
Configuration via environment variables:
| Variable | Default | Purpose |
|---|---|---|
AGENT_HARNESS_MODELS_URL |
https://models.dev/api.json |
Override the registry endpoint |
AGENT_HARNESS_CACHE_PATH |
<cache_dir>/agent-harness-rs/models.json |
Relocate the disk cache |
Approval modes
use ;
// Allow everything
new
// Read-only (hide bash/write/edit from model)
new
// Custom gate (e.g. ask user via UI)
;
License
MIT