Build and operate AI agents in one language.
Harn is a pipeline-oriented language for AI agents. LLM calls, tools, capability checks, durable steps, and deterministic replay are language and standard-library features, not SDKs you wire together yourself.
pipeline review(task) {
let files = ["src/main.rs", "src/lib.rs"]
let reviews = parallel each files { file ->
let content = harness.fs.read_text(file)
retry 3 {
llm_call("Review this code:\n${content}", "You are a code reviewer.")
}
}
for review in reviews {
log(review)
}
}call_closure, a missing bounds check, and one stale doc snippet.Runnable examples with real receipts
The same checked scenario files ship in the CLI demo bundle and run locally with deterministic fixtures.
Register supervised MCP servers without a live server fixture.
The receipt proves lazy registration, status snapshots, and graceful stop paths stay offline-runnable.
/**
* mcp-host demo: drive the supervised MCP-host primitive (#2504) on
* registration and status surfaces that work offline.
*
* Scope:
* - Register two lazy MCP server specs via `harn.mcp.spawn` (lazy =
* no eager connect, so we don't need a live MCP server bundled).
* - Snapshot `harn.mcp.status()` and emit a receipt that proves the
* registry view, supervision counters, circuit-breaker state, and
* cache slot all line up with a freshly-registered lazy server.
* - Issue a graceful `harn.mcp.stop` against one of the registrations
* and re-snapshot to show the deregistration path.
*
* Why a demo for this primitive: `harness.mcp.*` is a new public host
* surface that downstream callers (TUI, BurinCore, harn-cloud) will
* lean on. The demo gate (#2526 fragment) flags every public primitive,
* and this scenario keeps the offline-runnable smoke path covered
* without needing a live MCP server in the fixture set.
*
* Live-mode hint: `harn demo mcp-host --live` against a server with an
* MCP server actually configured will exercise `harn.mcp.tools` and
* `harn.mcp.call`; this scenario stays in lazy-mode by design so the
* tape stays small and offline.
*/
fn server_specs() {
return [
{name: "alpha", transport: "stdio", command: "/bin/true", args: []},
{name: "beta", transport: "http", url: "http://127.0.0.1:1/mcp", protocol_mode: "rc"},
]
}
pipeline default(_task) {
// 1. Register both servers lazily — no eager connect, so the demo
// runs even without a network or a bundled MCP fixture.
for spec in server_specs() {
let id = harn.mcp.spawn(spec, {lazy: true})
__io_println("spawned ${id} (lazy)")
}
// 2. Snapshot the host's view of every registered server. Each entry
// carries supervision counters (restart_count, consecutive_failures,
// circuit) plus the lazy/active/ref_count registry triple.
let after_spawn = harn.mcp.status()
__io_println("=== status after spawn ===")
for entry in after_spawn {
__io_println(json_stringify(entry))
}
// 3. Stop one of the registrations to release the handle. Stop on a
// never-connected lazy server is a no-op against the registry —
// the spec stays so a future `spawn` (or declarative reload)
// immediately re-finds it. The supervision counters reset
// regardless, which is the bit `status()` reflects.
harn.mcp.stop("alpha")
let after_stop = harn.mcp.status()
__io_println("=== status after stop alpha ===")
for entry in after_stop {
__io_println(json_stringify(entry))
}
let receipt = {
receipt_kind: "mcp_host_receipt",
registered_after_spawn: len(after_spawn),
registered_after_stop: len(after_stop),
every_initial_entry_is_lazy: all_lazy(after_spawn),
every_initial_entry_circuit_closed: all_closed(after_spawn),
}
__io_println("=== mcp-host receipt ===")
__io_println(json_stringify(receipt))
return receipt
}
/**
* Compact predicates so the receipt stays small. The status entry
* shape is documented in `crates/harn-vm/src/mcp_host.rs::McpHostStatus`.
*/
fn all_lazy(entries) {
var ok = true
for entry in entries {
if !entry.lazy {
ok = false
}
}
return ok
}
fn all_closed(entries) {
var ok = true
for entry in entries {
if entry.circuit != "closed" {
ok = false
}
}
return ok
}The agent runtime, built into the language
Orchestration, safety, and observability are primitives in Harn and its standard library — so they compose instead of fighting each other.
Pipelines are first-class
Compose work with the |> operator. Data and control flow read top to bottom, and the compiler tracks the shape of every stage.
LLMs and tools, built in
llm_call, agent_loop, tool vaults, MCP, reranking, and ensembles are language primitives, not a bolt-on SDK you assemble by hand.
Compile-time capability safety
Filesystem, network, and process access are capabilities checked before a single line runs. No surprise side effects inside an autonomous loop.
Deterministic replay
Every run records and replays. Step back through an agent's decisions, diff two runs, and debug non-determinism out of the system.
Durable steps and triggers
Checkpoint long-running work and resume after a crash. Fire pipelines from cron, webhooks, GitHub, Slack, and more.
Protocols, natively
Speak MCP, ACP, and A2A out of the box. Embed Harn in Rust, or run it as a server with harn serve.
Find your path
The documentation follows Diátaxis — organized by what you are trying to do.
Learn by building
Start from zero and build a working agent, MCP server, or eval pipeline step by step.
ExploreGet a task done
Recipes for the things you actually need: hooks, channels, pools, refactors, and more.
ExploreLook up the details
The complete language, runtime, standard-library, protocol, and CLI reference.
ExploreUnderstand the design
The reasoning behind the host boundary, sandboxing, and Harn's architectural decisions.
ExploreWrite your first pipeline
Install the CLI, write a few lines of Harn, and run a real agent in minutes.