🤖 feat: add Auto agent with switch_agent tool for backend-side agent switching#2411
🤖 feat: add Auto agent with switch_agent tool for backend-side agent switching#2411
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8ea3c4a05f
ℹ️ 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".
Add the Auto built-in agent markdown definition and a dedicated UI color token.
8ea3c4a to
8f97ea2
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 893b8e5b65
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6551f1406a
ℹ️ 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".
…om switch follow-up
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 45a26b6c0f
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 335cf982fc
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 82ac6dc4eb
ℹ️ 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".
…or disableWorkspaceAgents
|
@codex review |
|
Codex Review: Didn't find any major issues. Already looking forward to the next diff. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Summary
Adds an Auto agent that acts as a routing layer — it analyzes the user's request and calls
switch_agentto hand off to the best UI-selectable agent (plan, exec, explore, ask, etc.) without requiring any UI interaction. This enables headless/background workflows where no user click can complete agent handoffs.Background
Currently, switching between agents (plan → exec, exec → explore, etc.) requires manual UI interaction via the AgentModePicker dropdown. This blocks automated/headless workflows and prevents agents from self-routing based on task analysis. The Auto agent +
switch_agenttool solves this with a backend-side stream restart mechanism.Implementation
Architecture: Signal tool + backend follow-up
switch_agent({ agentId, followUp })— a signal tool that returns{ ok: true }immediatelyagent_report)sendMessagewith the target agent's IDKey components
src/node/builtinAgents/auto.mdAutoagent — routing-only, never does work itselfsrc/node/services/tools/switch_agent.ts{ ok, agentId, reason, followUp }src/common/orpc/schemas/workspace.tsagentSwitchingEnabledmetadata flagsrc/node/services/agentDefinitions/resolveToolPolicy.tsswitch_agentonly for Auto-started sessions, hard-deny for subagentssrc/node/services/streamManager.tsswitch_agentresultssrc/node/services/agentSession.tsSafety guardrails
switch_agentswitch_agentcannot be called from inside QuickJS sandboxValidation
make typecheck— passingmake lint— passingmake static-check— passing (including docs sync)switch_agent.test.ts— tool execution testsresolveToolPolicy.test.ts— policy gating tests (16 tests including new switch_agent coverage)agentSession.switchAgent.test.ts— target validation + follow-up dispatch integration testsstreamManager.test.ts— stop condition testsRisks
agentSwitchingEnabledflag is persisted as workspace metadata; once set, it stays enabled for the session lifetime (intentional — allows switching back and forth)📋 Implementation Plan
Auto agent +
switch_agenttool (backend stream restart)Context / Why
We want an Auto agent that can switch the active agent (between agents that are selectable in the UI) without relying on the frontend. This is important for headless/background runs where no UI click can complete handoffs.
Key requirements:
autoagent.switch_agenttool that lets Auto (and, conditionally, other UI agents) switch to another UI-selectable agent.switch_agenttool should be available in sessions started from Auto, but not when starting directly inplan/exec/etc.Evidence (why this is feasible)
src/node/services/agentDefinitions/resolveToolPolicy.ts.stopWhen(e.g.agent_report):src/node/services/streamManager.ts.src/node/services/agentSession.ts.uiSelectable) and enablement/disablement:src/node/orpc/router.ts(agents.list) +src/node/services/agentDefinitions/agentEnablement.ts.Recommended approach (single approach)
Implement
switch_agentas a signal tool plus a backend follow-up message:switch_agent({ agentId, ... }).StreamManagerdetects the successful tool result and stops the stream after the tool call completes.AgentSessioninspects thestream-endparts, finds the switch signal, and enqueues a synthetic follow-upsendMessagein the same workspace, withoptions.agentId = <target>.This keeps correctness properties we already rely on:
Net LoC estimate (product code only): ~250–400 LoC
Implementation details
1) Add a new built-in agent:
autoFile:
src/node/builtinAgents/auto.mdbase: exec(Auto should have full capabilities by default).ui: visible/selectable.tools.add: includeswitch_agent.switch_agent.Example frontmatter shape (exact schema may differ; confirm against existing built-ins):
2) Define the new tool:
switch_agentDefinition:
src/common/utils/tools/toolDefinitions.tsTOOL_DEFINITIONS.switch_agententry..nullish()for optional fields).Suggested schema shape:
Implementation:
src/node/services/tools/switch_agent.tsResponsibilities:
agentIdis:Suggested output:
Tool registry: add
createSwitchAgentToolto the base tool set so policy filtering can enable/disable it:src/common/utils/tools/tools.ts: importcreateSwitchAgentTooland addswitch_agent: createSwitchAgentTool(config)tononRuntimeTools.PTC /
code_executioncompatibility: prevent nestedswitch_agentcalls inside the QuickJS sandbox (keeps switching detectable + predictable):src/node/services/ptc/toolBridge.ts: add"switch_agent"toEXCLUDED_TOOLS.3) Gate tool availability to “Auto-started sessions”
We need
switch_agentto be injected into other UI agents only if the session was started from Auto.Recommended mechanism: persist a boolean on the workspace metadata, e.g.
agentSwitchingEnabled.WorkspaceMetadataSchema(src/common/orpc/schemas/workspace.ts).agentIdfor a turn isauto, setworkspace.metadata.agentSwitchingEnabled = true(persist via the existing config/metadata save path).WorkspaceMetadatafor a running workspace (likelyWorkspaceService.sendMessage()orAgentSession.sendMessage()).src/node/services/agentResolution.ts→ passenableAgentSwitchToolintoresolveToolPolicyForAgent().ResolveToolPolicyOptionsinsrc/node/services/agentDefinitions/resolveToolPolicy.tswithenableAgentSwitchTool: boolean.switch_agent(match existingpropose_plan/ask_user_questiondenies) to avoid child workspaces unexpectedly self-switching.Alternative: derive “Auto session” from history
Instead of persisting metadata, compute
enableAgentSwitchToolby scanning history for whether the earliest assistant message’sagentIdisauto.Pros: no schema changes.
Cons: requires parsing history at least once, and gets tricky for very fresh sessions (no assistant messages yet). Persisting a boolean is simpler and more robust.
Estimated LoC difference: -20 to +80 depending on caching.
4) Stop the current stream after
switch_agentFile:
src/node/services/streamManager.tscreateStopWhenCondition()to stop when a successfulswitch_agenttool result is observed.agent_reportlogic (stop autonomous tool loop cleanly; don’t abort).Pseudo-shape:
5) Backend-side restart into the selected agent (Option B)
File:
src/node/services/agentSession.tsIn the
stream-endhandler (withinattachAiListeners):event.partsfor aswitch_agenttool result.sendMessagedirectly if safe)options.agentId = <target>synthetic: trueskipAutoResumeReset: trueFollow-up message content:
followUpfrom tool input if provided; else default to something short and deterministic, e.g.:"Continue."or"Continue in the newly selected mode."Defensive guardrail: add a per-session counter (similar to TaskService’s
consecutiveAutoResumes) to prevent infinite ping-pong switching.6) Validate targets against “agents visible in UI”
Validation should match AgentModePicker’s selectable list.
Reuse backend logic from
agents.list(insrc/node/orpc/router.ts) to determine:uiSelectable(honorsui.hidden, legacyui.selectable, andui.requires: ["plan"])isAgentEffectivelyDisabled(honors config overrides anddisabledflags)The
switch_agenttool should reject:compact,explore,system1_bash)7) Tests
Add coverage for:
switch_agentrejects non-uiSelectable targets.switch_agentonly appears whenagentSwitchingEnabledis true (and not for subagents).switch_agentand confirm the session enqueues a follow-up stream with the new agentId(Place tests alongside existing node service tests; exact directory depends on current conventions.)
Validation checklist (when implementing)
make typecheckmake testmake lintManual smoke tests
auto.plan.autocallsswitch_agent(plan)and that the backend starts a new stream inplanwithout any UI interaction.plandoes not haveswitch_agentavailable.Generated with
mux• Model:anthropic:claude-opus-4-6• Thinking:xhigh• Cost:$2.83