feat(task): advertise role and tailored delegation in task prompts

Document the `role` parameter in the task-tool description (both the
batch and single-spawn shapes) and make tailored specialists the default
rule, not the exception. Direct a recursing worker to pass a `role` for
each sub-specialist. Activates the role field from #2467 for the model.

Refs #2468

Op: extend
This commit is contained in:
metaphorics
2026-06-14 04:49:13 +09:00
parent 5e5e237005
commit ecb46fc72b
4 changed files with 47 additions and 0 deletions
+4
View File
@@ -121,6 +121,10 @@
- Added an optional `role` field to `task` spawns that gives each subagent a tailored specialist identity: the role is injected as a system-prompt specialization preamble and becomes the subagent's display name and telemetry identity in the registry, IRC roster, and Agent Hub, so delegated trees are no longer clones of one generic worker ([#2467](https://github.com/can1357/oh-my-pi/issues/2467))
### Changed
- Documented the `role` task parameter in the task-tool description (both the batch and single-spawn shapes) and made tailored specialists the default delegation guidance, so the model gives each spawn a specialist identity instead of cloning generic workers ([#2468](https://github.com/can1357/oh-my-pi/issues/2468))
## [15.11.8] - 2026-06-12
### Added
@@ -13,4 +13,5 @@ You MUST maintain hyperfocus on the assigned task. NEVER deviate from it.
- You SHOULD prefer edits to existing files over creating new ones.
- You NEVER create documentation files (*.md) unless explicitly requested.
- You MUST follow the assignment and the instructions given to you. They were given for a reason.
- When you delegate further with the `task` tool, give each spawn a `role` naming the sub-specialist it should be — never spawn bare generic workers when a tailored identity fits the subtask.
</directives>
@@ -25,12 +25,14 @@
- `assignment`: complete self-contained instructions; one-liners and missing acceptance criteria are PROHIBITED
- `id`: stable agent id, CamelCase, ≤32 chars; generated when omitted
- `description`: UI label only — subagent never sees it
- `role`: specialist identity this subagent embodies (e.g. "Auth-flow security reviewer") — sets its system-prompt persona and roster display name; tailor every spawn rather than cloning a generic worker
{{#if isolationEnabled}}
- `isolated`: run this spawn in an isolated env; returns patches. Isolated agents are torn down at completion — not addressable afterwards
{{/if}}
{{else}}
- `id`: stable agent id, CamelCase, ≤32 chars; generated when omitted
- `description`: UI label only — subagent never sees it
- `role`: specialist identity this subagent embodies (e.g. "Auth-flow security reviewer") — sets its system-prompt persona and roster display name; tailor every spawn rather than cloning a generic worker
- `assignment`: complete self-contained instructions; one-liners and missing acceptance criteria are PROHIBITED
{{#if isolationEnabled}}
- `isolated`: run in isolated env; returns patches. Isolated agents are torn down at completion — not addressable afterwards
@@ -42,6 +44,7 @@
- **Maximize fan-out.** Issue the widest {{#if batchEnabled}}`tasks[]` batch{{else}}set of parallel `task` calls{{/if}} the work decomposes into. NEVER serialize work that could run concurrently.
- **Subagents do not verify, lint, or format.** Every assignment MUST instruct the subagent to skip all gates, formatters, and project-wide build/test/lint. You run them once at the end across the union of changed files.
- No globs, no "update all", no package-wide scope. Fan out.
- **Tailor every spawn with a `role`.** A role naming the specialist (e.g. "Parser edge-case tester", "SSE backpressure specialist") makes a sharper agent than a bare generic `task`/`quick_task` worker; decompose into named specialists, never clones of one generic worker. A role-less generic spawn is the exception.
- NEVER slow down or serialize because tasks might overlap on some files. Agents resolve collisions among themselves in real time.
- Subagents have no conversation history. Every fact, file path, and direction they need MUST be explicit in {{#if batchEnabled}}`context` or the item's `assignment`{{else}}the `assignment`{{/if}}.
{{#if batchEnabled}}
@@ -0,0 +1,39 @@
import { describe, expect, it } from "bun:test";
import { prompt } from "@oh-my-pi/pi-utils";
import taskDescriptionTemplate from "../../src/prompts/tools/task.md" with { type: "text" };
// Contract: the task tool description the model sees advertises the `role`
// parameter (in both the batch and flat shapes) and steers toward tailored
// specialists. Without this the `role` field added in #2467 stays dormant.
function render(batchEnabled: boolean): string {
return prompt.render(taskDescriptionTemplate, {
agents: [{ name: "explore", description: "scout", readOnly: true }],
spawningDisabled: false,
MAX_CONCURRENCY: 32,
isolationEnabled: true,
batchEnabled,
asyncEnabled: true,
ircEnabled: true,
});
}
describe("task tool description: role parameter", () => {
it("documents `role` in the batch parameter list", () => {
const out = render(true);
expect(out).toContain("`role`:");
expect(out).toMatch(/specialist identity/i);
});
it("documents `role` in the flat (single-spawn) parameter list", () => {
const out = render(false);
expect(out).toContain("`role`:");
});
it("makes tailored specialists the default, not the exception, in the rules", () => {
const out = render(true);
// Stable invariant — tailoring tied to `role` on one directive line —
// rather than the exact copy-edited wording/capitalization.
expect(out).toMatch(/tailor[^\n]*role/i);
});
});