Claude with the Anthropic API: teaching notes
Side-by-side notes for 06-praxis-claude-with-the-anthropic-api.html (14 slides). This is the developer course: the layer Claude Code and every other app sits on. The source 06-...-lessons.txt is video-only (the captures are unprocessed players, no transcript), so the depth here comes from the deck's leads and captions, read against the Praxis teaching library. Method: teaching-notes-method.md.
How to use these notes
- Guidance, not a script. Teach the person, not the slides.
- This is genuinely developer territory, and most of your room is not developers. The job here is not to teach them to code. It is to show them what the machinery under Claude Code actually is, so they can brief a developer, judge what they're handed, and recognise the concepts they already met as students (the system prompt is the skill file; an eval is "how would I know the output is right"; tool use is letting it act, not just answer). Translate every slide to their world at least once, then move on.
- Several slides are purely mechanical and do not vary by domain (the request shape, streaming, prompt caching, MCP plumbing). Where that's true these notes give one shared example and say so, rather than forcing nine. Use that collapse more freely here than on the fluency courses. Where a concept does land differently by role (system prompt, evals, tool use, RAG, workflow-vs-agent), the nine are there.
- Each teaching slide has a Pause, then ask block. Put the question, then stop. Don't fill the silence. If they freeze: "Take your time, type anything when you're ready, including 'I don't know'." Then wait again.
- Hold the voice (
train-the-trainer.mdPart 4): no "great question", no emoji, one term: Claude Code. Do not read code aloud (framings.md: voice). Underclaim. Cost is "about twenty dollars a month" and stop. - Know who's in the room before slide 1. A technical peer wants the mechanism; a non-technical operator wants the "so what". Most rooms are mixed: pitch to the operator, let the developer overhear.
Building with the API underneath the chat window
Set the frame: this is the layer everything else sits on. Eleven ideas, one screen each. The chat window and Claude Code are conveniences built on top of one plain request. By the end they'll know what that request is and what you can do with it.
"Everything you've used so far (the chat, Claude Code, the desktop app) sits on one thing: a request you send to the API. Eleven ideas, one screen each. You don't have to be able to write the request to understand it. The point is that you'll know what's under the floor, so you can brief whoever builds on it and judge what they hand back."
If the room is non-technical, name it straight: "Some of this is for the developer in your life, not for you to type. I'll tell you which parts those are. Your job is to recognise the ideas; most of them you've already met by another name."
The whole course on one screen
Four moves: make the call, make it reliable, extend its reach, then compose the pieces into systems. Show the shape so nobody feels lost in the machinery.
"Here's the whole thing on one screen. First we make a single call. Then we make it reliable: testing and clearer instructions. Then we extend its reach: tools, knowledge, more than text. Then we compose those pieces into real systems. If you lose the thread, this is the map back."
Don't teach the spine, just orient. Twenty seconds. Tool use (slide 7) is the heart of the back half; everything after it builds on that one mechanism.
One request, and the API forgets you
A single API call is the whole unit: you send a model, an optional system line, and the entire message list; it replies once and remembers nothing. A "conversation" is just that loop run by hand: you append the reply and send everything again. The growing message list is the memory.
"Underneath the chat, there's no conversation. There's one request, one reply, and then it forgets you completely. What looks like a conversation is the program quietly re-sending the whole history every single time. The list of messages is the memory; there's nowhere else it's kept." (This is the API-level version of framings.md, the folder is the memory: nothing persists unless something holds it.)
- "If the model itself remembers nothing between calls, where does that tell you the 'memory' in any AI product actually lives?"
- "What does that mean to you about trusting a chatbot to 'remember' something important?"
(wait)
this one is mechanical and shared; the request shape is the same whatever your work is. One example for everyone: the chat window you already use is this loop running invisibly; every time you send a message it re-sends the lot. Then connect it once to their world: this is exactly why a Claude Code folder beats a browser chat; the folder is a durable place to hold the history, instead of a chat that forgets when it gets long. (framings.md: context window; why the folder beats the browser.)
"So it doesn't remember me at all?" Right, and that's reassuring, not alarming, on the data question: the model holds nothing of yours between calls. Anything that persists is held by your system, in your control. (objections.md: IT/compliance.)
Verified against the course's 02_messages_format and 01_getting_started notebooks. The minimum a request needs is three fields in the body (model, messages, and max_tokens) plus your API key in the headers. The messages list: each entry has a role and content, the list starts with a user message and alternates user/assistant. (max_tokens is easy to forget but the API rejects the call without it.) On the key: the course teaches don't hardcode it: keep it in a .env file loaded with python-dotenv, and the SDK auto-reads the ANTHROPIC_API_KEY environment variable. Extension for a web app (beyond the course): the key lives on your
Never ship it to the browser; the browser calls your backend, your backend calls Claude.
Four dials on the same request
You change behaviour without changing the model: you turn four dials.
sets the role, rules and tone (it does the heavy lifting). Temperature trades reliability for variety (0 steady, higher looser). Streaming is about feel: tokens arrive as they're made. Structured output forces clean JSON a program can parse, not prose.
"Same model, four dials. The big one is the system prompt, the standing instructions for who it should be and what rules it follows. Temperature is how adventurous you let it be: zero for steady and repeatable, higher for variety. Streaming is just feel: words appear as they're written instead of all at once. Structured output is when you need clean data a program can read, not a paragraph."
- "The system prompt is the one you'll care about. Where in your world do you already keep 'the standing rules for how this gets done'?"
- "For your work, would you want the steady, same-every-time setting, or the loose, varied one?"
(wait)
- Investigator
- the report rules: cite every source, classify primary vs reported, never infer conduct. Temperature at zero: the report reads the same way every time.
- Analyst
- the column set and the "no data, never infer" rule. Zero temperature: a comparison you can defend, identical on re-run.
- Designer
- the brand voice and tone for campaign copy. Higher temperature here is a feature: you want varied options to choose from.
- Knowledge worker
- the extraction schema and "leave blanks blank". Zero temperature, so the same invoice yields the same row.
- Reporter
- the five-section briefing format and attribution rule. Steady, not creative.
- Content
- the house voice as the system prompt; higher temperature to draft several angles, then you curate.
- Form-filler
- the template's sections and the allocation rules. Zero temperature: a receipt lands in the same box every time.
- Outreach
- the five-section proposal format and "no invented numbers". Some variety in phrasing is fine; the facts stay fixed.
- Exec
- "my analyst, facts not editorial, one page". That's the system prompt. Zero temperature for a brief you'd stand behind at the board.
Streaming and structured-output are developer concerns, not theirs. Don't labour them. The one to land hard is the system prompt: it is the same object as the skill file they wrote as students, just lower in the stack. (framings.md: skill file as institutional memory.)
Verified against the course's tool_use/03_structured_outputs notebook. The API course's method is forced tool use: define a tool whose input_schema is the JSON shape you want, then force it with tool_choice. Claude returns the data as a validated object in the tool_use block. There's no prose to parse, because the structure isn't text Claude narrates. This is the robust path for an app. A lighter alternative (taught in Anthropic's prompt-engineering tutorial, a different course): prefill the assistant turn with { so Claude can't write a preamble, optionally clamping the end with stop_sequences: ["}"], then re-add both braces when you parse. The prefill+stop-sequence combo only works for flat JSON; nested objects trip the first }. Lead with tool_choice; reach for prefill only when you want minimal plumbing.
Stop guessing whether a prompt is good
An eval is a test suite for prompts: a set of cases, run automatically, graded, scored to one number. Change the prompt, re-run, watch the number move. Two ways to grade:
for anything exact (is it valid JSON? does it contain the answer?) and
for judgement (is it tactful? on-topic?), where you ask another Claude call to score it against a rubric.
"How do you know a prompt is actually good, not just good on the one example you tried? You build an eval: a set of test cases, run automatically and scored to a single number. Then when you change the wording, you re-run and watch the number move. Two ways to grade: by code, for anything you can check exactly, and by model, where you ask another Claude to judge it against a rubric, the same way you'd ask a second person to mark it." (This is the API-level form of the student question "how would I know the output is right?", 05-ai-fluency slide 12, Discernment, made measurable.)
- "How do you know, today, whether an AI output is good, beyond eyeballing one example?"
- "What does 'right' actually mean for your task, specifically enough that a test could check it?"
(wait: their answer to the second is the grading rubric.)
- Investigator
- does every claim cite a source? Is the Evidence Gaps section non-empty? (Code-based.) Is the tone non-accusatory? (Model-based.)
- Analyst
- is every cell either a sourced value or "no data"? (Code.) Is the basis named where two providers differ? (Model.)
- Designer
- does the manifest list every required variant with dimensions and format? (Code.) Is the copy on-brand? (Model.)
- Knowledge worker
- is the CSV valid, with no invented fields? (Code.) Are ambiguous rows correctly flagged for review? (Model.)
- Reporter
- are all five sections present and every line attributed? (Code.) Is a blocker buried as a win? (Model.)
- Content
- within word count, references a past post? (Code.) Does it sound like the house voice? (Model.)
- Form-filler
- do the totals reconcile and is every receipt allocated? (Code.) Is each receipt in the right section? (Model.)
- Outreach
- one proposal per customer, no invented numbers, subject line not a question? (Code.) Is the angle right for the relationship? (Model.)
- Exec
- one page, every decision with an owner and a date? (Code.) Are risks stated as fact, not editorialised? (Model.)
Non-technical people hear "test suite" and check out. Reframe: this is just writing down what "good" means and checking against it automatically, the thing they already do by hand, every time, when they review an output. The value is that it scales: you can change a rule and instantly see whether it helped or hurt across a hundred cases.
Verified against the course's 01_intro_to_evals. The eval loop is: build test cases (input + golden answer) → run the prompt so Claude generates responses → grade each against the golden answer → roll up to a score → change the prompt, re-run, watch the number move. So the step right after generating responses is grading. Two ways to grade: code-based for anything exact (valid JSON? contains the answer?), and model-based, which uses another model call to judge; see below.
It's the second of the two grading methods on this slide: instead of checking the output in code, you hand it to another model call (often Claude) to score against a rubric: "rate this reply 1–5 on whether it resolves the issue and stays polite; return the number and a one-line reason." Use it for the open-ended qualities code can't check exactly: tone, relevance, helpfulness, "did it actually answer". It scales human-like judgement across a whole test set without a person reading every output. The grader is itself a model, so it can be wrong. Good practice: a clear, specific rubric, ask for a reason alongside the score, and
on a sample before trusting it at scale. Verification: the code-based-vs-model-based split is straight from this slide and the prompt_evaluations course; the rubric/reason/validate practice is standard eval guidance, framed here as practice, not as quotable course text.
Four techniques, in order of leverage
When the output is wrong you rarely need a bigger model; you need a clearer prompt. Reach for four things, in order of leverage: be clear and direct, be specific, use XML tags to label the parts, and, the big one, give examples. A couple of worked input→output pairs teach format and edge cases that paragraphs of instruction can't.
"When it gets something wrong, the instinct is 'I need a smarter model'. Almost always you need a clearer instruction. Four moves, weakest to strongest: say exactly what you want; spell out the details; label the parts cleanly; and the one that moves quality most: show it a worked example. One good before-and-after teaches it more than a page of rules." (This is the same lesson as Claude 101 slide 5 and the AI Fluency prompting slide, here at the API level: when it's off, it's almost always fixable.)
- "When AI has disappointed you, was it really the model, or was the brief vague?"
- "What's one finished example of 'good' you could hand it, instead of describing what you want?"
(wait)
- Investigator
- one past background report in the house format; the structure carries everything.
- Analyst
- one filled comparison table, so the columns and "no data" handling are shown, not described.
- Designer
- one finished asset spec, so it copies the shape rather than guessing it.
- Knowledge worker
- one correctly-extracted invoice row, blanks and all.
- Reporter
- one past briefing in the five-section format.
- Content
- two past posts as the voice sample; show, don't tell.
- Form-filler
- one correctly-allocated receipt, including an edge case.
- Outreach
- one proposal you'd actually send, as the template.
- Exec
- one past one-page brief in the four-section shape.
The XML-tags point is genuinely technical: Claude is trained to respect <document>...</document> over loose quoting. Don't dwell on it for a non-technical room; just note that giving each part a clear label helps, and move to examples, which is the move that pays.
Tool use is a round trip you complete
Claude can't run anything. It can only ask. You describe the tools; it replies "call this, with these arguments" (stop_reason: tool_use); you run the real function and hand back the result; it continues. The loop can repeat across several turns. This one mechanism is what every agent is built on: the model proposes, your environment executes, the result comes back.
"Here's the thing that changes everything: Claude on its own can't do anything. It can't check your calendar, hit your database, send an email. All it can do is say 'I'd like to call this tool, with these inputs'. Your system runs it for real and hands the answer back, and it carries on. That round trip (it asks, you act, you return the result) is the whole basis of letting AI act, not just answer. Every agent you've heard of is built on exactly this." (This is the under-the-floor version of letting it act: augmentation becomes agency, 05-ai-fluency slide 4, through one mechanism.)
- "What does it change for you that the AI never acts directly; it only ever requests, and your system decides whether to run it?"
- "In your work, what's something you'd want it to do, not just tell you about?"
(wait)
- Investigator
- look up a name in Companies House or a sanctions list, then fold the result into the report, grounded in real records, not its memory.
- Analyst
- query the live pricing or the warehouse, so the comparison uses today's numbers, not a guess.
- Designer
- pull the exact retailer spec sheet for each channel before listing variants.
- Knowledge worker
- look up a supplier's standing PO number from the master list while extracting.
- Reporter
- read the live status board or ticket system as it assembles the briefing.
- Content
- check the CMS for whether a topic's already been covered before drafting.
- Form-filler
- look up the current year's tax thresholds rather than trusting a stale figure.
- Outreach
- pull the customer's latest record from the CRM so the proposal is current.
- Exec
- read the live P&L or pipeline figures into the board brief, rather than a number someone typed last month.
This is where the autonomy fear lives: "so it can just do things?" Answer it on the diagram: no. It only ever asks; your system is the gate. That's the same confirm-each-step-then-auto control they met as students, now visible in the mechanism. The model never has its hand on the lever. (objections.md: permission/auto.)
It's a plain function that runs in your own code when Claude needs information or an action, the correct framing, and the one to give if someone offers the other two. Not a special Anthropic-hosted endpoint: tool use all goes through the one Messages API endpoint, and the tool's logic lives on your side; the model only returns a tool_use request (a name plus arguments) and waits for you to send back the result. Not a config file that defines Claude's behaviour: what you send in the request's tools array is just a declaration (name, description, input schema) telling Claude what's available to call, not how to behave. Hold the distinction: the declaration is the interface; the
(your code) is what actually runs. Verification: matches the tool_use course (anthropics/courses) and the official tool-use docs: Claude returns tool_use, you execute and return a tool_result (June 2026).
Some tools you don't have to build
Most tools are yours to implement. A few ship with the API; you switch them on and Anthropic runs them server-side: a text editor (edits files in place), web search (live, cited results), code execution (runs Python in a sandbox). The text editor and code execution are exactly what powers Claude Code and the analysis features. The Files API lets a request reference an uploaded file without re-sending it every call.
"Most tools, your developer builds. A handful, Anthropic already built; you just switch them on. A text editor that changes files, web search that comes back with cited results, and a code sandbox that runs Python. Worth knowing because these aren't abstract: the text editor and the sandbox are literally what's running when you use Claude Code. You've been using these tools without knowing their names."
- "Knowing that web search and a code sandbox are built in, what's a job that needs live facts plus a calculation, that you'd hand to it?"
- "How does it sit with you that the Claude Code you've used is these same pieces, switched on?"
(wait)
mostly shared and mechanical; these are the same three built-in tools for everyone. Give one shared framing: web search for current facts, the sandbox for any real calculation or chart, the text editor for working on real files, and you've already met all three inside Claude Code. Then land it once per likely room: the Analyst and
care most about the code sandbox (real numbers, real charts, not a plausible-looking figure); the Investigator, Reporter and Outreach care most about cited web search (live, attributable, not from memory). Don't force all nine here.
"Runs Python in a sandbox" can spook a regulated room. Reassure: the sandbox is isolated and the web-search results come back with citations, which is the opposite of "trust me". This connects to the same floor-and-ceiling data conversation. (objections.md: IT/compliance; hallucinate.)
Verified against the official Files-API and code-execution docs. The code execution tool runs Python in an Anthropic-hosted sandbox with no network access; that isolation is the key limitation (no outbound calls, no internet pip install, no fetching URLs) and also the safety feature. It's not JavaScript-only, you don't supply your own environment, and it handles data/images, not just text. Data goes in and out through the Files API: a create-once / use-many store where you upload a file, get a file_id, and reference it across requests without re-sending it, and where you download outputs (e.g. charts) the tool produces. Two jobs for the Files API: stop re-uploading the same document, and serve as the input/output channel for code execution. (You can only download files Claude created; ones you uploaded can't be downloaded back.)
RAG: give it knowledge it was never trained on
You can't fit a whole knowledge base in one prompt, so you index it once, then for each question retrieve only the few chunks that question needs and paste them in. Two indexes do best together: embeddings catch meaning ("car" finds "vehicle"); BM25 catches exact terms (an error code, a part number). Production RAG runs both and merges.
"Claude was trained on the public internet up to a point in time. It was never trained on your documents. RAG is how you give it those: you index everything once, then for each question you pull only the handful of passages that matter and hand them over. Two ways to find the right passages: one that understands meaning, so 'car' also finds 'vehicle', and one that nails exact terms like a part number or an error code. The good systems use both." (This is the engine-room version of the Claude 101 connectors and Enterprise Search slides: work with your actual data, not a cold start.)
- "What's the body of knowledge that's yours, that no general AI would ever have seen?"
- "When you search it today, do you search by meaning or by exact term, or both?"
(wait: the answer tells them which index matters for their work.)
- Investigator
- the firm's past case files and house precedents; exact-term search matters (names, company numbers, sanctions codes).
- Analyst
- historic vendor responses and methodology notes; meaning-search to find comparable answers worded differently.
- Designer
- the brand guidelines and retailer spec library; exact-term for spec codes and dimensions.
- Knowledge worker
- the supplier master and past invoices; exact-term for PO and supplier IDs.
- Reporter
- past briefings and the project archive; meaning-search to surface related prior updates.
- Content
- the back catalogue of posts; meaning-search to find what's already been said on a topic.
- Form-filler
- the rules and category definitions for the template; exact-term for section codes and statute references.
- Outreach
- the knowledge base and past proposals; both: meaning for the angle, exact for product names and figures.
- Exec
- the retainer book, board packs and KPI definitions; exact-term for client names and metric names.
RAG is a developer build, not something they'll wire up. Keep it at the level of "this is how the connectors you've seen actually work, and why they cite a source". Don't go near chunking strategies or vector stores in a non-technical room.
The same API takes more than text
Four capabilities ride on the request they already know: two change what goes in, two change what comes out. Images (read charts, screenshots, photos) and PDFs (text and layout, page by page) are richer inputs. Extended thinking (reasons first, then answers) and citations (points to the source a claim came from) are richer outputs. Thinking gives room to work through hard problems; citations turn "trust me" into "here's the passage".
"The same request takes more than typed text. On the way in: images, so it can read a chart or a screenshot, and PDFs, page by page with the layout intact. On the way out: it can think through a hard problem before committing to an answer, and it can point at the exact source it drew a claim from. That last one, citations, is the backbone of any answer a business has to be able to stand behind." (Citations are the API-level answer to "what if it makes things up?", objections.md: hallucinate.)
- "How much of your real source material is not typed text; it's PDFs, scans, charts, screenshots?"
- "Where would 'here's the exact passage I got this from' change whether you could use the output at all?"
(wait)
- Investigator
- PDF court judgments and scanned filings in; every claim cited back to a filename, non-negotiable for a defensible report.
- Analyst
- vendor responses arrive as PDFs and screenshots; citations make the comparison auditable.
- Designer
- reads a reference image or a screenshot of a layout you like, and works from it.
- Knowledge worker
- invoices and receipts are images and PDFs, not text; this is the step that makes the real files work.
- Reporter
- consolidates from PDF reports and chart screenshots; attribution stays intact.
- Content
- reads a competitor's published PDF or a screenshot for reference.
- Form-filler
- the receipts are photos and scanned PDFs; reading them is the whole job.
- Outreach
- reads a prospect's PDF report or deck before drafting; cites what it used.
- Exec
- reads the board pack and P&L PDFs; citations let you trace any figure to source.
This is the slide that answers "but my real files are Word, Excel, PDFs, scans" (objections.md: Word/Excel/PDF). The dummy text files in the student courses were for ease of reading together; the real machinery handles the real formats. Say so plainly.
Verified against the official PDF-support docs. A PDF is processed as both text and images: each page is rendered as an image and its text is extracted, so Claude reads the words and sees charts, tables, and layout. An
Pixels, no separate text layer. That difference drives the rest: in the request a PDF uses a document block with media_type: application/pdf (an image uses an image block); citations are available for PDFs but not images; and a PDF costs more per page (billed as text tokens and image tokens). So PDFs give the richer, dual understanding plus citations, at more tokens; images are cheaper, vision-only, no citations. Common distractors to reject: PDFs are not text-only, and they need no special permissions (just a standard, unencrypted PDF).
Pay for the long part once
Most prompts start with the same big block: a system prompt, tool definitions, a document. Cache that prefix and later calls read it instead of re-paying for it. The rule: only an exact, unchanged prefix is reused, so put everything stable first and the variable part last. Cache lifetimes are short (minutes), so it pays off across a burst of related calls.
"Remember slide 3: every call re-sends the whole history. If that history starts with the same big block every time, a long document, a fat set of rules, you'd be paying for it again and again. Caching lets you pay for that stable part once and have later calls read it cheaply. It's a cost-and-speed optimisation, not a new capability."
- "What does it mean to you that the expensive part of running this is the repeated context, not the question?"
- "How does this apply to your work: is the big, unchanging part of your job the documents, or the rules?"
(wait)
mechanical and shared; a developer turns this on; it doesn't change what the tool does for any one role. One shared example: if you ask twenty questions of the same hundred-page contract, caching means you pay for the contract once, not twenty times. Then connect it once to the cost framing they care about; this is part of why running a built workflow is cheap. Hold the line: "about twenty dollars a month" and stop. Don't invent a larger figure. (framings.md: cost model. objections.md: burning through tokens.)
Don't let this become a pricing rabbit-hole. The honest, calm version: the marginal cost of re-running a built system is small, and caching is one of the reasons. Move on before someone asks you to model their bill.
Verified against the official prompt-caching docs. Two things must both hold: (1) you mark the block with cache_control: {"type": "ephemeral"}, and (2) the cached prefix clears your model's
Roughly 1,024 tokens on Sonnet 4.x, 4,096 tokens on Opus 4.5+ and Haiku 4.5. Below the threshold it silently runs uncached, no error. So a short system prompt marked for caching just won't cache. Confirm it worked via the response usage: cache_creation_input_tokens > 0 (written) or cache_read_input_tokens > 0 (hit); both 0 means no caching. And remember the rule from this slide: only an exact, unchanged prefix is reused, so put the stable content first.
MCP: one standard plug for tools and data
Without a standard, every app wires up every integration by hand. With MCP, a server exposes its capabilities once and any client can connect. A server publishes three things: tools (actions to call), resources (data to read), prompts (ready-made flows), and an inspector lets you test it before wiring it to a client. Build the integration once; plug it into Claude Code, your own app, or anyone else's.
"MCP is the standard plug. Before it, connecting Claude to your CRM, your drive, your database meant a custom wire for each, for each app. With MCP you build the connection once and any tool that speaks the standard can use it. You've heard 'USB-C for AI'; that's it. Build once, plug in everywhere." (This is the engine-room version of the Claude 101 connectors slide, same idea, one layer down: one standard behind every integration.)
- "What tools and data does your work live in, that you'd want Claude to reach, and reach the same way from every app?"
- "What does 'build the connection once, use it everywhere' mean for how your team would share it?"
(wait)
the mechanism is shared; what varies is the connector that earns its place, and that's the same list as the Claude 101 connectors slide. Don't re-run all nine here; point at it: whatever tool you said earns its place as a connector (the CRM, Drive, the warehouse), MCP is how that connection actually gets built and shared. Land it once for the room you have: for a team, the payoff is that one person builds the connector and everyone plugs in; for a solo operator, it's that the connector outlives any single app.
"Resources, tools, prompts, inspector" is developer vocabulary. Don't drill it. The one durable takeaway for a non-technical room: this is why the connectors they liked aren't bespoke magic; they're a standard, which means portable and shareable.
07 · Introduction to Model Context Protocol, "MCP review"). Match the job to the primitive- Tools: model-controlled. Use for actions Claude performs. The model decides to call them (verbs, side effects). Reading a document on the model's own initiative is a tool.
- Resources: application-controlled. Use for exposing data Claude can read. Read-only content addressed by a URI (e.g.
file:///docs/report.md); the app/user decides what to pull in. Exposing document contents is a resource. - Prompts: user-controlled. Use for pre-tested, reusable instructions. Vetted templates the user invokes (often as slash commands), can take arguments. Pre-tested formatting instructions are a prompt.
The easiest way is the @mcp.tool() decorator from FastMCP. Write a normal Python function and decorate it: the function name becomes the tool name, the docstring becomes the description, and the type hints become the input schema. No hand-written JSON Schema, no separate list/call handlers. ```python from mcp.server.fastmcp import FastMCP mcp = FastMCP("docs-server")
@mcp.tool() def read_document(path: str) -> str: """Read and return the contents of a document.""" with open(path) as f: return f.read() `` The lower-level path (implement list_tools()/call_tool()` and write the schema by hand) works but is the harder route.
The most common dev-time transport is stdio (standard input/output): the client launches the server as a subprocess and they exchange JSON-RPC over stdin/stdout, no ports, no network, no auth. The alternative is HTTP (Streamable HTTP, which replaced the older HTTP+SSE transport), used when the server runs as a separate or remote service.
Verification: the primitive/owner mapping is from the course spine. The @mcp.tool() decorator and stdio specifics match the official MCP Python SDK docs and quickstart; course 07 is video-only, so these aren't quotable from our capture but are confirmed against primary docs (June 2026).
Workflows vs agents: who decides the path
Both chain LLM calls. The difference is control. In a workflow you wire the steps in advance (chain, route, parallel). In an agent the model chooses the steps as it goes (think, act, observe, loop). Choose by predictability: if you can draw the steps ahead of time, a workflow is cheaper and more reliable; if the path depends on what's found along the way, you need an agent. Claude Code is an agent. Most production systems mix both.
"Two ways to build something real, and the difference is who's driving. In a workflow, you fix the steps in advance: do this, then this, then this. In an agent, the model decides the path as it goes, looping until it's done. Pick by how predictable the job is. If you could draw the steps on a whiteboard beforehand, build a workflow; it's cheaper and steadier. If the right next step depends on what it finds, you need an agent. Claude Code is one." (This is automation versus agency from 05-ai-fluency slide 4, made concrete: a fixed task you define versus a system that decides for itself.)
- "Think of one task you'd hand over. Could you write the steps down in advance, or does the next step depend on what it finds?"
- "Which feels right for your work: a fixed recipe, or something that figures out the path?"
(wait: their answer is the workflow-vs-agent call for their first build.)
- Investigator
- mostly agent: what to chase next depends on what the file reveals; a fixed recipe can't anticipate the gaps.
- Analyst
- workflow: read each submission, tabulate, flag gaps. The steps are the same every quarter.
- Designer
- workflow: read each brief, check the spec, list the variants. Predictable shape.
- Knowledge worker
- workflow: read, extract, validate, flag. The most fixed recipe of all.
- Reporter
- workflow: collect updates, sort into five sections, attribute. Same every week.
- Content
- workflow with a creative step: gather references, draft to the pattern, check voice.
- Form-filler
- workflow: read, classify, allocate, reconcile. Deterministic by design.
- Outreach
- workflow: one proposal per customer, fixed sections. The loop is the same per file.
- Exec
- workflow for the recurring brief; lean agent when the question is open ("what happened while I was out, and what should I worry about?").
The honest framing: most of what your room does is a workflow, and that's the good news: workflows are cheaper, steadier, and easier to trust. Don't oversell "agents". The recurring deliverable they each named in the student courses is almost always a workflow. (framings.md, the Excel-formula route: you write the recipe once, it runs the same every time.)
Grounded in Anthropic's "Building Effective Agents" guidance, the source behind lessons 76–82 (video-only in our capture); conceptual, matches the slide. The flexible move is to give Claude a few general, composable tools and let the agent loop decide which to call, not a narrow, single-purpose tool for every case you anticipated. General tools (run a query, read a file, search) recombine into behaviours you never scripted; narrow tools only cover the exact paths you foresaw. The catch is the slide's own point: an agent is less predictable and costs more tokens, so for a job you can draw on a whiteboard in advance, a workflow still wins. Flexibility and control trade off; you don't get both.
The fix is prompt chaining (lesson 78, "Chaining workflows"): break the one over-stuffed prompt into a short chain of focused steps, each handling a few rules and passing its output to the next. A single call carrying fifteen requirements overloads one inference and some instructions get dropped; a chain gives each step less to hold, and you can check the output between steps, a gate, before moving on. Note what it isn't: making the prompt louder ("IMPORTANT!!!") doesn't lighten the load; routing picks a path but doesn't reduce what's on it; parallelisation runs independent sub-tasks at once, which helps coverage, not instruction-following on a sequential job.
Make the call. Trust it. Give it reach. Compose it into systems.
The whole course in one line. A stateless request is the unit. Evals and prompting make it reliable; tools, RAG and the model's own capabilities give it reach; MCP and the workflow-vs-agent choice are how you build something real that lasts.
"Four moves. Make the call: one stateless request, the unit everything's built from. Make it reliable: test it, and brief it clearly. Give it reach: tools, your own knowledge, more than text. Then compose those into a system. If you keep one thing: nothing here is magic, it's all the same request with more switched on."
Bring it back to them. For a non-technical room: "You don't have to build any of this. But now when a developer says 'eval' or 'tool use' or 'agent', you know exactly what they mean, and you can tell them what 'good' looks like for your work, which is the part only you can do." Then point forward: the durable, plain-English version of all of it (the system prompt as a skill file, the workflow as a script in a folder) is the Praxis method, and that's where they already started.