ai newsDo., 5. Nov.
EilmeldungI ran a pre-launch audit on a deliberately broken vibe-coded app. Here are 10 findings and the prompt that fixes each one

Claude Code vs Direct Anthropic API in 2026: When to Use the SDK and When the Raw API Gives You More Control

Claude Code vs Direct Anthropic API in 2026: When to Use the SDK and When the Raw API Gives You More Control This article was written with the assistance of AI, under human supervision and review. Correction (2026-10-28): the code sample pinned claude-3-7-sonnet-20250219 , which Anthropic retired o

dev.toMittwoch 22:37 · 04.11.12 Min. Lesezeit
Bild: dev.to

Posted on Nov 4 • Originally published at jsmanifest.com

This article was written with the assistance of AI, under human supervision and review.

Correction (2026-10-28): the code sample pinned claude-3-7-sonnet-20250219, which Anthropic retired on February 19, 2026; the sample now uses the current claude-sonnet-5-5 ID, checked against the official model deprecations page.

Most teams building with Claude in 2026 face the same choice: use the Claude Agent SDK for its batteries-included tooling or call the raw Anthropic API for maximum control. The SDK abstracts away message formatting, tool execution loops, and file operations. The raw API exposes every token, every state transition, and every budget decision. Teams that pick the wrong layer end up rewriting their integration six months later.

The failure mode is subtle. The SDK hides complexity that matters when you scale to production traffic. A workflow that runs clean in development hits token limits at runtime because the SDK batches file reads into messages you cannot inspect. A custom agent that needs precise prompt caching cannot tune the SDK's built-in tool schema. The raw API requires more upfront code but gives you the knobs that production engineering demands.

The solution is to map your workload against a decision framework. If you are building an agentic assistant that runs git commands and edits code, the SDK pays for itself immediately. If you are building a high-volume API that needs token-level observability and custom prompt caching, the raw HTTP client is the only path that scales.

This post walks through both layers, shows the code patterns for each, and gives you the decision table that determines which approach fits your production constraints.

The Claude Agent SDK ships with a tool registry that handles file reads, shell execution, and code editing without custom implementations. Developers initialize a client, register the built-in tools, and start a conversation loop that automatically formats messages and executes tool calls. The SDK manages the request-response cycle, parses tool invocations from Claude's output, runs them in the local environment, and sends results back as the next user message.

The file operations tool reads and writes files relative to a workspace root. The command execution tool runs shell commands with configurable environment variables and timeout limits. The code editing tool applies diffs to existing files using a line-based format that Claude generates. These tools cover the common cases for developer-assistant workflows without custom code.

The SDK handles message history automatically. Each turn appends to an internal array that it sends with the next request. Developers do not construct messages arrays or manage conversation state manually. The SDK also handles tool results by formatting them into system messages that Claude expects in the next turn.

The trade-off here is opacity. The SDK decides when to batch multiple file reads into a single message. It controls how tool results get formatted and which metadata gets included. Developers cannot inspect the exact token count before sending a request because the SDK constructs the final payload internally. For prototypes and demos this abstraction saves time. For production systems that need token budget guarantees or custom caching strategies, this opacity becomes a constraint.

The raw Anthropic API accepts HTTP POST requests with a messages array, optional system prompt, model identifier, and configuration parameters like max tokens and temperature. Developers construct the entire request payload as JSON. Claude returns a response object with the generated text, stop reason, and token usage counts. Tool use requires an additional request-response cycle where developers parse tool invocations from the assistant message, execute them in application code, and send the results back as a new user message.

Every message object includes a role and content field. Content can be a string or an array of content blocks for mixed text and image inputs. Tool results go in user messages with a tool_result content type that references the tool call ID from the previous assistant message. Developers control the exact structure and order of every message.

Prompt caching happens at explicit boundaries developers mark in the message history. The API accepts a cache_control parameter on system messages and specific user messages. Anthropic caches the prefix up to that point and reuses it across requests that share the same prefix. The raw API exposes this mechanism directly. Developers decide which conversation turns to cache and when to invalidate the cache by changing the prefix. The SDK does not expose cache control.

