Hirð
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
*A hirð is a Norse king's household guard: sworn retainers, each with a
named duty, answerable to one lord. Illustration by Erik Werenskiold for
Magnús Erlingsson's saga in Snorri's Heimskringla (public domain, via
Wikimedia Commons).*
A typed language for long-running agent systems on BEAM: effect-row
tracking, auditable tool effects, typed actors, and OTP supervision.
Python agent frameworks hide side effects in coroutine soup; Hirð makes
every tool call, every actor message, and every supervisor boundary
visible in the types and queryable by tooling.
**What that buys: deterministic replay of real agent traffic.** Every
tool call is recorded unconditionally in a canonical wire format, so a
recorded run is a file you can replay — the same calls, in the same
order, each served the result the recorded run got back, with no service
contacted. That is a regression test with no oracle to maintain, a bug
report that reproduces, and a fixed environment to evaluate a change in.
It is also not something you can retrofit onto a framework that hides
its side effects: it needs the effects in the types and a single
dispatch path underneath them. hird demo is that claim in one command:
it records a run of the demo planner, replays that one recording against
three variants of the program, and prints where each parted from it.
**And systems that stand.** A Hirð program is not a script that exits:
fn main can start a supervision tree and stand, leaving typed actors
serving after its own work is done — driving their own periodic rounds
off a clock capability, crashing and restarting under a declared budget,
every round on the audit stream. hird run demo/agent_fleet is that
claim running: a hirð of three retainers that keeps working through a
deliberate crash.
**Status**: pre-1.0 and experimental. The v0.1 compiler pipeline works
end to end (the demos below type-check, compile to Erlang, and run on
BEAM), but the language surface is unstable, nothing is published to
crates.io, and breaking changes land without deprecation cycles. The
roadmap lives in the in-repo issue tracker (see .beads/README.md).
Install
Prebuilt binaries for Linux, macOS, and Windows are attached to every
release: extract the
archive for your platform and put hird (the compiler), hird-lsp, and
hird-mcp on your PATH.
From source, with Rust 1.97 or newer:
With Nix, the same three binaries are flake outputs
(nix run github:no-materials/hird#hird-mcp).
Compiling and running programs needs **Erlang/OTP** on PATH
(apt install erlang, brew install erlang, …); hird check works
without it.
Quick start
Hirð has no ambient print. Anything a program tells the outside world
goes through a *tool* — a declared, typed, audited external operation —
so the smallest observable program is a tool call. Save this as
hello.hird:
Three things happened. Declaring tool Say created the effect
Tool and a callable say. The handle block supplied an
implementation and discharged that effect, so main is honestly ! {}.
And the call was recorded on the audit stream — unconditionally, because
mocked and real tool calls audit identically. ASCII operator spellings
(->) normalise to their Unicode forms (→) at lex time, so either is
legal input.
| Command | What it does |
|---|---|
| hird check | type- and effect-check; coded diagnostics |
| hird build | emit readable Erlang, compile it to .beam |
| hird run | build, then execute fn main on BEAM |
| hird demo | record one run of the built-in demo, replay it against variants of the program |
| hird emit-ast --json | the typed IR of every definition |
| hird emit-effect-graph --json | actors, mailboxes, handler rows, supervisors, tools, function rows |
| hird effect-diff --exact | fail when the effect graph drifts from a committed baseline |
docs/writing-hird-human.md is the guided