feat(agents): add Plan Agent dependency and strengthen Deep Parallel Delegation for non-Claude models
Non-Claude models skip planning and under-parallelize. Two new sections injected only when model is not Claude: - Plan Agent Dependency: multi-step tasks MUST consult Plan Agent first, use session_id for follow-ups, ask aggressively when ambiguous - Deep Parallel Delegation (rewrite): explicit '4 units = 4 agents' pattern, each with clear GOAL + success criteria, all run_in_background
This commit is contained in:
@@ -4,6 +4,8 @@ import { describe, it, expect } from "bun:test"
|
||||
import {
|
||||
buildCategorySkillsDelegationGuide,
|
||||
buildUltraworkSection,
|
||||
buildDeepParallelSection,
|
||||
buildNonClaudePlannerSection,
|
||||
type AvailableSkill,
|
||||
type AvailableCategory,
|
||||
type AvailableAgent,
|
||||
@@ -172,4 +174,86 @@ describe("buildUltraworkSection", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("buildDeepParallelSection", () => {
|
||||
const deepCategory: AvailableCategory = { name: "deep", description: "Autonomous problem-solving" }
|
||||
const otherCategory: AvailableCategory = { name: "quick", description: "Trivial tasks" }
|
||||
|
||||
it("#given non-Claude model with deep category #when building #then returns parallel delegation section", () => {
|
||||
//#given
|
||||
const model = "google/gemini-3-pro"
|
||||
const categories = [deepCategory, otherCategory]
|
||||
|
||||
//#when
|
||||
const result = buildDeepParallelSection(model, categories)
|
||||
|
||||
//#then
|
||||
expect(result).toContain("Deep Parallel Delegation")
|
||||
expect(result).toContain("EVERY independent unit")
|
||||
expect(result).toContain("run_in_background=true")
|
||||
expect(result).toContain("4 independent units")
|
||||
})
|
||||
|
||||
it("#given Claude model #when building #then returns empty", () => {
|
||||
//#given
|
||||
const model = "anthropic/claude-opus-4-6"
|
||||
const categories = [deepCategory]
|
||||
|
||||
//#when
|
||||
const result = buildDeepParallelSection(model, categories)
|
||||
|
||||
//#then
|
||||
expect(result).toBe("")
|
||||
})
|
||||
|
||||
it("#given non-Claude model without deep category #when building #then returns empty", () => {
|
||||
//#given
|
||||
const model = "openai/gpt-5.2"
|
||||
const categories = [otherCategory]
|
||||
|
||||
//#when
|
||||
const result = buildDeepParallelSection(model, categories)
|
||||
|
||||
//#then
|
||||
expect(result).toBe("")
|
||||
})
|
||||
})
|
||||
|
||||
describe("buildNonClaudePlannerSection", () => {
|
||||
it("#given non-Claude model #when building #then returns plan agent section", () => {
|
||||
//#given
|
||||
const model = "google/gemini-3-pro"
|
||||
|
||||
//#when
|
||||
const result = buildNonClaudePlannerSection(model)
|
||||
|
||||
//#then
|
||||
expect(result).toContain("Plan Agent")
|
||||
expect(result).toContain("session_id")
|
||||
expect(result).toContain("Multi-step")
|
||||
})
|
||||
|
||||
it("#given Claude model #when building #then returns empty", () => {
|
||||
//#given
|
||||
const model = "anthropic/claude-sonnet-4-6"
|
||||
|
||||
//#when
|
||||
const result = buildNonClaudePlannerSection(model)
|
||||
|
||||
//#then
|
||||
expect(result).toBe("")
|
||||
})
|
||||
|
||||
it("#given GPT model #when building #then returns plan agent section", () => {
|
||||
//#given
|
||||
const model = "openai/gpt-5.2"
|
||||
|
||||
//#when
|
||||
const result = buildNonClaudePlannerSection(model)
|
||||
|
||||
//#then
|
||||
expect(result).toContain("Plan Agent")
|
||||
expect(result).not.toBe("")
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -316,6 +316,22 @@ export function buildAntiPatternsSection(): string {
|
||||
${patterns.join("\n")}`
|
||||
}
|
||||
|
||||
export function buildNonClaudePlannerSection(model: string): string {
|
||||
const isNonClaude = !model.toLowerCase().includes('claude')
|
||||
if (!isNonClaude) return ""
|
||||
|
||||
return `### Plan Agent Dependency (Non-Claude)
|
||||
|
||||
Multi-step task? **ALWAYS consult Plan Agent first.** Do NOT start implementation without a plan.
|
||||
|
||||
- Single-file fix or trivial change → proceed directly
|
||||
- Anything else (2+ steps, unclear scope, architecture) → \`task(subagent_type="plan", ...)\` FIRST
|
||||
- Use \`session_id\` to resume the same Plan Agent — ask follow-up questions aggressively
|
||||
- If ANY part of the task is ambiguous, ask Plan Agent before guessing
|
||||
|
||||
Plan Agent returns a structured work breakdown with parallel execution opportunities. Follow it.`
|
||||
}
|
||||
|
||||
export function buildDeepParallelSection(model: string, categories: AvailableCategory[]): string {
|
||||
const isNonClaude = !model.toLowerCase().includes('claude')
|
||||
const hasDeepCategory = categories.some(c => c.name === 'deep')
|
||||
@@ -324,12 +340,13 @@ export function buildDeepParallelSection(model: string, categories: AvailableCat
|
||||
|
||||
return `### Deep Parallel Delegation
|
||||
|
||||
For implementation tasks, actively decompose and delegate to \`deep\` category agents in parallel.
|
||||
Delegate EVERY independent unit to a \`deep\` agent in parallel (\`run_in_background=true\`).
|
||||
If a task decomposes into 4 independent units, spawn 4 agents simultaneously — not 1 at a time.
|
||||
|
||||
1. Break the implementation into independent work units
|
||||
2. Maximize parallel deep agents — spawn one per independent unit (\`run_in_background=true\`)
|
||||
3. Give each agent a GOAL, not step-by-step instructions — deep agents explore and solve autonomously
|
||||
4. Collect results, integrate, verify coherence`
|
||||
1. Decompose the implementation into independent work units
|
||||
2. Assign one \`deep\` agent per unit — all via \`run_in_background=true\`
|
||||
3. Give each agent a clear GOAL with success criteria, not step-by-step instructions
|
||||
4. Collect all results, integrate, verify coherence across units`
|
||||
}
|
||||
|
||||
export function buildUltraworkSection(
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
buildGeminiDelegationOverride,
|
||||
buildGeminiVerificationOverride,
|
||||
buildGeminiIntentGateEnforcement,
|
||||
buildGeminiToolGuide,
|
||||
buildGeminiToolCallExamples,
|
||||
} from "./sisyphus-gemini-overlays";
|
||||
|
||||
const MODE: AgentMode = "all";
|
||||
@@ -32,6 +34,7 @@ import {
|
||||
buildHardBlocksSection,
|
||||
buildAntiPatternsSection,
|
||||
buildDeepParallelSection,
|
||||
buildNonClaudePlannerSection,
|
||||
categorizeTools,
|
||||
} from "./dynamic-agent-prompt-builder";
|
||||
|
||||
@@ -170,6 +173,7 @@ function buildDynamicSisyphusPrompt(
|
||||
const hardBlocks = buildHardBlocksSection();
|
||||
const antiPatterns = buildAntiPatternsSection();
|
||||
const deepParallelSection = buildDeepParallelSection(model, availableCategories);
|
||||
const nonClaudePlannerSection = buildNonClaudePlannerSection(model);
|
||||
const taskManagementSection = buildTaskManagementSection(useTaskSystem);
|
||||
const todoHookNote = useTaskSystem
|
||||
? "YOUR TASK CREATION WOULD BE TRACKED BY HOOK([SYSTEM REMINDER - TASK CONTINUATION])"
|
||||
@@ -364,6 +368,8 @@ STOP searching when:
|
||||
|
||||
${categorySkillsGuide}
|
||||
|
||||
${nonClaudePlannerSection}
|
||||
|
||||
${deepParallelSection}
|
||||
|
||||
${delegationTable}
|
||||
@@ -564,12 +570,25 @@ export function createSisyphusAgent(
|
||||
: buildDynamicSisyphusPrompt(model, [], tools, skills, categories, useTaskSystem);
|
||||
|
||||
if (isGeminiModel(model)) {
|
||||
// 1. Intent gate + tool mandate — early in prompt (after intent verbalization)
|
||||
prompt = prompt.replace(
|
||||
"</intent_verbalization>",
|
||||
`</intent_verbalization>\n\n${buildGeminiIntentGateEnforcement()}\n\n${buildGeminiToolMandate()}`
|
||||
);
|
||||
prompt += "\n" + buildGeminiDelegationOverride();
|
||||
prompt += "\n" + buildGeminiVerificationOverride();
|
||||
|
||||
// 2. Tool guide + examples — after tool_usage_rules (where tools are discussed)
|
||||
prompt = prompt.replace(
|
||||
"</tool_usage_rules>",
|
||||
`</tool_usage_rules>\n\n${buildGeminiToolGuide()}\n\n${buildGeminiToolCallExamples()}`
|
||||
);
|
||||
|
||||
// 3. Delegation + verification overrides — before Constraints (NOT at prompt end)
|
||||
// Gemini suffers from lost-in-the-middle: content at prompt end gets weaker attention.
|
||||
// Placing these before <Constraints> ensures they're in a high-attention zone.
|
||||
prompt = prompt.replace(
|
||||
"<Constraints>",
|
||||
`${buildGeminiDelegationOverride()}\n\n${buildGeminiVerificationOverride()}\n\n<Constraints>`
|
||||
);
|
||||
}
|
||||
|
||||
const permission = {
|
||||
|
||||
Reference in New Issue
Block a user