claude-code-agent-harness
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClaude Code Agent Harness Architecture
Claude Code Agent Harness架构
Overview
概述
This project is a comprehensive 420,000-word architectural analysis of AI Agent Harness design, using Claude Code as the reference implementation. It provides production-ready patterns for building agent systems with conversation loops, tool execution, permission management, context compression, memory systems, and multi-agent orchestration.
Key Capabilities:
- Agent conversation loop architecture (async generator pattern)
- Tool system design with 50+ tool implementations
- Four-stage permission pipeline
- Context management and compression strategies
- Memory systems and fork mechanisms
- MCP (Model Context Protocol) integration
- Sub-agent orchestration patterns
- Streaming architecture and performance optimization
本项目是一份针对AI Agent Harness设计的42万字全面架构分析,以Claude Code为参考实现。它提供了构建具备对话循环、工具执行、权限管理、上下文压缩、内存系统和多Agent编排能力的Agent系统的生产就绪模式。
核心能力:
- Agent对话循环架构(异步生成器模式)
- 包含50+工具实现的工具系统设计
- 四阶段权限流水线
- 上下文管理与压缩策略
- 内存系统与分支机制
- MCP(Model Context Protocol)集成
- 子Agent编排模式
- 流式架构与性能优化
Installation
安装
bash
undefinedbash
undefinedClone the reference architecture
克隆参考架构
git clone https://github.com/lintsinghua/claude-code-book.git
cd claude-code-book
git clone https://github.com/lintsinghua/claude-code-book.git
cd claude-code-book
Read online (recommended for interactive diagrams)
在线阅读(推荐用于查看交互式图表)
undefinedundefinedCore Architecture Patterns
核心架构模式
1. Conversation Loop (Agent Heartbeat)
1. 对话循环(Agent心跳)
The conversation loop is an async generator that drives agent execution:
typescript
// Core conversation loop pattern
async function* conversationLoop(
deps: QueryDeps
): AsyncGenerator<YieldEvent, void, void> {
while (true) {
// 1. Generate LLM response
const response = await deps.llm.generate({
messages: deps.context.messages,
tools: deps.tools.available,
});
// 2. Yield streaming events
for (const chunk of response.stream) {
yield { type: 'text_delta', delta: chunk };
}
// 3. Handle tool calls
if (response.toolCalls) {
for (const call of response.toolCalls) {
const result = await deps.tools.execute(call);
yield { type: 'tool_result', result };
deps.context.addMessage({ role: 'tool', content: result });
}
continue; // Loop back for next turn
}
// 4. Check termination conditions
if (shouldTerminate(response, deps)) {
yield { type: 'done', reason: getTerminationReason(response) };
break;
}
}
}
// Five yield event types
type YieldEvent =
| { type: 'text_delta'; delta: string }
| { type: 'tool_call'; call: ToolCall }
| { type: 'tool_result'; result: ToolResult }
| { type: 'thinking'; content: string }
| { type: 'done'; reason: TerminationReason };
// Ten termination reasons
type TerminationReason =
| 'max_turns'
| 'user_interrupt'
| 'explicit_stop'
| 'error'
| 'context_overflow'
| 'permission_denied'
| 'natural_completion'
| 'timeout'
| 'sub_agent_complete'
| 'plan_complete';对话循环是驱动Agent执行的异步生成器:
typescript
// 核心对话循环模式
async function* conversationLoop(
deps: QueryDeps
): AsyncGenerator<YieldEvent, void, void> {
while (true) {
// 1. 生成LLM响应
const response = await deps.llm.generate({
messages: deps.context.messages,
tools: deps.tools.available,
});
// 2. 输出流式事件
for (const chunk of response.stream) {
yield { type: 'text_delta', delta: chunk };
}
// 3. 处理工具调用
if (response.toolCalls) {
for (const call of response.toolCalls) {
const result = await deps.tools.execute(call);
yield { type: 'tool_result', result };
deps.context.addMessage({ role: 'tool', content: result });
}
continue; // 循环进入下一回合
}
// 4. 检查终止条件
if (shouldTerminate(response, deps)) {
yield { type: 'done', reason: getTerminationReason(response) };
break;
}
}
}
// 五种输出事件类型
type YieldEvent =
| { type: 'text_delta'; delta: string }
| { type: 'tool_call'; call: ToolCall }
| { type: 'tool_result'; result: ToolResult }
| { type: 'thinking'; content: string }
| { type: 'done'; reason: TerminationReason };
// 十种终止原因
type TerminationReason =
| 'max_turns'
| 'user_interrupt'
| 'explicit_stop'
| 'error'
| 'context_overflow'
| 'permission_denied'
| 'natural_completion'
| 'timeout'
| 'sub_agent_complete'
| 'plan_complete';2. Tool System (Agent's Hands)
2. 工具系统(Agent的双手)
Tools follow a five-element protocol:
typescript
// Tool definition interface
interface Tool<TInput, TOutput, TParams> {
name: string;
description: string;
inputSchema: z.ZodSchema<TInput>;
execute: (input: TInput, params: TParams) => Promise<TOutput>;
metadata: ToolMetadata;
}
interface ToolMetadata {
readOnly: boolean;
destructive: boolean;
concurrencySafe: boolean;
requiresConfirmation: boolean;
category: ToolCategory;
}
// Fault-safe tool builder
function buildTool<TInput, TOutput>(
config: ToolConfig<TInput, TOutput>
): Tool<TInput, TOutput> {
return {
name: config.name,
description: config.description,
inputSchema: config.schema,
execute: async (input, params) => {
try {
// Validate input
const validated = config.schema.parse(input);
// Check permissions
if (config.requiresConfirmation && !params.autoApprove) {
const approved = await params.permissions.requestApproval({
tool: config.name,
input: validated,
});
if (!approved) throw new PermissionDeniedError();
}
// Execute with timeout
return await Promise.race([
config.handler(validated, params),
timeout(params.timeout || 30000),
]);
} catch (error) {
return handleToolError(error, config.name);
}
},
metadata: config.metadata,
};
}
// Example tool: file reader
const readFileTool = buildTool({
name: 'read_file',
description: 'Read content from a file',
schema: z.object({
path: z.string(),
encoding: z.enum(['utf8', 'base64']).default('utf8'),
}),
metadata: {
readOnly: true,
destructive: false,
concurrencySafe: true,
requiresConfirmation: false,
category: 'filesystem',
},
handler: async (input, params) => {
const fs = await import('fs/promises');
const content = await fs.readFile(input.path, input.encoding);
return { content, size: content.length };
},
});工具遵循五元协议:
typescript
// 工具定义接口
interface Tool<TInput, TOutput, TParams> {
name: string;
description: string;
inputSchema: z.ZodSchema<TInput>;
execute: (input: TInput, params: TParams) => Promise<TOutput>;
metadata: ToolMetadata;
}
interface ToolMetadata {
readOnly: boolean;
destructive: boolean;
concurrencySafe: boolean;
requiresConfirmation: boolean;
category: ToolCategory;
}
// 故障安全工具构建器
function buildTool<TInput, TOutput>(
config: ToolConfig<TInput, TOutput>
): Tool<TInput, TOutput> {
return {
name: config.name,
description: config.description,
inputSchema: config.schema,
execute: async (input, params) => {
try {
// 验证输入
const validated = config.schema.parse(input);
// 检查权限
if (config.requiresConfirmation && !params.autoApprove) {
const approved = await params.permissions.requestApproval({
tool: config.name,
input: validated,
});
if (!approved) throw new PermissionDeniedError();
}
// 带超时执行
return await Promise.race([
config.handler(validated, params),
timeout(params.timeout || 30000),
]);
} catch (error) {
return handleToolError(error, config.name);
}
},
metadata: config.metadata,
};
}
// 示例工具:文件读取器
const readFileTool = buildTool({
name: 'read_file',
description: '读取文件内容',
schema: z.object({
path: z.string(),
encoding: z.enum(['utf8', 'base64']).default('utf8'),
}),
metadata: {
readOnly: true,
destructive: false,
concurrencySafe: true,
requiresConfirmation: false,
category: 'filesystem',
},
handler: async (input, params) => {
const fs = await import('fs/promises');
const content = await fs.readFile(input.path, input.encoding);
return { content, size: content.length };
},
});3. Permission Pipeline (Agent's Guardrails)
3. 权限流水线(Agent的防护栏)
Four-stage permission management:
typescript
// Permission modes spectrum
type PermissionMode =
| 'autonomous' // Auto-approve all
| 'interactive' // Prompt for destructive
| 'strict' // Prompt for all
| 'read_only' // Block destructive
| 'sandbox'; // Isolated environment
interface PermissionPipeline {
// Stage 1: Static rule matching
checkRules(tool: ToolCall): Promise<RuleDecision>;
// Stage 2: Speculative classification
classify(tool: ToolCall): Promise<RiskLevel>;
// Stage 3: User approval (if needed)
requestApproval(tool: ToolCall): Promise<boolean>;
// Stage 4: Audit logging
logExecution(tool: ToolCall, result: ToolResult): Promise<void>;
}
class FourStagePermissionPipeline implements PermissionPipeline {
async checkRules(tool: ToolCall): Promise<RuleDecision> {
// Bash pattern matching for file paths
for (const rule of this.rules) {
if (matchPattern(rule.pattern, tool.input)) {
return rule.decision;
}
}
return { decision: 'defer', reason: 'no_match' };
}
async classify(tool: ToolCall): Promise<RiskLevel> {
// 2-second Promise.race with LLM classifier
const classification = await Promise.race([
this.llmClassifier.classify(tool),
timeout(2000, { risk: 'medium' }),
]);
return classification.risk;
}
async requestApproval(tool: ToolCall): Promise<boolean> {
if (this.mode === 'autonomous') return true;
if (this.mode === 'read_only' && tool.metadata.destructive) {
return false;
}
return await this.ui.prompt({
message: `Allow ${tool.name}?`,
details: tool.input,
risk: await this.classify(tool),
});
}
async logExecution(
tool: ToolCall,
result: ToolResult
): Promise<void> {
await this.auditLog.write({
timestamp: Date.now(),
tool: tool.name,
input: tool.input,
output: result,
approved: result.approved,
userId: this.userId,
});
}
}四阶段权限管理:
typescript
// 权限模式范围
type PermissionMode =
| 'autonomous' // 自动批准所有请求
| 'interactive' // 对破坏性操作提示确认
| 'strict' // 对所有操作提示确认
| 'read_only' // 阻止破坏性操作
| 'sandbox'; // 隔离环境
interface PermissionPipeline {
// 阶段1:静态规则匹配
checkRules(tool: ToolCall): Promise<RuleDecision>;
// 阶段2:风险分类预测
classify(tool: ToolCall): Promise<RiskLevel>;
// 阶段3:用户批准(如需)
requestApproval(tool: ToolCall): Promise<boolean>;
// 阶段4:审计日志
logExecution(tool: ToolCall, result: ToolResult): Promise<void>;
}
class FourStagePermissionPipeline implements PermissionPipeline {
async checkRules(tool: ToolCall): Promise<RuleDecision> {
// 文件路径的Bash模式匹配
for (const rule of this.rules) {
if (matchPattern(rule.pattern, tool.input)) {
return rule.decision;
}
}
return { decision: 'defer', reason: 'no_match' };
}
async classify(tool: ToolCall): Promise<RiskLevel> {
// 带LLM分类器的2秒Promise.race
const classification = await Promise.race([
this.llmClassifier.classify(tool),
timeout(2000, { risk: 'medium' }),
]);
return classification.risk;
}
async requestApproval(tool: ToolCall): Promise<boolean> {
if (this.mode === 'autonomous') return true;
if (this.mode === 'read_only' && tool.metadata.destructive) {
return false;
}
return await this.ui.prompt({
message: `是否允许${tool.name}?`,
details: tool.input,
risk: await this.classify(tool),
});
}
async logExecution(
tool: ToolCall,
result: ToolResult
): Promise<void> {
await this.auditLog.write({
timestamp: Date.now(),
tool: tool.name,
input: tool.input,
output: result,
approved: result.approved,
userId: this.userId,
});
}
}4. Context Management (Working Memory)
4. 上下文管理(工作内存)
Progressive compression with circuit breaker:
typescript
// Effective window formula
interface ContextWindow {
total: number;
reserved: {
system: number;
tools: number;
recent: number;
};
available: number; // total - sum(reserved)
}
// Four-level progressive compression
class ContextManager {
private stages: CompressionStage[] = [
{ name: 'snip', threshold: 0.7, handler: this.snipOldMessages },
{ name: 'micro_compact', threshold: 0.8, handler: this.microCompact },
{ name: 'collapse', threshold: 0.9, handler: this.collapseBlocks },
{ name: 'auto_compact', threshold: 0.95, handler: this.autoCompact },
];
async compress(
messages: Message[],
budget: ContextWindow
): Promise<Message[]> {
const usage = this.calculateUsage(messages);
const ratio = usage / budget.available;
// Apply compression stages progressively
for (const stage of this.stages) {
if (ratio >= stage.threshold) {
messages = await stage.handler(messages, budget);
}
}
// Circuit breaker if still over budget
if (this.calculateUsage(messages) > budget.available) {
throw new ContextOverflowError('Cannot compress within budget');
}
return messages;
}
private async snipOldMessages(
messages: Message[],
budget: ContextWindow
): Promise<Message[]> {
// Keep system + recent + important, snip middle
const recent = messages.slice(-budget.reserved.recent);
const important = messages.filter(m => m.metadata?.important);
const system = messages.filter(m => m.role === 'system');
return [...system, ...important, ...recent];
}
private async microCompact(
messages: Message[]
): Promise<Message[]> {
// Compress tool results to summaries
return messages.map(msg => {
if (msg.role === 'tool' && msg.content.length > 1000) {
return {
...msg,
content: this.summarize(msg.content, 200),
metadata: { ...msg.metadata, compressed: true },
};
}
return msg;
});
}
}带熔断机制的渐进式压缩:
typescript
// 有效窗口公式
interface ContextWindow {
total: number;
reserved: {
system: number;
tools: number;
recent: number;
};
available: number; // total - sum(reserved)
}
// 四级渐进式压缩
class ContextManager {
private stages: CompressionStage[] = [
{ name: 'snip', threshold: 0.7, handler: this.snipOldMessages },
{ name: 'micro_compact', threshold: 0.8, handler: this.microCompact },
{ name: 'collapse', threshold: 0.9, handler: this.collapseBlocks },
{ name: 'auto_compact', threshold: 0.95, handler: this.autoCompact },
];
async compress(
messages: Message[],
budget: ContextWindow
): Promise<Message[]> {
const usage = this.calculateUsage(messages);
const ratio = usage / budget.available;
// 渐进式应用压缩阶段
for (const stage of this.stages) {
if (ratio >= stage.threshold) {
messages = await stage.handler(messages, budget);
}
}
// 若仍超出预算则触发熔断
if (this.calculateUsage(messages) > budget.available) {
throw new ContextOverflowError('无法在预算内完成压缩');
}
return messages;
}
private async snipOldMessages(
messages: Message[],
budget: ContextWindow
): Promise<Message[]> {
// 保留系统消息、近期消息和重要消息,裁剪中间部分
const recent = messages.slice(-budget.reserved.recent);
const important = messages.filter(m => m.metadata?.important);
const system = messages.filter(m => m.role === 'system');
return [...system, ...important, ...recent];
}
private async microCompact(
messages: Message[]
): Promise<Message[]> {
// 将工具结果压缩为摘要
return messages.map(msg => {
if (msg.role === 'tool' && msg.content.length > 1000) {
return {
...msg,
content: this.summarize(msg.content, 200),
metadata: { ...msg.metadata, compressed: true },
};
}
return msg;
});
}
}5. Memory System (Long-term Memory)
5. 内存系统(长期内存)
Four closed-form memory types:
typescript
// Memory types
interface MemorySystem {
facts: Map<string, Fact>; // Immutable truths
preferences: Map<string, any>; // User settings
context: Map<string, Context>; // Session state
learned: Map<string, Learned>; // Accumulated knowledge
}
class AgentMemory {
private index: MemoryIndex; // MEMORY.md file
async save(key: string, value: MemoryEntry): Promise<void> {
// "Only save what cannot be derived"
if (this.isDerived(value)) {
return; // Skip redundant information
}
await this.store.set(key, value);
await this.updateIndex(key, value);
}
async fork(parentMemory: AgentMemory): Promise<AgentMemory> {
// Byte-level context inheritance for sub-agents
const forked = new AgentMemory();
// Copy immutable facts (reference, not clone)
forked.facts = parentMemory.facts;
// Clone mutable state
forked.context = new Map(parentMemory.context);
forked.preferences = new Map(parentMemory.preferences);
// Start fresh learned knowledge
forked.learned = new Map();
return forked;
}
private async updateIndex(
key: string,
value: MemoryEntry
): Promise<void> {
const index = await this.loadIndex();
index.entries[key] = {
type: value.type,
created: value.timestamp,
summary: this.summarize(value),
};
await this.saveIndex(index);
}
}四种封闭形式的内存类型:
typescript
// 内存类型
interface MemorySystem {
facts: Map<string, Fact>; // 不可变事实
preferences: Map<string, any>; // 用户设置
context: Map<string, Context>; // 会话状态
learned: Map<string, Learned>; // 累积知识
}
class AgentMemory {
private index: MemoryIndex; // MEMORY.md文件
async save(key: string, value: MemoryEntry): Promise<void> {
// "仅保存无法推导的信息"
if (this.isDerived(value)) {
return; // 跳过冗余信息
}
await this.store.set(key, value);
await this.updateIndex(key, value);
}
async fork(parentMemory: AgentMemory): Promise<AgentMemory> {
// 子Agent的字节级上下文继承
const forked = new AgentMemory();
// 复制不可变事实(引用,而非克隆)
forked.facts = parentMemory.facts;
// 克隆可变状态
forked.context = new Map(parentMemory.context);
forked.preferences = new Map(parentMemory.preferences);
// 重置累积知识
forked.learned = new Map();
return forked;
}
private async updateIndex(
key: string,
value: MemoryEntry
): Promise<void> {
const index = await this.loadIndex();
index.entries[key] = {
type: value.type,
created: value.timestamp,
summary: this.summarize(value),
};
await this.saveIndex(index);
}
}6. Sub-Agent Fork Pattern
6. 子Agent分支模式
Recursive agent spawning with inheritance:
typescript
interface SubAgentConfig {
type: 'custom' | 'builtin';
agentPath?: string;
builtinName?: 'coordinator' | 'specialist' | 'reviewer' | 'planner';
inheritContext: boolean;
inheritMemory: boolean;
inheritTools: boolean;
}
class AgentFork {
async spawn(
parent: Agent,
config: SubAgentConfig
): Promise<Agent> {
// Load agent definition
const agentDef = config.type === 'builtin'
? await this.loadBuiltin(config.builtinName!)
: await this.loadCustom(config.agentPath!);
// Create child with inheritance
const child = new Agent({
...agentDef,
context: config.inheritContext
? parent.context.fork()
: new Context(),
memory: config.inheritMemory
? await parent.memory.fork()
: new AgentMemory(),
tools: config.inheritTools
? [...parent.tools.available]
: agentDef.tools,
});
// Recursive fork prevention
child.metadata.forkDepth = (parent.metadata.forkDepth || 0) + 1;
if (child.metadata.forkDepth > this.maxForkDepth) {
throw new MaxForkDepthError();
}
return child;
}
}
// Coordinator-Worker pattern
async function coordinatorWorkerPattern(
task: Task
): Promise<Result> {
const coordinator = await agentFork.spawn(mainAgent, {
type: 'builtin',
builtinName: 'coordinator',
inheritContext: true,
inheritMemory: false,
inheritTools: false, // Coordinators only orchestrate
});
const plan = await coordinator.plan(task);
const workers = await Promise.all(
plan.subtasks.map(subtask =>
agentFork.spawn(coordinator, {
type: 'builtin',
builtinName: 'specialist',
inheritContext: true,
inheritMemory: true,
inheritTools: true,
})
)
);
const results = await Promise.all(
workers.map((worker, i) => worker.execute(plan.subtasks[i]))
);
return coordinator.synthesize(results);
}带继承的递归Agent生成:
typescript
interface SubAgentConfig {
type: 'custom' | 'builtin';
agentPath?: string;
builtinName?: 'coordinator' | 'specialist' | 'reviewer' | 'planner';
inheritContext: boolean;
inheritMemory: boolean;
inheritTools: boolean;
}
class AgentFork {
async spawn(
parent: Agent,
config: SubAgentConfig
): Promise<Agent> {
// 加载Agent定义
const agentDef = config.type === 'builtin'
? await this.loadBuiltin(config.builtinName!)
: await this.loadCustom(config.agentPath!);
// 创建带继承的子Agent
const child = new Agent({
...agentDef,
context: config.inheritContext
? parent.context.fork()
: new Context(),
memory: config.inheritMemory
? await parent.memory.fork()
: new AgentMemory(),
tools: config.inheritTools
? [...parent.tools.available]
: agentDef.tools,
});
// 递归分支防护
child.metadata.forkDepth = (parent.metadata.forkDepth || 0) + 1;
if (child.metadata.forkDepth > this.maxForkDepth) {
throw new MaxForkDepthError();
}
return child;
}
}
// 协调者-工作者模式
async function coordinatorWorkerPattern(
task: Task
): Promise<Result> {
const coordinator = await agentFork.spawn(mainAgent, {
type: 'builtin',
builtinName: 'coordinator',
inheritContext: true,
inheritMemory: false,
inheritTools: false, // 协调者仅负责编排
});
const plan = await coordinator.plan(task);
const workers = await Promise.all(
plan.subtasks.map(subtask =>
agentFork.spawn(coordinator, {
type: 'builtin',
builtinName: 'specialist',
inheritContext: true,
inheritMemory: true,
inheritTools: true,
})
)
);
const results = await Promise.all(
workers.map((worker, i) => worker.execute(plan.subtasks[i]))
);
return coordinator.synthesize(results);
}7. MCP Integration
7. MCP集成
Model Context Protocol bridge for external tools:
typescript
// Eight transport protocols
type MCPTransport =
| 'stdio'
| 'http'
| 'websocket'
| 'grpc'
| 'ipc'
| 'sse'
| 'stdio+stderr'
| 'custom';
// Five-state connection lifecycle
type ConnectionState =
| 'disconnected'
| 'connecting'
| 'connected'
| 'error'
| 'reconnecting';
class MCPBridge {
private connections = new Map<string, MCPConnection>();
async connect(server: MCPServerConfig): Promise<void> {
const conn = new MCPConnection(server);
conn.on('state', (state) => {
if (state === 'error') {
this.reconnect(conn);
}
});
await conn.connect();
this.connections.set(server.name, conn);
// Register MCP tools with three-segment naming
const tools = await conn.listTools();
for (const tool of tools) {
this.registerTool({
name: `mcp.${server.name}.${tool.name}`,
description: tool.description,
schema: tool.inputSchema,
handler: (input) => conn.invoke(tool.name, input),
});
}
}
async invoke(
toolName: string,
input: unknown
): Promise<unknown> {
// Parse three-segment name: mcp.{server}.{tool}
const [_mcp, serverName, mcpToolName] = toolName.split('.');
const conn = this.connections.get(serverName);
if (!conn) throw new Error(`MCP server ${serverName} not connected`);
return await conn.invoke(mcpToolName, input);
}
private async reconnect(conn: MCPConnection): Promise<void> {
conn.state = 'reconnecting';
await new Promise(r => setTimeout(r, 1000));
await conn.connect();
}
}用于外部工具的Model Context Protocol桥接:
typescript
// 八种传输协议
type MCPTransport =
| 'stdio'
| 'http'
| 'websocket'
| 'grpc'
| 'ipc'
| 'sse'
| 'stdio+stderr'
| 'custom';
// 五种连接生命周期状态
type ConnectionState =
| 'disconnected'
| 'connecting'
| 'connected'
| 'error'
| 'reconnecting';
class MCPBridge {
private connections = new Map<string, MCPConnection>();
async connect(server: MCPServerConfig): Promise<void> {
const conn = new MCPConnection(server);
conn.on('state', (state) => {
if (state === 'error') {
this.reconnect(conn);
}
});
await conn.connect();
this.connections.set(server.name, conn);
// 注册三段式命名的MCP工具
const tools = await conn.listTools();
for (const tool of tools) {
this.registerTool({
name: `mcp.${server.name}.${tool.name}`,
description: tool.description,
schema: tool.inputSchema,
handler: (input) => conn.invoke(tool.name, input),
});
}
}
async invoke(
toolName: string,
input: unknown
): Promise<unknown> {
// 解析三段式名称:mcp.{server}.{tool}
const [_mcp, serverName, mcpToolName] = toolName.split('.');
const conn = this.connections.get(serverName);
if (!conn) throw new Error(`MCP服务器${serverName}未连接`);
return await conn.invoke(mcpToolName, input);
}
private async reconnect(conn: MCPConnection): Promise<void> {
conn.state = 'reconnecting';
await new Promise(r => setTimeout(r, 1000));
await conn.connect();
}
}8. Skill System
8. Skill系统
Plugin architecture with frontmatter metadata:
typescript
interface Skill {
metadata: SkillMetadata;
content: string;
tools?: Tool[];
hooks?: Hook[];
}
interface SkillMetadata {
name: string;
description: string;
triggers: string[];
version?: string;
dependencies?: string[];
}
class SkillLoader {
async load(path: string): Promise<Skill> {
const raw = await this.readFile(path);
const { frontmatter, content } = this.parseFrontmatter(raw);
// Three-level parameter substitution
const processed = await this.substitute(content, {
env: process.env,
config: this.config,
runtime: this.getRuntimeVars(),
});
return {
metadata: frontmatter as SkillMetadata,
content: processed,
tools: await this.extractTools(processed),
hooks: await this.extractHooks(processed),
};
}
private async substitute(
content: string,
context: SubstitutionContext
): Promise<string> {
// Level 1: Environment variables
content = content.replace(/\$\{env:(\w+)\}/g, (_, key) =>
context.env[key] || ''
);
// Level 2: Config values
content = content.replace(/\$\{config:(\w+)\}/g, (_, key) =>
context.config[key] || ''
);
// Level 3: Runtime values
content = content.replace(/\$\{runtime:(\w+)\}/g, (_, key) =>
context.runtime[key] || ''
);
return content;
}
}带前置元数据的插件架构:
typescript
interface Skill {
metadata: SkillMetadata;
content: string;
tools?: Tool[];
hooks?: Hook[];
}
interface SkillMetadata {
name: string;
description: string;
triggers: string[];
version?: string;
dependencies?: string[];
}
class SkillLoader {
async load(path: string): Promise<Skill> {
const raw = await this.readFile(path);
const { frontmatter, content } = this.parseFrontmatter(raw);
// 三级参数替换
const processed = await this.substitute(content, {
env: process.env,
config: this.config,
runtime: this.getRuntimeVars(),
});
return {
metadata: frontmatter as SkillMetadata,
content: processed,
tools: await this.extractTools(processed),
hooks: await this.extractHooks(processed),
};
}
private async substitute(
content: string,
context: SubstitutionContext
): Promise<string> {
// 第一级:环境变量
content = content.replace(/\$\{env:(\w+)\}/g, (_, key) =>
context.env[key] || ''
);
// 第二级:配置值
content = content.replace(/\$\{config:(\w+)\}/g, (_, key) =>
context.config[key] || ''
);
// 第三级:运行时值
content = content.replace(/\$\{runtime:(\w+)\}/g, (_, key) =>
context.runtime[key] || ''
);
return content;
}
}Configuration
配置
Agent configuration follows six-layer priority chain:
typescript
// Six-layer priority (highest to lowest)
const config = mergeConfig([
runtimeOverrides, // 1. Runtime flags
environmentVariables, // 2. Environment (AGENT_*)
projectConfig, // 3. .agentrc.json
userConfig, // 4. ~/.config/agent/config.json
skillDefaults, // 5. Skill-provided defaults
systemDefaults, // 6. Harness defaults
]);
// Feature flag system
interface FeatureFlags {
// Compile-time flags
enable_mcp: boolean;
enable_sub_agents: boolean;
enable_plan_mode: boolean;
// Runtime flags
auto_approve: boolean;
debug_mode: boolean;
trace_tools: boolean;
}
// Configuration with security boundaries
interface AgentConfig {
model: ModelConfig;
tools: ToolConfig;
permissions: PermissionConfig;
context: ContextConfig;
memory: MemoryConfig;
features: FeatureFlags;
// Security constraints
security: {
maxForkDepth: number;
allowedPaths: string[];
blockedCommands: string[];
rateLimits: RateLimitConfig;
};
}Agent配置遵循六层优先级链:
typescript
// 六层优先级(从高到低)
const config = mergeConfig([
runtimeOverrides, // 1. 运行时标志
environmentVariables, // 2. 环境变量(AGENT_*)
projectConfig, // 3. .agentrc.json
userConfig, // 4. ~/.config/agent/config.json
skillDefaults, // 5. Skill提供的默认值
systemDefaults, // 6. Harness默认值
]);
// 功能标志系统
interface FeatureFlags {
// 编译时标志
enable_mcp: boolean;
enable_sub_agents: boolean;
enable_plan_mode: boolean;
// 运行时标志
auto_approve: boolean;
debug_mode: boolean;
trace_tools: boolean;
}
// 带安全边界的配置
interface AgentConfig {
model: ModelConfig;
tools: ToolConfig;
permissions: PermissionConfig;
context: ContextConfig;
memory: MemoryConfig;
features: FeatureFlags;
// 安全约束
security: {
maxForkDepth: number;
allowedPaths: string[];
blockedCommands: string[];
rateLimits: RateLimitConfig;
};
}Performance Optimization
性能优化
Startup Optimization
启动优化
typescript
// Lazy loading pattern (160ms → 65ms, -59%)
class LazyAgentLoader {
private loaded = new Set<string>();
async loadOnDemand(module: string): Promise<void> {
if (this.loaded.has(module)) return;
switch (module) {
case 'tools':
await this.loadTools();
break;
case 'mcp':
await this.loadMCP();
break;
case 'skills':
await this.loadSkills();
break;
}
this.loaded.add(module);
}
private async loadTools(): Promise<void> {
// Parallel import with Promise.all
const toolModules = [
'filesystem',
'shell',
'network',
'search',
];
await Promise.all(
toolModules.map(m => import(`./tools/${m}`))
);
}
}
// Concurrent control
class ConcurrencyController {
constructor(private maxConcurrent: number = 5) {}
async executeInBatches<T>(
tasks: (() => Promise<T>)[],
): Promise<T[]> {
const results: T[] = [];
for (let i = 0; i < tasks.length; i += this.maxConcurrent) {
const batch = tasks.slice(i, i + this.maxConcurrent);
const batchResults = await Promise.all(
batch.map(task => task())
);
results.push(...batchResults);
}
return results;
}
}typescript
// 懒加载模式(160ms → 65ms,提升59%)
class LazyAgentLoader {
private loaded = new Set<string>();
async loadOnDemand(module: string): Promise<void> {
if (this.loaded.has(module)) return;
switch (module) {
case 'tools':
await this.loadTools();
break;
case 'mcp':
await this.loadMCP();
break;
case 'skills':
await this.loadSkills();
break;
}
this.loaded.add(module);
}
private async loadTools(): Promise<void> {
// 并行导入Promise.all
const toolModules = [
'filesystem',
'shell',
'network',
'search',
];
await Promise.all(
toolModules.map(m => import(`./tools/${m}`))
);
}
}
// 并发控制
class ConcurrencyController {
constructor(private maxConcurrent: number = 5) {}
async executeInBatches<T>(
tasks: (() => Promise<T>)[],
): Promise<T[]> {
const results: T[] = [];
for (let i = 0; i < tasks.length; i += this.maxConcurrent) {
const batch = tasks.slice(i, i + this.maxConcurrent);
const batchResults = await Promise.all(
batch.map(task => task())
);
results.push(...batchResults);
}
return results;
}
}Observability
可观测性
Four-layer monitoring system:
typescript
interface Observability {
// Layer 1: Structured logging
logger: Logger;
// Layer 2: Metrics
metrics: MetricsCollector;
// Layer 3: Tracing
tracer: DistributedTracer;
// Layer 4: Debugging
debugger: AgentDebugger;
}
class AgentObservability implements Observability {
logger = new Logger({
level: process.env.LOG_LEVEL || 'info',
format: 'json',
fields: {
agent_id: this.agentId,
session_id: this.sessionId,
},
});
metrics = new MetricsCollector({
counters: [
'tool_executions',
'permission_denials',
'context_compressions',
],
histograms: [
'turn_duration',
'tool_latency',
'context_size',
],
});
tracer = new DistributedTracer({
service: 'agent-harness',
samplingRate: 0.1,
exporters: [
new OTLPExporter({ endpoint: process.env.OTEL_ENDPOINT }),
],
});
async trace<T>(
operation: string,
fn: () => Promise<T>
): Promise<T> {
const span = this.tracer.startSpan(operation);
try {
const result = await fn();
span.setStatus({ code: 'OK' });
return result;
} catch (error) {
span.setStatus({ code: 'ERROR', message: error.message });
throw error;
} finally {
span.end();
}
}
}四层监控系统:
typescript
interface Observability {
// 第一层:结构化日志
logger: Logger;
// 第二层:指标
metrics: MetricsCollector;
// 第三层:追踪
tracer: DistributedTracer;
// 第四层:调试
debugger: AgentDebugger;
}
class AgentObservability implements Observability {
logger = new Logger({
level: process.env.LOG_LEVEL || 'info',
format: 'json',
fields: {
agent_id: this.agentId,
session_id: this.sessionId,
},
});
metrics = new MetricsCollector({
counters: [
'tool_executions',
'permission_denials',
'context_compressions',
],
histograms: [
'turn_duration',
'tool_latency',
'context_size',
],
});
tracer = new DistributedTracer({
service: 'agent-harness',
samplingRate: 0.1,
exporters: [
new OTLPExporter({ endpoint: process.env.OTEL_ENDPOINT }),
],
});
async trace<T>(
operation: string,
fn: () => Promise<T>
): Promise<T> {
const span = this.tracer.startSpan(operation);
try {
const result = await fn();
span.setStatus({ code: 'OK' });
return result;
} catch (error) {
span.setStatus({ code: 'ERROR', message: error.message });
throw error;
} finally {
span.end();
}
}
}Common Patterns
通用模式
Pattern 1: Graceful Degradation
模式1:优雅降级
typescript
async function executeWithFallback<T>(
primary: () => Promise<T>,
fallback: () => Promise<T>,
timeout: number = 5000
): Promise<T> {
try {
return await Promise.race([
primary(),
new Promise<T>((_, reject) =>
setTimeout(() => reject(new TimeoutError()), timeout)
),
]);
} catch (error) {
console.warn('Primary failed, using fallback:', error);
return await fallback();
}
}
// Usage in tool execution
const result = await executeWithFallback(
() => mcpBridge.invoke('mcp.search.web', query),
() => localSearch.execute(query),
3000
);typescript
async function executeWithFallback<T>(
primary: () => Promise<T>,
fallback: () => Promise<T>,
timeout: number = 5000
): Promise<T> {
try {
return await Promise.race([
primary(),
new Promise<T>((_, reject) =>
setTimeout(() => reject(new TimeoutError()), timeout)
),
]);
} catch (error) {
console.warn('主执行失败,使用降级方案:', error);
return await fallback();
}
}
// 在工具执行中的用法
const result = await executeWithFallback(
() => mcpBridge.invoke('mcp.search.web', query),
() => localSearch.execute(query),
3000
);Pattern 2: Dependency Injection
模式2:依赖注入
typescript
// QueryDeps pattern for testability
interface QueryDeps {
llm: LLMClient;
tools: ToolRegistry;
permissions: PermissionPipeline;
context: ContextManager;
memory: AgentMemory;
ui: UserInterface;
config: AgentConfig;
}
class Agent {
constructor(private deps: QueryDeps) {}
async run(query: string): Promise<void> {
for await (const event of conversationLoop(this.deps)) {
await this.deps.ui.render(event);
}
}
}
// Testing with mocks
const testAgent = new Agent({
llm: new MockLLM(),
tools: new MockToolRegistry(),
permissions: new AutoApprovePermissions(),
context: new InMemoryContext(),
memory: new InMemoryMemory(),
ui: new TestUI(),
config: testConfig,
});typescript
// 用于可测试性的QueryDeps模式
interface QueryDeps {
llm: LLMClient;
tools: ToolRegistry;
permissions: PermissionPipeline;
context: ContextManager;
memory: AgentMemory;
ui: UserInterface;
config: AgentConfig;
}
class Agent {
constructor(private deps: QueryDeps) {}
async run(query: string): Promise<void> {
for await (const event of conversationLoop(this.deps)) {
await this.deps.ui.render(event);
}
}
}
// 使用模拟对象测试
const testAgent = new Agent({
llm: new MockLLM(),
tools: new MockToolRegistry(),
permissions: new AutoApprovePermissions(),
context: new InMemoryContext(),
memory: new InMemoryMemory(),
ui: new TestUI(),
config: testConfig,
});Pattern 3: Hook-Based Extension
模式3:基于Hook的扩展
typescript
// 26 lifecycle events
type HookEvent =
| 'agent:init'
| 'agent:start'
| 'turn:start'
| 'llm:request'
| 'llm:response'
| 'tool:call'
| 'tool:result'
| 'permission:check'
| 'context:compress'
| 'memory:save'
// ... 16 more
class HookSystem {
private hooks = new Map<HookEvent, Hook[]>();
register(event: HookEvent, hook: Hook): void {
const hooks = this.hooks.get(event) || [];
hooks.push(hook);
hooks.sort((a, b) => a.priority - b.priority);
this.hooks.set(event, hooks);
}
async trigger(event: HookEvent, data: unknown): Promise<void> {
const hooks = this.hooks.get(event) || [];
for (const hook of hooks) {
try {
await hook.handler(data);
} catch (error) {
console.error(`Hook ${hook.name} failed:`, error);
// Continue with other hooks
}
}
}
}
// Example: Audit logging hook
hookSystem.register('tool:result', {
name: 'audit_logger',
priority: 100,
handler: async (data) => {
await auditLog.write({
timestamp: Date.now(),
tool: data.tool,
result: data.result,
});
},
});typescript
// 26个生命周期事件
type HookEvent =
| 'agent:init'
| 'agent:start'
| 'turn:start'
| 'llm:request'
| 'llm:response'
| 'tool:call'
| 'tool:result'
| 'permission:check'
| 'context:compress'
| 'memory:save'
// ... 还有16个
class HookSystem {
private hooks = new Map<HookEvent, Hook[]>();
register(event: HookEvent, hook: Hook): void {
const hooks = this.hooks.get(event) || [];
hooks.push(hook);
hooks.sort((a, b) => a.priority - b.priority);
this.hooks.set(event, hooks);
}
async trigger(event: HookEvent, data: unknown): Promise<void> {
const hooks = this.hooks.get(event) || [];
for (const hook of hooks) {
try {
await hook.handler(data);
} catch (error) {
console.error(`Hook ${hook.name}执行失败:`, error);
// 继续执行其他Hook
}
}
}
}
// 示例:审计日志Hook
hookSystem.register('tool:result', {
name: 'audit_logger',
priority: 100,
handler: async (data) => {
await auditLog.write({
timestamp: Date.now(),
tool: data.tool,
result: data.result,
});
},
});Troubleshooting
故障排查
Context Overflow
上下文溢出
typescript
// Symptom: Agent fails with "context budget exceeded"
// Solution 1: Increase reserved budget
const config = {
context: {
total: 200000,
reserved: {
system: 2000,
tools: 5000,
recent: 10000, // Increase this
},
},
};
// Solution 2: Enable aggressive compression
const config = {
features: {
enable_auto_compact: true,
compression_threshold: 0.7, // Trigger earlier
},
};
// Solution 3: Implement custom compression
class CustomCompressor extends ContextManager {
async compress(messages: Message[]): Promise<Message[]> {
// Your domain-specific logic
return messages.filter(m => m.metadata.important);
}
}typescript
// 症状:Agent因"context budget exceeded"失败
// 解决方案1:增加预留预算
const config = {
context: {
total: 200000,
reserved: {
system: 2000,
tools: 5000,
recent: 10000, // 增加该值
},
},
};
// 解决方案2:启用激进压缩
const config = {
features: {
enable_auto_compact: true,
compression_threshold: 0.7, // 提前触发
},
};
// 解决方案3:实现自定义压缩
class CustomCompressor extends ContextManager {
async compress(messages: Message[]): Promise<Message[]> {
// 你的领域特定逻辑
return messages.filter(m => m.metadata.important);
}
}Permission Deadlock
权限死锁
typescript
// Symptom: Agent hangs waiting for approval
// Solution: Set timeout on permission requests
class TimeoutPermissions extends PermissionPipeline {
async requestApproval(tool: ToolCall): Promise<boolean> {
try {
return await Promise.race([
super.requestApproval(tool),
timeout(30000, false), // Auto-deny after 30s
]);
} catch (error) {
console.error('Permission timeout:', tool.name);
return false;
}
}
}typescript
// 症状:Agent因等待批准而挂起
// 解决方案:为权限请求设置超时
class TimeoutPermissions extends PermissionPipeline {
async requestApproval(tool: ToolCall): Promise<boolean> {
try {
return await Promise.race([
super.requestApproval(tool),
timeout(30000, false), // 30秒后自动拒绝
]);
} catch (error) {
console.error('权限请求超时:', tool.name);
return false;
}
}
}MCP Connection Failures
MCP连接失败
typescript
// Symptom: MCP tools fail with "connection refused"
// Solution: Implement exponential backoff
class ResilientMCPBridge extends MCPBridge {
async reconnect(
conn: MCPConnection,
attempt: number = 0
): Promise<void> {
const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
try {
await new Promise(r => setTimeout(r, delay));
await conn.connect();
} catch (error) {
if (attempt < 5) {
await this.reconnect(conn, attempt + 1);
} else {
throw new MaxRetriesError();
}
}
}
}typescript
// 症状:MCP工具因"connection refused"失败
// 解决方案:实现指数退避
class ResilientMCPBridge extends MCPBridge {
async reconnect(
conn: MCPConnection,
attempt: number = 0
): Promise<void> {
const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
try {
await new Promise(r => setTimeout(r, delay));
await conn.connect();
} catch (error) {
if (attempt < 5) {
await this.reconnect(conn, attempt + 1);
} else {
throw new MaxRetriesError();
}
}
}
}Memory Leak in Long Sessions
长会话内存泄漏
typescript
// Symptom: Memory usage grows unbounded
// Solution: Implement periodic cleanup
class BoundedMemory extends AgentMemory {
private maxSize = 1000;
async save(key: string, value: MemoryEntry): Promise<void> {
await super.save(key, value);
// Evict old entries if over limit
if (this.store.size > this.maxSize) {
const sorted = [...this.store.entries()]
.sort((a, b) => a[1].timestamp - b[1].timestamp);
const toDelete = sorted.slice(0, this.store.size - this.maxSize);
for (const [key] of toDelete) {
this.store.delete(key);
}
}
}
}typescript
// 症状:内存使用无限制增长
// 解决方案:实现定期清理
class BoundedMemory extends AgentMemory {
private maxSize = 1000;
async save(key: string, value: MemoryEntry): Promise<void> {
await super.save(key, value);
// 超出限制时淘汰旧条目
if (this.store.size > this.maxSize) {
const sorted = [...this.store.entries()]
.sort((a, b) => a[1].timestamp - b[1].timestamp);
const toDelete = sorted.slice(0, this.store.size - this.maxSize);
for (const [key] of toDelete) {
this.store.delete(key);
}
}
}
}Advanced Usage
高级用法
Building a Custom Harness
构建自定义Harness
Six-step implementation roadmap:
typescript
// Step 1: Define agent interface
interface CustomAgent {
run(query: string): Promise<void>;
addTool(tool: Tool): void;
fork(config: SubAgentConfig): Promise<CustomAgent>;
}
// Step 2: Implement conversation loop
class CustomAgentImpl implements CustomAgent {
async run(query: string): Promise<void> {
const deps = this.buildDeps();
for await (const event of conversationLoop(deps)) {
await this.handleEvent(event);
}
}
}
// Step 3: Build tool registry
class CustomToolRegistry extends ToolRegistry {
// Your custom tool loading logic
}
// Step 4: Implement permission system
class CustomPermissions extends PermissionPipeline {
// Your custom approval flow
}
// Step 5: Add observability
const agent = new CustomAgentImpl({
observability: new AgentObservability(),
});
// Step 6: Test and iterate
await agent.run('Build a web scraper');六步实现路线图:
typescript
// 步骤1:定义Agent接口
interface CustomAgent {
run(query: string): Promise<void>;
addTool(tool: Tool): void;
fork(config: SubAgentConfig): Promise<CustomAgent>;
}
// 步骤2:实现对话循环
class CustomAgentImpl implements CustomAgent {
async run(query: string): Promise<void> {
const deps = this.buildDeps();
for await (const event of conversationLoop(deps)) {
await this.handleEvent(event);
}
}
}
// 步骤3:构建工具注册表
class CustomToolRegistry extends ToolRegistry {
// 你的自定义工具加载逻辑
}
// 步骤4:实现权限系统
class CustomPermissions extends PermissionPipeline {
// 你的自定义批准流程
}
// 步骤5:添加可观测性
const agent = new CustomAgentImpl({
observability: new AgentObservability(),
});
// 步骤6:测试与迭代
await agent.run('构建一个网页爬虫');References
参考资料
- Online Documentation: https://lintsinghua.github.io
- Repository:
- 在线文档: https://lintsinghua.github.io
- 代码仓库: