fix(background-task): clarify task id contracts

This commit is contained in:
YeonGyu-Kim
2026-05-15 15:41:30 +09:00
parent 15e7330ff0
commit c25cb8dcef
30 changed files with 238 additions and 79 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ describe("buildAntiDuplicationSection", () => {
expect(result).toContain("Wait for Results Properly")
expect(result).toContain("End your response")
expect(result).toContain("Wait for the completion notification")
expect(result).toContain("background_output")
expect(result).toContain('background_output(task_id="bg_...")')
})
it("#given no arguments #when building #then explains why this matters", () => {
+7
View File
@@ -126,6 +126,13 @@ describe("Atlas prompts use task_id (not session_id) for retries", () => {
expect(prompt, `${name}: missing task_id retry reference`).toMatch(/task_id/)
}
})
test("all variants should separate background ids from continuation task ids", () => {
for (const [name, prompt] of ALL_VARIANTS) {
expect(prompt, `${name}: missing bg result collection contract`).toContain('background_output(task_id="bg_...")')
expect(prompt, `${name}: missing ses continuation contract`).toContain('task(task_id="ses_..."')
}
})
})
describe("Atlas prompts no-excuses retry policy", () => {
+2 -2
View File
@@ -243,6 +243,6 @@ export const DEFAULT_ATLAS_CRITICAL_RULES = `<critical_overrides>
- Run lsp_diagnostics after every delegation
- Pass inherited wisdom to every subagent
- Verify with your own tools
- **Store task_id from every delegation output**
- **Use \`task_id="{task_id}"\` for retries, fixes, and follow-ups**
- **Store continuation task_id (\`ses_...\`) from every delegation output**
- **Use \`task(task_id="ses_...", prompt="...")\` for retries, fixes, and follow-ups**
</critical_overrides>`
+2 -2
View File
@@ -216,6 +216,6 @@ export const KIMI_ATLAS_CRITICAL_RULES = `<critical_overrides>
- Run lsp_diagnostics after every delegation
- Pass inherited wisdom to every subagent
- Verify with your own tools
- **Store task_id from every delegation output**
- **Use \`task_id="{task_id}"\` for retries, fixes, and follow-ups**
- **Store continuation task_id (\`ses_...\`) from every delegation output**
- **Use \`task(task_id="ses_...", prompt="...")\` for retries, fixes, and follow-ups**
</critical_overrides>`
+2 -2
View File
@@ -232,6 +232,6 @@ export const OPUS_47_ATLAS_CRITICAL_RULES = `<critical_overrides>
- Run lsp_diagnostics after every delegation
- Pass inherited wisdom to every subagent
- Verify with your own tools
- **Store task_id from every delegation output**
- **Use \`task_id="{task_id}"\` for retries, fixes, and follow-ups**
- **Store continuation task_id (\`ses_...\`) from every delegation output**
- **Use \`task(task_id="ses_...", prompt="...")\` for retries, fixes, and follow-ups**
</critical_overrides>`
+2 -1
View File
@@ -120,7 +120,8 @@ task(category="quick", load_skills=[], run_in_background=false, prompt="...task
- **Task execution** (\`category="..."\`): \`run_in_background=false\` — blocks for verification
**Background management:**
- Collect: \`background_output(task_id="...")\`
- Collect with background task IDs (\`bg_...\`): \`background_output(task_id="bg_...")\`
- Continue follow-ups with continuation task IDs (\`ses_...\`): \`task(task_id="ses_...")\`
- Cancel DISPOSABLE background tasks individually before final answer: \`background_cancel(taskId="bg_explore_xxx")\`
- **NEVER \`background_cancel(all=true)\`** — it kills tasks whose output you have not collected.
</parallel_by_default>`
+1 -1
View File
@@ -148,7 +148,7 @@ When you need the delegated results but they're not ready:
1. **End your response** - do NOT continue with work that depends on those results
2. **Wait for the completion notification** - the system will trigger your next turn
3. **Then** collect results via \`background_output(task_id="...")\`
3. **Then** collect results via \`background_output(task_id="bg_...")\`
4. **Do NOT** impatiently re-search the same topics while waiting
### Why This Matters:
+30
View File
@@ -0,0 +1,30 @@
/// <reference types="bun-types" />
import { describe, expect, test } from "bun:test"
import { buildHephaestusPrompt as buildGptHephaestusPrompt } from "./hephaestus/gpt"
import { buildHephaestusPrompt as buildGpt53CodexHephaestusPrompt } from "./hephaestus/gpt-5-3-codex"
import { buildHephaestusPrompt as buildGpt54HephaestusPrompt } from "./hephaestus/gpt-5-4"
import { buildGpt55HephaestusPrompt } from "./hephaestus/gpt-5-5"
describe("Hephaestus background task ID guidance", () => {
const promptBuilders = [
["gpt", () => buildGptHephaestusPrompt()],
["gpt-5.3-codex", () => buildGpt53CodexHephaestusPrompt()],
["gpt-5.4", () => buildGpt54HephaestusPrompt()],
["gpt-5.5", () => buildGpt55HephaestusPrompt([])],
] as const
for (const [name, buildPrompt] of promptBuilders) {
test(`#given ${name} prompt #when describing task follow-ups #then bg ids and continuation ids are disambiguated`, () => {
// given, when
const prompt = buildPrompt()
// then
expect(prompt).toContain("background task IDs (`bg_...`)")
expect(prompt).toContain("continuation IDs (`ses_...`)")
expect(prompt).toContain("background_output(task_id=\"bg_...\")")
expect(prompt).toContain("task(task_id=\"ses_...\")")
expect(prompt).not.toContain("returns a task_id")
})
}
})
+5 -5
View File
@@ -299,7 +299,7 @@ Prompt structure for each agent:
- Parallelize independent file reads - don't read files one at a time
- NEVER use \`run_in_background=false\` for explore/librarian
- Continue only with non-overlapping work after launching background agents
- Collect results with \`background_output(task_id="...")\` when needed
- Keep IDs separate: collect results with background task IDs (\`bg_...\`) via \`background_output(task_id="bg_...")\`; continue follow-up sessions with continuation IDs (\`ses_...\`) via \`task(task_id="ses_...")\`
- BEFORE final answer, cancel DISPOSABLE tasks individually: \`background_cancel(taskId="bg_explore_xxx")\`, \`background_cancel(taskId="bg_librarian_xxx")\`
- **NEVER use \`background_cancel(all=true)\`** - it kills tasks whose results you haven't collected yet
@@ -407,11 +407,11 @@ After delegation, ALWAYS verify: works as expected? follows codebase pattern? MU
### Session Continuity
Every \`task()\` output includes a session_id. **USE IT for follow-ups.**
Every \`task()\` output includes a continuation ID (\`ses_...\`). **USE IT for follow-ups.**
- **Task failed/incomplete** - \`task_id="{id}", prompt="Fix: {error}"\`
- **Follow-up on result** - \`task_id="{id}", prompt="Also: {question}"\`
- **Verification failed** - \`task_id="{id}", prompt="Failed: {error}. Fix."\`
- **Task failed/incomplete** - \`task(task_id="ses_...", prompt="Fix: {error}")\`
- **Follow-up on result** - \`task(task_id="ses_...", prompt="Also: {question}")\`
- **Verification failed** - \`task(task_id="ses_...", prompt="Failed: {error}. Fix.")\`
${
oracleSection
+7 -5
View File
@@ -111,6 +111,8 @@ export function buildHephaestusPrompt(
const identityBlock = `<identity>
You are Hephaestus, an autonomous deep worker for software engineering.
ID contract: background task IDs (\`bg_...\`) use \`background_output(task_id="bg_...")\`; continuation IDs (\`ses_...\`) use \`task(task_id="ses_...")\`.
You communicate warmly and directly, like a senior colleague walking through a problem together. You explain the why behind decisions, not just the what. You stay concise in volume but generous in clarity - every sentence carries meaning.
You build context by examining the codebase first without assumptions. You think through the nuances of the code you encounter. You persist until the task is fully handled end-to-end, even when tool calls fail. You only end your turn when the problem is solved and verified.
@@ -234,7 +236,7 @@ Agent prompt structure:
- [REQUEST]: What to find, format to return, what to skip
Background task management:
- Collect results with \`background_output(task_id="...")\` when completed
- Keep IDs separate: collect results with background task IDs (\`bg_...\`) via \`background_output(task_id="bg_...")\`; continue follow-up sessions with continuation IDs (\`ses_...\`) via \`task(task_id="ses_...")\`
- Before final answer, cancel disposable tasks individually: \`background_cancel(taskId="...")\`
- Never use \`background_cancel(all=true)\` - it kills tasks whose results you have not collected yet
@@ -312,10 +314,10 @@ Every delegation prompt needs these 6 sections:
After delegation, verify by reading every file the subagent touched. Check: works as expected? follows codebase pattern? Do not trust self-reports.
<session_continuity>
Every \`task()\` returns a task_id. Use it for all follow-ups:
- Task failed/incomplete: \`task_id="{id}", prompt="Fix: {error}"\`
- Follow-up on result: \`task_id="{id}", prompt="Also: {question}"\`
- Verification failed: \`task_id="{id}", prompt="Failed: {error}. Fix."\`
Every \`task()\` output includes a continuation ID (\`ses_...\`). Use it for all follow-ups:
- Task failed/incomplete: \`task(task_id="ses_...", prompt="Fix: {error}")\`
- Follow-up on result: \`task(task_id="ses_...", prompt="Also: {question}")\`
- Verification failed: \`task(task_id="ses_...", prompt="Failed: {error}. Fix.")\`
This preserves full context, avoids repeated exploration, saves 70%+ tokens.
</session_continuity>
+4 -2
View File
@@ -22,6 +22,8 @@ function buildTaskSystemGuide(useTaskSystem: boolean): string {
const HEPHAESTUS_GPT_5_5_TEMPLATE = `You are Hephaestus, an autonomous deep worker based on GPT-5.5. You and the user share one workspace. You receive goals, not step-by-step instructions, and execute them end-to-end.
ID contract: background task IDs (\`bg_...\`) use \`background_output(task_id="bg_...")\`; continuation IDs (\`ses_...\`) use \`task(task_id="ses_...")\`.
# Tone
Warm but spare. Communicate efficiently - enough context for the user to trust the work, then stop. No flattery, no narration, no padding. Acknowledge real progress briefly; never invent it.
@@ -172,7 +174,7 @@ AGENTS.md files in your context carry directory-scoped conventions. Obey them fo
**\`task()\`** for both research sub-agents and category-based delegation. Allowed: \`subagent_type="explore"\`, \`"librarian"\`, \`"oracle"\`, or \`category="..."\`.
- Every \`task()\` call needs \`load_skills\` (an empty array \`[]\` is valid).
- Reuse \`task_id\` for follow-ups; never start a fresh session on a continuation. Saves 70%+ of tokens and preserves the sub-agent's full context.
- Reuse continuation IDs (\`ses_...\`) for follow-ups via \`task(task_id="ses_...")\`; never pass background task IDs (\`bg_...\`) to \`task()\`. Saves 70%+ of tokens and preserves the sub-agent's full context.
Each sub-agent prompt should include four fields:
@@ -181,7 +183,7 @@ Each sub-agent prompt should include four fields:
- **DOWNSTREAM**: how you will use the results.
- **REQUEST**: what to find, what format to return, what to skip.
**Background tasks.** Collect with \`background_output(task_id="...")\` once they complete. Before the final answer, cancel disposable tasks individually via \`background_cancel(taskId="...")\`. Never use \`background_cancel(all=true)\` - it kills tasks whose results you have not collected.
**Background tasks.** Collect with background task IDs (\`bg_...\`) via \`background_output(task_id="bg_...")\` once they complete. Use continuation IDs (\`ses_...\`) only for \`task(task_id="ses_...")\` follow-ups. Before the final answer, cancel disposable tasks individually via \`background_cancel(taskId="bg_...")\`. Never use \`background_cancel(all=true)\` - it kills tasks whose results you have not collected.
**\`skill\`** loads specialized instruction packs. Load a skill whenever its declared domain even loosely connects to your current task. Loading an irrelevant skill costs almost nothing; missing a relevant one degrades the work measurably.
+5 -5
View File
@@ -201,7 +201,7 @@ task(subagent_type="librarian", run_in_background=true, load_skills=[], descript
- Parallelize independent file reads - don't read files one at a time
- NEVER use \`run_in_background=false\` for explore/librarian
- Continue only with non-overlapping work after launching background agents
- Collect results with \`background_output(task_id="...")\` when needed
- Keep IDs separate: collect results with background task IDs (\`bg_...\`) via \`background_output(task_id="bg_...")\`; continue follow-up sessions with continuation IDs (\`ses_...\`) via \`task(task_id="ses_...")\`
- BEFORE final answer, cancel DISPOSABLE tasks individually
- **NEVER use \`background_cancel(all=true)\`**
@@ -277,11 +277,11 @@ After delegation, ALWAYS verify: works as expected? follows codebase pattern? MU
### Session Continuity
Every \`task()\` output includes a task_id. **USE IT for follow-ups.**
Every \`task()\` output includes a continuation ID (\`ses_...\`). **USE IT for follow-ups.**
- **Task failed/incomplete** - \`task_id="{id}", prompt="Fix: {error}"\`
- **Follow-up on result** - \`task_id="{id}", prompt="Also: {question}"\`
- **Verification failed** - \`task_id="{id}", prompt="Failed: {error}. Fix."\`
- **Task failed/incomplete** - \`task(task_id="ses_...", prompt="Fix: {error}")\`
- **Follow-up on result** - \`task(task_id="ses_...", prompt="Also: {question}")\`
- **Verification failed** - \`task(task_id="ses_...", prompt="Failed: {error}. Fix.")\`
${
oracleSection
+32
View File
@@ -0,0 +1,32 @@
/// <reference types="bun-types" />
import { describe, expect, test } from "bun:test"
import { buildClaudeOpus47SisyphusPrompt } from "./sisyphus/claude-opus-4-7"
import { buildDefaultSisyphusPrompt } from "./sisyphus/default"
import { buildGpt54SisyphusPrompt } from "./sisyphus/gpt-5-4"
import { buildGpt55SisyphusPrompt } from "./sisyphus/gpt-5-5"
import { buildKimiK26SisyphusPrompt } from "./sisyphus/kimi-k2-6"
describe("Sisyphus background task ID guidance", () => {
const promptBuilders = [
["claude-opus-4-7", buildClaudeOpus47SisyphusPrompt],
["default", buildDefaultSisyphusPrompt],
["gpt-5.4", buildGpt54SisyphusPrompt],
["gpt-5.5", buildGpt55SisyphusPrompt],
["kimi-k2.6", buildKimiK26SisyphusPrompt],
] as const
for (const [name, buildPrompt] of promptBuilders) {
test(`#given ${name} prompt #when describing background tasks #then bg ids and session ids are disambiguated`, () => {
// given, when
const prompt = buildPrompt(name, [])
// then
expect(prompt).toContain("background task IDs (`bg_...`)")
expect(prompt).toContain("continuation session IDs (`ses_...`)")
expect(prompt).toContain("background_output(task_id=\"bg_...\")")
expect(prompt).toContain("task(task_id=\"ses_...\")")
expect(prompt).not.toContain("receive task_ids")
})
}
})
+12 -9
View File
@@ -266,14 +266,15 @@ result = task(..., run_in_background=false) // Never wait synchronously for exp
\`\`\`
### Background Result Collection:
1. Launch parallel agents \u2192 receive task_ids
1. Launch parallel agents \u2192 receive background task IDs (\`bg_...\`) for results and continuation session IDs (\`ses_...\`) for follow-ups
2. Continue only with non-overlapping work
- If you have DIFFERENT independent work \u2192 do it now
- Otherwise \u2192 **END YOUR RESPONSE.**
3. **STOP. END YOUR RESPONSE.** The system will send \`<system-reminder>\` when tasks complete.
4. On receiving \`<system-reminder>\` \u2192 collect results via \`background_output(task_id="...")\`
4. On receiving \`<system-reminder>\` \u2192 collect results via \`background_output(task_id="bg_...")\`
5. **NEVER call \`background_output\` before receiving \`<system-reminder>\`.** This is a BLOCKING anti-pattern.
6. Cleanup: Cancel disposable tasks individually via \`background_cancel(taskId="...")\`
7. Use \`task(task_id="ses_...")\` only to continue the same sub-agent session
${buildAntiDuplicationSection()}
@@ -328,15 +329,17 @@ AFTER THE WORK YOU DELEGATED SEEMS DONE, ALWAYS VERIFY THE RESULTS AS FOLLOWING:
### Session Continuity (MANDATORY)
Every \`task()\` output includes a task_id. **USE IT.**
Every \`task()\` output exposes a continuation session ID (\`ses_...\`). Pass it to \`task(task_id="ses_...")\` for follow-ups. **USE IT.**
**ALWAYS continue when:**
- Task failed/incomplete → \`task_id=\"{task_id}\", prompt=\"Fix: {specific error}\"\`
- Follow-up question on result → \`task_id=\"{task_id}\", prompt=\"Also: {question}\"\`
- Multi-turn with same agent → \`task_id=\"{task_id}\"\` - NEVER start fresh
- Verification failed → \`task_id=\"{task_id}\", prompt=\"Failed verification: {error}. Fix.\"\`
- Task failed/incomplete → \`task(task_id="ses_...", prompt="Fix: {specific error}")\`
- Follow-up question on result → \`task(task_id="ses_...", prompt="Also: {question}")\`
- Multi-turn with same agent → \`task(task_id="ses_...")\` - NEVER start fresh
- Verification failed → \`task(task_id="ses_...", prompt="Failed verification: {error}. Fix.")\`
**Why task_id is CRITICAL:**
**Keep IDs separate:** background task IDs (\`bg_...\`) are for \`background_output(task_id="bg_...")\`; continuation session IDs (\`ses_...\`) are for \`task(task_id="ses_...")\`.
**Why continuation is CRITICAL:**
- Subagent has FULL conversation context preserved
- No repeated file reads, exploration, or setup
- Saves 70%+ tokens on follow-ups
@@ -350,7 +353,7 @@ task(category="quick", load_skills=[], run_in_background=false, description="Fix
task(task_id="ses_abc123", load_skills=[], run_in_background=false, description="Fix type error", prompt="Fix: Type error on line 42")
\`\`\`
**After EVERY delegation, STORE the task_id for potential continuation.**
**After EVERY delegation, STORE the \`ses_...\` continuation ID for potential continuation.**
### Code Changes:
- Match existing patterns (if codebase is disciplined)
+6 -4
View File
@@ -301,11 +301,12 @@ Fire similar parallel calls for error patterns (explore), JWT security best prac
### Background Result Collection:
1. Launch parallel agents → receive task_ids
1. Launch parallel agents → receive background task IDs (\`bg_...\`) for results and continuation session IDs (\`ses_...\`) for follow-ups.
2. Continue ONLY with non-overlapping work. If none → END YOUR RESPONSE.
3. System sends \`<system-reminder>\` when tasks complete.
4. Collect via \`background_output(task_id="...")\` ONLY after \`<system-reminder>\`.
4. Collect via \`background_output(task_id="bg_...")\` ONLY after \`<system-reminder>\`.
5. Cancel disposable tasks INDIVIDUALLY via \`background_cancel(taskId="...")\`. NEVER \`background_cancel(all=true)\`.
6. Use \`task(task_id="ses_...")\` only to continue the same sub-agent session.
${buildAntiDuplicationSection()}
@@ -347,9 +348,10 @@ After delegation: VERIFY against MUST DO/MUST NOT DO + existing patterns. Vague
### Session Continuity (apply to ALL follow-ups)
Every \`task()\` returns \`task_id\`. **REUSE IT.**
Every \`task()\` output exposes a continuation session ID (\`ses_...\`). Pass it to \`task(task_id="ses_...")\`. **REUSE IT.**
Use \`task_id\` for: failed/incomplete work, follow-up questions, multi-turn refinement, verification failures.
Use \`task(task_id="ses_...")\` for: failed/incomplete work, follow-up questions, multi-turn refinement, verification failures.
Keep IDs separate: background task IDs (\`bg_...\`) are for \`background_output(task_id="bg_...")\`; continuation session IDs (\`ses_...\`) are for \`task(task_id="ses_...")\`.
\`\`\`typescript
// WRONG: starting fresh loses everything
+12 -9
View File
@@ -327,14 +327,15 @@ result = task(..., run_in_background=false) // Never wait synchronously for exp
\`\`\`
### Background Result Collection:
1. Launch parallel agents → receive task_ids
1. Launch parallel agents → receive background task IDs (\`bg_...\`) for results and continuation session IDs (\`ses_...\`) for follow-ups
2. Continue only with non-overlapping work
- If you have DIFFERENT independent work → do it now
- Otherwise → **END YOUR RESPONSE.**
3. **STOP. END YOUR RESPONSE.** The system will send \`<system-reminder>\` when tasks complete.
4. On receiving \`<system-reminder>\` → collect results via \`background_output(task_id="...")\`
4. On receiving \`<system-reminder>\` → collect results via \`background_output(task_id="bg_...")\`
5. **NEVER call \`background_output\` before receiving \`<system-reminder>\`.** This is a BLOCKING anti-pattern.
6. Cleanup: Cancel disposable tasks individually via \`background_cancel(taskId="...")\`
7. Use \`task(task_id="ses_...")\` only to continue the same sub-agent session
${buildAntiDuplicationSection()}
@@ -389,15 +390,17 @@ AFTER THE WORK YOU DELEGATED SEEMS DONE, ALWAYS VERIFY THE RESULTS AS FOLLOWING:
### Session Continuity (MANDATORY)
Every \`task()\` output includes a task_id. **USE IT.**
Every \`task()\` output exposes a continuation session ID (\`ses_...\`). Pass it to \`task(task_id="ses_...")\` for follow-ups. **USE IT.**
**ALWAYS continue when:**
- Task failed/incomplete → \`task_id="{task_id}", prompt="Fix: {specific error}"\`
- Follow-up question on result → \`task_id="{task_id}", prompt="Also: {question}"\`
- Multi-turn with same agent → \`task_id="{task_id}"\` - NEVER start fresh
- Verification failed → \`task_id="{task_id}", prompt="Failed verification: {error}. Fix."\`
- Task failed/incomplete → \`task(task_id="ses_...", prompt="Fix: {specific error}")\`
- Follow-up question on result → \`task(task_id="ses_...", prompt="Also: {question}")\`
- Multi-turn with same agent → \`task(task_id="ses_...")\` - NEVER start fresh
- Verification failed → \`task(task_id="ses_...", prompt="Failed verification: {error}. Fix.")\`
**Why task_id is CRITICAL:**
**Keep IDs separate:** background task IDs (\`bg_...\`) are for \`background_output(task_id="bg_...")\`; continuation session IDs (\`ses_...\`) are for \`task(task_id="ses_...")\`.
**Why continuation is CRITICAL:**
- Subagent has FULL conversation context preserved
- No repeated file reads, exploration, or setup
- Saves 70%+ tokens on follow-ups
@@ -411,7 +414,7 @@ task(category="quick", load_skills=[], run_in_background=false, description="Fix
task(task_id="ses_abc123", load_skills=[], run_in_background=false, description="Fix type error", prompt="Fix: Type error on line 42")
\`\`\`
**After EVERY delegation, STORE the task_id for potential continuation.**
**After EVERY delegation, STORE the \`ses_...\` continuation ID for potential continuation.**
### Code Changes:
- Match existing patterns (if codebase is disciplined)
+9 -6
View File
@@ -263,14 +263,15 @@ Each agent prompt should include:
- [REQUEST]: What to find, what format, what to skip
Background result collection:
1. Launch parallel agents → receive task_ids
1. Launch parallel agents → receive background task IDs (\`bg_...\`) for results and continuation session IDs (\`ses_...\`) for follow-ups
2. Continue only with non-overlapping work
- If you have DIFFERENT independent work → do it now
- Otherwise → **END YOUR RESPONSE.**
3. **STOP. END YOUR RESPONSE.** The system will send \`<system-reminder>\` when tasks complete.
4. On receiving \`<system-reminder>\` → collect results via \`background_output(task_id="...")\`
4. On receiving \`<system-reminder>\` → collect results via \`background_output(task_id="bg_...")\`
5. **NEVER call \`background_output\` before receiving \`<system-reminder>\`.** This is a BLOCKING anti-pattern.
6. Cancel disposable tasks individually via \`background_cancel(taskId="...")\`
7. Use \`task(task_id="ses_...")\` only to continue the same sub-agent session
${buildAntiDuplicationSection()}
@@ -387,10 +388,12 @@ Post-delegation: delegation never substitutes for verification. Always run \`<ve
### Session continuity
Every \`task()\` returns a task_id. Use it for all follow-ups:
- Failed/incomplete → \`task_id="{id}", prompt="Fix: {specific error}"\`
- Follow-up → \`task_id="{id}", prompt="Also: {question}"\`
- Multi-turn → always \`task_id\`, never start fresh
Every \`task()\` output exposes a continuation session ID (\`ses_...\`). Pass it to \`task(task_id="ses_...")\` for all follow-ups:
- Failed/incomplete → \`task(task_id="ses_...", prompt="Fix: {specific error}")\`
- Follow-up → \`task(task_id="ses_...", prompt="Also: {question}")\`
- Multi-turn → always \`task(task_id="ses_...")\`, never start fresh
Keep IDs separate: background task IDs (\`bg_...\`) are for \`background_output(task_id="bg_...")\`; continuation session IDs (\`ses_...\`) are for \`task(task_id="ses_...")\`.
This preserves full context, avoids repeated exploration, saves 70%+ tokens.
+7 -5
View File
@@ -218,11 +218,13 @@ After a delegation completes, verification is not optional. Read every file the
### Session continuity
Every \`task()\` returns a \`task_id\`. Reuse it for every follow-up interaction with the same sub-agent:
Every \`task()\` output exposes a continuation session ID (\`ses_...\`). Pass it to \`task(task_id="ses_...")\` for every follow-up with the same sub-agent:
- Failed or incomplete work: \`task(task_id="{id}", prompt="Fix: {specific error}")\`
- Follow-up question on a result: \`task(task_id="{id}", prompt="Also: {question}")\`
- Multi-turn refinement: always \`task_id\`, never a fresh session.
- Failed or incomplete work: \`task(task_id="ses_...", prompt="Fix: {specific error}")\`
- Follow-up question on a result: \`task(task_id="ses_...", prompt="Also: {question}")\`
- Multi-turn refinement: always \`task(task_id="ses_...")\`, never a fresh session.
Keep IDs separate: background task IDs (\`bg_...\`) are for \`background_output(task_id="bg_...")\`; continuation session IDs (\`ses_...\`) are for \`task(task_id="ses_...")\`.
Starting fresh on a follow-up throws away the sub-agent's full context. Session continuity typically saves 70% of the tokens a fresh session would burn.
@@ -235,7 +237,7 @@ Exploration is cheap; assumption is expensive. Before implementation on anything
Each exploration prompt should include four fields: **CONTEXT** (what task, which modules), **GOAL** (what decision the results will unblock), **DOWNSTREAM** (how you will use the results), **REQUEST** (what to find, what format, what to skip).
After firing exploration agents, do not manually perform the same search yourself. That is duplicate work and wastes your context window. Continue only with non-overlapping preparation: setting up files, reading known-path files, drafting questions. If no non-overlapping work exists, end your response and wait for the completion notification; do not poll \`background_output\` on a running task.
After firing exploration agents, keep the returned background task IDs (\`bg_...\`) for result collection and continuation session IDs (\`ses_...\`) for follow-ups. Continue only with non-overlapping preparation: setting up files, reading known-path files, drafting questions. If no non-overlapping work exists, end your response and wait for the completion notification; then use \`background_output(task_id="bg_...")\`, not \`task(task_id="ses_...")\`, to collect results.
Stop searching when you have enough context to proceed confidently, when the same information keeps appearing across sources, when two iterations yield no new useful data, or when you found a direct answer.
+9 -6
View File
@@ -307,14 +307,15 @@ Each agent prompt should include:
- [REQUEST]: What to find, what format, what to skip
Background result collection:
1. Launch parallel agents → receive task_ids
1. Launch parallel agents → receive background task IDs (\`bg_...\`) for results and continuation session IDs (\`ses_...\`) for follow-ups
2. Continue only with non-overlapping work
- If you have DIFFERENT independent work → do it now
- Otherwise → **END YOUR RESPONSE.**
3. **STOP. END YOUR RESPONSE.** The system will send \`<system-reminder>\` when tasks complete.
4. On receiving \`<system-reminder>\` → collect results via \`background_output(task_id="...")\`
4. On receiving \`<system-reminder>\` → collect results via \`background_output(task_id="bg_...")\`
5. **NEVER call \`background_output\` before receiving \`<system-reminder>\`.** This is a BLOCKING anti-pattern.
6. Cancel disposable tasks individually via \`background_cancel(taskId="...")\`
7. Use \`task(task_id="ses_...")\` only to continue the same sub-agent session
${buildAntiDuplicationSection()}
@@ -462,10 +463,12 @@ Post-delegation: delegation never substitutes for verification. Always run \`<ve
### Session continuity
Every \`task()\` returns a session_id. Use it for all follow-ups:
- Failed/incomplete → \`session_id="{id}", prompt="Fix: {specific error}"\`
- Follow-up → \`session_id="{id}", prompt="Also: {question}"\`
- Multi-turn → always \`session_id\`, never start fresh
Every \`task()\` output exposes a continuation session ID (\`ses_...\`). Pass it to \`task(task_id="ses_...")\` for all follow-ups:
- Failed/incomplete → \`task(task_id="ses_...", prompt="Fix: {specific error}")\`
- Follow-up → \`task(task_id="ses_...", prompt="Also: {question}")\`
- Multi-turn → always \`task(task_id="ses_...")\`, never start fresh
Keep IDs separate: background task IDs (\`bg_...\`) are for \`background_output(task_id="bg_...")\`; continuation session IDs (\`ses_...\`) are for \`task(task_id="ses_...")\`.
This preserves full context, avoids repeated exploration, saves 70%+ tokens.