Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Claude Code Tool Calling Architecture Analysis

This analysis examines the tool calling mechanism in Claude Code, emphasizing its focus on type safety, token efficiency, and hierarchical steering.

1. Tool Definitions

Claim: Tools are defined using a strict Tool interface that enforces a Zod-based input schema, a call method for execution, and metadata for discovery and UI rendering.

Path: ai_agents/research/ai_coding_agents/claude-code-main/src/Tool.ts

Snippet:

export type Tool<
  Input extends AnyObject = AnyObject,
  Output = unknown,
  P extends ToolProgressData = ToolProgressData,
> = {
  // ... (metadata fields)
  call(
    args: z.infer<Input>,
    context: ToolUseContext,
    canUseTool: CanUseToolFn,
    parentMessage: AssistantMessage,
    onProgress?: ToolCallProgress<P>,
  ): Promise<ToolResult<Output>>
  description(
    input: z.infer<Input>,
    options: {
      isNonInteractiveSession: boolean
      toolPermissionContext: ToolPermissionContext
      tools: Tools
    },
  ): Promise<string>
  readonly inputSchema: Input
  // ... (rendering and validation methods)
}

Claim: Individual tools (e.g., BashTool) implement this interface by defining a specific inputSchema and a call handler that interacts with the system shell.

Path: ai_agents/research/ai_coding_agents/claude-code-main/src/tools/BashTool/BashTool.tsx

Snippet:

const fullInputSchema = lazySchema(() => z.strictObject({
  command: z.string().describe('The command to execute'),
  timeout: semanticNumber(z.number().optional()).describe(`Optional timeout in milliseconds (max ${getMaxTimeoutMs()})`),
  description: z.string().optional().describe(`Clear, concise description of what this command does...`),
  run_in_background: semanticBoolean(z.boolean().optional()).describe(`Set to true to run this command in the background...`),
  dangerouslyDisableSandbox: semanticBoolean(z.boolean().optional()).describe('Set this to true to dangerously override sandbox mode...'),
  _simulatedSedEdit: z.object({
    filePath: z.string(),
    newContent: z.string()
  }).optional().describe('Internal: pre-computed sed edit result from preview')
}));

2. LLM Integration and Deferred Loading

Claim: Tools are converted from Zod schemas to JSON schemas compatible with the Anthropic API, with support for “deferred loading” to manage prompt token budgets.

Path: ai_agents/research/ai_coding_agents/claude-code-main/src/utils/api.ts

Snippet:

export async function toolToAPISchema(
  tool: Tool,
  options: {
    // ...
    deferLoading?: boolean
    // ...
  },
): Promise<BetaToolUnion> {
  // ...
  const base = {
    name: tool.name,
    description: await tool.prompt({ /* ... */ }),
    input_schema,
  }
  // ...
  const schema: BetaToolWithExtras = { ...base }
  if (options.deferLoading) {
    schema.defer_loading = true
  }
  return schema as BetaTool
}

Explanation: By marking tools as defer_loading: true, the agent avoids flooding the system prompt with every possible tool schema. The model must first use a ToolSearch tool to “discover” and load the specific schema it needs.

Path: ai_agents/research/ai_coding_agents/claude-code-main/src/services/api/claude.ts

Snippet:

function shouldDeferLspTool(tool: Tool): boolean {
  if (!('isLsp' in tool) || !tool.isLsp) {
    return false
  }
  const status = getInitializationStatus()
  return status.status === 'pending' || status.status === 'not-started'
}

// ... inside queryModel
const willDefer = (t: Tool) =>
  useToolSearch && (deferredToolNames.has(t.name) || shouldDeferLspTool(t))

3. Tool Invocation Pipeline

Claim: Tool execution follows a strict validation pipeline: Zod type parsing →\rightarrow semantic validation →\rightarrow permission checking →\rightarrow execution.

Path: ai_agents/research/ai_coding_agents/claude-code-main/src/services/tools/toolExecution.ts

Snippet:

async function checkPermissionsAndCallTool(...) {
  // 1. Zod parse
  const parsedInput = tool.inputSchema.safeParse(input)
  if (!parsedInput.success) {
    // return InputValidationError
  }

  // 2. Semantic validation
  const isValidCall = await tool.validateInput?.(
    parsedInput.data,
    toolUseContext,
  )
  if (isValidCall?.result === false) {
    // return validation error
  }

  // 3. Permission check (delegated to canUseTool/permission system)
  // ... logic calling checkPermissions() and potentially prompting the user
}

4. The Three-Tier Steering Model

Claude Code employs a hierarchical steering architecture that separates global behavioral guardrails, tool-specific operational constraints, and project-level domain conventions.

Tier 1: Tool-Level Steering (Semantic)

Claude Code uses Distributed Steering, where each tool is paired with a dedicated prompt.ts file to define imperative constraints.

Tier 2: Operational Steering (Modality)

Operational steering is managed through a modular system prompt assembly pipeline.

Tier 3: Contextual Steering (Conventions)

Claude Code uses a layered discovery mechanism to inject project-specific rules without bloating the global prompt.