Token budgets become explicit with the raw API. The max_tokens parameter sets the generation limit. The response includes prompt_tokens, completion_tokens, and cache hit statistics. Applications can track cumulative usage across requests and enforce hard limits before making calls. The SDK hides these counts until after the request completes, making preemptive budget checks impossible.

Custom tool schemas go directly in the tools array. Developers define input parameters, types, and descriptions as JSON Schema objects. Claude invokes tools by generating a tool_use block in its response. The application code matches the tool name, extracts parameters, runs the logic, and sends the output back in the next user message. This manual loop gives complete control over execution policy, error handling, and result formatting.

This example shows a simple workflow: read a configuration file, run a shell command to check installed packages, and return results. The SDK version uses built-in tools. The raw API version implements the same logic with explicit message construction and tool execution.

import { ClaudeAgentSDK } from ' @anthropic-ai/agent-sdk '; const agent = new ClaudeAgentSDK ({ apiKey: process. env. ANTHROPIC_API_KEY, workspaceRoot: process. cwd (), }); agent. registerBuiltInTools ([ ' file_read ', ' command_execute ' ]); const response = await agent. chat ( ' Read package.json and run npm list to check installed dependencies ' ); console. log ( response. text ); Enter fullscreen mode Exit fullscreen mode The SDK handles tool registration, message formatting, and the execution loop. Developers do not see the tool schema or the intermediate messages. The abstraction works when the built-in tools match the task requirements and opacity is acceptable.

import Anthropic from ' @anthropic-ai/sdk '; import { readFileSync } from ' fs '; import { execSync } from ' child_process '; const client = new Anthropic ({ apiKey: process. env. ANTHROPIC_API_KEY, }); const tools = [ { name: ' read_file ', description: ' Read a file from the workspace ', input_schema: { type: ' object ', properties: { path: { type: ' string ', description: ' File path relative to workspace ' }, }, required: [ ' path ' ], }, }, { name: ' run_command ', description: ' Execute a shell command ', input_schema: { type: ' object ', properties: { command: { type: ' string ', description: ' Shell command to run ' }, }, required: [ ' command ' ], }, }, ]; const messages: Anthropic. MessageParam [] = [ { role: ' user ', content: ' Read package.json and run npm list to check installed dependencies ', }, ]; let continueLoop = true; while ( continueLoop ) { const response = await client. messages. create ({ model: ' claude-sonnet-5-5 ', max_tokens: 4096, tools, messages, }); console. log ( `Tokens used: ${ response. usage. input_tokens } in, ${ response. usage. output_tokens } out` ); if ( response. stop_reason === ' end_turn ' ) { console. log ( response. content [ 0 ]. type === ' text '? response. content [ 0 ]. text: '' ); continueLoop = false; } else if ( response. stop_reason === ' tool_use ' ) { messages. push ({ role: ' assistant ', content: response. content }); const toolResults = response. content. filter (( block ): block is Anthropic.

ToolUseBlock => block. type === ' tool_use ' ). map (( toolUse ) => { let result: string; if ( toolUse. name === ' read_file ' ) { const { path } = toolUse. input as { path: string }; result = readFileSync ( path, ' utf-8 ' ); } else if ( toolUse. name === ' run_command ' ) { const { command } = toolUse. input as { command: string }; result = execSync ( command, { encoding: ' utf-8 ' }); } else { result = ' Unknown tool '; } return { type: ' tool_result ' as const, tool_use_id: toolUse. id, content: result, }; }); messages. push ({ role: ' user ', content: toolResults }); } } Enter fullscreen mode Exit fullscreen mode The raw API version defines tool schemas explicitly, constructs messages manually, and implements the tool execution loop in application code. It logs token counts after each turn and gives complete visibility into the request-response cycle. The code is longer but every decision is explicit.

The token count logging in the raw version shows exactly when budget constraints appear. The SDK hides these counts until the workflow completes. For applications that enforce per-request or per-user token limits, this visibility difference is critical.

The SDK pays off for developer-assistant use cases where the built-in tools match the task domain. A code review agent that reads source files, runs linters, and suggests fixes benefits from the file operations and command execution tools without custom implementations. A documentation generator that scans a codebase and writes markdown files uses the same tools with minimal setup.

