Skip to content

Other software calling it

Everything so far assumed the caller is you, or another agent you run. The front door is for the case where it is not: another company’s backend, a customer’s application, a partner system.

The shape that makes this safe:

the caller their software open a session ask a question runner agent /external/auth /external/incoming bound to a person ONE sealed procedure a caller chooses the question · never the method

A caller can ask a question. A caller cannot choose the mission, inject priming, or reach anything outside the fence.

ask-daemonthe agent binary’s client mode — it makes one encrypted call to another agent and prints the reply
peer / peer_urlwho you are calling, by identity name, and where it listens
capabilitywhich sealed capability on that agent you are asking for
on_behalf_ofthe person this turn is for, as sha512(their email) — never the address
HEIA_DIRan agent’s own store. The caller and the door must not share one (see gate 3)

Use a separate agent for the front door. It gets its own ports, its own policy store, and one sealed engine — and it can run alongside your workspace agent.

Terminal window
hexaeight-activate add-external-agent \
--from /home/you/my-agent \
--dir /home/you/my-runner \
--mission My_Workflow \
--license personal \
--base-port 8930

--from supplies the identity only — hexaeight.mac and env-file are hardlinked, never copied.

Six things stand between a freshly provisioned runner and its first successful call. Each fails differently, and none of them says “policy”.

These are setup steps, not bugs — but provisioning could do several of them for you, and the intent is that it will. Until then, work through them in order; each one’s symptom is given so you can tell which you have hit.

1. The vouch subject is the hash, not the email

Section titled “1. The vouch subject is the hash, not the email”

An external turn binds to sha512(email), not the address.

Terminal window
cd /home/you/my-runner
set -a; . ./env-file; set +a
SUB=$(printf '[email protected]' | sha512sum | cut -d' ' -f1)
./hexaeight-agent-linux-x64 vouch allow --caller <your-agent-name> --subject "$SUB"

Symptom without it: not permitted to act on behalf of that subject.

Terminal window
./hexaeight-agent-linux-x64 hexaeight-agent.json \
--add-rule "${SUB},<your-agent-name>,inbound,allow"

Symptom without it, and this is the one nothing prepares you for — the router approves and the agent then refuses:

[engineproxy] REFUSED to register router session … no matching allow rule (default-deny)
[engineproxy] router authorized … but the agent policy refused to register it

3. The caller and the door need separate stores

Section titled “3. The caller and the door need separate stores”

Both resolve through HEIA_DIR. Sharing one means the caller’s “expecting a reply” record and the door’s inbox are the same file, and the door answers your own question back to you:

{"ok":true,"accepted":"response"}

Give each its own:

Terminal window
export HEIA_DIR=/home/you/my-runner/runner-heia # starting the door
export HEIA_DIR=/home/you/caller-heia # making the call

4. The wrapper’s harness root starts empty

Section titled “4. The wrapper’s harness root starts empty”

The wrapper runs the engine with --root <its own dir>/harness-root. That directory is created empty. Copy the mission and every memory its fence names into it, or the mission has nothing to navigate — the turn returns a permissions frame in about a second and writes nothing.

5. Re-sealing drops the wrapper unless you say otherwise

Section titled “5. Re-sealing drops the wrapper unless you say otherwise”

engine --add without --file unbinds the wrapper silently. Same symptom as above.

A binary older than the sealed-mission feature ignores the mission and reports -> process rather than runs ONE mission (sealed): <name>. No error, no log line explaining it.

Terminal window
cd /path/to/caller-identity
set -a; . ./env-file; set +a
export HEIA_DIR=/home/you/caller-heia
export HEIA_ASK_TIMEOUT_SECONDS=0 # 0 = wait for the work; the peer bounds its own turn
SUB=$(printf '[email protected]' | sha512sum | cut -d' ' -f1)
printf '{"ask":"<question>","on_behalf_of":"%s","peer":"<agent>",
"peer_url":"http://127.0.0.1:8930","capability":"<cap>"}\n' "$SUB" \
| ./hexaeight-agent-linux-x64 ask-daemon

Only a line starting with { is a result — the tool narrates to the same stdout.

{"sent":true,"reason":"sent","peer":"<agent>","session":"s-2ec7a313…","reply":"…"}

sent:true means it was delivered and answered. The reply holds the turn’s frames; the last one is the result:

{"type":"result","subtype":"success","is_error":false,
"result":"<the answer>","num_turns":11,"duration_ms":152906,
"usage":{"input_tokens":117855,"output_tokens":1475}}

Read subtype first: success means the procedure ran to an answer. And check the door’s own log recorded the turn — if the wrapper never ran, nothing is written there:

2026-09-25T22:21:08+00:00 mission=My_Workflow in=431 chars out=701 chars

A failure is just as legible:

{"sent":true,"reply":"{\"ok\":false,\"error\":\"not permitted to act on behalf of that subject\"}"}

which is gate 1 above — the vouch names the address instead of sha512(address).

This is where a day goes if it is not written down. Each has its own rule list, and a rule in one is invisible to the other two.

#who decidesrules live in
1the serving agentthe runner folder, via --add-rule
2the router, relay gatethe router’s own sealed policy
3the router, model gatethe same file

The router’s policy is sealed under the router’s key — the agent’s CLI cannot write it, and the router does not hot-reload. Restart it after a change.

Sessions are cached by (peer, on_behalf_of). A session opened before you fixed a rule — or before you re-sealed the mission — keeps being reused and keeps failing:

'<subject>' may not post to session 'ext-s-…'

Retire the cached entry under <HEIA_DIR>/peer-sessions/ and the next call mints a fresh one. It does not self-heal.

[hexaeight-agent] engine 'missionrun-external' runs ONE mission (sealed): My_Workflow
[exec-policy] mission 'My_Workflow': enforce ON, NO cmdset — shell denied
[external] enabled — authenticated:missionrun-external cleartext:OFF
[byoa] vouch policy loaded: 2 rule(s)

Four lines. If the first is missing the caller can choose the mission. If the second says anything other than shell denied the mission can run commands. Read them after every restart.