Let mail start a session
Normally a message waits until the recipient's attached session fetches it.
The owner can also let mail start a harness session for a mailbox that has no
live session. The receiving host then launches the mailbox's harness in its
workspace, supervised like an Exec job. It hands the session the message IDs,
never the bodies, with the exact ax messages fetch command to run.
Launching is off until the owner enables it, one mailbox at a time, and only senders the owner lists can start a session. Notifying a live attached session never depends on it.
- Name the senders in the receiving workspace's
agent.ax.toml. Copy each sender'snodeandidfrom the[agents.NAME]entry in the sender's ownagent.ax.toml:
[[agents.assistant.allowed_senders]]
kind = "agent"
key = { node = "<sender-node-hex>", agent = "<sender-id-hex>" }
- On the owner machine, enable launching and check the result:
ax admin processing enable assistant
ax admin processing show assistant
Agent: assistant
Automatic processing: enabled
Session launching: available on this host
Allowed senders: agent <sender-id-hex> on node <sender-node-hex>
...
Launch executable: ~/.local/bin/claude (recorded at agent setup)
Claude permissions: allowed Bash(ax messages fetch:*), Bash(ax messages inbox:*), Bash(ax messages status:*), Bash(ax reply:*) in <workspace>/.claude/settings.local.json
Session launching says whether this host can start a session now and, when
it cannot, why not. enable reads the sender list when it runs, so run it
again after you edit the list. show reports the stored policy. When the
workspace's agent.ax.toml lists different senders, show says that they
apply once enable runs again. The
allowlist reference
explains owner entries and held messages. enable also writes the harness
permission rules described in Harness permissions.
Requirements:
- The commands are signed with the owner key and run on the owner machine. A deployed host cannot change its own processing policy, and an agent cannot opt itself in.
- macOS: sessions run in the account's login session, where Claude Code can
read its sign-in from the login keychain. With no one logged in to that
account on the Mac,
Session launchingreports the missing login session. Log in, then restart ax with the command the reason names (ax exec daemon restarton the owner machine).
Turn launching off
ax admin processing disable assistant turns launching off and keeps the
sender list. ax admin processing stop assistant suppresses further automatic
attempts for the mailbox. Add --cancel-run to also cancel the supervised
session.
Which program a launch runs
The Launch executable line names the program a launch runs and where it came
from. ax takes the first of these:
--executable PATHonenable- the launcher
ax agent setuprecorded from the agent's own session - the
claudeorcodexfound on the launch PATH
A sender can never choose the program. If a recorded launcher has since been
removed, the launch is held instead of falling back to the search path. Repeat
setup from the session, or pass --executable.
For a hook harness such as opencode, the hook chooses the program. The line shows the launcher setup recorded, which ax passes to the hook, and the hook's registration may name another.
Which session a launch starts, and its model
Each launch starts a new harness session by default. That session never becomes the mailbox's session, so the next message launches another new one. Resuming replays the whole earlier conversation as input on every launch, so a long-lived mailbox costs more with each message.
A fresh session knows nothing about earlier mail or earlier launches except what it fetches. The launch hands it only the message IDs and the commands to fetch and reply. Put what it needs in the message, or in the workspace files the harness reads at startup.
The owner chooses per mailbox, and the choice is kept until changed:
ax admin processing enable assistant --session resume # resume the previous session; a new one when it is gone
ax admin processing enable assistant --session resume-only # resume the previous session, or hold the mail
ax admin processing enable assistant --session fresh # back to the default
With resume, ax resumes the session ax agent setup attached, or the one an
earlier launch started. A launched session becomes the mailbox's session once
its run succeeds. A policy stored by an earlier ax, which never let the owner
choose, reads as fresh.
A session you attached with ax agent setup is still told about mail while it
is live, whatever the setting. fresh only means that ax never resumes it
after it has exited. Its attachment stays as it was, so ax agent list still
shows it, and setup and --takeover behave as before. Sessions ax started
stay in the harness's own history (Claude Code transcripts, Codex threads,
opencode sessions titled ax NAME). ax does not delete them.
--model NAME sets the model that launched sessions use, passed to the
harness as one argument. No sender can set it. With no model, the harness's
own default applies. A live session that is told about mail keeps the model it
already has.
ax admin processing enable assistant --model haiku # Claude Code: claude --model haiku
ax admin processing enable codex-assistant --model <model> # Codex: codex exec --model <model>
ax admin processing enable opencode-assistant --model <provider>/<model> # opencode: opencode run --model <provider>/<model>
ax admin processing enable assistant --model '' # clear it
An empty value clears a stored model, and --executable '' likewise clears a
stored executable. show prints both settings:
Launched session: fresh (a new session for every launch)
Model: haiku
In JSON they are session (fresh, resume or resume_only) and model
(null for the harness default). The opencode hook ax ships passes the model
to opencode run unchanged. A hook declares that it accepts a model with the
launch_model capability, and enable --model is refused for a hook that
does not. An older host refuses --session and --model as unknown fields,
and an older owner ax cannot read show from a newer host, so update both.
ax messages status MESSAGE_ID shows why a held message is held, on a
Held because: line (held_detail in JSON). A launched session may end
without fetching its message (incomplete_handoff). The line then names the
attempt, its Exec job, the harness, and the likely cause: the session was not
permitted to run ax messages fetch.
When a Codex session has ended
A Codex mailbox whose interactive session has ended is not held for
good. When Codex's shared daemon answers and reports the saved thread as not
loaded, the next message launches a new session. With --session resume, it
runs codex exec … resume THREAD if Codex's session store still holds that
thread, and otherwise starts a new session.
The message is held as session_unavailable instead in these cases, so that
a thread is never run twice at once:
- the thread is loaded but busy or not accepting input
- a turn is stopped on an approval or a question that nobody may be watching
- the daemon does not answer
A thread waiting on a prompt takes notices again once the prompt is answered. A mailbox runs one launched session at a time. The next launch waits until the previous one has finished.
Deployed hosts
Name the host as in ax admin send:
ax admin processing enable build-host/assistant
ax admin processing show build-host/assistant
The owner machine reads the host's identity, the mailbox and the allowlist in
the agent's workspace through the host's own ax over Exec. It checks that
the host trusts this owner and is the node the name was saved for, signs the
request, and has the host apply it. Each change is bound to the policy
revision read just before it, so a captured request cannot be applied twice.
A Linux or macOS host deployed in user scope launches sessions. A system-scope
Linux host reports in Session launching that it needs a user-scope
deployment. After fixing a blocked reason on a host, restart its service with
the command the reason names.
Next
- Access and accounts: set up the sender allowlist, owner entries and held messages.
- Harness permissions lists the rules
enablewrites for each harness. - opencode sessions explains how a launch works for an opencode mailbox.
- Follow and cancel a message lists every message status.