Purpose
Hirð is a typed language running on the BEAM (Erlang virtual machine), with the goal of providing an auditable, replayable development foundation for long-running LLM agent systems. Python agent frameworks often hide side effects in coroutines, whereas Hirð makes every tool call, every Actor message, and every supervision boundary visible in the types and queryable by tools.
Main Capabilities
Effect Row Tracking and Tool Auditing
Hirð has no environment-provided print. For a program to output to the outside world, it must go through a "tool"—a declared, typed, audited external operation. Declaring tool Say creates the effect Tool<Say> as well as a callable say. A handle block provides the implementation and eliminates that effect, so main's effects can be honestly annotated as ! {}. Whether the call is simulated or real, it is unconditionally written to the audit stream in the same canonical JSON line format.
Recording and Replay
Because the audit stream fully records all arguments and tagged results of every call, a recorded run is a replayable environment. The replay cursor takes precedence over all handle and install blocks, so during replay no tools run, no services are touched, and each call receives the result recorded in the log (including failures). Matching is strict: the call at each position must be consistent with the log record, otherwise it crashes with replay_divergence, indicating the position, the recorded call, and the provided call. Checked-in recordings can serve as regression tests that require no oracle to maintain, and can also serve as a fixed environment against which to compare program variants.
Typed Actors and OTP Supervision
A Hirð program is not a script that exits after finishing execution: fn main can start a supervision tree and "reside," continuing to provide services through typed Actors after its own work is done, driving periodic rounds via clock capabilities, and crashing and restarting within a declared budget, with every round entering the audit stream. The example demo/agent_fleet demonstrates three supervised Actors continuing to work after a deliberate crash: FleetSup uses the rest_for_one strategy, the auditor downstream of the crash point is restarted along with it, and the planner retains its round count. Actor state dies with the process; the audit stream is the persistent record. The supervision tree itself is queryable, and its effect graph is the system's live organizational chart.
MCP Compiler Query
hird-mcp is coverageA Model Context Protocol server on the same compiler pipeline, communicating over stdio, provides structured compiler queries for LLM agents rather than reading source code and guessing. Tools include: check_file (all diagnostics including warnings), list_definitions (module outline with token cost per symbol), infer_type, lookup_definition, explain_effect_row, render_ir_fragment, explain_actor_protocol, emit_actor_effect_graph, get_context_for_symbol (token-budget-aware symbol summary), and get_context_budget. Errors are returned in structured form: undefined names list the available names, parse and type errors carry encoded diagnostics, and the agent can self-correct from tool output alone. The server is self-describing: it provides agent-facing writing guides, a parser code index, and a phrasebook as MCP resources, and offers a prompt (author_supervised_module) to orchestrate a "write-then-verify" loop.
LSP and editor support
hird-lsp is a Language Server Protocol server covering the compiler frontend, communicating over stdio: diagnostics on open and save, hover showing inferred types and effect rows, go-to-definition for top-level declarations. tree-sitter-hird provides a tree-sitter grammar for the v0.1 surface syntax plus highlight, indent, and fold queries.
Usage
Release builds ship prebuilt binaries for Linux, macOS, and Windows. Unpack the archive for your platform and put hird (the compiler), hird-lsp, and hird-mcp on your PATH. Building from source requires Rust 1.97 or newer; with Nix, the three binaries are provided as flake outputs (nix run github:no-materials/hird#hird-mcp). Compiling and running programs requires Erlang/OTP on your PATH (apt install erlang, brew install erlang, etc.); hird check does notrequire it.
The minimal observable program example (save as hello.hird) needs to declare a tool, provide a handle implementation, and call it, producing one audited tool call. The ASCII operator spelling (->) is normalized to its Unicode form (→) during lexing; both are valid input.
docs/writing-hird-human.md is a guided tutorial, and phrasebook.md is a dense syntax reference.
The repository ships a project-level .mcp.json, and a Claude Code session started here automatically picks up that server (it starts nix run .#hird-mcp; running nix build .#hird-mcp once first avoids waiting for a cold build in the first session). Other MCP clients can launch the hird-mcp binary directly with no arguments.
Running the demos: hird demo runs with no arguments, needs nothing beyond an Erlang installation, records its own episode and replays it against three variants; hird run demo/agent_fleet runs an example of three guardians working continuously.
When it applies
- Development and regression testing of LLM agent systems: oracle-free regression testing via record-and-replay, and comparing program variants under a fixed environment.
- Agent services that need long-lived residency, crash recovery, and periodic jobs: use typed Actors and OTP supervision.
- Compliance or debugging scenarios that need every external call audited: the audit stream records all tool calls completely.
- LLM agent-assisted programming: query the compiler via MCP tools to obtain types, definitions, effect rows, IR fragments, Actor protocols, and effect graphs, and self-verify code.
- In-editor development: get diagnostics, hover types, and go-to-definition via LSP.
Limitations
The project is pre-1.0 experimental. The v0.1 compiler pipeline works end to end (the demo type-checks, compiles to Erlang, and runs on the BEAM), but the language surface is unstable, it is not published to crates.io, and breaking changes do not go through a deprecation cycle. The roadmap lives in the repository's issue tracker (see .beads/README.md). The MSRV is Rust 1.97 (edition 2024). BEAM-related tests are automatically skipped when erlc is not on the PATH. Guarantees of the audit streamAnd non-guarantees see docs/audit-evidence.md; for the canonical format of tool effects and replay see docs/tool-effects.md.