# Five-minute quickstart

This builds a real harness from nothing, runs it without an API call, then runs
it for real. Every mutation is validated and rolls back on error.

## 1. Explore the contract

No API key needed for either of these:

```bash
hiveloom schema --annotated
hiveloom catalog tools
```

## 2. Construct a harness

```bash
hiveloom init ./summarizer --name summarizer \
  --task "Summarize a text file into JSON."

printf '%s\n' "The quick brown fox jumps over the lazy dog." \
  > ./summarizer/notes.txt

hiveloom add tool --builtin file_read --dir ./summarizer
hiveloom add validator --builtin regex_match --pattern '"summary"' \
  --dir ./summarizer
hiveloom validate ./summarizer --json
```

Do not hand-edit `harness.yaml`. Use `init`, `add`, `set`, `remove`, or the
gated `evolve` flow — they share one transactional construction API.

## 3. Assemble the first call without contacting the model

```bash
hiveloom run ./summarizer --input notes.txt --dry-run --json
```

`--dry-run` makes no model call. Note that declared MCP servers *are* still
contacted, because their tools are discovered eagerly.

## 4. Run it for real

```bash
export ANTHROPIC_API_KEY=sk-...
hiveloom run ./summarizer --input notes.txt --json
```

Or point it at any other lab:

```bash
hiveloom models
hiveloom set model openai/gpt-4.1-mini --dir ./summarizer
```

## 5. Find the signal, propose an aimed improvement, check it

```bash
hiveloom stats ./summarizer --json
hiveloom signal ./summarizer              # free: where failures concentrate
hiveloom evolve ./summarizer --propose --json
hiveloom proposals apply ./summarizer <proposal_id> --yes --json
hiveloom assess ./summarizer              # free: did the change do what it predicted?
```

`signal` and `assess` make no model call. `evolve --propose` never writes to
the harness: it queues a proposal aimed at one located signal, and a human
applies it explicitly. With an eval, `evolve --experiment eval.yaml --yes`
measures each change and keeps only what the eval confirms — see
[Signal-driven evolution](/signal-driven-evolution) and
[Deploying and evolving](/deploying-and-evolving).

## Prefer model-driven construction?

```bash
hiveloom generate "Summarize a text file into JSON." -o ./summarizer --json
```

A complete version of this harness lives in
[`harnesses/example-summarizer`](https://github.com/FrancescoMrn/hiveloom/tree/main/harnesses/example-summarizer).
To see the whole loop — failures located, a change refuted and reverted, a
change confirmed and kept — without any API key, run the offline
[`signal-lab`](/demos) demo.

## Prefer not to type any of that?

Install and open [the workbench](/workbench), the same framework driven by a
conversation, with the spec, runs, journal, versions, and proposals open beside
it:

```bash
npx hiveloom-workbench
```

It builds the harness above for you and makes long traces readable. Contributors
can run the hot-reload version from a source checkout with `devtools/ui/dev.sh`.

## A harness is a folder

```text
my-harness/
├── harness.yaml          # declarative runtime contract
├── tools/                # optional code tools
├── validators/           # optional task-specific verification
├── schemas/
├── skills/
├── .hiveloom/
│   ├── traces/           # the append-only run journal
│   └── forks/            # experiments on this harness
├── .env.example
└── requirements.txt
```

## Core interfaces

Every CLI command supports `--json`. Exit codes are stable: `0` success,
`1` verification failed, `2` guardrail halt, `3` invalid spec or request, and
`4` runtime failure.

```bash
# Explore and construct
hiveloom schema --json
hiveloom explain context.compaction --json
hiveloom catalog validators --json
hiveloom set loop.max_turns 20 --dir ./my-harness --json
hiveloom add tool --builtin file_read --dir ./my-harness --json

# Run and inspect
hiveloom run ./my-harness --input input.txt --stream
hiveloom trace <run-id> --json
hiveloom trace <run-id> --verify
hiveloom stats ./my-harness --json

# Debug a failure at the turn it went wrong
hiveloom fork <run-id> --at <seq> --name probe
hiveloom run ./my-harness/.hiveloom/forks/probe --resume
hiveloom lineage <run-id> --json

# Improve with a human gate
hiveloom evolve ./my-harness --propose --json
hiveloom proposals list ./my-harness --json
hiveloom proposals apply ./my-harness <proposal-id> --json

# Extend and ship
hiveloom extensions --json
hiveloom mcp list-tools --dir ./my-harness --json
hiveloom package ./my-harness --docker --json
hiveloom serve ./my-harness
hiveloom mcp serve ./my-harness ./other-harness
```

## Serving a harness to other agents

`mcp serve` is the agent-facing front door. It exposes each harness as an MCP
tool (`run_<name>`) plus a `list_harnesses` tool that carries each harness's
measured success rate and cost — so any MCP-capable agent can pick a harness on
evidence and delegate to it, getting back a structured, validator-checked
result instead of improvising the task itself.

Input is always treated as literal text, and untrusted directories fail at
startup (approve them with `hiveloom trust`). Register harnesses once and serve
them together:

```bash
hiveloom registry add ./my-harness
hiveloom mcp serve --registered
hiveloom mcp serve --registered --http   # needs HIVELOOM_API_KEY
```

## Python SDK

The root package exposes a small, semver-stable embedding surface:

```python
from hiveloom import (
    Hive,
    dry_run,
    generate_harness,
    load_spec,
    run_harness,
    validate_harness,
)

info = dry_run("./my-harness", "input.txt")
result = run_harness(
    "./my-harness",
    "input.txt",
    on_event=lambda event: print(event.type),
)
spec = generate_harness("Reconcile invoices", "./invoice-reconciler")
```

Inject a `ModelProvider` into `run_harness` or a `StrongModel` into
`generate_harness` for custom embedding and deterministic tests. For
language-neutral integration, use `run --stream` (JSONL) or `serve` (HTTP).

## Next

- [The workbench](/workbench) — build and debug all of this in a UI.
- [Journal and forks](/journal) — what a run leaves behind, and how to re-enter
  it at the turn it went wrong.
