feat(agents): add build agent prompt extension and configuration override support

- Add BUILD_AGENT_PROMPT_EXTENSION for orchestrator-focused main agent behavior
- Introduce OverridableAgentName type to allow build agent customization
- Update config schema to support build agent override in oh-my-opencode.json
- Inject orchestration prompt into build agent's system prompt

🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2025-12-13 22:13:23 +09:00
parent f3b2fccba7
commit b24b00fad2
6 changed files with 116 additions and 9 deletions

77
src/agents/build.ts Normal file
View File

@@ -0,0 +1,77 @@
export const BUILD_AGENT_PROMPT_EXTENSION = `
# Agent Orchestration & Task Management
You are not just a coder - you are an **ORCHESTRATOR**. Your primary job is to delegate work to specialized agents and track progress obsessively.
## Think Before Acting
When you receive a user request, STOP and think deeply:
1. **What specialized agents can handle this better than me?**
- explore: File search, codebase navigation, pattern matching
- librarian: Documentation lookup, API references, implementation examples
- oracle: Architecture decisions, code review, complex logic analysis
- frontend-ui-ux-engineer: UI/UX implementation, component design
- document-writer: Documentation, README, technical writing
2. **Can I parallelize this work?**
- Fire multiple background_task calls simultaneously
- Continue working on other parts while agents investigate
- Aggregate results when notified
3. **Have I planned this in my TODO list?**
- Break down the task into atomic steps FIRST
- Track every investigation, every delegation
## TODO Tool Obsession
**USE TODO TOOLS AGGRESSIVELY.** This is non-negotiable.
### When to Use TodoWrite:
- IMMEDIATELY after receiving a user request
- Before ANY multi-step task (even if it seems "simple")
- When delegating to agents (track what you delegated)
- After completing each step (mark it done)
### TODO Workflow:
\`\`\`
User Request → TodoWrite (plan) → Mark in_progress → Execute/Delegate → Mark complete → Next
\`\`\`
### Rules:
- Only ONE task in_progress at a time
- Mark complete IMMEDIATELY after finishing (never batch)
- Never proceed without updating TODO status
## Delegation Pattern
\`\`\`typescript
// 1. PLAN with TODO first
todowrite([
{ id: "research", content: "Research X implementation", status: "in_progress", priority: "high" },
{ id: "impl", content: "Implement X feature", status: "pending", priority: "high" },
{ id: "test", content: "Test X feature", status: "pending", priority: "medium" }
])
// 2. DELEGATE research in parallel
background_task(agent="explore", prompt="Find all files related to X")
background_task(agent="librarian", prompt="Look up X documentation")
// 3. CONTINUE working on implementation skeleton while agents research
// 4. When notified, INTEGRATE findings and mark TODO complete
\`\`\`
## Anti-Patterns (AVOID):
- Doing everything yourself when agents can help
- Skipping TODO planning for "quick" tasks
- Forgetting to mark tasks complete
- Sequential execution when parallel is possible
- Direct tool calls without considering delegation
## Remember:
- You are the **team lead**, not the grunt worker
- Your context window is precious - delegate to preserve it
- Agents have specialized expertise - USE THEM
- TODO tracking gives users visibility into your progress
- Parallel execution = faster results
`;

View File

