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:
A caller can ask a question. A caller cannot choose the mission, inject priming, or reach anything outside the fence.
The words this page uses
Section titled “The words this page uses”ask-daemon | the agent binary’s client mode — it makes one encrypted call to another agent and prints the reply |
peer / peer_url | who you are calling, by identity name, and where it listens |
capability | which sealed capability on that agent you are asking for |
on_behalf_of | the person this turn is for, as sha512(their email) — never the address |
HEIA_DIR | an agent’s own store. The caller and the door must not share one (see gate 3) |
Provision the runner
Section titled “Provision the runner”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.
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.
What provisioning does not do for you
Section titled “What provisioning does not do for you”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.
cd /home/you/my-runnerset -a; . ./env-file; set +a./hexaeight-agent-linux-x64 vouch allow --caller <your-agent-name> --subject "$SUB"Symptom without it: not permitted to act on behalf of that subject.
2. The same subject needs an inbound rule
Section titled “2. The same subject needs an inbound rule”./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 it3. 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:
export HEIA_DIR=/home/you/my-runner/runner-heia # starting the doorexport HEIA_DIR=/home/you/caller-heia # making the call4. 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.
6. The agent binary must be new enough
Section titled “6. The agent binary must be new enough”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.
Make the call
Section titled “Make the call”cd /path/to/caller-identityset -a; . ./env-file; set +aexport HEIA_DIR=/home/you/caller-heiaexport HEIA_ASK_TIMEOUT_SECONDS=0 # 0 = wait for the work; the peer bounds its own turn
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-daemonOnly a line starting with { is a result — the tool narrates to the same stdout.
What success looks like
Section titled “What success looks like”{"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 charsA 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).
Three policy stores authorise one turn
Section titled “Three policy stores authorise one turn”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 decides | rules live in |
|---|---|---|
| 1 | the serving agent | the runner folder, via --add-rule |
| 2 | the router, relay gate | the router’s own sealed policy |
| 3 | the router, model gate | the 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.
A cached session outlives a policy change
Section titled “A cached session outlives a policy 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.
Verifying the door is really closed
Section titled “Verifying the door is really closed”[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.