Dev.to AI 🤖 Ai 👁 0 📖 16 min read

A Study Guide for Building on Claude

The knowledge you need to design on Claude. What this guide covers The Claude Certified Developer – Foundations (CCD-F) exam is scenario-based. You’re the lead engineer on a new project with constraints (late

A Study Guide for Building on Claude

The knowledge you need to design on Claude.

What this guide covers

The Claude Certified Developer – Foundations (CCD-F) exam is scenario-based. You’re the lead engineer on a new project with constraints (latency, volume, budget, compliance, autonomy), and you choose the model, API features and architecture. The right answer is the simplest design that meets every constraint.

Outline

  1. The API and SDKs: the stack, the agent loop, tools and MCP, and settings
  2. Delivery and reliability: streaming, batching, rate limits, errors and retries
  3. Caching and costs: what you pay for, how the cache works, and how to pay less
  4. Prompt engineering: the anatomy of a request, techniques and structured outputs
  5. Context engineering: subagents, compaction, context editing and memory
  6. Agent patterns: from single calls to orchestrators and agents
  7. Evals and safety: measuring quality, versioning prompts, prompt injection, agent permissions, keys and data residency

Module 1: The API and SDKs

Every option below makes the same stateless API call. What changes is how much of the work around it your code does.

The stack

Each layer moves the line between your code and the platform

Each layer moves the line between your code and the platform. The split to remember: with the Client SDK your code runs the loop and the tools. With the Agent SDK, the SDK does.

The agent loop

At any layer, an agent is this loop: call the model, read stop_reason, act on it, call again.

Your code runs the loop, and stop_reason says what happens next

  • Append, never edit. Add the assistant turn exactly as returned, thinking blocks included, then one user message with every tool_result, matched by tool_use_id. To change the rules later, append a mid-conversation system message: editing system, tools or earlier turns misses the cache, and the API can reject the earlier thinking blocks with a 400.
  • Read blocks by type. A reply’s content is a list of blocks (thinking, text, tool_use), and it can start with a thinking block. So content[0].text breaks: loop over content and keep the blocks whose type is "text".
  • Cap the loop with a turn or token limit. The tool runner (beta) runs this loop for you, capped by max_iterations.
  • Run independent tools in parallel. Claude can request several tools in one reply. Run them together and return every tool_result in one user message.
  • Report tool failures, don’t crash. When a tool fails, return its tool_result with is_error: true and a short message. Claude can then retry or try another way.

Tools and MCP

A tool has three parts: a name, a description and an input_schema (JSON Schema). Set strict: true on the tool to guarantee that Claude’s inputs always match that schema, with no missing fields or wrong types.

Claude decides when to call a tool from its description, which the docs call “by far the most important factor in tool performance.”

  • Be detailed. Cover what the tool does, when to use it and when not to, what each parameter means, and its limits.
  • Make tools easy to tell apart. Group related actions into one tool with an action parameter, and prefix names by service, such as github_list_prs.
Kind Who runs it Examples
Client tools Your code: you get tool_use, you return tool_result Your functions, bash, text_editor, memory
Server tools Anthropic: results arrive in the reply web_search, web_fetch, code_execution
MCP tools An MCP server GitHub, databases, Slack

MCP (Model Context Protocol) is an open standard for plugging tool servers into an agent.

Connected from How Limits
Messages API MCP connector (beta) Remote HTTPS servers, tool calls only, you supply the token
Agent SDK mcp_servers or .mcp.json Local, remote or in-process. Allow each tool in allowed_tools

With many tools, tool search loads definitions on demand instead of filling the context. It’s on by default in the Agent SDK.

Extending an agent

Each extension point changes something different: what Claude knows, what it can reach, or what always happens.

Mechanism What it is Use it when
CLAUDE.md Instructions loaded at the start of every session Project rules that always apply
Rules Markdown files in .claude/rules/, loaded like CLAUDE.md, or only when Claude reads files matching their paths Rules for one part of the codebase, such as the API folder
Skill Instructions, scripts and files Claude loads on demand, name and description first A reusable procedure Claude should pick up when it’s relevant
MCP server Tools, resources and prompts exposed through a standard protocol Connecting external systems and data
Hook A script, HTTP endpoint, MCP tool or prompt, run automatically at events like PreToolUse or PostToolUse Steps that must happen at a fixed point, whatever the model decides. For a hard allow or deny, use permission rules
Subagent A separate context with its own prompt and tools Noisy side work kept out of the main context
Plugin A package of skills, subagents, hooks and MCP servers, installed from a marketplace (a CLAUDE.md inside it isn’t loaded) Sharing one setup across teams

Settings: who overrides whom

Claude Code and the Agent SDK read settings from up to five files, so the same key can be set in more than one place. The higher level wins.

A key set at a higher level wins

Module 2: Delivery and reliability

Module 1 covered a single call. In production you also choose how replies arrive, and you plan for limits and failures. Pick the delivery mode by who is waiting.

Pick the delivery mode by who is waiting

Streaming

Streaming returns the reply as server-sent events, so users see text as it is generated. The events always arrive in the same order.

A stream is a fixed sequence of events

The SDK requires streaming when a request may run long. If you only need the final result, use messages.stream() with get_final_message().

Batching

When nobody is waiting, the Batch API runs requests asynchronously at half price.

A batch goes from submit to results within 24 hours

Results can come back in any order. Give each request a unique custom_id and match results on it, never on position.

Rate limits

Limit Counts Good to know
RPM Requests per minute Set per model class
ITPM Input tokens per minute Cache reads don’t count on most models, so caching raises throughput too
OTPM Output tokens per minute Counts tokens generated, not your max_tokens
  • On a 429, wait the seconds in retry-after. A 429 without it means the spend cap is reached, and retrying won’t help.
  • Read the headers. anthropic-ratelimit-* show each limit, what’s left and when it resets.
  • Limits are per organization and refill continuously (a token bucket), not once a minute. Workspaces can have lower limits of their own.
  • Scale gradually. Limits rise with your usage tier, and a sudden spike can hit acceleration limits.

Errors: transient vs. permanent

Retry transient errors, fix permanent ones

  • Back off with jitter. Retry transient errors only.
  • Cap it. Limit both attempts and total time, and set max_retries=0 if you add your own loop.
  • Degrade under load. Log the request-id, and under sustained 529s queue or shed work instead of hammering the API.

Module 3: Caching and costs

You pay per token, and output costs more than input. Prompt caching is the biggest single lever on input cost.

What is billed

What Counts Price
Input tokens Everything you send: system, tools, history, documents The base rate
Output tokens Everything generated, including thinking you never see 5 times the input rate
Cache writes The prefix you mark, the first time More than input, once
Cache reads The same prefix, reused A small fraction of input
Server tools Web search Per search, plus its tokens

Two traps: thinking is billed as output even when hidden, and newer models use a tokenizer that produces up to about 35% more tokens for the same text.

Prompt caching

Mark a cache_control breakpoint, and on the next call everything before it is served from cache.

Everything before the breakpoint is served from cache

  • A hit needs an identical prefix. The API looks back up to 20 blocks from each breakpoint for a match.
  • Short prompts fail silently. Below the minimum (512 tokens on the newest models, 1,024 to 4,096 on older ones) nothing is cached and no error is returned.
  • Automatic mode (a top-level cache_control) moves the breakpoint forward as the conversation grows. It uses one of the 4 slots.
  • A write costs more than no cache, so it pays off only if the prefix is read before it expires. Caching stacks with the batch discount.

What breaks the cache

The prefix runs tools, then system, then messages. A change invalidates its own level and every level after it.

A change invalidates its own level and every level after it

Other levers

Lever What it saves How
Smaller model Every token costs less Route simple, high-volume inputs to a smaller model and keep the larger one for hard cases (Module 6)
Lower effort Thinking tokens, billed as output Defaults differ by model, so set effort yourself and lower it until your evals show a drop
Batch API Half the price of input and output Send anything nobody is waiting for. The discount stacks with caching
Less context Input you resend on every turn Trim history, clear old tool results, hand side work to subagents (Module 5)
Caps A runaway loop or reply max_tokens caps each reply. In the Agent SDK, max_turns and max_budget_usd cap each run

Measuring spend

Field Tells you
Token counting Input tokens, before you send
input_tokens Tokens after the last breakpoint, full price
cache_creation_input_tokens Tokens written to the cache, write price
cache_read_input_tokens Tokens read from the cache, read price
output_tokens Output, thinking included
total_cost_usd Cost of a whole Agent SDK run

Both cache fields at 0 on a repeated call means the prefix changed or is under the minimum.

Module 4: Prompt engineering

Write the prompt as a spec for a contractor who has never seen your codebase. If a colleague with no context would be confused, Claude will be too.

Anatomy of a request

A request has four places to put instructions, and each technique below has a natural home in one of them.

Where each technique goes in a request

Techniques

Technique Do Avoid
Clear and direct Say what done looks like and why each rule exists. Ask for the action: “Change this function to…” “Format the code properly”, “Can you suggest changes to…”
Positive, calm wording “Write in flowing prose”, “Use this tool when…”. Write the prompt in the style you want back “Don’t use markdown”, “CRITICAL: you MUST…”
Scope Say how far to go: “Go beyond the basics” or “Keep changes minimal” An open-ended “improve this”
Role and examples One-sentence role in system. 3 to 5 varied examples in <example> tags Near-identical examples Claude copies
Structure Consistent XML tags. Documents at the top, question at the end, quotes first Data and instructions mixed, the question above long input
Reasoning Raise effort and ask in general terms (“think it through”). If it overthinks: “Choose an approach and commit to it” A hand-written step-by-step plan
Grounding “Never speculate about code you have not opened.” “Before you finish, verify against…” Answers about files it hasn’t read
Tools and steps Tool descriptions say what, when and when not, and each parameter. Separate calls when you must check each step (Module 6) One-line descriptions, one giant prompt for a multi-stage task

Putting the question last can improve answers by up to 30% on long, multi-document inputs (Anthropic’s tests).

Structured outputs

Setting What it guarantees
output_config.format with a JSON schema The reply always parses against the schema
strict: true on a tool Tool inputs always match the tool’s schema
additionalProperties: false Required on every object in a strict schema

Still validate before passing output downstream: a refusal or a max_tokens cutoff can leave output that doesn’t match the schema.

Don’t ask the model to write out its reasoning, in a field or in <thinking> tags: it can be declined with a reasoning_extraction refusal. Raise effort instead.

Module 5: Context engineering

Prompt engineering is what you say. Context engineering is what the model sees at each step. The window is limited working memory: every token costs on every turn, and quality drops as it fills.

The toolkit

Technique What it does
Subagent Does noisy work in its own context and returns a summary
Compaction Replaces old history with a summary
Fresh context Starts a fresh context between unrelated tasks
Context editing Clears the oldest tool results or thinking blocks
Memory tool Saves notes outside the window to read back later
Just-in-time loading Keeps paths and IDs in context, loads content on demand
Progressive disclosure Loads a skill’s name and description first, its instructions when triggered, its files only when used

Subagents

A subagent spends its own context and returns only a summary

A subagent spends its own context and returns only a summary. That costs more tokens overall, so use one when keeping the main context clean is worth it.

Compaction and context editing

Two ways to shrink a full context window

  • Compaction is opt-in on the Messages API, and Anthropic’s recommended default for long conversations. In the Agent SDK and Claude Code it runs automatically, and /compact <focus> steers what’s kept.
  • It loses detail, so anything that must survive goes in memory or CLAUDE.md.

  • Context editing (beta) runs on the server, so your client keeps the full history.

Module 6: Agent patterns

Anthropic’s rule from Building effective agents: start with the simplest design, and add complexity only when evals show it helps.

The patterns

Each LLM box below is an augmented LLM: one model call with retrieval, tools and memory. Often that single call is enough.

What separates the patterns is who decides the steps. In the first five, the workflows, your code fixes the shape. In the agent loop, the model picks each step. Since any box can itself be an agent loop, the bottom row shows ways to coordinate several of them.

Nine patterns, from fixed code paths to teams of agents - A Nine patterns, from fixed code paths to teams of agents - B

When a lead agent delegates, give each subagent a budget, an output schema and a clear handoff, and check outputs before passing them on.

Pipeline vs. graph

Draw any pattern as boxes and arrows and you get one of three shapes. In a pipeline or a static graph, your code fixes every step and branch before the run starts. In a dynamic graph, the model picks the next step while it runs, so you only see the full shape afterward.

Who draws the graph: your code, or the model at runtime

Module 7: Evals and safety

A lead engineer has to answer two questions before shipping: how do we know it works, and what is the worst it can do?

Evals

Evals turn every change into a measured change

Good criteria are specific, measurable, achievable and relevant (“accurate sentiment classification”, not “good performance”). Most systems need several: task fidelity, consistency, tone, privacy, latency and price.

Grading Use for Trade-off
Code-based Labels, formats, exact answers Fastest, most reliable and most scalable, but can’t judge nuance
LLM-based Tone, relevance, leaks of private data Handles complex judgments. Test its reliability first, then scale. Give it a clear rubric and use a different model than the one graded
Human Only what automation can’t judge Most flexible and highest quality, but slow and expensive. Avoid if possible

Prefer many auto-graded cases over a few hand-graded ones, and include edge cases: ambiguous, overlong, irrelevant and harmful inputs. Re-run the set when you change the prompt, the model or effort.

For coding agents, ask for a general solution and for wrong tests to be reported, never hardcoded around.

Evals are one layer of testing. The code around the model needs the usual layers too.

Layer Tests When
Unit Parsing, tool handlers and loop logic, against a mocked API Every commit
Integration and end-to-end The Claude integration with real API calls (tools, schemas, streaming, errors), and critical user flows end to end Before merge, on a fixed set
Evals Output quality on a graded dataset In CI, on every prompt change and model upgrade
Production Monitoring for drift and real-world failures, user feedback, sampled transcript review, A/B tests for big changes After launch, ongoing
Human review Calibrate LLM graders, judge subjective output Periodically

To debug a change such as new refusals, start from the traces of the failing requests (input, system prompt, context, stop_reason), then compare them with past successes.

Versioning prompts

A prompt is code: it changes behavior, so it needs history, review and rollback. The Console Playground, which replaced the Workbench, doesn’t store prompts or versions, so your repository is the source of truth.

Version this Why
The prompt text, in git, with a version ID Review changes in pull requests and roll back a bad one
The whole request: model ID, effort, tools, schemas A prompt only behaves the same with the same settings
The model ID, pinned IDs from the 4.6 generation on are fixed snapshots, but each has its own retirement date
The eval score of each version Promote a version only when its score holds or improves
The prompt version and request-id in every log line Trace a bad answer back to the exact prompt that produced it

Roll a new version out gradually, behind a flag or a percentage, and keep the previous one ready. Expect a burst of cache writes after each deploy, since a changed prefix starts a new cache. On a model upgrade, adapt the prompt to the new model and re-run evals before switching. When a parameter is deprecated, add regression tests for its current behavior, then migrate call sites in batches validated against them, well before the removal date.

In CI, run Claude Code headless with claude --bare -p "..." --output-format json. --bare skips local hooks, plugins, MCP servers and CLAUDE.md, so every run is the same, and --allowedTools limits what the job can touch.

Prompt injection

The second question is what the worst case is. Jailbreaks and prompt injection try to make Claude ignore your instructions, and each source of attack needs its own defense.

Threat Mitigation
Direct: the user is the attacker Screen input with a small model such as Haiku and structured outputs, and treat a refusal from the screen as a harmful verdict. State boundaries and how to refuse in system. Throttle repeat offenders
Indirect: content the agent reads is the attacker Treat tool content as data, never as commands, and say so in system. Put third-party content only in tool_result blocks, labelled with its source and JSON-encoded. Keep your own instructions in the user turn after it. Screen tool output with a small classifier
Too much power Least privilege: no secrets it doesn’t need, sandboxed tools, narrow permissions. Red-team with planted injections before launch, then monitor outputs for injections that got through

For rules that must never break, filter Claude’s output in code before it reaches users. A prompt alone is not enforcement.

Agent SDK permissions

The last line of defense is what the agent is allowed to do. In the Agent SDK, every tool call passes these checks in order, and the first that decides wins:

Each tool call passes six checks in order, and the first that decides wins

Mode Behavior
default Nothing approved by the mode. Unmatched calls go to canUseTool
dontAsk Anything that would prompt is denied: for headless agents with a fixed tool list
acceptEdits Approves file edits and filesystem commands inside the working directory
plan Explores and plans. File edits and shell writes always go to canUseTool
auto A model classifier approves or denies prompts
bypassPermissions Approves everything that reaches the mode step. Sandboxes only

Rules, modes and callbacks interact in ways that are easy to miss. allowed_tools pre-approves the tools you list but doesn’t restrict bypassPermissions, which still approves everything else. Calls approved by a mode or an allow rule never reach canUseTool, so put checks that must always run in a PreToolUse hook, and back hard limits with deny rules. Subagents inherit the parent’s mode, so a bypassPermissions parent hands every subagent full access. And a scoped deny such as Bash(rm *) only blocks calls written that way (/bin/rm gets through), while a bare name such as Bash in disallowed_tools removes the tool entirely. For a locked-down headless agent, pair allowed_tools with dontAsk.

Scope each hook with a matcher to the risky tools, such as Bash, Write or sensitive data access, so safe calls don’t pay for the check.

Permissions stop what the agent can do. In the prompt, also ask it to confirm before anything irreversible or shared, such as git push --force or dropping a table.

Keys and data residency

Give each environment (dev, staging, prod) its own API key, as recommended: a leaked key can then be revoked without stopping the others. Keep keys in a secret manager, never in code or prompts, and rotate them.

The Claude API can keep inference in the US (inference_geo: "us", at 1.1× the price) but has no EU option, and workspace data is stored in the US. If data must stay in the EU, call Claude through Amazon Bedrock or Google Cloud (Google managed) in an EU region, where the endpoint sets the region. Zero data retention is enabled per organization through Anthropic sales, and it doesn’t cover every feature: the Batch API, code execution and the Files API keep data.

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.