Building with Claude

Building with Claude

01

The API in plain terms

Every call to Claude goes through the same structure: a messages array plus an optional system prompt. The messages array is ordered chronologically: user turn, assistant turn, user turn, and so on. Each call re-sends the full conversation history — there is no server-side session state between API calls. The model has no memory of prior calls except what you explicitly include in the messages array.

Message roles

user — the human's input. Can contain text, images (as base64 or URL), and tool results. This is the primary channel for giving Claude information and instructions.

assistant — Claude's prior responses. In a multi-turn conversation, every Claude response gets appended to messages as an assistant turn before the next user message. This is what creates the illusion of conversation memory: the assistant's prior responses are in the context window, not in a separate memory store.

system — the system prompt. Passed as a top-level parameter (not inside messages) in the Anthropic API. Functions as standing instructions that apply across all turns: the model's persona, domain restrictions, output format requirements, and context about the application.

Key request parameters

model — the model ID string, e.g. claude-sonnet-5. Use the API docs for current IDs; they change with each release.

max_tokens — upper bound on output tokens. Required. If Claude's natural completion would exceed this, the response is truncated mid-sentence. Set it high enough for your expected output; you only pay for tokens actually generated.

temperature — controls output randomness. Range 0–1. Zero for deterministic, factual, or code generation tasks. Higher for creative tasks where variety is desirable. Default is often 1.0 but task-specific defaults vary.

stream — whether to stream tokens as they're generated. Streaming reduces perceived latency for interactive applications. For batch processing where latency doesn't matter, non-streaming is simpler.

Note
The Anthropic API uses a different messages format than OpenAI's — the system prompt is a top-level parameter, not a message with role "system." If you're migrating from OpenAI or using a multi-model router, this is the most common compatibility issue. The Anthropic SDK handles it for you if you use it directly.
02

System prompts

The system prompt is the application layer's standing instruction to the model. It's the first thing Claude reads in every conversation turn, and it establishes the frame within which all subsequent user messages are interpreted. Well-written system prompts are the single highest-leverage place to improve Claude's behavior across an application.

What system prompts control

Character and persona. "You are a customer support agent for Acme Corp" establishes the voice, domain, and assumed context. The model will answer in-role consistently across all user turns unless explicitly asked to break frame.

Constraints and scope. "Answer questions only about cooking. For all other topics, say you can't help with that." Domain restrictions, output format requirements (always respond as JSON, use markdown headers), and behavioral guardrails all go here.

Context injection. Background information the model needs across all turns — the user's account details, the state of the application, available actions, relevant docs — can be embedded in the system prompt or in a user message at the start of the conversation.

Tool definitions. When you pass tools (see next section), Claude uses the system prompt's context to decide when and how to call them. Explaining what the tools are for in the system prompt significantly improves tool selection accuracy.

Writing effective system prompts

Be specific, not vague. "Be helpful" adds nothing — Claude is already trained to be helpful. "When the user asks about pricing, always quote from the pricing table provided below, not from your training data" adds real constraint.

Put the most critical instructions at the top and near the end. The lost-in-the-middle effect applies here: a critical constraint buried in paragraph 12 of a long system prompt receives less attention weight than the same constraint placed prominently.

Use XML tags for structure when passing multiple sections. Claude was trained heavily on XML-structured text and reliably parses tag boundaries: <context>, <instructions>, <tools> are all conventional and work well.

03

Tool use

Tool use (also called function calling) is how Claude interacts with the world outside its context window. You define a set of functions the model can call; when the model decides a tool call is appropriate, it generates a structured tool call response instead of regular text. Your application executes the function and returns the result; the model then uses that result to continue.

Defining a tool

Tools are defined as JSON Schema objects with a name, description, and input schema. The description is the most important field — it's what the model reads to decide when to call the tool. A precise, accurate description prevents both over-calling (using the tool when it's not needed) and under-calling (failing to use it when it is).

Example: a get_weather tool with a description "Get the current weather for a given city and date. Use this when the user asks about weather conditions in a specific location" will be called when someone asks about weather and not called when they ask about restaurants — the description tells Claude the precondition.

The tool use loop

1. You send a request with the tools array and the user message.

2. If Claude decides to call a tool, it returns a response with stop_reason: "tool_use" and a tool_use block containing the tool name and input arguments.

3. Your application executes the function with the provided arguments and captures the result.

4. You append both the assistant's tool call and a user-role tool_result message to the conversation and call the API again.

5. Claude reads the tool result in context and either calls another tool or generates the final text response.

Parallel tool calls

Claude can call multiple tools in a single response when the calls are independent. A research agent might simultaneously call search_web, read_file, and query_database when the results don't depend on each other. Your application executes them in parallel and returns all results together. This is a significant latency optimization for multi-tool agents.

Note
Tool input validation is your responsibility. Claude generates the arguments, but it may produce arguments that fail your schema validation or produce unexpected results when executed. Always validate tool inputs before execution, handle errors gracefully, and return an informative error message in the tool_result so Claude can try a different approach.
04

Model Context Protocol

The Model Context Protocol (MCP) is an open standard that Anthropic released in November 2024 and that has since been adopted by OpenAI, Google, and most major AI tooling providers. It solves the tool integration problem at the ecosystem level: instead of every application building custom tool definitions for every data source, MCP defines a standard client-server protocol that any tool provider can implement once.

How it works

An MCP server is a process that exposes tools (callable functions), resources (data that can be fetched), and prompts (template fragments) over a standard JSON-RPC protocol. You can run an MCP server locally (stdio transport) or remotely (HTTP/SSE transport).

An MCP client is the host application — Claude Code, a custom API client, or an IDE extension — that connects to MCP servers and makes their tools available to the model. The client handles discovery: it asks each server what tools it exposes, then includes those tool definitions in the model's context.

From Claude's perspective, MCP tools look identical to regular API tools — they arrive as tool definitions in the request. The difference is in how they were generated: the client discovered them dynamically from running servers rather than hard-coding them.

What MCP enables in practice

Pre-built connectors. Hundreds of MCP servers already exist for common services: GitHub, Linear, Notion, Slack, Google Drive, Postgres, Stripe. You configure them in your Claude Code settings or custom client — no custom integration code required.

Custom servers. Building an MCP server for your own API is straightforward using the TypeScript or Python SDKs. Define your tools using the same JSON Schema format as the API; the SDK handles the transport layer.

Resources and prompts. Beyond callable tools, MCP servers can expose resources — chunks of data that the model or application can fetch on demand — and prompt templates that users can invoke by name. Resources are well-suited for large documents or dataset access that would be too large to include in every context window.

05

Prompt caching

Prompt caching is the single highest-leverage performance optimization available for Claude API applications with long system prompts or repeated context. Anthropic caches the computed KV state of your prompt prefix so that subsequent calls with the same prefix skip recomputation and pay a fraction of the normal input token cost.

The economics

Cache reads cost 10% of the normal input token price. A 100K-token system prompt (large docs, code base context, tool definitions) that would normally cost $0.30 per request costs $0.03 per request on a cache hit. For an application making 1,000 calls per day with this context, that's $270/day vs $27/day — a direct 90% cost reduction on the cached portion.

Cache writes cost 25% more than normal — the first call that populates the cache is slightly more expensive. The cache TTL is 5 minutes; any call within 5 minutes of the last hit refreshes the TTL. Applications that call the API frequently (agentic loops, chat interfaces) maintain a warm cache easily. Long gaps between calls may cause cache misses.

How to use it

Add cache_control: { type: 'ephemeral' } to any content block to mark it as a cache breakpoint. The API caches everything up to and including that block. You can set up to 4 cache breakpoints per request.

The critical rule: everything before the cache breakpoint must be identical across requests for the cache to hit. This means your static context — system prompt, tool definitions, large reference documents — should come first in the prompt, before anything that changes per request (the user's message, the current conversation history). Structure your prompts with stable content first, dynamic content last.

What to cache

Large system prompts. If your system prompt exceeds a few thousand tokens — detailed instructions, persona, embedded documentation — cache it. It's static; it should always be cached.

Reference documents. Code files, product specs, long documents you want the model to reason over. Cache them once; pay 10% per request after the first.

Tool definitions. If you're passing 20+ tool definitions, their total token count is significant. Cache them before the dynamic conversation history.

Note
Claude Code uses prompt caching internally for its project memory — the CLAUDE.md file and prior conversation context are cached so that long sessions don't pay full input token cost for the growing conversation history on every message. This is why Claude Code sessions with long histories don't cost exponentially more as they grow.
01The API in plain terms1/5
Sections18 min