-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Context
Port of upstream PR sst/opencode#5313 which addresses sst/opencode#4443.
This feature allows users to configure a custom default agent instead of always defaulting to "build". Users with custom agents or different workflows can now set their preferred agent as the default.
Problem
Currently, when no agent is specified, the application always defaults to "build". This is hardcoded in multiple places across the codebase, making it inflexible for users who:
- Have custom agents they prefer to use as their primary agent
- Want to use a different built-in agent (e.g., "plan") as their default
- Have disabled the "build" agent and need a fallback
Proposed Solution
Implement the upstream PR with modifications based on reviewer feedback from @rekram1-node:
I don't like the "!" assertion, I feel like this should behave the same way say "model" does, where we don't force the default at the config level for consistency. So this would be:
session.modeId ?? globalCfg.default_agent ?? "build"
This means instead of forcing default_agent to always be set in config (using ! assertions), we should use the nullish coalescing pattern throughout: value ?? config.default_agent ?? "build".
Acceptance Criteria
- Users can set
default_agentinopencode.jsonconfig - The
default_agentfield properly falls back to "build" when not specified - If configured
default_agentdoesn't exist or is disabled, fallback to first available primary agent - Agent list command shows which agent is the default (e.g.,
build (primary, default)) - TUI initializes with the default agent selected
- All hardcoded "build" references use the fallback chain:
specificValue ?? config.default_agent ?? "build" - Tests verify custom default agent, disabled agent fallback, and nonexistent agent fallback
Implementation Details
Files to Modify
-
packages/opencode/src/config/config.ts- Add
default_agentfield to config schema (line ~594) - Add
firstPrimaryAgent()helper function to find fallback agent - Add validation: if
default_agentis missing, doesn't exist, or is disabled → select first primary agent
- Add
-
packages/opencode/src/agent/agent.ts- Add
default: z.boolean().optional()toAgent.Infoschema (line ~15) - Set
result[key].default = truewhen agent matchescfg.default_agent(after line ~227)
- Add
-
packages/opencode/src/acp/agent.ts- Update
currentModeIdcalculation (line ~472):const availableAgents = agents.filter((agent) => agent.mode !== "subagent") const currentModeId = availableAgents.find((agent) => agent.default)?.name ?? availableAgents[0]?.name
- In
prompt()method (line ~574), use fallback pattern:const agent = session.modeId ?? globalCfg.default_agent ?? "build"
- Update
-
packages/opencode/src/cli/cmd/agent.ts(line ~237)- Update agent list output to show default:
process.stdout.write(`${agent.name} (${agent.mode}${agent.default ? ", default" : ""})${EOL}`)
- Update agent list output to show default:
-
packages/opencode/src/cli/cmd/run.ts(lines ~227, ~236)- Import Config and use fallback pattern:
agent: args.agent || cfg.default_agent ?? "build"
- Import Config and use fallback pattern:
-
packages/opencode/src/cli/cmd/tui/context/local.tsx(line ~59)- Use default agent for initial selection:
current: agents().find((x) => x.default)?.name ?? agents()[0].name
- Use default agent for initial selection:
-
packages/opencode/src/server/server.ts(lines ~1003, ~1007)- Use fallback pattern for agent in compaction:
let currentAgent = cfg.default_agent ?? "build" // ... currentAgent = info.agent ?? cfg.default_agent ?? "build"
- Use fallback pattern for agent in compaction:
-
packages/opencode/src/session/prompt.ts(line ~864)- Use fallback pattern in
createUserMessage:const cfg = await Config.get() const agent = await Agent.get(input.agent ?? cfg.default_agent ?? "build")
- Use fallback pattern in
-
packages/sdk/js/src/v2/gen/types.gen.ts- Add
default_agent?: stringto Config type (after line ~1287) - Add
default?: booleanto Agent type (after line ~1606)
- Add
-
packages/opencode/test/config/config.test.ts- Add tests for:
- Custom
default_agentbeing used - Fallback when
default_agentis disabled - Fallback when
default_agentdoesn't exist
- Custom
- Add tests for:
Key Modification from Upstream PR
Replace all globalCfg.default_agent! (non-null assertion) patterns with globalCfg.default_agent ?? "build" to maintain consistency with how other config defaults (like model) are handled.
Example Config
{
"$schema": "https://opencode.ai/config.json",
"default_agent": "custom",
"agent": {
"custom": {
"model": "anthropic/claude-sonnet-4-20250514",
"description": "My custom default agent"
}
}
}Related Links
- Upstream PR: feat: Support custom default agent anomalyco/opencode#5313
- Original Issue: Is it possible to start in plan mode by default? anomalyco/opencode#4443
- Superseded PR: default_agent settings anomalyco/opencode#4447