Exercise 6: Function Schema Design (bad vs good)¶
Corresponds to Stage 3 — Tool Use & Your First Agent Loop Exercise 6.
🎓 How to use this: First run the provided
starter_bad.pyandstarter_good.py(python starter_bad.py,python starter_good.py), then change exactly one small thing and run the existing tests again:python test.pyandpython test_anthropic.py. If a test fails, undo or fix that one change and try again. You do not need to rename the files or rewrite the whole solution. Seedocs/HOW_TO_USE.mdfor the full method.📚 Want the chapter-length version? The starter in this folder is a 70-150 line illustrative build focused on
the core pattern + two SDK paths— it is not in-depth teaching material. Recommended for depth: -datawhalechina/hello-agents⭐ the most complete Chinese-language course out there — chapter-based, covering 16 production capabilities. this exercise maps to hello-agents' Extra08 — How to Write a Good Skill - OpenAI Function Calling guide + the schema design cheatsheet - Full references in Stage 3 Curated Projects
Why this matters¶
Schemas are part of the prompt — and they're the part the model leans on hardest when choosing a tool. This exercise gives you starter_bad and starter_good for the same question: "Convert 32 Celsius to Fahrenheit."
- Bad schema: short descriptions, every param as string, no
required, noenum→ LLM frequently misroutes temperature conversion toprocess_data - Good schema: clear usage,
value: number,unit: enum["celsius", "fahrenheit"], all required fields listed → use a fixed eval to measure whether it routes toconvert_temperaturemore often
When you write a schema, don't aim for "a human can read this". Aim for "the model can use this to rule out the wrong tool".
How to run — two paths¶
Path A (default, free, local, 4 starters)¶
pip install -r requirements.txt
ollama pull qwen2.5:3b
ollama serve
python starter_bad.py # watch a bad schema mislead qwen
python starter_good.py # watch a good schema lead qwen to the right tool
Budget: $0 API cost; hardware, memory, and electricity are excluded.
Path B (Anthropic, cloud comparison)¶
pip install -r requirements.txt
$env:ANTHROPIC_API_KEY = "your-key"
python starter_bad_anthropic.py
python starter_good_anthropic.py
Budget: reserve $0.05 per run. Actual cost is input tokens × $1 / 1,000,000 + output tokens × $5 / 1,000,000; Tool Use also adds prompt tokens. Prices checked on 2026-08-27.
Validate the logic without API credits (mock-based)¶
python test.py # validates Path A (Ollama) starter_bad + starter_good
python test_anthropic.py # validates Path B (Anthropic) starter_*_anthropic
Each test suite also asserts on the schema structure directly (good has required + enum; bad doesn't) — not just on the LLM's choice.
Bad vs good schema A/B¶
| Design dimension | Bad | Good |
|---|---|---|
| Description | "Process data." | "Use only to summarize structured JSON table rows. Do not use for temperature conversion." |
| Param types | All string |
number / array / actual types |
| Required | None | ["value", "unit"] |
| Enum constraint | None | ["celsius", "fahrenheit"] |
| Error return | Plain string | Structured dict + retry_hint |
What to watch on each path (the teaching point)¶
Models may respond differently to schema quality; keep the prompt, schema, and test set fixed and use an eval to record behavior. Ollama is especially useful for observing this difference:
| Observation | Anthropic Claude haiku | Ollama qwen2.5:3b |
|---|---|---|
| Whether bad schema guesses right | Measure with a fixed eval | Measure with a fixed eval |
| Whether good schema picks correctly | Measure with a fixed eval | Measure with a fixed eval |
| Gap between bad and good | Measure with a fixed eval | Measure with a fixed eval |
In other words: measure schema quality and model behavior together with a fixed eval. Want to run a cheap model (qwen / mistral) in production? Your schemas need to be solid enough to run in production.
Further reading¶
More schema design rules in resources/schema-design-cheatsheet.en.md: clear usage, correct types, required fields, enum constraints, structured error returns.
Extensions¶
- Deliberately break the good schema — remove one
enumconstraint and watch qwen start to miss - Add a third tool — one with usage similar to but boundary-blurry with
convert_temperature, and observe the LLM's choice - Combine with the structured-error pattern from
../05-error-handling/— schema design + error handling is the combo for shipping to production