Skip to content

🤖 refactor: clean up Mux agent system (switch_agent, ui.requires, redundant schema)#3408

Merged
ammario merged 5 commits into
mainfrom
agent-system-1ap8
May 28, 2026
Merged

🤖 refactor: clean up Mux agent system (switch_agent, ui.requires, redundant schema)#3408
ammario merged 5 commits into
mainfrom
agent-system-1ap8

Conversation

@ammar-agent
Copy link
Copy Markdown
Collaborator

@ammar-agent ammar-agent commented May 27, 2026

Summary

Four-commit cleanup of Mux's Agent system, all internal:

  1. Docs rewritedocs/agents/index.mdx brought in line with schema + runtime.
  2. Schema cleanup — removed ui.selectable, ui.disabled, internal AgentDiscoveryEntry.disabled; extracted resolveAgentVisibility.
  3. switch_agent removed — the tool, the ui.routable field, the dispatchAgentSwitch machinery, the forceToolChoice plumbing.
  4. ui.requires removed — replaced with a one-liner that names the desktop agent directly.

No user-visible change in the docs or schema-cleanup commits. The two removal commits are behavioural changes (see Risks).

Background

While auditing every frontmatter field for necessity, two pieces fell out:

Schema redundancyui.selectable was a dead legacy fallback to ui.hidden. ui.disabled duplicated top-level disabled. Five files re-implemented the same visibility ladder inline.

Dead subsystemswitch_agent was introduced for the Auto agent (#2717) and the hidden mux agent (Chat-with-Mux). Both were removed (#3087, #3123). After the audit, switch_agent had zero built-in producers; the only built-in marked routable: true was desktop, which is already invoked via task (and exec.md explicitly says so). Decorative routing.

ui.requires redundancyrequires: ["plan"] was used only by the (now-gone) switch_agent plan check and a UI agents-refresh hook. requires: ["desktop"] was used by the desktop built-in to filter itself from the task tool's subagent menu, but the agents.list capability probe was always dead weight (desktop is hidden: true). The one remaining live job (hide desktop from the LLM's task menu on capability-less workspaces) is now a one-line check naming descriptor.id === "desktop" directly.

Commit-by-commit

Commit 1: docs rewrite

Bugs fixed: wrong picker keybind (was Cmd+Shift+M, actually Cmd+Shift+A); wrong subagent hard-deny list; wrong "no recursive task" claim. Previously-undocumented fields documented: top-level disabled, subagent.append_prompt, tools.require, regex anchoring, base resolution rules, the inheritance cap, runtime restriction table.

Commit 2: schema cleanup

  • Deleted ui.selectable, ui.disabled from the Zod schema.
  • Deleted AgentDiscoveryEntry and its internal debug-only disabled flag.
  • New src/node/services/agentDefinitions/agentVisibility.ts houses resolveAgentVisibility(ui).

Commit 3: remove switch_agent

Deleted: tool schema/factory/handler/tests, UI component/story, oRPC field ui.routable + uiRoutable, the entire dispatchAgentSwitch machinery in agentSession.ts (~400 lines + 9 helper methods), the forceToolChoice parameter chain in streamManager + aiService, isExplicitSwitchAgentEnablePattern/matchesSwitchAgentPattern helpers, the routable: true on desktop.md.

Commit 4: drop ui.requires

  • Schema: ui.requires and AgentDefinitionUiRequirementSchema deleted.
  • router.ts agents.list: dropped planReady probe, desktopCapabilityAvailable probe, requiresPlan/requiresDesktop gating. uiSelectable collapses to entry.uiSelectableBase.
  • streamContextBuilder.discoverAvailableSubagentsForToolContext: replaced the requires?.includes("desktop") check with descriptor.id === "desktop". Same observable behaviour, no generic field needed.
  • applyWorkspaceChatEventToAggregator.ts: removed the propose_plan → AGENTS_REFRESH_REQUESTED dispatch and its helpers. (The event itself is kept; Settings still dispatches it when users toggle agent enablement.)
  • Built-in desktop.md no longer declares requires: ["desktop"].