@@ -17,3 +17,4 @@ export const builtinAgents: Record<string, AgentConfig> = {
export * from "./types" export * from "./types"
export { createBuiltinAgents } from "./utils" export { createBuiltinAgents } from "./utils"
export { BUILD_AGENT_PROMPT_EXTENSION } from "./build"

View File

@@ -1,6 +1,6 @@
import type { AgentConfig } from "@opencode-ai/sdk" import type { AgentConfig } from "@opencode-ai/sdk"
export type AgentName = export type BuiltinAgentName =
| "oracle" | "oracle"
| "librarian" | "librarian"
| "explore" | "explore"
@@ -8,6 +8,12 @@ export type AgentName =
| "document-writer" | "document-writer"
| "multimodal-looker" | "multimodal-looker"
export type OverridableAgentName =
| "build"
| BuiltinAgentName
export type AgentName = BuiltinAgentName
export type AgentOverrideConfig = Partial<AgentConfig> export type AgentOverrideConfig = Partial<AgentConfig>
export type AgentOverrides = Partial<Record<AgentName, AgentOverrideConfig>> export type AgentOverrides = Partial<Record<OverridableAgentName, AgentOverrideConfig>>

View File

@@ -1,5 +1,5 @@
import type { AgentConfig } from "@opencode-ai/sdk" import type { AgentConfig } from "@opencode-ai/sdk"
import type { AgentName, AgentOverrideConfig, AgentOverrides } from "./types" import type { BuiltinAgentName, AgentOverrideConfig, AgentOverrides } from "./types"
import { oracleAgent } from "./oracle" import { oracleAgent } from "./oracle"
import { librarianAgent } from "./librarian" import { librarianAgent } from "./librarian"
import { exploreAgent } from "./explore" import { exploreAgent } from "./explore"
@@ -8,7 +8,7 @@ import { documentWriterAgent } from "./document-writer"
import { multimodalLookerAgent } from "./multimodal-looker" import { multimodalLookerAgent } from "./multimodal-looker"
import { deepMerge } from "../shared" import { deepMerge } from "../shared"
const allBuiltinAgents: Record<AgentName, AgentConfig> = { const allBuiltinAgents: Record<BuiltinAgentName, AgentConfig> = {
oracle: oracleAgent, oracle: oracleAgent,
librarian: librarianAgent, librarian: librarianAgent,
explore: exploreAgent, explore: exploreAgent,
@@ -25,13 +25,13 @@ function mergeAgentConfig(
} }
export function createBuiltinAgents( export function createBuiltinAgents(
disabledAgents: AgentName[] = [], disabledAgents: BuiltinAgentName[] = [],
agentOverrides: AgentOverrides = {} agentOverrides: AgentOverrides = {}
): Record<string, AgentConfig> { ): Record<string, AgentConfig> {
const result: Record<string, AgentConfig> = {} const result: Record<string, AgentConfig> = {}
for (const [name, config] of Object.entries(allBuiltinAgents)) { for (const [name, config] of Object.entries(allBuiltinAgents)) {
const agentName = name as AgentName const agentName = name as BuiltinAgentName
if (disabledAgents.includes(agentName)) { if (disabledAgents.includes(agentName)) {
continue continue

View File

@@ -16,7 +16,7 @@ const AgentPermissionSchema = z.object({
external_directory: PermissionValue.optional(), external_directory: PermissionValue.optional(),
}) })
export const AgentNameSchema = z.enum([ export const BuiltinAgentNameSchema = z.enum([
"oracle", "oracle",
"librarian", "librarian",
"explore", "explore",
@@ -25,6 +25,18 @@ export const AgentNameSchema = z.enum([
"multimodal-looker", "multimodal-looker",
]) ])
export const OverridableAgentNameSchema = z.enum([
"build",
"oracle",
"librarian",
"explore",
"frontend-ui-ux-engineer",
"document-writer",
"multimodal-looker",
])
export const AgentNameSchema = BuiltinAgentNameSchema
export const HookNameSchema = z.enum([ export const HookNameSchema = z.enum([
"todo-continuation-enforcer", "todo-continuation-enforcer",
"context-window-monitor", "context-window-monitor",
@@ -62,6 +74,7 @@ export const AgentOverrideConfigSchema = z.object({
export const AgentOverridesSchema = z export const AgentOverridesSchema = z
.object({ .object({
build: AgentOverrideConfigSchema.optional(),
oracle: AgentOverrideConfigSchema.optional(), oracle: AgentOverrideConfigSchema.optional(),
librarian: AgentOverrideConfigSchema.optional(), librarian: AgentOverrideConfigSchema.optional(),
explore: AgentOverrideConfigSchema.optional(), explore: AgentOverrideConfigSchema.optional(),
@@ -82,7 +95,7 @@ export const ClaudeCodeConfigSchema = z.object({
export const OhMyOpenCodeConfigSchema = z.object({ export const OhMyOpenCodeConfigSchema = z.object({
$schema: z.string().optional(), $schema: z.string().optional(),
disabled_mcps: z.array(McpNameSchema).optional(), disabled_mcps: z.array(McpNameSchema).optional(),
disabled_agents: z.array(AgentNameSchema).optional(), disabled_agents: z.array(BuiltinAgentNameSchema).optional(),
disabled_hooks: z.array(HookNameSchema).optional(), disabled_hooks: z.array(HookNameSchema).optional(),
agents: AgentOverridesSchema.optional(), agents: AgentOverridesSchema.optional(),
claude_code: ClaudeCodeConfigSchema.optional(), claude_code: ClaudeCodeConfigSchema.optional(),

View File

@@ -1,5 +1,5 @@
import type { Plugin } from "@opencode-ai/plugin"; import type { Plugin } from "@opencode-ai/plugin";
import { createBuiltinAgents } from "./agents"; import { createBuiltinAgents, BUILD_AGENT_PROMPT_EXTENSION } from "./agents";
import { import {
createTodoContinuationEnforcer, createTodoContinuationEnforcer,
createContextWindowMonitorHook, createContextWindowMonitorHook,
@@ -258,6 +258,16 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
...projectAgents, ...projectAgents,
...config.agent, ...config.agent,
}; };
if (config.agent.build) {
const existingPrompt = config.agent.build.prompt || "";
const userOverride = pluginConfig.agents?.build?.prompt || "";
config.agent.build = {
...config.agent.build,
prompt: existingPrompt + BUILD_AGENT_PROMPT_EXTENSION + userOverride,
};
}
config.tools = { config.tools = {
...config.tools, ...config.tools,
}; };