
create-specialized-subagent
by aliou
SKILL.md
name: create-specialized-subagent description: Create specialized subagents within the specialized-subagents extension. Use when asked to create a new subagent like scout, librarian, oracle, etc.
Create Specialized Subagent
Create subagents within extensions/specialized-subagents/subagents/.
Subagents are autonomous agents with their own tools, system prompt, and model. They run as Pi tools, streaming progress and rendering results.
Directory Structure
extensions/specialized-subagents/subagents/<name>/
├── index.ts # Main tool definition (createXxxTool, executeXxx, XXX_GUIDANCE)
├── config.ts # Model config, provider constants
├── system-prompt.ts # System prompt string
├── types.ts # XxxInput, XxxDetails interfaces
├── tool-formatter.ts # formatXxxToolCall() for display
└── tools/
├── index.ts # createXxxTools() aggregator
└── <tool>.ts # Individual tool definitions
Files Overview
types.ts
XxxInput: Parameters the parent agent provides- Include
skills?: string[]for optional skill passthrough
- Include
XxxDetails: State for UI rendering, must include:toolCalls: SubagentToolCall[]spinnerFrame: numberresponse?: stringaborted?: booleanerror?: stringusage?: SubagentUsageskills?: string[]- Requested skill names (from input)skillsResolved?: number- Number of skills successfully resolvedskillsNotFound?: string[]- Skill names that were not found
config.ts
MODEL: Provider and model ID- Optional provider type aliases for external APIs
system-prompt.ts
- Role definition
- Available tools list
- Behavior rules per input combination
- Response format guidelines
- Constraints and guardrails
tool-formatter.ts
formatXxxToolCall(tc): Returns{ label, detail }for human-readable displaylabel: Action name ("Search", "Fetch")detail: Context (hostname, query, repo path)
tools/
- Individual tool definitions
- Must return
costin details for cost aggregation:return { content: [...], details: { ..., cost: response.costDollars?.total }, };
index.ts
Exports:
createXxxTool(): Tool definition withexecute,renderCall,renderResultexecuteXxx(): Direct execution without tool wrapperXXX_GUIDANCE: Markdown guidance for parent agent's system prompt
Execute Function
- Resolve skills if provided:
const { skills: skillNames } = args; let resolvedSkills: Skill[] = []; let notFoundSkills: string[] = []; if (skillNames && skillNames.length > 0) { const result = resolveSkillsByName(skillNames, ctx.cwd); resolvedSkills = result.skills; notFoundSkills = result.notFound; } - Validate inputs, return error in details if invalid (include skill info)
- Set up spinner interval (80ms), clear in
finally - Build user message, append warning if skills not found:
if (notFoundSkills.length > 0) { userMessage += `\n\n**Note:** The following skills were not found and could not be loaded: ${notFoundSkills.join(", ")}`; } - Call
executeSubagent()with:skills: resolvedSkillsin configonTextUpdateandonToolUpdatecallbacks that include skill info in details
- Handle abort/error states (include skill info in all return paths)
- Use final tool calls from
result.toolCallsfor failure checks - Check if all tool calls failed → return error
- Return
usagefrom result (include skill info)
renderResult States
| State | Display |
|---|---|
| Aborted | Warning "Aborted" + optional completion count |
| Error | Error message |
| Running + collapsed | Spinner + current tool name |
| Running + expanded | Status line + all tool calls with indicators |
| Done + collapsed | ✓ or ✗ (if all failed) + stats |
| Done + expanded | Stats + tool summary + failed tool details + markdown response |
Registration
In extensions/specialized-subagents/index.ts:
- Import the tool and guidance
- Add guidance to
SUBAGENT_GUIDANCESarray - Register tool with
pi.registerTool(createXxxTool()) - If the subagent requires API keys, add them to
checkApiKeys()
See the existing registration pattern in the file.
API Key Validation
If your subagent requires external API keys, validate them at extension load time. This prevents the extension from loading if required keys are missing.
Add your required keys to checkApiKeys() in extensions/specialized-subagents/index.ts. See the existing implementation for the pattern.
Checklist
- Create directory:
subagents/<name>/ - Create
types.tswith Input and Details interfaces- Add
skills?: string[]to Input interface - Add
skills?,skillsResolved?,skillsNotFound?to Details interface
- Add
- Create
config.tswith model configuration - Create
system-prompt.tswith subagent instructions - Create
tools/directory with subagent's tools - Create
tool-formatter.tsfor display formatting - Create
index.tswith createXxxTool, executeXxx, XXX_GUIDANCE- Import
resolveSkillsByNameandSkilltype from lib - Add
skillsparameter to TypeBox schema - Update tool description to mention skill support
- Resolve skills in execute function
- Pass
skills: resolvedSkillsto executeSubagent - Include skill info in all details returns
- Show skills in renderCall if provided
- Import
- Register in
extensions/specialized-subagents/index.ts - Run
pnpm typecheck
Key Points
- Details interface: Must include
toolCalls,spinnerFrame,response,aborted,error,usage, and skill tracking fields - Skills support: All subagents should support optional
skillsparameter for specialized context - Cost tracking: Tools must return
costin details for aggregation - Spinner: 80ms interval, clear in finally block
- Extensions disabled: Subagents don't run user extensions (
extensions: []) - Failed tools: Show individually in done+expanded state
- All failed: Show error indicator only when ALL tools failed (partial success = success indicator)
- Final tool calls: Use
result.toolCallsif present to decide failure state - Mark tool as failed: When all internal tools fail, return error so parent agent sees failure
- Skill resolution: Use
resolveSkillsByName()from lib to convert skill names to Skill objects - Skill warnings: Append warning to user message if skills not found (don't fail the request)
Notifications
Subagents can emit notifications to alert users. This is useful for long-running subagent tasks or when user attention is needed.
Emitting Notifications
const NOTIFICATION_EVENT = "ad:notification";
interface NotificationEvent {
message: string;
sound?: string;
}
// In execute function, after completion
pi.events.emit(NOTIFICATION_EVENT, {
message: "Research completed",
sound: "/System/Library/Sounds/Blow.aiff",
});
When to Notify
- Subagent completes a long-running task
- Subagent encounters errors that need user attention
- Subagent needs user input (though prefer interactive tools like
ask_user)
Reference
Refer to the scout subagent for complete implementation:
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon