Français Previous slide Next slide Toggle fullscreen Toggle overview view Open presenter view
title: "Claude API: Deep Dive"
subtitle: "Applied AI — Advanced Level · Session 1"
author: "Yann Isola"
theme: "ink #1A2230 / teal #0F7A6C / copper #B4612A / light-teal #E9F6F3 / bg #F4F7F6"
Slide 1 — Title
Claude API: Deep Dive
Applied AI — Advanced Level · Session 1
Yann Isola · Preparation Claude Certified Architect
Slide 2 — Session Objectives
Build a complete API request and justify each parameter
Interpret the 4 values of stop_reason → application logic
Reason about the context window as working memory
Master prompt caching (cache_control) and its ROI
Implement SSE streaming (SSE = Server-Sent Events)
Arbitrate synchronously / streaming / API Batches
Design error handling: 429, backoff, retry-after
Slide 3 — The minimum contract
Three required fields: model, max_tokens, messages
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY " \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello"}]
}'
Volatile model names — always check docs.anthropic.com
Slide 5 — Calling via Python SDK
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-5" ,
max_tokens=1024 ,
temperature=0.2 ,
stop_sequences=["END_REPORT" ],
system="Financial analyst. English, concise." ,
messages=[{"role" : "user" , "content" : "..." }],
)
print (response.content[0 ].text)
print (response.usage, response.stop_reason)
Slide 6 — Sampling Settings
Parameter
Role
Reco architect
temperature 0–1
hazard
0–0.3 extraction · 0.7–1 creative
top_p
nucleus sampling
do not combine with temperature
top_k
k most probable tokens
advanced cases only
stop_sequences
personalized stops
delimited exits
Certif trap: temperature: 0 ≠ perfect determinism
Slide 7 — Three roles, three privileges
system — privileged channel (outside the messages table)
→ persona, rules, exit policy. Not “a disguised first message”
user — the caller: questions, documents, tool_result
assistant — the model… and the prefilling
Rule: strict alternation, first message = user
Two consecutive identical roles → 400
Slide 8 — Prefilling: putting words in the model’s mouth
messages=[
{"role" : "user" , "content" : "List 3 risks in JSON." },
{"role" : "assistant" , "content" : "{" }
]
Model continues from {
Remove preambles (“Of course! Here…”)
The prefill is not in the response → re-prefix on client side
Slide 9 — stop_reason: the 4 signals
stop_reason
Meaning
Reaction
end_turn
natural ending
nominal
max_tokens
truncated (HTTP 200!)
alert / restart
stop_sequence
sequence encountered
read response.stop_sequence
tool_use
requested tool
execute → tool_result → loop
Slide 10 — The canonical safeguard
match response.stop_reason:
case "end_turn" :
return extract_text(response)
case "max_tokens" :
raise TruncatedResponseError(partial=...)
case "stop_sequence" :
return parse_delimited(..., response.stop_sequence)
case "tool_use" :
return handle_tool_loop(response)
case _:
raise UnexpectedStopReason(...)
Slide 11 — The context window = working memory
~200,000 tokens (some models: 1M in beta)
Contains EVERYTHING: system + history + docs + tools + results
It's not "a limit" — it's what the model knows for this query
3 consequences: linear cost · lost in the middle · latency (TTFT)
Slide 12 — Cost: the conversation that becomes quadratic
API stateless → full history is re-invoiced every round
total = sum (cout(30_000 , 500 ) for _ in range (20 ))
× 10,000 users/day → technical direction topic
Parades: summary · sliding truncation · prompt caching
Slide 13 — “Lost in the middle”
Recall of information according to its position in the context:
START ████████████ excellent
MIDDLE ██████ degraded ← bury nothing here
END ███████████ excellent
Strategic placement:
Large documents → at the top
Critical instructions + question → at the end
Key instruction in the middle of 80k log tokens →
Slide 14 — Prompt caching: the principle
Reuse a prefix already processed via cache_control
Economy (volatile):
Reading (hit): ~10% of the price → −90%
Writing: additional cost ~25%
TTL ~5 min , refreshed on each hit (1 h option )
Profitable from 2 requests : 1.25 + 0.10 = 1.35 < 2.00
Slide 15 — cache_control: syntax
system=[{
"type" : "text" ,
"text" : GROS_CONTEXTE,
"cache_control" : {"type" : "ephemeral" }
}]
u = response.usage
u.cache_creation_input_tokens
u.cache_read_input_tokens
u.input_tokens
Slide 16 — Cache Invalidation Rules
Prefix exact : a byte modified upstream → invalidated
Order: tools → system → messages
Minimum cacheable: 1,024 tokens (otherwise ignored silently )
Max 4 breakpoints per request
Target design: stable at the head, variable at the tail
Slide 17 — Anti-pattern: the cache that costs more
system = f"[{datetime.now()} ] You are an assistant..."
Leading timestamp → never identical prefix
0% hits + 25% write overhead on each call
Result: we pay more than without cache
Slide 18 — Count before paying: count_tokens
count = client.messages.count_tokens(
model="claude-sonnet-4-5" ,
system="..." ,
messages=[{"role" : "user" , "content" : doc}],
)
print (count.input_tokens)
Each model family has its tokenizer
Never reuse a tiktoken count (OpenAI) for Claude
Orders of magnitude: ~3.5–4 car./token (English), a little denser in French
Slide 19 — Streaming: why
UX : first token in ~1 s instead of waiting 30 s
Long generations: essential (HTTP timeouts)
SSE = Server-Sent Events : unidirectional HTTP flow text/event-stream
event: content_block_delta
data: {"delta":{"type":"text_delta","text":"The"}}
Slide 20 — The HSE event cycle
message_start ← id, model, INPUT usage
content_block_start ← opening of block 0
content_block_delta ×n ← the text chunks
content_block_stop ← closing of block 0
message_delta ← stop_reason + output_tokens ★
message_stop ← end of stream
(+ ping keep-alive, + error possible during flow)
★ Certificate trap: final metadata is in message_delta
Slide 21 — Streaming: implementation
with client.messages.stream(
model="claude-sonnet-4-5" , max_tokens=1024 ,
messages=[...],
) as stream:
for text in stream.text_stream:
print (text, end="" , flush=True )
final = stream.get_final_message()
print (final.stop_reason)
Low level version: stream=True + loop on event.type
→ required for certification (exercise 2)
Slide 22 — API Batches: the 3rd execution mode
Fashion
Latency
Cost
Usage
Synchronous
seconds
100%
interactive
Streaming
TTFT ~1 s
100%
interactive long
Batch
24 hour SLA
−50%
mass, non-urgent
Up to 100,000 requests / ~256 MB per batch
In practice: often < 1 hour
Results unordered → correlation by custom_id mandatory
Slide 23 — Batch: code
batch = client.messages.batches.create(requests=[
{"custom_id" : f"doc-{i} " ,
"params" : {"model" : "claude-haiku-4-5" ,
"max_tokens" : 512 ,
"messages" : [...]}}
for i, doc in enumerate (documents)
])
for r in client.messages.batches.results(batch.id ):
if r.result.type == "succeeded" : traiter(r.custom_id, ...)
else : rejouer(r.custom_id, r.result)
Slide 25 — Exponential backoff with jitter
except anthropic.RateLimitError as e:
retry_after = e.response.headers.get("retry-after" )
if retry_after:
delai = float (retry_after)
else :
delai = min (60 , 2 **tentative) * random.uniform(0.5 , 1.5 )
time.sleep(delai)
retry-after bonus on your formula
Mandatory Jitter (“thundering herd” effect)
The retry SDK already 2× by default → watch out for multiplicative layers
Slide 26 — Architect’s decision tree
Real-time need ?
├── YES → long response ? → streaming SSE
│ short response ? → synchronous
└── NO → massive volume? → Batches API (−50 % )
+ small model
+ prompt caching if common prefix
Always: guard stop_reason + backoff 429 + log of usage
Slide 27 — The 7 certification pitfalls seen today
max_tokens mandatory, no default value
Truncation = HTTP 200 + stop_reason: "max_tokens"
The prefill is not included in the response
temperature: 0 ≠ perfect determinism
Cache: exact prefix, tools → system → messages
stop_reason final streaming → message_delta
Unordered batch results → custom_id
Slide 28 — Next steps
Exercises: robust client · low-level streaming · 80k emails batch pipeline
Quiz: 10 certification MCQs (threshold 7/10)
Interactive page: query builder + SSE viewer + token counter (offline)
Session 2: tool use & agents — the loop tool_use → tool_result in depth
Permanent reflex: revalidate prices, limits and model names on docs.anthropic.com
Notes: Frame from the start — this session is not prompting, it's architecture. API contract, token economy, failure modes.
Notes: 7 objectives = 7 blocks. Everything is evaluated in MCQ certification.
Notes: `anthropic-version` pins API contract. Without him → error. `max_tokens` has NO defect (pitfall Q1 of the quiz).
Notes: Field anecdote: systems in production delivering truncated JSON for weeks due to failure to test stop_reason. Transition to slide 8.
Notes: SDK = Software Development Kit. Insist: log `usage` systematically (cost observability). `content` is an ARRAY of blocks.
Notes: Correct wording: “strongly reduces variability”. Residual numerical non-determinism.
Notes: The system prompt is treated with particular priority by the model — increased resistance to bypasses in user towers. Stateless API: Everything is returned on each call.
Notes: Live demo: same question with/without prefill. JSON = JavaScript Object Notation. Another use: forcing a choice of MCQ with prefill “The answer is (”.
Notes: LE slide certification. An architect writes a branch by value. max_tokens is NOT an HTTP error — self-detecting business state.
Notes: The `case _` protects against future API values. To be written in exercise 1.
Notes: TTFT = Time To First Token. Change of mental model: from “constraint” to “resource to be architected”.
Notes: Sum of prefixes = quadratic growth. Natural transition to caching.
Notes: Question to the group: “RAG with 40 chunks — where does the user question go?” Answer: after the docs, possibly repeated.
Notes: TTL = Time To Live. Have the group calculate the profitability before giving the answer.
Notes: Three separate counters in usage — showing them is what allows you to verify that the cache is really working in prod.
Notes: Quiz trap Q7: modifying the last user message DOES NOT invalidate the cache (it is after the breakpoint).
Notes: Frequent real case. Same with a session ID, a nonce, a counter. Anything that varies goes AFTER the breakpoint.
Notes: Uses: validate the window BEFORE paying, size max_tokens, internal chargeback. Pass the FULL request (system+messages+tools).
Notes: UX = User eXperience. SSE ≠ WebSocket: unidirectional, simple HTTP, proxy compatible (except buffering — see exercise 2C).
Notes: Demo: viewer of the session web page (offline). Run the “truncation” version to show stop_reason=max_tokens streaming.
Notes: Even in streaming, max_tokens truncation exists. A front that nicely displays truncated text remains a bug.
Notes: SLA = Service Level Agreement. Use cases to find: nightly classification, CRM enrichment, massive evaluation of prompts.
Notes: Final states: succeeded / errored / expired / canceled — a replay policy for everyone. Bonus: batch + caching CUMULATES (hits not guaranteed).
Notes: Three independent rate limit counters — you can be limited in output tokens while still being under the request limit.
Notes: Bonus: `anthropic-ratelimit-*-remaining` headers for PROACTIVE throttling. Remember the opening question of the course (who has experienced a 429?).
Notes: Operational summary. The bottom three reflexes apply to all THREE modes.
Notes: Have a participant read this list out loud again. This is the revision checklist.
Notes: Distribute exit tickets (5 questions, 3 min). Pick up at exit — they calibrate session 2 opening.