cmux NEXT: Chief messages the agent chats the person started, restored ones included
Fixes #25571
A Chief can now message the agent chats the person started in the app (nudge, steer, ask), not only its own subagents. This includes a chat restored at launch that no tab has shown yet.
Stacked on https://github.com/manaflow-ai/cmux/pull/23074. That PR makes agents chat send|read|state find a chat in the app's own acpmux when the caller's acpmux is another one, as a Chief turn's is (its home's). This branch merges its head (8610c1b435). Until 23074 lands, the diff below includes its 13 files. This PR's own changes are the commits c0e047c6fe and 2b875697d9. Land 23074 first; this PR then shrinks to those commits.
What changed
- Chief tool: a Chief turn keeps
agents_chat_send,agents_chat_readandagents_chat_stateamong its cmux MCP tools. They are listed insession_dir::CHIEF_CMUX_TOOLSand in acpmux's mirroragent_tools::CHIEF_TURN_TOOLS, whichharness.rskeeps equal. Before this change the turn's settings denied every other cmux tool, so a Chief had no way to reach a GUI chat. - Chief instructions (
prompt.rs, Home rules):- The chat id is the acpmux session of a conversation tab:
extra.conversation.agent_session.sessioninagents_snapshot. The daemon keeps that for restored tabs too. - The send starts a turn there as the Chief's message.
agents_chat_state,agents_waitandagents_chat_readfollow it.- Subagents stay
tell.
- The chat id is the acpmux session of a conversation tab:
- CLI/MCP verb:
cmux agents chat send <chat> <text>and MCPagents_chat_sendalready existed. With 23074 they also reach the app's acpmux. This PR does not change them. - Restored, unvisited chats: these need no app change. acpmux keeps the session after a restart, and a prompt resumes its harness (
session/load). The app builds a tab's page only when the tab is first shown, and that page then reads the transcript, the new turn included. plans/cmux-next/cli-gui-parity.mdnotes the Chief's chat tools.
Defaults I chose (no human decision was available)
- "Submitted as a user turn" means the send is the chat's next turn, a
session/promptthat starts a turn, or steers the turn already running. It does not mean the person's own words. The send stays an agent message with the Chief's provenance, under the daemon's agent message policy (verified sender, session scope, limits, the acpmux runaway-pair guard). The chat shows it as the Chief's message. Sending text as if the person typed it would be a trust-policy change. This PR changes no trust policy, so nothing went to https://github.com/manaflow-ai/cmux/issues/13742. - Only send, read and state:
agents_chat_newandagents_chat_interruptstay denied to a Chief turn. A Chief starts work withspawn, and stopping a person's running turn stays the person's choice. - The prompt rule says "when the user asks": a Chief messages a person's chat only on request.
- A
heldreceipt waits for the person: onheld, the Chief tells the user the message waits for their release (cmux agent message release) and never says it was sent. Today a Chief turn holds no launch credential, because acpmux'scredential.mintis refused (origin_gate.rscheck_credential_ownerallows only the verified app). Its sends are therefore the local user's: they are queued and delivered, as the tests show. Once acpmux can mint credentials, a turn in the Chief home's acpmux would be an agent whose workspace the daemon cannot tell (workspace_unknown), and its send would be held. Delivering it then needs a policy decision on #13742 (a Chief turn as the person's delegate).
Tests
cmux-tui/crates/cmux-tui/tests/cli/agents_chat_tools.rsa_caller_sends_to_a_restored_chat_no_tab_has_shown: a real daemon and acpmux.- The person's chat runs a turn, then acpmux shuts down with its agents ended and starts again, so the chat is restored with no client attached.
- A Chief-like caller (its own acpmux elsewhere, a fake app naming the real one) reads it.
- The caller then sends; the resumed harness runs the send as one new turn, marked
agent_message, and answers.
- Live chats: 23074's
a_caller_with_its_own_acpmux_starts_and_drives_a_chat_of_the_apps_acpmuxand the base'san_agent_prompts_another_chat_and_reads_its_reply_over_mcp. Native/OptChat/optchat-chief/tests/cloud_app_tools.rsa_chief_turn_keeps_the_tools_that_message_agent_chats: a Chief turn's cmux tool denials leave the chat send, read and state tools and denyagents_chat_new,agents_chat_interruptand app actions. It fails on the base, where everyagents_chat_*tool is denied.harness.rsacpmux_built_in_turns_allow_the_same_cmux_toolskeeps the two lists equal.
Observed / Not run
Observed (Rust on the rbx builder; the branch at c0e047c6fe, the merge of 23074 and this change):
cargo test -p cmux-tui --test cli agents_chat: 9/9 passed, includinga_caller_sends_to_a_restored_chat_no_tab_has_shownand 23074's live-chat tests.optchat-chief:cargo test --test cloud_app_tools --test harnesspassed 9/9 and 27/27, includinga_chief_turn_keeps_the_tools_that_message_agent_chatsandacpmux_built_in_turns_allow_the_same_cmux_tools.cargo test -p acpmux --lib agent_tools: 5/6. The failure,own_servers_run_under_the_daemon_prefix, is a base finding: base commit d07f7f3a9aecd added theacpmuxMCP server (acpmux-mcp) without updating that test's expected list.chief_turn_tools_contain_no_mac_app_actionspassed.2b875697d9changes only the Chief prompt text; no test reads that sentence.
Not run:
- A live Chief turn in a GUI build messaging a real restored chat. The tagged build
25571-message-gui-agent-chatsis for that dogfood. - A sender holding an acpmux-minted credential, because acpmux cannot mint today (see Defaults).
Changelog
- Added: a Chief can message, nudge and read the agent chats you started, including ones restored at launch that you haven't opened yet.
š¤ Generated with Claude Code