Chapter 7: Designing Claude Applications

Learning Objectives

Pre-Reading Check — Requirements & the Systems Life Cycle

Which of the following is best classified as an infrastructure requirement rather than a functional requirement?

According to Anthropic's "Building Effective Agents" guidance, what is the recommended default when starting a new design?

In the develop → implement → operate → maintain life cycle, why should token budgets and rate limits be addressed during the develop phase?

1. Requirements and the Systems Life Cycle

Key Points

A functional requirement is anything you can phrase as "the system shall…" — the observable behavior a stakeholder cares about. An infrastructure requirement is the operational scaffolding the user never sees but that decides whether the product survives production. Think of functional requirements as the restaurant menu and infrastructure requirements as the kitchen and plumbing: a great menu backed by a broken kitchen fails just as surely as a working kitchen with a menu nobody wants.

Functional requirements (what)Infrastructure requirements (how)
The task and its quality barAuthentication (IdP integration)
Tone and voiceRate limits (RPM / TPM)
Structured-output contractRetry logic and backoff
Permitted tools and actionsConnection pooling / request queuing
Safety and compliance policyMonitoring and observability
Cost budgets and data retention

Solution architecture turns requirements into components, control flow, and integration patterns. Anthropic's "Building Effective Agents" guidance draws a sharp line: workflows use a predefined control flow (testable, predictable), while agents let the LLM dynamically decide the next step (flexible, suited to open-ended tasks). The core recommendation: start with workflows and graduate to agents only when the task genuinely requires dynamic routing or open-ended exploration.

Within the workflow family, five composable patterns combine like building blocks: prompt chaining, routing, parallelization, orchestrator–worker, and evaluator–optimizer. Overarching principles: keep it simple, build modularly, and make reasoning visible. Production guidance adds progressive disclosure, per-tenant system prompts with clear isolation, and connection pooling plus request queuing for traffic spikes.

flowchart TD A["Business need + requirements"] --> B{"Is the task structure known in advance?"} B -->|Yes| C["Workflow: predefined control flow (testable, predictable)"] C --> D["Compose five patterns: prompt chaining, routing, parallelization, orchestrator-worker, evaluator-optimizer"] B -->|"No: novel / open-ended / adaptive"| E["Agent: LLM dynamically decides next step"] D --> F["Start simple, build modularly, make reasoning visible"] E --> F

The systems life cycle is the end-to-end sequence a Claude application moves through. Develop: choose the building block, define the output contract and tools, engineer prompts, design state, and budget tokens and rate limits here. Implement: wire auth via IdP, add input sanitization and injection defenses, red-team before go-live, establish CI/CD security. Operate: deploy behind rate-limit handling, retries with backoff, and pooling, with dual observability (traditional latency/error signals plus AI-specific quality signals). Maintain: monitor for injection and quality drift, track cost/ROI, manage model migration deliberately, and rotate/scope secrets.

stateDiagram-v2 direction LR [*] --> Develop Develop --> Implement Implement --> Operate Operate --> Maintain Maintain --> Develop: iterate on prompts, filters, model migration Develop: Develop — Building block, output contract, prompts, state design, token budget Implement: Implement — Auth via IdP, input sanitization, red-teaming, CI/CD security Operate: Operate — Rate limits, retries+backoff, pooling, dual observability Maintain: Maintain — Monitor injection and drift, cost/ROI, secret rotation
Animation slot: an interactive decision tree that walks from "Is the task structure known?" through the workflow vs. agent branch, then loops through the four life-cycle phases.
Post-Reading Check — Requirements & the Systems Life Cycle

Which of the following is best classified as an infrastructure requirement rather than a functional requirement?

According to Anthropic's "Building Effective Agents" guidance, what is the recommended default when starting a new design?

In the develop → implement → operate → maintain life cycle, why should token budgets and rate limits be addressed during the develop phase?

Pre-Reading Check — Instruction Interpretation Across Interfaces

A developer builds a prototype in claude.ai that "just works," then ports it to the Claude Messages API and finds Claude no longer knows the current date or prefers Markdown. What is the most accurate explanation?

When building on the Agent SDK, a developer opts into the claude_code preset but finds their CLAUDE.md project instructions are being ignored. What did they most likely forget?

Which statement about consistency across Claude surfaces is correct?

2. Instruction Interpretation Across Interfaces

Key Points

