| name | claude-code-harness-architecture |
| description | Expert guidance on AI Agent Harness architecture based on the comprehensive Claude Code analysis book |
| triggers | ["how do I build an agent harness","explain agent conversation loop architecture","show me tool permission pipeline design","how does context compression work in agents","implement agent memory system","design multi-agent coordinator pattern","set up MCP integration for agents","build fork-based sub-agent system"] |
Claude Code Harness Architecture
Skill by ara.so — Claude Code Skills collection.
This skill provides deep architectural knowledge from the 420,000-word book "Decoding Agent Harness" (御舆:解码 Agent Harness), a comprehensive analysis of Claude Code's internal architecture. Use this to design, build, and debug production-grade AI Agent systems.
What This Covers
The book analyzes the complete Agent Harness architecture through 15 chapters:
- Conversation Loop: Async generator-based dialog control
- Tool System: 45+ tools, concurrent execution, safety protocols
- Permission Pipeline: 4-stage access control with speculative classification
- Context Management: 4-level progressive compression with circuit breakers
- Memory System: 4 types of closed-form memory, fork inheritance
- Hook System: 26 lifecycle events, 5 hook types
- Sub-Agents: Fork mode with byte-level context inheritance
- MCP Integration: 8 transport protocols, bridge architecture
- Skills & Plugins: 11 core skills, frontmatter-based loading
- Streaming Architecture: Performance optimization patterns
Core Architecture Patterns
1. Conversation Loop (The Heartbeat)
The main loop is an async generator with 5 yield event types:
async function* conversationLoop(
deps: QueryDeps
): AsyncGenerator<ConversationEvent> {
while (true) {
yield { type: 'thinking', phase: 'analyzing' };
const response = await streamLLMCompletion(deps);
yield { type: 'text', content: response.delta };
if (response.toolUse) {
yield { type: 'tool_call', tool: response.toolUse.name };
const result = await executeTool(response.toolUse, deps);
yield { type: 'tool_result', data: result };
}
if (shouldTerminate(response, deps)) {
yield { type: 'done', reason: response.stopReason };
break;
}
}
}
10 Termination Reasons:
end_turn: Natural completion
max_tokens: Context limit reached
stop_sequence: Explicit stop marker
tool_use: Waiting for tool approval
user_interrupt: Manual cancellation
error: Execution failure
timeout: Time limit exceeded
budget_exceeded: Token budget exhausted
recursion_limit: Max fork depth reached
safety_violation: Permission denied
2. Tool System Architecture
Tool Protocol (5 elements):
interface Tool<I = unknown, O = unknown, P = unknown> {
input: z.ZodType<I>;
name: string;
description: string;
parameters?: P;
execute: (input: I, params: P, deps: QueryDeps) => Promise<O>;
readOnly: boolean;
destructive: boolean;
concurrencySafe: boolean;
}
Fault-Safe Tool Factory:
function buildTool<I, O, P>(spec: ToolSpec<I, O, P>): Tool<I, O, P> {
return {
...spec,
execute: async (input, params, deps) => {
try {
const validated = spec.input.parse(input);
const result = await Promise.race([
spec.execute(validated, params, deps),
new Promise((_, reject) =>
setTimeout(() => reject('timeout'), deps.timeout)
)
]);
return result as O;
} catch (error) {
return {
success: false,
error: error.message,
recovery: spec.errorRecovery?.(error)
} as O;
}
}
};
}
12 Tool Categories (from Appendix B):
- File Operations:
read_file, write_file, search_files
- Shell:
execute_command, bash_session
- Browser:
navigate, screenshot, extract
- Git:
commit, diff, log
- Search:
web_search, codebase_search
- Memory:
remember, recall, forget
- Agent:
fork_agent, call_coordinator
- MCP:
mcp_call_tool, mcp_list_resources
- Plan:
create_plan, update_plan_step
- Config:
get_setting, update_setting
- Debug:
inspect_context, trace_tool_call
- System:
sleep, notify, request_permission
3. Permission Pipeline (4 Stages)
type PermissionMode =
| 'auto'
| 'notify'
| 'confirm'
| 'reject'
| 'interactive';
async function permissionPipeline(
toolCall: ToolCall,
deps: QueryDeps
): Promise<PermissionResult> {
const mode = matchPermissionRule(toolCall.name, deps.config.permissions);
if (mode === 'auto') return { approved: true };
if (mode === 'reject') return { approved: false, reason: 'policy' };
const classification = await Promise.race([
classifyToolIntent(toolCall, deps),
Promise.resolve({ risk: , : })
]);
(classification. === && classification. > ) {
{ : , : };
}
(mode === || mode === ) {
response = deps..({
: toolCall.,
: toolCall.,
: classification.,
: (toolCall)
});
{ : response., : response. };
}
{ : , : };
}
Rule Matching Examples:
permissions:
- pattern: "read_*"
mode: auto
- pattern: "write_file:/tmp/**"
mode: notify
- pattern: "execute_command:rm *"
mode: reject
- pattern: "fork_agent:**"
mode: confirm
max_depth: 3
4. Context Management (Compression Strategies)
Effective Window Formula:
EffectiveWindow = MaxContext - (SystemPrompt + Tools + Config + Memory + OutputReserve)
4-Level Progressive Compression:
async function manageContext(deps: QueryDeps): Promise<Message[]> {
const budget = calculateBudget(deps);
let messages = deps.conversation.messages;
if (getTokenCount(messages) > budget.warning) {
messages = snipOldMessages(messages, budget.target);
}
if (getTokenCount(messages) > budget.warning) {
messages = await microCompact(messages, {
maxCodeLength: 500,
preserveErrors: true
});
}
if (getTokenCount(messages) > budget.critical) {
messages = await collapseMessages(messages, {
minPairAge: 10,
maxCollapse: 0.5
});
}
if (getTokenCount(messages) > budget.critical) {
messages = await autoCompact(messages, deps);
}
((messages) > budget.) {
messages = messages.(-budget.);
deps..();
}
messages;
}
Circuit Breaker Pattern:
class ContextCircuitBreaker {
private failures = 0;
private state: 'closed' | 'open' | 'half_open' = 'closed';
async execute<T>(fn: () => Promise<T>): Promise<T> {
if (this.state === 'open') {
throw new Error('Circuit breaker open');
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
private onFailure() {
this.failures++;
if (this.failures >= 3) {
this.state = 'open';
setTimeout(() => this.state = 'half_open', );
}
}
() {
. = ;
. = ;
}
}
5. Memory System (4 Types)
Closed-Form Memory (only store non-derivable information):
interface Memory {
type: 'fact' | 'preference' | 'context' | 'goal';
content: string;
source: 'user' | 'agent' | 'tool';
timestamp: number;
expiresAt?: number;
confidence: number;
}
class MemorySystem {
async remember(memory: Memory, deps: QueryDeps) {
if (await this.isDerivable(memory, deps)) {
return { stored: false, reason: 'derivable' };
}
await deps.fs.appendFile('.claude/MEMORY.md',
`\n## ${memory.type} (${new Date(memory.timestamp).toISOString()})\n` +
`${memory.content}\n` +
`Source: ${memory.source} | Confidence: \n`
);
.(memory, deps);
}
(: , : ): <[]> {
results = deps..(query, {
: [, , , ],
: ,
:
});
results.(
!m. || m. > .()
);
}
}
Fork Memory Inheritance:
async function forkAgent(config: ForkConfig, deps: QueryDeps): Promise<Agent> {
const childMemory = {
facts: deps.memory.getFacts(),
preferences: { ...deps.memory.getPreferences() },
context: [],
goals: config.inheritGoals ? deps.memory.getGoals() : []
};
return createAgent({
...config,
memory: childMemory,
parent: deps.agentId,
depth: deps.forkDepth + 1
});
}
6. Sub-Agent & Coordinator Pattern
Fork Mode (byte-level context inheritance):
interface ForkConfig {
type: 'fork' | 'spawn' | 'clone';
inheritContext: boolean;
inheritMemory: boolean;
inheritTools: boolean;
inheritGoals: boolean;
maxDepth: number;
}
async function forkAgent(
config: ForkConfig,
deps: QueryDeps
): Promise<{ agentId: string; channel: MessageChannel }> {
if (deps.forkDepth >= config.maxDepth) {
throw new Error(`Max fork depth ${config.maxDepth} exceeded`);
}
const childContext = config.inheritContext
? structuredClone(deps.conversation)
: { messages: [] };
const child = await createAgent({
...config,
context: childContext,
memory: config.inheritMemory ? (deps.) : {},
: config. ? deps. : (),
: deps.,
: deps. +
});
{
: child.,
: child.
};
}
Coordinator Pattern (orchestration-only):
class CoordinatorAgent {
private readonly allowedTools = [
'fork_agent',
'send_message_to_agent',
'wait_for_agent',
'aggregate_results'
];
async orchestrate(task: Task, deps: QueryDeps) {
const subtasks = await this.decompose(task, deps);
const workers = await Promise.all(
subtasks.map(st => forkAgent({
type: 'spawn',
inheritContext: false,
inheritMemory: true,
inheritTools: true,
inheritGoals: false,
maxDepth: deps.forkDepth + 1
}, deps))
);
await Promise.all(
workers.map((w, i) => .(w, subtasks[i]))
);
results = .(
workers.( .(w))
);
.(results, task);
}
(: ): {
..(toolName);
}
}
4 Addressing Modes:
type AgentAddress =
| { type: 'direct', id: string }
| { type: 'role', role: string }
| { type: 'capability', skills: string[] }
| { type: 'broadcast', scope: 'all' | 'siblings' };
async function routeMessage(
message: Message,
address: AgentAddress,
deps: QueryDeps
): Promise<void> {
const targets = resolveAddress(address, deps);
await Promise.all(
targets.map(agent => agent.channel.postMessage(message))
);
}
7. MCP Integration
8 Transport Protocols (from Ch12):
stdio: Standard input/output
sse: Server-Sent Events
ws: WebSocket
http: HTTP polling
ipc: Inter-Process Communication
tcp: Raw TCP socket
unix: Unix domain socket
embedded: In-process
5-State Connection Management:
type MCPConnectionState =
| 'disconnected'
| 'connecting'
| 'connected'
| 'reconnecting'
| 'failed';
class MCPConnection {
private state: MCPConnectionState = 'disconnected';
private reconnectAttempts = 0;
private maxReconnectAttempts = 5;
async connect(config: MCPConfig): Promise<void> {
this.state = 'connecting';
try {
const transport = createTransport(config.protocol, config);
await transport.connect();
const capabilities = await this.handshake(transport);
this.state = 'connected';
this.reconnectAttempts = 0;
return { transport, capabilities };
} catch (error) {
await this.handleConnectionError(error, config);
}
}
(
: ,
:
): <> {
(. < .) {
. = ;
.++;
delay = .( * ** ., );
(delay);
.(config);
} {
. = ;
error;
}
}
}
3-Segment Tool Naming:
mcp://<server>/<category>/<tool>
Example:
const toolName = 'mcp://github/repo/create_issue';
const [protocol, server, category, tool] = toolName.split('/');
Bridge Pattern (bidirectional communication):
class MCPBridge {
async callTool(
toolName: string,
args: unknown,
deps: QueryDeps
): Promise<unknown> {
const [server, category, tool] = parseMCPToolName(toolName);
const connection = deps.mcpConnections.get(server);
const result = await connection.request({
method: 'tools/call',
params: { name: `${category}/${tool}`, arguments: args }
});
return result;
}
async handleNotification(
notification: MCPNotification,
deps: QueryDeps
): Promise<void> {
switch (notification.method) {
case 'notifications/resources/updated':
await deps.memory.invalidateCache(notification.params.uri);
break;
:
deps..(notification..);
;
}
}
}
8. Hook System (26 Lifecycle Events)
5 Hook Types:
type HookType =
| 'before'
| 'after'
| 'transform'
| 'validate'
| 'observe';
interface Hook {
type: HookType;
event: LifecycleEvent;
priority: number;
execute: (context: HookContext) => Promise<HookResult>;
conditions?: HookCondition[];
}
26 Lifecycle Events (partial list from Ch08):
type LifecycleEvent =
| 'conversation:start'
| 'conversation:message'
| 'conversation:end'
| 'tool:before_call'
| 'tool:after_call'
| 'tool:error'
| 'context:compress'
| 'context:overflow'
| 'permission:request'
| 'permission:denied'
| 'memory:store'
| 'memory:recall'
| 'agent:fork'
| 'agent:terminate'
| 'mcp:connect'
| 'mcp:disconnect'
| 'plan:create'
| 'plan:step_complete'
| 'system:error'
| 'system:shutdown';
Hook Registration:
async function registerHook(
hook: Hook,
deps: QueryDeps
): Promise<void> {
if (!deps.config.allowExternalHooks && hook.source !== 'builtin') {
throw new Error('External hooks disabled');
}
await validateHookSchema(hook);
deps.hooks.register(hook.event, hook.priority, hook.execute);
}
async function executeHooks(
event: LifecycleEvent,
context: HookContext,
deps: QueryDeps
): Promise<HookContext> {
const hooks = deps.hooks.get(event).sort((a, b) => b.priority - a.priority);
let currentContext = context;
for ( hook hooks) {
(hook. && !(hook., currentContext)) {
;
}
{
result = .([
hook.(currentContext),
(, )
]);
(result.) {
currentContext = result.;
}
(result.) {
;
}
} (error) {
deps..(hook., error);
}
}
currentContext;
}
9. Skills & Plugins (Frontmatter-Based Loading)
SKILL.md Frontmatter:
---
name: git-workflow-automation
version: 1.2.0
description: Automated git workflows with conventional commits
triggers:
- "create a feature branch"
- "commit with conventional format"
- "prepare a release"
dependencies:
tools: [execute_command, read_file, write_file]
mcpServers: [github]
config:
commitFormat: conventional
branchPrefix: feature/
autoSquash: true
parameters:
mainBranch: ${param.mainBranch|main}
remote: ${param.remote|origin}
signCommits: ${param.signCommits|false}
---
3-Level Parameter Replacement:
function resolveParameters(
skillConfig: SkillConfig,
deps: QueryDeps
): Record<string, unknown> {
const resolved = {};
for (const [key, template] of Object.entries(skillConfig.parameters)) {
if (deps.userParams[key] !== undefined) {
resolved[key] = deps.userParams[key];
continue;
}
const envMatch = template.match(/\${env\.([^}|]+)(\|(.+))?}/);
if (envMatch) {
const [, envVar, , defaultValue] = envMatch;
resolved[key] = process.env[envVar] ?? defaultValue;
continue;
}
const defaultMatch = template.match(/\${param\.[^}|]+\|(.+)}/);
if (defaultMatch) {
resolved[key] = defaultMatch[1];
}
}
return resolved;
}
Layered Loading:
async function loadSkills(deps: QueryDeps): Promise<Skill[]> {
const skills: Skill[] = [];
const builtinPath = path.join(__dirname, '../skills');
skills.push(...await loadSkillsFromDir(builtinPath));
const userPath = path.join(deps.config.skillsDir);
if (await exists(userPath)) {
skills.push(...await loadSkillsFromDir(userPath));
}
const projectPath = path.join(deps.workingDir, '.claude/skills');
if (await exists(projectPath)) {
skills.push(...await loadSkillsFromDir(projectPath));
}
return deduplicateSkills(skills);
}
10. Performance Optimization
Startup Optimization (Ch13: 160ms → 65ms, -59%):
async function initialize(deps: QueryDeps) {
await loadAllTools();
await loadAllSkills();
await connectAllMCP();
await loadMemory();
await initializeHooks();
}
async function initialize(deps: QueryDeps) {
await Promise.all([
loadCoreTools(),
initializeConversation()
]);
Promise.all([
lazyLoadSkills(),
lazyConnectMCP(),
backgroundLoadMemory()
]);
}
Lazy Tool Loading:
class LazyToolRegistry {
private loaded = new Set<string>();
private loaders = new Map<string, () => Promise<Tool>>();
register(name: string, loader: () => Promise<Tool>) {
this.loaders.set(name, loader);
}
async get(name: string): Promise<Tool> {
if (!this.loaded.has(name)) {
const tool = await this.loaders.get(name)!();
this.tools.set(name, tool);
this.loaded.add(name);
}
return this.tools.get(name)!;
}
}
Configuration
6-Layer Priority Chain (Ch05):
- CLI arguments (highest)
- Environment variables
- Project config (
.claude/config.json)
- User config (
~/.claude/config.json)
- Workspace config
- Default config (lowest)
Example Config:
{
"model": "claude-3-7-sonnet-20250219",
"maxTokens": 8192,
"temperature": 0.7,
"tools": {
"enabled": ["read_file", "write_file", "execute_command"],
"disabled": ["browser_*"],
"concurrency": {
"max": 5,
"perCategory": 3
}
},
"permissions": {
"defaultMode": "confirm",
"rules": [
{ "pattern":
Building Your Own Harness (Ch15)
6-Step Implementation Roadmap:
async function* conversationLoop(deps: QueryDeps) {
while (true) {
const response = await streamLLM(deps);
yield { type: 'text', content: response.delta };
if (response.toolUse) {
const result = await executeTool(response.toolUse, deps);
yield { type: 'tool_result', data: result };
}
if (shouldTerminate(response)) break;
}
}
const tools = new ToolRegistry();
tools.register(buildTool({
name: 'read_file',
input: z.object({ path: z.string() }),
execute: async (input) => await fs.readFile(input.path, 'utf-8')
}));
async function () {
mode = (toolCall., deps..);
(mode === ) {
deps..(toolCall);
}
mode === ;
}
() {
compressed = messages;
((compressed) > budget) {
compressed = (compressed, budget);
}
((compressed) > budget) {
compressed = (compressed);
}
compressed;
}
{
() {
(! .(fact)) {
.(fact);
}
}
() {
.(query);
}
}