| name | claude-code-agent-harness-architecture |
| description | Expert guidance on AI Agent architecture, harness design patterns, and building production-grade Agent systems based on Claude Code analysis |
| triggers | ["how do I build an AI agent harness","explain agent architecture patterns","design a production agent system","implement agent tool calling system","build agent permission pipeline","create agent context management","design agent conversation loop","implement agent memory system"] |
Claude Code Agent Harness Architecture
Skill by ara.so — Claude Code Skills collection.
What This Skill Covers
This skill provides deep architectural knowledge for building production-grade AI Agent systems (Agent Harness), based on the comprehensive analysis of Claude Code's architecture from the claude-code-book project. You'll learn:
- Core Agent Harness patterns: conversation loops, tool systems, permission pipelines
- Context & memory management: token budgeting, compression strategies, long-term memory
- Multi-agent orchestration: fork patterns, coordinator models, sub-agent spawning
- Integration patterns: MCP protocol, hooks system, skill/plugin architecture
- Production concerns: streaming, performance optimization, safety guardrails
Installation & Access
The knowledge base is available at:
git clone https://github.com/lintsinghua/claude-code-book.git
cd claude-code-book
Core Architecture Patterns
1. Conversation Loop (Agent Heartbeat)
The fundamental while(true) async generator pattern that drives all Agent interactions:
async function* conversationLoop(deps: QueryDeps): AsyncGenerator<QueryEvent> {
while (true) {
const context = await buildContext(deps);
const response = await llmClient.chat({
messages: context.messages,
tools: context.availableTools,
max_tokens: context.tokenBudget
});
if (response.type === 'text') {
yield { type: 'text_delta', delta: response.content };
} else if (response.type === 'tool_use') {
const result = await executeToolWithPermission(response.tool, deps);
yield { type: 'tool_result', result };
}
if (shouldTerminate(response)) {
{ : , : response. };
;
}
}
}
Ten termination reasons:
end_turn - Natural completion
max_tokens - Token limit reached
stop_sequence - Stop token encountered
tool_use - Waiting for tool result
content_filter - Safety filter triggered
timeout - Time limit exceeded
user_interrupt - User cancellation
error - Fatal error
rate_limit - API quota exceeded
context_overflow - Context window exhausted
2. Tool System (Agent's Hands)
Tools follow a strict 5-element protocol:
interface Tool<I, O, P extends PermissionLevel> {
schema: z.ZodType<I>;
handler: (input: I, deps: QueryDeps) => Promise<O>;
metadata: {
name: string;
description: string;
parameters: JSONSchema;
};
properties: {
readOnly: boolean;
destructive: boolean;
concurrencySafe: boolean;
};
permission: P;
}
const readFileTool = buildTool({
schema: z.object({
path: z.string(),
encoding: z.([, ]).()
}),
: ,
: {
: ,
: ,
:
},
: ({ path, encoding }, deps) => {
absPath = deps..(path);
(!deps..(absPath)) {
(, { path });
}
deps..(absPath, encoding);
}
});
Concurrent execution algorithm (partition-greedy):
async function executeConcurrently(tools: ToolCall[]): Promise<ToolResult[]> {
const [readOnly, sideEffecting] = partition(
tools,
t => t.properties.readOnly && t.properties.concurrencySafe
);
const readOnlyResults = await Promise.all(
readOnly.map(t => t.handler(t.input, deps))
);
const sideEffectingResults = [];
for (const tool of sideEffecting) {
sideEffectingResults.push(await tool.handler(tool.input, deps));
}
return [...readOnlyResults, ...sideEffectingResults];
}
3. Permission Pipeline (4-Stage Guardrails)
type PermissionStage =
| 'classification'
| 'validation'
| 'authorization'
| 'execution';
async function permissionPipeline(
toolCall: ToolCall,
mode: PermissionMode
): Promise<ToolResult> {
const classification = await Promise.race([
classifyRisk(toolCall),
timeout(2000, { risk: 'unknown' })
]);
const validated = await validateToolCall(toolCall, {
schema: toolCall.tool.schema,
bashRules: mode === 'safe' ? SAFE_BASH_RULES : null,
pathRestrictions: deps.workspace.boundaries
});
if (requiresConsent(toolCall, mode, classification)) {
consent = deps..({
: toolCall..,
: toolCall.,
: classification.,
: classification.
});
(!consent.) {
(consent.);
}
}
toolCall..(validated., deps);
}
=
|
|
|
|
| ;
= {
: [, , , , , ],
: [
,
,
,
],
:
};
4. Context Management (Token Budget)
Effective window calculation and 4-level compression:
interface ContextWindow {
total: number;
systemPrompt: number;
toolDefinitions: number;
reserved: number;
effective: number;
}
function calculateEffectiveWindow(deps: QueryDeps): ContextWindow {
const total = deps.model.contextLimit;
const systemPrompt = estimateTokens(deps.systemPrompt);
const toolDefinitions = deps.tools.length * 50;
const reserved = 4_000;
return {
total,
systemPrompt,
toolDefinitions,
reserved,
effective: total - systemPrompt - toolDefinitions - reserved
};
}
async function compressContext(
messages: Message[],
targetTokens: number
): <[]> {
compressed = messages;
currentTokens = (compressed);
(currentTokens > targetTokens) {
compressed = (compressed, { : });
currentTokens = (compressed);
}
(currentTokens > targetTokens) {
compressed = (compressed);
currentTokens = (compressed);
}
(currentTokens > targetTokens) {
compressed = (compressed, {
: ,
:
});
currentTokens = (compressed);
}
(currentTokens > targetTokens) {
compressed = (compressed, {
: ,
:
});
}
compressed;
}
{
failureCount = ;
lastReset = .();
attempt<T>(: <T>): <T> {
(. >= ) {
(.() - . < ) {
();
}
.();
}
{
result = ();
.();
result;
} (error) {
.++;
error;
}
}
() {
. = ;
. = .();
}
}
5. Memory System (Long-term Memory)
Four closed-type memory categories:
type MemoryType =
| 'code_patterns'
| 'user_preferences'
| 'project_context'
| 'task_progress';
interface Memory {
type: MemoryType;
key: string;
content: string;
metadata: {
created: string;
accessed: string;
confidence: number;
};
}
async function shouldStore(content: string, deps: QueryDeps): Promise<boolean> {
const derivable = [
() => deps.workspace..(content),
.(content),
(content)
];
!derivable.( ());
}
(): <> {
childDeps = {
...parentDeps,
: {
: (parentDeps..),
: parentDeps...(
[, ].(m.)
),
: {}
}
};
(childDeps);
}
6. Hook System (Lifecycle Extension)
26 lifecycle events across 5 categories:
type HookCategory =
| 'lifecycle'
| 'tool'
| 'content'
| 'system'
| 'agent';
interface Hook {
event: string;
handler: string;
config?: {
priority: number;
async: boolean;
timeout: number;
};
}
interface HookResponse {
allow?: boolean;
modify?: {
input?: unknown;
output?: unknown;
};
metadata?: Record<string, unknown>;
}
(): <> {
(event. === ) {
fs.(
,
.({
: ().(),
: event...,
: event..,
: process..
}) +
);
}
{ : };
}
7. Sub-Agent Fork Pattern
Byte-level context inheritance with recursive protection:
type AgentSource =
| 'builtin'
| 'skill'
| 'fork';
async function forkCurrentAgent(
purpose: string,
deps: QueryDeps
): Promise<Agent> {
if (deps.forkDepth >= 3) {
throw new Error('Max fork depth exceeded (prevents infinite recursion)');
}
const childAgent = new Agent({
...deps,
forkDepth: deps.forkDepth + 1,
context: {
messages: structuredClone(deps.context.messages),
tokenBudget: deps.context.tokenBudget * 0.8
},
memory: forkMemory(deps., [, ]),
: ,
: deps.,
: deps.
});
childAgent;
}
= {
: {
: ,
: [, , ],
: [, ]
},
: {
: ,
: [],
: []
},
: {
: ,
: [, , , ],
: []
},
: {
: ,
: [, , ],
: []
}
};
8. MCP Integration (External Protocol Bridge)
Model Context Protocol for external tool/resource integration:
type MCPTransport =
| 'stdio'
| 'http'
| 'websocket'
| 'grpc'
| 'ipc'
| 'tcp'
| 'udp'
| 'sse';
type MCPConnectionState =
| 'disconnected'
| 'connecting'
| 'connected'
| 'error'
| 'reconnecting';
class MCPConnection {
state: MCPConnectionState = 'disconnected';
retryCount = 0;
maxRetries = 3;
async connect(config: MCPServerConfig) {
this.state = 'connecting';
try {
const transport = createTransport(config.transport);
await transport.initialize();
serverInfo = transport.({
: ,
: {
: { : , : },
: [, , ]
}
});
. = ;
serverInfo;
} (error) {
. = ;
(. < .) {
.++;
. = ;
( * .);
.(config);
}
error;
}
}
}
mcpTool = {
: ,
: (input, deps) => {
connection = deps..();
connection.(, input);
}
};
{
() {
conn = ..(server);
conn.({
: ,
: { : tool, : input }
});
}
() {
(notification. === ) {
.(notification..);
}
}
}
Practical Patterns
Building a Custom Tool
import { buildTool } from './tool-factory';
import { z } from 'zod';
const createJiraIssueTool = buildTool({
schema: z.object({
project: z.string(),
summary: z.string(),
description: z.string(),
issueType: z.enum(['Bug', 'Task', 'Story']).default('Task'),
priority: z.enum(['Low', 'Medium', 'High']).default('Medium')
}),
permission: 'write',
properties: {
readOnly: false,
destructive: false,
concurrencySafe: true
},
handler: async (input, deps) => {
const jiraClient = new JiraClient({
host: process..,
: {
: process..,
: process..
}
});
{
issue = jiraClient..({
: {
: { : input. },
: input.,
: input.,
: { : input. },
: { : input. }
}
});
{
: ,
: issue.,
:
};
} (error) {
(, {
: error.,
: error.
});
}
}
});
Implementing a Permission Strategy
class RBACPermissionStrategy implements PermissionStrategy {
private userRole: 'developer' | 'senior' | 'admin';
constructor(role: string) {
this.userRole = role as any;
}
async authorize(toolCall: ToolCall): Promise<AuthResult> {
const permissions = {
developer: {
allowed: ['read_file', 'search', 'run_tests'],
denied: ['execute_bash', 'write_file', 'git_push']
},
senior: {
allowed: ['read_file', 'write_file', 'execute_bash', 'git_commit'],
denied: ['git_push', 'delete_file', 'modify_settings']
},
admin: {
allowed: ['*'],
denied: []
}
};
const config = permissions[.];
(config..(toolCall..)) {
{ : , : };
}
(config..() || config..(toolCall..)) {
(toolCall...) {
{
: ,
: . !==
};
}
{ : };
}
{ : , : };
}
}
Context Compression Strategy
class AggressiveCompressionStrategy {
async compress(messages: Message[], targetTokens: number): Promise<Message[]> {
let result = messages;
const steps = [
{ name: 'Remove images', fn: this.removeAllImages },
{ name: 'Summarize tool outputs', fn: this.summarizeToolOutputs },
{ name: 'Collapse redundant exchanges', fn: this.collapseRedundant },
{ name: 'Semantic compression', fn: this.semanticCompress }
];
for (const step of steps) {
const currentTokens = estimateTokens(result);
if (currentTokens <= targetTokens) {
break;
}
console.log(`Compression step: ${step.name} (${currentTokens} → target ${targetTokens})`);
result = await step.(result, targetTokens);
}
result;
}
(
: [],
:
): <[]> {
summary = llmClient.({
: [
{
: ,
:
}
]
});
[
{
: ,
:
},
...messages.(-)
];
}
}
Configuration
Setting Up Agent Harness
{
"version": "1.0",
"agent": {
"model": "claude-3-5-sonnet-20241022",
"contextWindow": 200000,
"permissionMode": "normal",
"features": {
"toolCalling": true,
"memorySystem": true,
"subAgents": true,
"mcpIntegration": true
}
},
"tools": {
"enabled": [
"read_file",
"write_file",
"execute_bash",
"ripgrep_search",
"git_*"
],
"disabled": [
"delete_file"
],
"concurrency": {
"maxParallel": 5,
"partitionStrategy": "read-write-split"
}
},
"context": {
"compression": {
"strategy": "progressive",
"levels": ["snip", "micro-compact", "collapse", "auto-compact"],
"targetUtilization": 0.9
}
},
: {
: ,
: ,
: {
: ,
:
}
},
: {
: ,
: ,
:
},
: {
: {
: {
: ,
: ,
: {
: ,
:
}
},
: {
: ,
: ,
: [, ],
: {
:
}
}
}
}
}
Feature Flags (89 total)
const FEATURE_FLAGS = {
'agent.tool_calling': true,
'agent.sub_agents': true,
'agent.memory_system': true,
'safety.permission_pipeline': true,
'safety.bash_validation': true,
'safety.path_restrictions': true,
'perf.lazy_tool_loading': true,