Files
2025-11-29 18:45:35 +08:00

357 lines
8.4 KiB
Markdown

# Agent Lifecycle Patterns
Detailed implementations of common agent lifecycle patterns.
## Table of Contents
1. [Session-Scoped Advisor](#pattern-1-session-scoped-advisor)
2. [Workflow-Scoped Execution](#pattern-2-workflow-scoped-execution)
3. [Turn-Scoped Helper](#pattern-3-turn-scoped-helper)
4. [Project Singleton](#pattern-4-project-singleton)
5. [Multi-Agent Orchestration](#pattern-5-multi-agent-orchestration)
---
## Pattern 1: Session-Scoped Advisor
Agents that persist throughout a Claude Code session, ideal for knowledge retrieval and advisory roles.
### Use Cases
- Knowledge advisors (Shadow Advisor, Librarian)
- Context-aware assistants
- Session-wide configuration managers
### Implementation
```typescript
import { AgentRegistry } from 'claude-agent-lifecycle';
export async function getSessionAdvisor(role: string) {
const registry = new AgentRegistry();
const { agent, isNew } = await registry.create({
lifespan: 'session',
name: `${role}-advisor`,
model: 'haiku',
metadata: {
role,
capabilities: ['knowledge-retrieval', 'pattern-matching'],
preloadedAt: new Date().toISOString(),
},
});
if (isNew) {
// First creation - load initial context
console.log(`Created new ${role} advisor`);
// Initialize with domain knowledge...
} else {
// Resumed - increment interaction count
console.log(`Resumed ${role} advisor (turn ${agent.turnCount})`);
}
return agent;
}
// Usage
const shadow = await getSessionAdvisor('shadow');
const librarian = await getSessionAdvisor('librarian');
```
### Hook Integration
Automatically disposed at SessionEnd:
```typescript
// hooks/session-cleanup.ts
import { AgentRegistry } from 'claude-agent-lifecycle';
import { getHookEvent } from 'claude-hooks-sdk';
const event = getHookEvent();
if (event.type === 'SessionEnd') {
const registry = new AgentRegistry();
const count = await registry.disposeByScope(event.session.sessionId);
console.log(`Disposed ${count} session agents`);
}
```
---
## Pattern 2: Workflow-Scoped Execution
Agents tied to a bounded unit of work (story, feature, task). Multiple specialists collaborate on a shared workflow.
### Use Cases
- Story execution (Loom)
- Feature development
- Multi-step task orchestration
### Implementation
```typescript
import { AgentRegistry } from 'claude-agent-lifecycle';
export class WorkflowOrchestrator {
private registry: AgentRegistry;
private workflowId: string;
constructor(workflowId: string) {
this.registry = new AgentRegistry();
this.workflowId = workflowId;
}
async start() {
// Create main executor
return await this.registry.startWorkflow({
lifespan: 'workflow',
workflowId: this.workflowId,
name: 'executor',
workflowType: 'story-execution',
model: 'sonnet',
metadata: {
startedAt: new Date().toISOString(),
status: 'in-progress',
},
});
}
async addSpecialist(role: string) {
const validRoles = [
'backend-dev',
'frontend-dev',
'backend-qa',
'frontend-qa',
'cli-dev',
];
if (!validRoles.includes(role)) {
throw new Error(`Invalid role: ${role}`);
}
return await this.registry.startWorkflow({
lifespan: 'workflow',
workflowId: this.workflowId,
name: role,
model: role.includes('qa') ? 'haiku' : 'sonnet',
metadata: { role, assignedAt: new Date().toISOString() },
});
}
async getStatus() {
const agents = await this.registry.getWorkflowAgents(this.workflowId);
return {
workflowId: this.workflowId,
agentCount: agents.length,
agents: agents.map(a => ({
name: a.name,
turnCount: a.turnCount,
lastActive: a.lastActiveAt,
})),
};
}
async complete() {
const count = await this.registry.completeWorkflow(this.workflowId);
console.log(`Completed workflow ${this.workflowId}, disposed ${count} agents`);
return count;
}
}
// Usage
const orchestrator = new WorkflowOrchestrator('FEAT-001');
await orchestrator.start();
await orchestrator.addSpecialist('backend-dev');
await orchestrator.addSpecialist('backend-qa');
// ... execute work ...
await orchestrator.complete();
```
---
## Pattern 3: Turn-Scoped Helper
Short-lived agents that assist with a single response cycle. Automatically disposed when Stop hook fires.
### Use Cases
- Code analysis helpers
- One-off data processors
- Temporary computation agents
### Implementation
```typescript
import { AgentRegistry } from 'claude-agent-lifecycle';
export async function createTurnHelper(task: string) {
const registry = new AgentRegistry();
const { agent } = await registry.create({
lifespan: 'turn',
name: `helper-${task}`,
model: 'haiku',
metadata: {
task,
createdFor: 'single-response',
},
});
return agent;
}
// Usage - agent disposed automatically at Stop
const analyzer = await createTurnHelper('code-analysis');
const formatter = await createTurnHelper('output-formatting');
```
### Hook Integration
```typescript
// hooks/turn-cleanup.ts
import { AgentRegistry } from 'claude-agent-lifecycle';
import { getHookEvent } from 'claude-hooks-sdk';
const event = getHookEvent();
if (event.type === 'Stop') {
const registry = new AgentRegistry();
const count = await registry.disposeByLifespan('turn');
if (count > 0) {
console.log(`Disposed ${count} turn-scoped agents`);
}
}
```
---
## Pattern 4: Project Singleton
Agents that persist indefinitely, shared across all sessions. Requires manual disposal.
### Use Cases
- Project configuration managers
- Shared knowledge bases
- Cross-session state holders
### Implementation
```typescript
import { AgentRegistry } from 'claude-agent-lifecycle';
export async function getProjectSingleton(name: string) {
const registry = new AgentRegistry();
const { agent, isNew } = await registry.create({
lifespan: 'project',
name,
metadata: {
singleton: true,
initVersion: '1.0.0',
},
});
if (isNew) {
console.log(`Created project singleton: ${name}`);
} else {
console.log(`Using existing singleton: ${name} (${agent.turnCount} turns)`);
}
return agent;
}
// Manual disposal when needed
export async function disposeProjectSingleton(name: string) {
const registry = new AgentRegistry();
const agent = await registry.resume(name);
if (agent) {
await registry.dispose(agent.agentId);
console.log(`Disposed project singleton: ${name}`);
}
}
```
---
## Pattern 5: Multi-Agent Orchestration
Coordinating multiple agents across different lifespans.
### Implementation
```typescript
import { AgentRegistry } from 'claude-agent-lifecycle';
export class MultiAgentSystem {
private registry: AgentRegistry;
constructor() {
this.registry = new AgentRegistry({ debug: true });
}
async initialize(sessionId: string, workflowId: string) {
// Session-scoped: knowledge advisors
await this.registry.create({
lifespan: 'session',
name: 'shadow-advisor',
sessionId,
model: 'haiku',
});
await this.registry.create({
lifespan: 'session',
name: 'librarian',
sessionId,
model: 'haiku',
});
// Workflow-scoped: execution agents
await this.registry.startWorkflow({
lifespan: 'workflow',
workflowId,
name: 'executor',
model: 'sonnet',
});
// Turn-scoped: temporary helpers created as needed
// (created per-request, not at initialization)
}
async getSystemStatus() {
const agents = await this.registry.list();
return {
total: agents.length,
byLifespan: {
session: agents.filter(a => a.lifespan === 'session').length,
workflow: agents.filter(a => a.lifespan === 'workflow').length,
turn: agents.filter(a => a.lifespan === 'turn').length,
project: agents.filter(a => a.lifespan === 'project').length,
},
agents: agents.map(a => ({
name: a.name,
lifespan: a.lifespan,
scope: a.scope,
turns: a.turnCount,
})),
};
}
}
```
---
## Best Practices Summary
| Pattern | Lifespan | Model | Disposal |
|---------|----------|-------|----------|
| Knowledge Advisor | session | haiku | SessionEnd hook |
| Workflow Executor | workflow | sonnet | completeWorkflow() |
| Workflow Specialist | workflow | sonnet/haiku | completeWorkflow() |
| Turn Helper | turn | haiku | Stop hook |
| Project Singleton | project | varies | Manual |