# Phase 3: Agent-Based Orchestration Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Transform BeadBoard from archetype-based to agent-based orchestration where the orchestrator spawns, coordinates, and manages numbered agent instances that users can see in real-time. **Architecture:** - Rename "archetypes" to "agents" everywhere user-facing - Agents = typed workers with specific prompts/configs (what archetypes were) - Agent instances = running copies, numbered while active (e.g., "Engineer 01", "Engineer 02") - Templates = named agent compositions (e.g., "Feature Dev" = Architect + 2x Engineer + Reviewer) - Right panel shows active agent instances with status + numbers - Orchestrator picks which agents to spawn based on task scope **Tech Stack:** - Next.js, TypeScript, Pi SDK - BeadBoard's existing beads/epics system - Runtime console events for agent status --- ## Rename: Archetype → Agent ### Task 1: Rename in Code (Internal) **Files:** - Modify: `src/lib/types-swarm.ts` - rename `AgentArchetype` → `AgentType` - Modify: `src/lib/server/beads-fs.ts` - update SEED_ARCHETYPES comments - Modify: `src/lib/worker-session-manager.ts` - update type imports and comments **Step 1: Rename AgentArchetype type** ```typescript // src/lib/types-swarm.ts export interface AgentType { id: string; name: string; description: string; systemPrompt: string; capabilities: string[]; color: string; icon?: string; createdAt: string; updatedAt: string; isBuiltIn: boolean; } ``` **Step 2: Update worker-session-manager imports** ```typescript // src/lib/worker-session-manager.ts line 4 import type { AgentType } from './types-swarm'; ``` **Step 3: Commit** ```bash git add src/lib/types-swarm.ts src/lib/worker-session-manager.ts git commit -m "refactor: rename AgentArchetype → AgentType internally" ``` --- ### Task 2: Rename in Tools (User-Facing) **Files:** - Modify: `src/tui/tools/bb-list-archetypes.ts` → rename to `bb-list-agents.ts` - Modify: `src/tui/tools/bb-create-archetype.ts` → rename to `bb-create-agent.ts` - Modify: `src/tui/tools/bb-update-archetype.ts` → rename to `bb-update-agent.ts` - Modify: `src/tui/tools/bb-delete-archetype.ts` → rename to `bb-delete-agent.ts` - Modify: `src/tui/tools/bb-spawn-worker.ts` - update archetype param description - Modify: `src/lib/pi-daemon-adapter.ts` - update imports **Step 1: Rename bb-list-archetypes.ts** ```typescript // src/tui/tools/bb-list-agents.ts import { Type } from '@sinclair/typebox'; import type { CustomAgentTool } from '@mariozechner/pi-coding-agent'; import { getAgentTypes } from '../../lib/server/beads-fs'; export function createListAgentsTool(projectRoot: string): CustomAgentTool { return { name: 'bb_list_agents', label: 'List Agent Types', description: 'List all available agent types. Returns id, name, description, capabilities for each. Agent types are the kinds of workers the orchestrator can spawn.', parameters: Type.Object({}), async execute() { // ... same as existing, but rename "archetype" → "agent" in output }, }; } ``` **Step 2: Rename other archetype tools similarly** Create new files with "agent" naming, delete old "archetype" files. **Step 3: Update bb-spawn-worker.ts param description** ```typescript // src/tui/tools/bb-spawn-worker.ts line 11 archetype: Type.Optional(Type.String({ description: 'Agent type to spawn. Options: "architect", "engineer", "reviewer", "tester", "investigator", "shipper". Default: engineer.' })), ``` **Step 4: Update pi-daemon-adapter.ts imports** ```typescript // src/lib/pi-daemon-adapter.ts - update import paths import { createListAgentsTool } from '../tui/tools/bb-list-agents'; // ... update all 8 tool imports ``` **Step 5: Commit** ```bash git add src/tui/tools/ src/lib/pi-daemon-adapter.ts git commit -m "refactor: rename archetype tools → agent tools" ``` --- ### Task 3: Rename in Database Seed **Files:** - Modify: `src/lib/server/beads-fs.ts` - rename SEED_ARCHETYPES → SEED_AGENTS **Step 1: Rename constants** ```typescript // src/lib/server/beads-fs.ts const SEED_AGENTS: AgentType[] = [ /* same content */ ]; const SEED_TEMPLATES: SwarmTemplate[] = [ /* same content */ ]; ``` **Step 2: Rename functions** ```typescript export async function getAgentTypes(projectRoot: string = process.cwd()): Promise { // ... same implementation } ``` **Step 3: Update callers** ```bash grep -rn "getArchetypes" src/ | grep -v test # Update each to getAgentTypes ``` **Step 4: Commit** ```bash git add src/lib/server/beads-fs.ts git commit -m "refactor: rename getArchetypes → getAgentTypes" ``` --- ### Task 4: Rename in UI Components **Files:** - Modify: `src/components/swarm/archetype-inspector.tsx` → `agent-inspector.tsx` - Modify: `src/components/swarm/telemetry-grid.tsx` - update archetype props - Modify: Any other UI files referencing "archetype" **Step 1: Rename archetype-inspector.tsx** ```bash mv src/components/swarm/archetype-inspector.tsx src/components/swarm/agent-inspector.tsx ``` **Step 2: Update internal references** ```typescript // In agent-inspector.tsx // Change "Archetype" → "Agent" in all display text ``` **Step 3: Commit** ```bash git add src/components/swarm/ git commit -m "refactor: rename archetype UI → agent UI" ``` --- ## Agent Instance Display ### Task 5: Design Agent Instance Model **Files:** - Create: `src/lib/agent-instance.ts` **Step 1: Define AgentInstance type** ```typescript // src/lib/agent-instance.ts export interface AgentInstance { id: string; // unique instance ID (e.g., "engineer-01-abc123") agentTypeId: string; // what kind of agent (e.g., "engineer") displayName: string; // e.g., "Engineer 01" status: 'spawning' | 'working' | 'idle' | 'completed' | 'failed'; currentBeadId?: string; // bead they're working on startedAt: string; completedAt?: string; result?: string; error?: string; } export interface AgentStatus { totalActive: number; byType: Record; // { "engineer": 2, "architect": 1 } instances: AgentInstance[]; } ``` **Step 2: Create helper functions** ```typescript export function generateInstanceId(agentTypeId: string, existingCount: number): string { const suffix = String(existingCount + 1).padStart(2, '0'); const random = Math.random().toString(36).slice(2, 8); return `${agentTypeId}-${suffix}-${random}`; } export function getDisplayName(agentTypeId: string, instanceNumber: number, agentTypeName: string): string { const num = String(instanceNumber).padStart(2, '0'); return `${agentTypeName} ${num}`; } ``` **Step 3: Commit** ```bash git add src/lib/agent-instance.ts git commit -m "feat: add AgentInstance model for tracking running agents" ``` --- ### Task 6: Integrate with Worker Session Manager **Files:** - Modify: `src/lib/worker-session-manager.ts` **Step 1: Import AgentInstance** ```typescript import { generateInstanceId, getDisplayName, type AgentInstance } from './agent-instance'; ``` **Step 2: Add instance tracking to worker session** ```typescript // In WorkerSession interface, add: agentInstanceId: string; agentTypeId: string; displayName: string; ``` **Step 3: Generate instance ID when spawning** ```typescript // In spawnWorker(), when creating worker: const existingCount = [...this.workers.values()].filter(w => w.agentTypeId === archetype).length; const agentType = archetype || 'engineer'; const agentTypeName = getAgentTypeName(agentType); // lookup name worker.agentInstanceId = generateInstanceId(agentType, existingCount); worker.agentTypeId = agentType; worker.displayName = getDisplayName(agentType, existingCount + 1, agentTypeName); ``` **Step 4: Add AgentInstance to event emissions** ```typescript // When emitting worker events, include instance info: embeddedPiDaemon.appendWorkerEvent(projectRoot, worker.id, { kind: 'worker.spawned', title: `${worker.displayName} started`, detail: `Agent working on task ${taskId}`, status: 'working', metadata: { workerId: worker.id, agentInstanceId: worker.agentInstanceId, agentTypeId: worker.agentTypeId, displayName: worker.displayName, taskId, }, }); ``` **Step 5: Commit** ```bash git add src/lib/worker-session-manager.ts git commit -m "feat: track agent instances with numbered display names" ``` --- ### Task 7: Create Agent Status Panel **Files:** - Create: `src/components/agents/agent-status-panel.tsx` **Step 1: Define AgentStatusPanel component** ```typescript // src/components/agents/agent-status-panel.tsx 'use client'; import { useEffect, useState } from 'react'; import { AgentInstance, type AgentStatus } from '../../lib/agent-instance'; interface AgentStatusPanelProps { projectRoot: string; } export function AgentStatusPanel({ projectRoot }: AgentStatusPanelProps) { const [status, setStatus] = useState(null); useEffect(() => { // Poll for agent status updates const poll = setInterval(async () => { const res = await fetch(`/api/runtime/agents?projectRoot=${encodeURIComponent(projectRoot)}`); const data = await res.json(); if (data.ok) setStatus(data.status); }, 2000); return () => clearInterval(poll); }, [projectRoot]); if (!status) return
Loading agents...
; return (
{/* Active Agents Section */}

Active Agents ({status.totalActive})

{status.instances.length === 0 ? (

No active agents

) : (
{status.instances.map(instance => ( ))}
)}
{/* Available Agents Section */}

Available Agents

); } function AgentInstanceCard({ instance }: { instance: AgentInstance }) { const statusColors = { spawning: 'bg-yellow-500', working: 'bg-cyan-500', idle: 'bg-gray-500', completed: 'bg-green-500', failed: 'bg-red-500', }; return (
{instance.displayName} {instance.currentBeadId && ( → {instance.currentBeadId} )}
); } ``` **Step 2: Create API endpoint for agent status** ```typescript // src/app/api/runtime/agents/route.ts import { NextResponse } from 'next/server'; import { workerSessionManager } from '../../../../lib/worker-session-manager'; export const dynamic = 'force-dynamic'; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const projectRoot = searchParams.get('projectRoot'); if (!projectRoot) { return NextResponse.json({ ok: false, error: 'projectRoot required' }); } const workers = workerSessionManager.listWorkers(projectRoot); const instances = workers.map(w => ({ id: w.agentInstanceId, agentTypeId: w.agentTypeId, displayName: w.displayName, status: w.status, currentBeadId: w.currentBeadId, startedAt: w.createdAt, })); const byType: Record = {}; for (const w of workers) { byType[w.agentTypeId] = (byType[w.agentTypeId] || 0) + 1; } return NextResponse.json({ ok: true, status: { totalActive: workers.length, byType, instances, }, }); } ``` **Step 3: Commit** ```bash git add src/components/agents/ src/app/api/runtime/agents/ git commit -m "feat: add agent status panel and API" ``` --- ## Orchestrator Behavior ### Task 8: Update System Prompt for Agent-Based Thinking **Files:** - Modify: `src/tui/system-prompt.ts` - update orchestrator prompt **Step 1: Update the prompt template** ```typescript // Add this section to the system prompt: ## Agent System You can spawn agent workers to accomplish tasks in parallel. Agents are typed workers with specific capabilities: - **architect**: System design, work decomposition, technical decisions - **engineer**: Implementation, coding, testing, debugging - **reviewer**: Code review, quality analysis (read-only, does not modify code) - **tester**: Test design and implementation - **investigator**: Debugging, root cause analysis (read-only unless implementing fix) - **shipper**: Deployment, CI/CD, release management ### Spawning Agents Use `bb_spawn_worker` to spawn an agent for a specific task/bead. You can spawn multiple agents in parallel. ### Agent Instances When you spawn an agent, it gets a numbered instance (e.g., "Engineer 01", "Engineer 02"). The right panel shows all active agent instances with their status. ### Templates Templates are named compositions of agents: - **feature-dev**: architect + 2x engineer + reviewer + tester - **bug-fix**: investigator + engineer + tester - **greenfield**: architect + 3x engineer + tester + shipper Use templates for large efforts (epics). For small tasks, spawn individual agents directly. ### Deviation If you modify or ignore a template, use `bb_record_deviation` to explain why. ``` **Step 2: Commit** ```bash git add src/tui/system-prompt.ts git commit -m "feat: update orchestrator prompt for agent-based thinking" ``` --- ### Task 9: Add Template Selection Tool **Files:** - Create: `src/tui/tools/bb-spawn-template.ts` **Step 1: Create spawn-template tool** ```typescript import { Type } from '@sinclair/typebox'; import type { CustomAgentTool } from '@mariozechner/pi-coding-agent'; import { getTemplates } from '../../lib/server/beads-fs'; import { workerSessionManager } from '../../lib/worker-session-manager'; export function createSpawnTemplateTool(projectRoot: string): CustomAgentTool { return { name: 'bb_spawn_template', label: 'Spawn Template Team', description: 'Spawn a team of agents based on a template. Creates an epic with beads assigned to appropriate agent types. Use for larger efforts.', parameters: Type.Object({ template_id: Type.String({ description: 'Template ID to use (e.g., "feature-dev", "bug-fix", "greenfield", "full-squad")' }), epic_title: Type.String({ description: 'Title for the epic/task being worked on' }), epic_description: Type.Optional(Type.String({ description: 'Detailed description of what needs to be done' })), }), async execute(_toolCallId, params) { const { template_id, epic_title, epic_description } = params; // Load template const templates = await getTemplates(projectRoot); const template = templates.find(t => t.id === template_id); if (!template) { return { content: [{ type: 'text', text: `Template "${template_id}" not found. Available: ${templates.map(t => t.id).join(', ')}` }], isError: true, }; } // For each agent in template, spawn a worker const spawned = []; for (const member of template.team) { for (let i = 0; i < member.count; i++) { const worker = await workerSessionManager.spawnWorker({ projectRoot, taskId: `${epic_title}-${member.archetypeId}-${i+1}`, taskContext: epic_description || `Part of ${epic_title} using ${template.name} template`, archetype: member.archetypeId, }); spawned.push(worker); } } return { content: [{ type: 'text', text: `Spawned ${spawned.length} agents from template "${template.name}"!\n\n` + template.team.map(m => `- ${m.count}x ${m.archetypeId}`).join('\n') + '\n\n' + `Active agents: ${spawned.map(s => s.displayName).join(', ')}` }], details: { template, spawned: spawned.map(s => ({ id: s.id, displayName: s.displayName })) }, }; }, }; } ``` **Step 2: Register in pi-daemon-adapter.ts** ```typescript import { createSpawnTemplateTool } from '../tui/tools/bb-spawn-template'; // In createTools(): tools.push({ tool: createSpawnTemplateTool(projectRoot) }); ``` **Step 3: Commit** ```bash git add src/tui/tools/bb-spawn-template.ts src/lib/pi-daemon-adapter.ts git commit -m "feat: add template spawning tool" ``` --- ### Task 10: Integration Tests **Files:** - Create: `tests/integration/agent-spawning.test.ts` **Step 1: Write integration test** ```typescript import { describe, it, expect, beforeEach } from 'vitest'; describe('Agent Spawning', () => { const projectRoot = process.cwd(); it('spawns agent with correct instance ID', async () => { const { workerSessionManager } = await import('../../src/lib/worker-session-manager'); const worker = await workerSessionManager.spawnWorker({ projectRoot, taskId: 'test-task-1', taskContext: 'Test task', archetype: 'engineer', }); expect(worker.displayName).toMatch(/Engineer \d+/); expect(worker.agentTypeId).toBe('engineer'); expect(worker.agentInstanceId).toBeDefined(); }); it('numbers instances correctly', async () => { const { workerSessionManager } = await import('../../src/lib/worker-session-manager'); // Spawn 3 engineers const workers = []; for (let i = 0; i < 3; i++) { workers.push(await workerSessionManager.spawnWorker({ projectRoot, taskId: `test-task-${i}`, taskContext: 'Test', archetype: 'engineer', })); } // Check numbering const engineerWorkers = workers.filter(w => w.agentTypeId === 'engineer'); const numbers = engineerWorkers.map(w => w.displayName); expect(numbers).toContain('Engineer 01'); expect(numbers).toContain('Engineer 02'); expect(numbers).toContain('Engineer 03'); }); it('spawns from template', async () => { const { workerSessionManager } = await import('../../src/lib/worker-session-manager'); const { getTemplates } = await import('../../src/lib/server/beads-fs'); const templates = await getTemplates(projectRoot); const featureDev = templates.find(t => t.id === 'feature-dev'); expect(featureDev).toBeDefined(); // Should spawn 5 agents: 1 architect + 2 engineer + 1 reviewer + 1 tester expect(featureDev.team.reduce((sum, m) => sum + m.count, 0)).toBe(5); }); }); ``` **Step 2: Run tests** ```bash cd /home/clawdbot/clawd/repos/beadboard && npx vitest run tests/integration/agent-spawning.test.ts ``` **Step 3: Commit** ```bash git add tests/integration/agent-spawning.test.ts git commit -m "test: add agent spawning integration tests" ``` --- ## Agent-Bead Relationship ### Task 11: Add Agent Assignment to Beads **Files:** - Modify: `src/lib/types.ts` - add `agentTypeId` to BeadIssue - Modify: `src/lib/server/beads-fs.ts` - update bead creation/queries - Create: `src/tui/tools/bb-assign-agent.ts` - assign agent to bead - Modify: `src/components/social/social-card.tsx` - show agent badge **Step 1: Add agentTypeId to BeadIssue type** ```typescript // src/lib/types.ts - in BeadIssue interface export interface BeadIssue { // ... existing fields agentTypeId?: string; // Which agent type is assigned agentInstanceId?: string; // Which specific instance (if running) } ``` **Step 2: Create bb_assign_agent tool** ```typescript // src/tui/tools/bb-assign-agent.ts import { Type } from '@sinclair/typebox'; import type { CustomAgentTool } from '@mariozechner/pi-coding-agent'; export function createAssignAgentTool(projectRoot: string): CustomAgentTool { return { name: 'bb_assign_agent', label: 'Assign Agent to Bead', description: 'Assign an agent type to a bead. This signals which kind of agent should work on this task.', parameters: Type.Object({ bead_id: Type.String({ description: 'Bead ID to assign agent to' }), agent_type: Type.String({ description: 'Agent type ID (e.g., "engineer", "architect", "reviewer")' }), }), async execute(_toolCallId, params) { const { bead_id, agent_type } = params; // Update bead with agent type // This writes to .beads/issues.jsonl via the beads system return { content: [{ type: 'text', text: `Assigned ${agent_type} to bead ${bead_id}. When an agent of this type is spawned, it will pick up this bead.`, }], details: { bead_id, agent_type }, }; }, }; } ``` **Step 3: Update social card to show agent badge** ```typescript // In social-card.tsx, add agent badge display {issue.agentTypeId && (
{issue.agentTypeId}
)} ``` **Step 4: Commit** ```bash git add src/lib/types.ts src/tui/tools/bb-assign-agent.ts src/components/social/ git commit -m "feat: add agent assignment to beads" ``` --- ## Orchestrator Decision Logic ### Task 12: Implement Orchestrator Decision Tree **Files:** - Modify: `src/tui/system-prompt.ts` - add decision tree to prompt - Modify: `src/tui/tools/bb-spawn-worker.ts` - add scope analysis hint **Step 1: Add decision tree to system prompt** ```typescript // In system-prompt.ts, add this section: ## Task Scope Decision Tree Before spawning agents, assess task scope: ### Small Task (Single Agent) - Bug fix with known cause - Single file change - Quick refactor - Single test addition **Action:** Spawn 1 agent directly. Example: `bb_spawn_worker` with `archetype: "engineer"` ### Medium Task (2-3 Agents) - Feature with clear design - Bug investigation + fix - Code review + fixes **Action:** Spawn 2-3 agents based on template or custom composition. ### Large Task (Use Template) - New feature from scratch - System redesign - Multi-component changes **Action:** Use `bb_spawn_template` with appropriate template: - `feature-dev` for new features - `bug-fix` for debugging issues - `greenfield` for new projects - `full-squad` for complex multi-domain work ### Epic Creation If the task requires multiple beads with dependencies: 1. Use `bb_create_epic` to create the epic 2. Use `bb_create` to create child beads 3. Assign agent types to each bead with `bb_assign_agent` 4. Spawn agents to work on unblocked beads **Example Flow:** ``` User: "Build user authentication system" Orchestrator: 1. "This is a large task. Creating epic 'User Authentication'." 2. Creates epic + decomposes into beads: - BEAD-001: Design auth schema [architect] - BEAD-002: Implement JWT service [engineer] - BEAD-003: Implement refresh tokens [engineer] - BEAD-004: Write auth tests [tester] - BEAD-005: Review implementation [reviewer] 3. Spawns Architect 01 to start on BEAD-001 4. When BEAD-001 done, spawns Engineer 01 and 02 for BEAD-002 and BEAD-003 5. And so on... ``` ``` **Step 2: Commit** ```bash git add src/tui/system-prompt.ts git commit -m "feat: add orchestrator decision tree for agent spawning" ``` --- ## Right Panel Integration ### Task 13: Wire Agent Panel into Right Panel **Files:** - Modify: `src/components/shared/right-panel.tsx` - add agents tab - Modify: `src/components/activity/contextual-right-panel.tsx` - include agent status - Modify: `src/hooks/use-url-state.ts` - add agents tab state **Step 1: Add agents tab to right panel** ```typescript // In right-panel.tsx, add tab system const TABS = ['details', 'agents', 'activity'] as const; type RightPanelTab = typeof TABS[number]; export function RightPanel({ issues, selectedTask, ... }: RightPanelProps) { const [activeTab, setActiveTab] = useState('details'); return (
{/* Tab bar */}
{TABS.map(tab => ( ))}
{/* Tab content */}
{activeTab === 'details' && } {activeTab === 'agents' && } {activeTab === 'activity' && }
); } ``` **Step 2: Update ContextualRightPanel** ```typescript // Include AgentStatusPanel when showing swarm/epic context {contextType === 'swarm' && (
{/* ... other swarm context */}
)} ``` **Step 3: Commit** ```bash git add src/components/shared/right-panel.tsx src/components/activity/contextual-right-panel.tsx git commit -m "feat: wire agent status panel into right panel tabs" ``` --- ## Agent State Persistence ### Task 14: Persist Agent Instances to Disk **Files:** - Create: `src/lib/agent-persistence.ts` - Modify: `src/lib/worker-session-manager.ts` - load/save on changes - Create: `src/app/api/runtime/agents/history/route.ts` **Step 1: Create persistence layer** ```typescript // src/lib/agent-persistence.ts import fs from 'fs/promises'; import path from 'path'; import type { AgentInstance } from './agent-instance'; const AGENTS_FILE = (projectRoot: string) => path.join(projectRoot, '.beads', 'agents.jsonl'); export async function loadAgentInstances(projectRoot: string): Promise { try { const content = await fs.readFile(AGENTS_FILE(projectRoot), 'utf-8'); return content.trim().split('\n').filter(Boolean).map(line => JSON.parse(line)); } catch { return []; } } export async function saveAgentInstance(projectRoot: string, instance: AgentInstance): Promise { const line = JSON.stringify(instance) + '\n'; await fs.appendFile(AGENTS_FILE(projectRoot), line, 'utf-8'); } export async function updateAgentInstance(projectRoot: string, instance: AgentInstance): Promise { // Load all, update the matching one, rewrite const instances = await loadAgentInstances(projectRoot); const idx = instances.findIndex(i => i.id === instance.id); if (idx >= 0) { instances[idx] = instance; await fs.writeFile( AGENTS_FILE(projectRoot), instances.map(i => JSON.stringify(i)).join('\n') + '\n', 'utf-8' ); } } export async function getActiveInstances(projectRoot: string): Promise { const all = await loadAgentInstances(projectRoot); return all.filter(i => i.status === 'working' || i.status === 'spawning' || i.status === 'idle'); } export async function getRecentInstances(projectRoot: string, limit = 20): Promise { const all = await loadAgentInstances(projectRoot); return all .filter(i => i.status === 'completed' || i.status === 'failed') .sort((a, b) => new Date(b.completedAt || 0).getTime() - new Date(a.completedAt || 0).getTime()) .slice(0, limit); } ``` **Step 2: Integrate with worker-session-manager** ```typescript // In worker-session-manager.ts import { saveAgentInstance, updateAgentInstance } from './agent-persistence'; // After spawning worker: await saveAgentInstance(projectRoot, { id: worker.agentInstanceId, agentTypeId: worker.agentTypeId, displayName: worker.displayName, status: worker.status, startedAt: worker.createdAt, }); // On status change: await updateAgentInstance(projectRoot, instance); ``` **Step 3: Create history API endpoint** ```typescript // src/app/api/runtime/agents/history/route.ts import { NextResponse } from 'next/server'; import { getRecentInstances } from '../../../../../lib/agent-persistence'; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const projectRoot = searchParams.get('projectRoot'); if (!projectRoot) { return NextResponse.json({ ok: false, error: 'projectRoot required' }); } const recent = await getRecentInstances(projectRoot, 50); return NextResponse.json({ ok: true, instances: recent }); } ``` **Step 4: Commit** ```bash git add src/lib/agent-persistence.ts src/lib/worker-session-manager.ts src/app/api/runtime/agents/history/ git commit -m "feat: persist agent instances to disk" ``` --- ## Agent History ### Task 15: Show Completed Agents in Panel **Files:** - Modify: `src/components/agents/agent-status-panel.tsx` - add history section - Create: `src/components/agents/agent-history-list.tsx` **Step 1: Add history section to AgentStatusPanel** ```typescript // In agent-status-panel.tsx, add after active agents: const [history, setHistory] = useState([]); // Load history useEffect(() => { const loadHistory = async () => { const res = await fetch(`/api/runtime/agents/history?projectRoot=${encodeURIComponent(projectRoot)}`); const data = await res.json(); if (data.ok) setHistory(data.instances); }; loadHistory(); const interval = setInterval(loadHistory, 10000); return () => clearInterval(interval); }, [projectRoot]); // In render:

Recent Completions ({history.length})

{history.slice(0, 10).map(instance => (
{instance.status === 'completed' ? '✓' : '✗'} {instance.displayName} {instance.currentBeadId && ( → {instance.currentBeadId} )}
))}
``` **Step 2: Commit** ```bash git add src/components/agents/ git commit -m "feat: show completed agent history in status panel" ``` --- ## Updated Files Summary | File | Action | |------|--------| | **Rename (Tasks 1-4)** || | `src/lib/types-swarm.ts` | Modify: rename AgentArchetype → AgentType | | `src/lib/server/beads-fs.ts` | Modify: rename getArchetypes → getAgentTypes | | `src/tui/tools/bb-list-agents.ts` | Create (rename from bb-list-archetypes) | | `src/tui/tools/bb-create-agent.ts` | Create (rename) | | `src/tui/tools/bb-update-agent.ts` | Create (rename) | | `src/tui/tools/bb-delete-agent.ts` | Create (rename) | | `src/tui/tools/bb-list-archetypes.ts` | Delete | | `src/tui/tools/bb-create-archetype.ts` | Delete | | `src/tui/tools/bb-update-archetype.ts` | Delete | | `src/tui/tools/bb-delete-archetype.ts` | Delete | | `src/lib/pi-daemon-adapter.ts` | Modify: update imports | | `src/components/swarm/agent-inspector.tsx` | Create (rename) | | `src/components/swarm/archetype-inspector.tsx` | Delete | | **Agent Instances (Tasks 5-7)** || | `src/lib/agent-instance.ts` | Create | | `src/lib/worker-session-manager.ts` | Modify: add instance tracking | | `src/components/agents/agent-status-panel.tsx` | Create | | `src/app/api/runtime/agents/route.ts` | Create | | **Orchestrator (Tasks 8-9)** || | `src/tui/system-prompt.ts` | Modify: update prompt + decision tree | | `src/tui/tools/bb-spawn-template.ts` | Create | | `src/tui/tools/bb-spawn-worker.ts` | Modify: update descriptions | | **Tests (Task 10)** || | `tests/integration/agent-spawning.test.ts` | Create | | **Agent-Bead (Task 11)** || | `src/lib/types.ts` | Modify: add agentTypeId to BeadIssue | | `src/tui/tools/bb-assign-agent.ts` | Create | | `src/components/social/social-card.tsx` | Modify: show agent badge | | **Decision Tree (Task 12)** || | (included in Task 8) | | | **Right Panel (Task 13)** || | `src/components/shared/right-panel.tsx` | Modify: add agents tab | | `src/components/activity/contextual-right-panel.tsx` | Modify: include agents | | **Persistence (Task 14)** || | `src/lib/agent-persistence.ts` | Create | | `src/app/api/runtime/agents/history/route.ts` | Create | | **History (Task 15)** || | `src/components/agents/agent-history-list.tsx` | Create | **Total: 26 files (14 create, 10 modify, 5 delete)** --- ## Estimated Effort **10-12 hours** | Phase | Tasks | Effort | |-------|-------|--------| | Rename | 1-4 | 2h | | Agent Instances | 5-7 | 2h | | Orchestrator | 8-9 | 1.5h | | Tests | 10 | 1h | | Agent-Bead | 11 | 1.5h | | Decision Tree | 12 | 0.5h | | Right Panel | 13 | 1h | | Persistence | 14 | 1.5h | | History | 15 | 1h | --- ## Success Criteria - [ ] "Archetype" renamed to "Agent" in all user-facing text - [ ] Agent tools work: list, create, update, delete - [ ] Spawning a worker creates numbered instance (Engineer 01, etc.) - [ ] Right panel has Agents tab showing active + history - [ ] Template spawning spawns correct number of agents - [ ] Orchestrator uses decision tree for scope assessment - [ ] Beads can have agentTypeId assigned - [ ] Agent instances persist across restarts - [ ] History shows recent completions - [ ] Tests pass --- ## Plan Complete **Saved to:** `docs/plans/2026-03-07-phase-3-agent-orchestration.md` **Two execution options:** **1. Subagent-Driven (this session)** - I dispatch fresh subagent per task, review between tasks, fast iteration **2. Parallel Session (separate)** - Open new session with executing-plans, batch execution with checkpoints **Which approach?**