Validation

  • make static-check (lint, typecheck, fmt-check, eager-imports, shellcheck, hadolint, code-docs-links, mintlify broken-links): passed.
  • Full non-integration test sweep: 4,460 pass / 0 fail / 11 skip across 270 files (bun test src/node/ src/browser/utils/messages/ tests/).

Net diff

Commit Insertions Deletions
Docs rewrite +136 −107
Schema cleanup +81 −189
Remove switch_agent +49 −916
Drop ui.requires +13 −316
Total +279 −1,528

Risks

  • Schema-breaking changes:
    • User .md files with ui.selectable: / ui.disabled: silently drop those keys (Zod .strip()). No built-in used them; never documented externally.
    • User agents with tools.require: ["switch_agent"] or tools.add: ["switch_agent"] silently drop the rule. No built-in used switch_agent; never documented as a stable primitive.
    • User agents with ui.requires: silently drop the rule. No built-in (other than desktop, which is updated here) used it.
  • agents.list no longer toggles uiSelectable for capability-gated agents. The only built-in that was capability-gated (desktop) is hidden: true, so uiSelectable is already false regardless. Future user-authored desktop-capability-gated visible agents would need to handle their own gating.
  • All other changes are internal refactoring with identical observable behaviour.

Generated with mux • Model: anthropic:claude-opus-4-7 • Thinking: xhigh • Cost: $45.14

Accurate map of the Agent system: frontmatter fields, base resolution,
tool-policy layering, runtime restrictions. Fixes the wrong agent
picker keybind and documents previously-undocumented fields
(top-level disabled, ui.routable, ui.requires, subagent.append_prompt,
tools.require, regex anchoring, switch_agent literal opt-in, plan-mode
file-edit restriction).
@mintlify
Copy link
Copy Markdown

mintlify Bot commented May 27, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Mux 🟢 Ready View Preview May 27, 2026, 9:19 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f0b01572a8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/agents/index.mdx Outdated
Removed three sources of duplication in the Agent definition system:

- `ui.selectable` (legacy opt-in) had been kept solely as a fallback
  alongside `ui.hidden` (modern opt-out). No built-in used it, no docs
  referenced it. The five inline resolver ladders that supported both
  forms collapse into one helper.
- `ui.disabled` was functionally identical to top-level `disabled`,
  kept only because the same-name precedence rule existed. Standardize
  on top-level `disabled` (it gates `task()` and `switch_agent`, not
  just UI) and drop the dead second field.
- `AgentDiscoveryEntry.disabled` was an internal flag the resolver code
  computed from `ui.disabled` for "debugging/logging only" — no reader
  in the codebase. Goes away with `ui.disabled`.

Extract `resolveAgentVisibility(ui)` so the four call sites that had
re-implemented the `hidden → selectable → routable` ladder inline
(agentDefinitionsService, router, streamContextBuilder, agentSession,
acp/configOptions) all share one definition.