An interface is a distinct Claude surface — claude.ai and mobile, the Claude API, the Agent SDK, Claude Code, and Claude Cowork/Desktop — each with its own convention for where instructions live. On claude.ai, Anthropic automatically loads a full, date-stamped system prompt at the start of every conversation and layers organization and individual instructions on top. The Messages API gets none of that: the published claude.ai updates do not apply, the org/individual instructions live only inside claude.ai, and the API is stateless, so you must resend the full instruction set and history every request.

Claude Code ships its own extensive built-in prompt geared toward agentic coding, instructing Claude to weigh the "reversibility and blast radius" of every action. On the Agent SDK you opt into this with systemPrompt: { type: "preset", preset: "claude_code" } — but note the gotcha: the preset does not auto-load CLAUDE.md; you must set settingSources: ['project'] for those instructions to load.

SurfaceDefault system prompt?Org / individual instructions?StatePrimary control surface
claude.ai / mobileYes — Anthropic-authored, auto-loaded, date-stampedYesManaged (rolling FIFO)Anthropic + account settings
Claude APINoneNoStateless — resend each turnDeveloper's system parameter
Agent SDKOptional claude_code presetVia settings sourcesDeveloper-managedsystemPrompt config
Claude CodeYes — large built-in (~600 tokens)Via CLAUDE.md (if enabled)Session-managedBuilt-in preset + CLAUDE.md
Cowork / DesktopInherited base behaviorCustom instructionsSession-managedModel + custom instructions

The exam-relevant theme: safety guardrails are applied uniformly at the model level across all surfaces, but the system-prompt layer differs. A useful mental model is that claude.ai is a furnished apartment (lights, appliances, and house rules pre-installed) while the API is a bare shell where you supply every fixture yourself. Never assume a prototype that "just works" in claude.ai will behave identically on the API.

Animation slot: a side-by-side "furnished apartment vs. bare shell" panel that toggles between surfaces, lighting up which layers (default prompt, org instructions, state) are present on each.
Post-Reading Check — Instruction Interpretation Across Interfaces

A developer builds a prototype in claude.ai that "just works," then ports it to the Claude Messages API and finds Claude no longer knows the current date or prefers Markdown. What is the most accurate explanation?

When building on the Agent SDK, a developer opts into the claude_code preset but finds their CLAUDE.md project instructions are being ignored. What did they most likely forget?

Which statement about consistency across Claude surfaces is correct?

Pre-Reading Check — Content Boundaries & Schema Design

Where should untrusted third-party content (an inbound email body, OCR text, a fetched web page) be placed to keep it as data-to-report rather than commands-to-obey?

Why is constrained decoding fundamentally stronger than merely prompting "please return valid JSON"?

A developer wants their support-triage output to be parseable with confidence and route on category without defensive retries. Which schema practice most directly supports that?

3. Content Boundaries and Schema Design

Key Points

Content boundaries are the design decisions that separate trusted instructions from untrusted content. Claude is inherently resilient (Anthropic hardens it via RL that exposes it to injections during training), but application-level design is still required. Documented techniques: put untrusted content only in tool_result blocks (never in system or plain user text); label the content's nature and source; state an untrusted-content policy in the system prompt; JSON-encode third-party strings so escaping gives unambiguous delimiters; keep your own instructions out of tool results; apply least privilege; screen inputs and outputs with a lightweight model (e.g., Haiku 4.5) constrained to a boolean verdict; and red-team before deploying while monitoring continuously.

Think of it like a newsroom: the editor's standards (your system prompt) are trusted, and a tip that arrives in the mail (an untrusted tool result) might contain useful facts — but a professional newsroom reports on the tip; it never lets an anonymous letter rewrite editorial policy.

flowchart TD subgraph Trusted["Trusted zone — instructions to obey"] SP["System prompt (incl. untrusted-content policy)"] UR["User's genuine request (user text block)"] end subgraph Untrusted["Untrusted zone — data to report, never obey"] TR["tool_result blocks: web pages, emails, docs, OCR, search results"] end TR -->|"labeled + JSON-encoded"| CLAUDE["Claude reads with skepticism"] SP --> CLAUDE UR --> CLAUDE CLAUDE --> OUT["Reports on untrusted content; never lets it override system prompt or user request"]

Schema design defines explicit, machine-checkable structures for inputs and outputs. On the output side, structured outputs constrain responses to a specific schema. JSON outputs control what Claude says; strict tool use (strict: true) validates how Claude calls your functions. The mechanism underneath is constrained decoding: the schema is compiled into a grammar that restricts token generation during inference — structurally stronger than just asking for valid JSON.

