Declarative
Tracing, cost, budgets, guardrails, typed output, tool governance, policy, approvals, routing, retrieval governance and evals, all in one spec. Your code stays one call.
The composable AI harness framework
Bring your models. Choose your plugins. Define your execution. HarnessWeaver puts tracing, budgets, guardrails, typed output, tool governance, policy and approvals around the executor you already use, declared in one harness.yaml.
uv add "harnessweaver[openai]"npm install @harnessweaver/corePython 3.12+ / Node 22+ / Apache-2.0
One spec
Typed output, guards, business rules and a budget live in the spec. The app still calls harness.run("triage", ticket).
apiVersion: harnessweaver/v1
kind: Harness
metadata:
name: support-desk
owner: support-team
extends: ["profile://extraction"] # PII and secrets guards
models:
provider: openai.chat
base_url: http://localhost:4000
api_key_env: LITELLM_API_KEY
default: fast
aliases: { fast: fast-chat }
tasks:
triage:
runner: direct
prompt: triage@2
input: helpdesk.models:Ticket
output: helpdesk.models:Triage
budget: { max_model_calls: 3, max_usd: 0.01, deadline: 30s }
validation:
rules:
- id: bugs-are-urgent
when: "output.category == 'bug' && output.priority > 2"
message: "a bug is priority 1 or 2"
How it works
Modules install middleware on fixed hook points. Every model call, tool call and output passes them, whatever executor runs the task.
Later layers extend earlier ones. The org baseline's locks and bounds are enforced at load: an app can't remove a control, and a value out of bounds is an error, never clamped.
Middleware runs in bands, baseline, platform, app and task: inbound hooks outermost first, outbound hooks innermost first.
Middleware returns an outcome instead of raising. A classifier or LLM judge may tighten a decision, but never grant one.
Why HarnessWeaver
Tracing, cost, budgets, guardrails, typed output, tool governance, policy, approvals, routing, retrieval governance and evals, all in one spec. Your code stays one call.
Keep raw SDK calls, Pydantic AI, the Vercel AI SDK or your own pipeline. Govern an existing client in three lines.
The org baseline can't be removed by an app, controls fail closed, and nothing reaches a log or span unredacted.
Every capability is a module behind a port, with providers you swap and plugins anyone can write in their own repository.
One spec serves Python, TypeScript, and any language through the harnessd sidecar.
Everything runs offline against fakes, with no network and no model spend, and every decision is in a trace your tests can check.
OpenTelemetry GenAI conventions, JSON Schema contracts, an OpenAPI sidecar and a CEL subset for rules.
In the box
Not an agent framework
HarnessWeaver has no planner, memory model, prompt template language or vector store of its own. Bring your agent framework in through an adapter, and the same controls apply to it.
Packages
The core depends only on Pydantic, the OpenTelemetry API, PyYAML, anyio and loguru. Each package has its own version.
Or run harnessd and call it over HTTP from any language: one spec, the same controls.
The quickstart runs offline: no API keys, no network calls to a model, no spend.