Agentic workflows that need multi-turn interactions without strict token budgets fit the SDK abstraction. The automatic message history management removes boilerplate. Developers write high-level task descriptions and let the SDK handle the tool invocation loop. Prototypes and internal tools ship faster because the SDK handles the common cases.

The SDK also works when the application does not need custom tool schemas or fine-grained control over message construction. Teams that want to integrate Claude quickly and do not have production-scale requirements can skip the raw API complexity. The trade-off is accepting the abstraction boundaries the SDK defines.

Teams using the SDK should monitor token usage in development to ensure the hidden batching behavior does not create surprises in production. The SDK does not expose token counts before requests, so tracking usage requires logging response objects and correlating them with tasks. Applications that hit unexpected token limits often discover the SDK batched multiple operations into a single large message.

High-volume APIs that serve Claude responses to end users need token-level observability and budget enforcement before making requests. The raw API exposes token counts in every response and allows applications to estimate costs before calling the model. Production systems that enforce per-user quotas or per-request cost limits cannot rely on the SDK's post-request usage reporting.

Custom prompt caching strategies require the raw API. Applications that reuse long system prompts or conversation prefixes across many requests benefit from caching the shared prefix. The cache_control parameter marks cache boundaries explicitly. The SDK does not expose this mechanism, so applications that need caching must use the raw API.

Integrations with existing state management systems work better with the raw API. Applications that store conversation history in databases or distributed caches need to construct messages from stored data. The SDK's internal message history does not sync with external storage. The raw API lets developers build messages from any source and send them without SDK mediation.

Custom tool implementations that need specific error handling, retry logic, or integration with proprietary systems require raw API tool execution. The SDK's built-in tools run in a sandboxed environment with fixed behavior. Applications that need to validate tool inputs against business rules, log tool executions to audit systems, or integrate with internal APIs must implement tools manually and use the raw API's tool loop.

Applications that need to inspect intermediate messages for debugging or compliance purposes benefit from the raw API's explicit message construction. Every message goes through application code where developers can log, validate, or transform content. The SDK hides intermediate messages, making it hard to debug unexpected behavior or verify that sensitive data does not leak into requests.

The decision comes down to control versus convenience. The SDK trades control for faster development. The raw API trades convenience for production-grade observability and flexibility. Teams should choose based on their specific constraints, not abstract preferences.

Applications that start with the SDK and later hit scale or customization limits face a rewrite. Moving from SDK to raw API requires reimplementing the tool execution loop, message construction logic, and state management. The migration cost is high because the SDK's abstractions do not map cleanly to raw API patterns. Teams should evaluate their long-term requirements before committing to the SDK path.

No. The SDK does not expose the cache_control parameter that marks cache boundaries in the raw API. Applications that need prompt caching must use the raw Anthropic API and manage message construction manually.

The SDK catches exceptions from built-in tools and formats them as error messages sent back to Claude in the next turn. Developers can register error handlers for custom behavior, but the default retry logic is fixed. The raw API gives complete control over error handling and retry policies.

Yes, but the SDK maintains internal state that does not sync with raw API calls. If you use the SDK for some workflows and the raw API for others, treat them as separate integration paths with no shared state. Trying to share conversation history between the two layers creates inconsistencies.

You cannot. The SDK constructs messages internally and does not expose token counts before sending the request. Applications that need preemptive budget checks must use the raw API and implement token estimation logic before calling the model.

Yes. The raw API supports server-sent events for streaming responses, allowing applications to process tokens as Claude generates them. The SDK does not expose streaming in the current version. Applications that need real-time output must use the raw API with stream handling logic.

The Claude Agent SDK and raw Anthropic API serve different production constraints. The SDK ships workflows faster when built-in tools match the task and opacity is acceptable. The raw API gives control when token budgets, custom caching, or production-scale observability matter more than development speed.

Teams that ignore this trade-off end up rewriting integrations after discovering the SDK hides critical control points. Applications that need token-level visibility, custom prompt caching, or tight budget enforcement should start with the raw API from day one. Prototypes and internal tools benefit from the SDK's abstractions when scale is not a factor.

That covers the essential patterns for choosing between the Claude Agent SDK and raw Anthropic API. Apply this decision framework in your next integration and the token budget surprises will disappear.

Quelle: dev.to (dev.to). Original öffnen