An agent = model + harness. A .NET 10 framework where guides shape the model's context each turn and sensors guard every step — loop, PII & prompt-injection detection.
FAQ (answers come from our records)
How do I install it?
We did not find an install command for this repository (our install coverage is only about 4%). Check its README or releases page.
Who is it for?
We filed it under these tags: 开源项目. The tags come from the entry itself, not a taxonomy we imposed.
Who maintains it?
repository AnilKerai/model-harness;first catalogued 2026-10-10;last seen 2026-10-10。There is no official certification or quality rating here — we record sources and dates only.
Model Harness
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
**A ports-and-adapters agent framework for .NET 8 and .NET 10.** An agent is a *model + harness* — model-harness is the harness: the loop, guides, sensors, and budget that turn a raw model into a controllable agent. Every moving part is a port with a working default, so you can wire the standard agent in a few lines or replace any single piece without touching the loop.
*I wrote this to learn how agentic systems work by building one, and to teach my team with it.
Corrections and criticism are genuinely welcome — more below.*
Why model-harness
**Do more with less.** The prevailing assumption is that a better agent needs a bigger frontier model. This framework is a bet on the opposite: that a well-structured harness closes much of that gap — enough that a smaller, cheaper, or locally-hosted model can run the same task at *acceptable* quality. That's a claim to be measured, not one this repo has benchmarked yet. The practical ambition is to swap ClaudeModelClient for OllamaModelClient on a 7B local model and still get a usable result, at a fraction of the cost. Where that bar sits is a product decision, not a model decision.
The harness gets there by making every control point a swappable port with a sensible default:
- **Everything is an extension point.** Context shaping, safety checks, budget, rate limiting, memory, compaction, tracing, checkpointing, and model transport are each a named port you replace via the builder — no loop changes. → extension points
- **Two patterns, total control.** Guides shape what the model sees each turn; sensors observe and intervene at five hookpoints. Most features are built purely from these two.
- **Bounded by construction.** Turns, tokens, cost, and wall-clock are hard limits checked every turn; exhaustion returns a partial result, never an exception.
- **Batteries included.** Prompt-injection defense, PII redaction, loop/stuck detection, taint tracking, skills/learning, incremental compaction, sub-agents, and human-in-the-loop ship in the box. → what's included
- **Bring any model.** Anthropic, Azure OpenAI / AI Foundry, and Ollama adapters ship today; IModelClient is the port for anything else.
- **Production-minded.** OpenTelemetry GenAI spans + metrics, checkpoint/resume, circuit-breaker resilience, and prompt caching are wired or one call away.
---
Quickstart
AddStandardModelHarness is the recommended entry point — supply a model, your tools, and any overrides:
No API key? Samples fall back to a FakeModelClient, so the harness runs without one. A minimal runnable project is in getting-started/ — open GettingStarted.slnx, drop an appsettings.local.json with your key, and run. Then: **RUNNING.md** to run the samples, **EXTENDING.md** for how-to recipes, **PRIMER.md** for the ideas behind it, **CHANGELOG.md** for release history — every breaking change there carries a migration guide.
---
Extension points
Every part of the harness is a port you replace via the builder — but be clear-eyed about what ships: many ports default to a deliberate **no-op**, several have a **real** default that works out of the box, and a couple you **supply** yourself. The map, then the three groups:
Works out of the box — real defaults
A real implementation runs unless you override it.
| Port | Default | What it does |
|---|---|---|
| IBudgetEnforcer | DefaultBudgetEnforcer | Enforces turn / token / cost / wall-clock limits at the top of each turn; returns PartialResult on exhaustion rather than throwing. |
| IContextBuilder | DefaultContextBuilder | Assembles the final prompt from the ContextDraft guides produce. |
| ITrajectoryGuide | HeadEvictionTrajectoryGuide | Renders turn history into the context window, evicting the oldest steps when the budget is tight. Always runs last. |
| IToolSelector | PassthroughToolSelector | Filters which tools the model sees each turn — all of them, by default. |
| IToolRegistry | InMemoryToolRegistry *(standard)* | Holds and dispatches tools. Bare AddModelHarness starts empty with NullToolRegistry. |
| ITracer | OpenTelemetryTracer *(standard)* | Nested gen_ai.* spans + metrics; per-turn events for sensors, guides, compaction, checkpoints, rate-limit waits, and budget burn-down. Bare uses NullTracer; add WithConsoleTracer() / WithOtelTracer() / WithLiveDashboardTracer() (in-process live console, no backend). |
No-op until you opt in
A null default does nothing until you wire a real one — free until used.