The harness engine
An agent does not do the work itself; it encloses an engine. You can write your own
(Bring your own engine), but every agent already has one: the harness
engine, the batteries-included runtime. chat, mission and runmission in the workspace all run
on it, and so does every runner.
| the binary | hexaeight-engine (the docs also call it hexaeight-harness-engine), installed with the agent under ~/.heia/runtime/harness/ |
| started by | the agent, once per turn, inside the agent’s jail |
| model | never holds a key — every call goes to the agent’s model route, and from there to the router |
| its data | the harness root: ~/.hexaeight-harness for your workspace agent; each runner has its own |
Not the same as the
harnessentry you may see in the workspace’s session list — that is an older skills-based engine kept for sessions that already use it.
What it brings
Section titled “What it brings”Memories. Searchable bodies of documents — see Documents it can search.
A local memory is an index in the harness root (memories/<name>/); a served memory is a
pointer (memories/<name>/remote.json) to another agent’s corpus or API, searched through
service_call over the turn’s ticket and the agent’s policy. The engine searches both the same way.
Other agents, through one memory. Every harness root has connect-to-agent:
memory_search("connect-to-agent", "<agent name> <question>") asks that agent — by name, over DDE —
and returns its answer. A turn serving someone else does not relay unless switched on; the memory is kept
exactly as shipped. See Two agents talking to each other.
Sessions. Each conversation has a transcript and resumes where it left off. Each session also gets its own working folder, so one conversation’s files never appear in another’s.
The tool loop. In a guided turn the model reasons, calls a tool (search a memory, run a skill, record state), reads the result and continues, until it can answer. Every model call in that loop goes through the agent’s route.
Missions. A written method the engine follows instead of improvising — see What a mission is:
- guided — the model walks the mission’s map and cards, step by step;
- direct — one card, one approved command: the engine writes the message to a file, runs the command, and returns what it printed, making no model call of its own. This is how framework runners work.
It also copies a mission’s own files (a framework’s runner.py, say) into each turn’s folder, fresh.
The command gate. A mission runs a shell command only if it is in the mission’s command set, sealed in the agent and pinned to the sha256 of the file it runs. Anything else is denied, not asked about. No command set means no shell at all.
The jail. Every turn runs with the agent’s identity folder masked, so a turn — and anything it launches — cannot read the identity files, even though it runs as the agent.
The model route and the turn’s ticket, handed on. A command the engine launches (a framework
runner) receives the turn’s model route (ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN,
ANTHROPIC_MODEL) and the turn’s MCP ticket (HEIA_MCP_CONFIG), so it can use the model and reach
shared memories and APIs — without a provider key, and under the same policy as the turn.
Where it keeps things
Section titled “Where it keeps things”~/.hexaeight-harness/ the harness root (a runner: <runner>-frontdoor/harness-root) memories/ <memory>/ a local memory: sources/ + its index <memory>/remote.json a served memory: a pointer, nothing else connect-to-agent/remote.json asks other agents (written and kept by the engine) <mission>/ a mission: sources/ (map, cards, fence) + its files + index sessions, projects, … conversation recordsA runner’s root starts with its mission only; hexaeight-activate runner-memory --share decides what
else it may see.
The engines built on it
Section titled “The engines built on it”| engine | what it is for |
|---|---|
chat | conversation, with whatever memories you attach |
mission | building a mission in the workspace — the cards take shape beside the conversation |
runmission | running a mission you pick; per-model variants are made with hexaeight-activate engine --add runmission --model … |
missionrun-external | a runner’s engine: runmission sealed to one mission, for outside callers |
They are the same binary with different instructions, sealed as entries in the agent’s
engines.he.
Running it by hand
Section titled “Running it by hand”The binary also works on its own, which is how you build and check memories outside the workspace:
E=~/.heia/runtime/harness/hexaeight-engine$E --addmemory <name> --file <file-or-folder> --root ~/.hexaeight-harness # build or add to a memory$E --memory-search <name> --root ~/.hexaeight-harness -p "<question>" # search it$E --memory-refresh <name> --root ~/.hexaeight-harness # re-read changed sources, drop removed ones$E --connector-relay status --root ~/.hexaeight-harness # on | off: may it ask agents for someone elseHow it fits with your own engine and frameworks
Section titled “How it fits with your own engine and frameworks”| the harness engine | your own engine | a framework as a sealed mission | |
|---|---|---|---|
| who does the work | the built-in runtime | your process | your framework, launched by a direct mission |
| memories, sessions, tool loop | built in | yours to provide | the framework’s own loop; HexaEight’s memories via the ticket |
| policy, identity, model route | the agent | the agent | the agent |
| how you add it | nothing to add | Bring your own engine | hexaeight-activate enable <framework> |