With additionalProperties: false and constrained decoding, an app can call JSON.parse with confidence and route on a field like category without defensive retry logic. Best practices: avoid recursive schemas, use additionalProperties: false, write descriptive field names/descriptions, set generous max_tokens buffers, and monitor stop_reason for refusals or truncation. Expect a small overhead (~50–200 tokens, ~2–3% cost at scale) — more than offset by eliminating retry code. A schema is a contract between Claude and the rest of the system, enforceable at generation time.

Animation slot: a live "context window" panel where dragging an untrusted document into the system-prompt zone triggers a warning, and dropping it into a labeled JSON-encoded tool_result block turns it safe.
Post-Reading Check — Content Boundaries & Schema Design

Where should untrusted third-party content (an inbound email body, OCR text, a fetched web page) be placed to keep it as data-to-report rather than commands-to-obey?

Why is constrained decoding fundamentally stronger than merely prompting "please return valid JSON"?

A developer wants their support-triage output to be parseable with confidence and route on category without defensive retries. Which schema practice most directly supports that?

Pre-Reading Check — Session Hygiene & Plugins

What is "context rot," and why does it make session hygiene matter beyond raw window capacity?

Because the Claude Messages API is stateless, how is state leakage between two tenants' sessions best prevented?

In Claude Code, using a marketplace is a two-step process and plugins should be treated as dependencies. Which statement reflects the correct posture?

4. Session Hygiene and Plugins

Key Points

Because the Messages API is stateless, sustaining a multi-turn conversation means resending the entire message array each turn, with user and assistant roles alternating and starting with user. Session hygiene is the discipline of keeping that accumulating state clean, relevant, and bounded — it matters because everything counts toward the context window. Capacity is not the whole story: as token count grows, accuracy and recall degrade, a phenomenon called context rot. The context window is a whiteboard, not a filing cabinet: once it fills, stale scribbles must be erased or you run out of room mid-thought.

The hygiene toolkit: server-side compaction (beta) summarizes earlier turns; context editing clears tool results and thinking blocks; context awareness and explicit task budgets help the model pace long tasks; and the token counting API estimates size before sending. Overflow before generation returns a 400 invalid_request_error; overflow during generation on 4.5+ models stops with stop_reason: "model_context_window_exceeded".

flowchart TD A["Context window (bounded budget): system prompt + all messages + tool defs + generated output"] --> B{"Approaching token limit?"} B -->|No| C["Continue conversation"] B -->|Yes| D["Apply hygiene toolkit"] D --> E["Server-side compaction: summarize earlier turns"] D --> F["Context editing: clear tool results / thinking"] D --> G["Token counting API: estimate before sending"] E --> C F --> C G --> C B -->|"Overflow anyway"| H["400 invalid_request_error or stop_reason: model_context_window_exceeded"] C --> I["Guards against context rot and state leakage"]

In Claude Code, plugins extend the tool with skills, agents, hooks, MCP servers, and LSP servers, and marketplaces are catalogs of plugins. Using one is two steps: add the marketplace (registers the catalog, installs nothing), then install individual plugins. The /plugin manager (Discover, Installed, Marketplaces, Errors) shows a context-cost estimate per plugin — a direct tie back to session hygiene. Install scopes are user, project, local, and managed. Security is central: plugins can execute arbitrary code with the user's privileges, so install only from trusted sources; organizations can restrict marketplaces via managed settings (strictKnownMarketplaces, extraKnownMarketplaces, pluginSuggestionMarketplaces).

Since the API is stateless, the developer owns the boundaries between sessions. Two practices prevent state leakage: per-tenant system prompts with clear isolation (so tenant A's history never shares a window with tenant B's), and session hygiene tooling (clearing tool results, compacting old turns, starting fresh message arrays). Statelessness is a gift here — nothing persists automatically, so leakage only happens if you carry it over.

Animation slot: a "whiteboard" that fills with turns until it hits the limit, then lets the learner apply compaction or context editing to reclaim space and watch recall recover.
Post-Reading Check — Session Hygiene & Plugins

What is "context rot," and why does it make session hygiene matter beyond raw window capacity?

Because the Claude Messages API is stateless, how is state leakage between two tenants' sessions best prevented?

In Claude Code, using a marketplace is a two-step process and plugins should be treated as dependencies. Which statement reflects the correct posture?

Your Progress

Answer Explanations