No user-visible behavior change: built-ins use neither `ui.selectable`
nor `ui.disabled`, and top-level `disabled` semantics are preserved.
@ammar-agent ammar-agent changed the title 🤖 docs: rewrite agents reference page 🤖 refactor: clean up agent definition schema + rewrite agents docs May 27, 2026
The switch_agent tool was originally introduced for the Auto agent
(#2717) and let it dynamically hand off to other agents — most notably
the hidden `mux` agent for global config edits. Auto mode was removed
in #3087 and the Chat-with-Mux flow in #3123, leaving switch_agent as
opt-in machinery used by exactly one built-in (desktop, as a routable
target) and no built-in producer.

The desktop agent is already documented to be invoked via `task`
(exec.md system prompt says "delegate to the `desktop` agent via task"),
and the task tool filters by `subagent.runnable`, not `ui.routable`.
So removing switch_agent does not compromise the desktop workflow.

Removed:

- `switch_agent` tool: schema, factory, handler, tests, UI component +
  story, icon mapping, tool-component registry entry, oRPC schema field
  `ui.routable` + descriptor `uiRoutable`.
- `forceToolChoice` plumbing in streamManager + aiService (the only
  required-tool that needed forced toolChoice was switch_agent).
- `dispatchAgentSwitch` and its 9 helper methods in agentSession.ts
  (~400 lines), including the consecutive-switch ping-pong guard,
  fallback target resolver, and stream-end dispatch block.
- switch_agent literal opt-in machinery in `resolveToolPolicy` (the
  `isExplicitSwitchAgentEnablePattern` / `matchesSwitchAgentPattern`
  helpers and runtime require/disable rules).
- switch_agent entry in `SUBAGENT_HARD_DENIED_TOOLS` and
  `EXCLUDED_TOOLS` (ToolBridge).
- `routable: true` on `desktop.md` and its assertion in
  `builtInAgentDefinitions.test.ts`.

Kept:

- `ui.requires` (`"plan" | "desktop"`). This gates picker visibility
  and — more importantly — `task`-tool subagent discovery. Without
  `requires: [desktop]`, the LLM could try to spawn a desktop subagent
  on a workspace with no desktop capability.

Net: +49 / -916 lines across 32 files. All 4,090 non-integration
tests pass.
@ammar-agent ammar-agent changed the title 🤖 refactor: clean up agent definition schema + rewrite agents docs 🤖 refactor: remove switch_agent + clean up agent schema + rewrite docs May 27, 2026
ui.requires had two values:

- requires: ["plan"] — used by the (now-deleted) switch_agent
  plan-gated check and by a UI hook that re-ran agents.list after
  propose_plan succeeded. Zero built-ins used it, no shipped docs
  surface featured it as a stable user-facing knob.
- requires: ["desktop"] — used by the desktop built-in. After audit,
  the only remaining live job was hiding desktop from the task tool's
  subagent menu on workspaces without desktop capability. Since desktop
  is already hidden: true in the picker and never selectable that way,
  the agents.list gate was decorative.

Replaced the generic field with a hardcoded check in the one place
that still mattered: discoverAvailableSubagentsForToolContext now
filters when `descriptor.id === "desktop"`. The router.ts agents.list
machinery (plan-ready probe, desktop-capability probe, requires gating)
is gone. The propose_plan → agents-refresh path in the chat aggregator
is gone (kept the AGENTS_REFRESH_REQUESTED event; it is still
dispatched from Settings when users toggle agent enablement manually).

Net: +29 / -244 lines. 4,460 / 4,460 non-integration tests pass.
@ammar-agent ammar-agent changed the title 🤖 refactor: remove switch_agent + clean up agent schema + rewrite docs 🤖 refactor: clean up Mux agent system (switch_agent, ui.requires, redundant schema) May 28, 2026
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

The previous comment referenced documentation for tools.add: ["switch_agent"] that no longer exists — the entire switch_agent subsystem was removed in commit 3 of this PR. Please take another pass on the latest commit (aa5dbfe0b).

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aa5dbfe0b1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/streamContextBuilder.ts Outdated
A user-defined .mux/agents/desktop.md (or global equivalent) replaces the
built-in semantics entirely. Without the scope check, the runtime gate
silently hid such overrides whenever the workspace lacked desktop
capability, even when the override no longer depended on it.

Tighten the check to descriptor.scope === "built-in" so only the
shipped built-in is gated; same-name overrides resolve via the agent
discovery override chain as usual.

Addresses Codex review on PR #3408.
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

Addressed your desktop capability gate finding in 8b3827: the runtime check now requires descriptor.scope === "built-in", so user overrides at .mux/agents/desktop.md (or the global equivalent) pass through untouched. Regression test added.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ammario ammario merged commit 5be3fd3 into main May 28, 2026
24 checks passed
@ammario ammario deleted the agent-system-1ap8 branch May 28, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants