4 min read · 823 wordsreferenceexercises
Exercises
Every exercise below is grounded in this specific codebase — a real function, a real endpoint, or a real bug found while writing this course. Each links back to the lesson that explains the context.
Reading Exercises — Understand the Existing Code
- Trace
normalize_due_date("2020-01-01")by hand through every branch of the function. What does it return, and why? (Lesson 09a) - Without running any code, predict the output of
split_text_into_chunks("A" * 1600, chunk_size=800, overlap=100)— how many chunks, and what are the(start, end)boundaries? Then verify by running it. (Lesson 08d) - Read
evaluate_nodeinrag_graph_service.pyand explain, in one sentence, why it checksif not retrieved_chunksbefore callingevaluate_retrieved_contextinstead of always calling the evaluator. (Lesson 08e) - Find every place
os.getenv("OPENAI_MODEL", "gpt-4o-mini")is called directly instead of through a shared constant. How many call sites, and in which files? (Lesson 27)
Debugging Exercises — Fix Real, Verified Bugs
- The
/statsbug.GET /agents/{agent_id}/statsqueriesmodels.Agent.agent_id, which doesn't exist on the model. Fix the attribute reference, then decide: should this endpoint delete the agent (as its current body suggests) or report statistics (as its name andresponse_modelsuggest)? Implement whichever you choose correctly, matchingschemas.AgentStatsResponse. (Lesson 09a) - The double import.
routers/documents.pyimportsgenerate_rag_answerfrom bothopenai_serviceandrag_graph_service, with the second shadowing the first. Clean up the import so only one, clearly-sourced name remains. (Lesson 09b) - The empty-context crash.
openai_service.generate_rag_answerassignssystem_promptanduser_promptinside itsforloop overcontexts. Call it directly withcontexts=[]and observe theUnboundLocalError. Fix the function so it either raises a clear, intentional error for empty contexts or handles them gracefully. (Lesson 08e) - The task ownership gap.
PUT /tasks/{task_id}/statusnever checks which agent a task belongs to. Add an ownership check so a task can only be updated via its own agent's ID in the URL. (Lesson 25)
Writing Exercises — Implement New Features
- Add a sixth environment variable,
OPENAI_TEMPERATURE_OVERRIDE, that if set, overrides the hardcodedtemperature=value in everychat.completions.createcall. Decide whether this should apply uniformly or per-function, and justify your choice. (Lesson 19, Lesson 27) - Give
chat_with_agentreal conversation memory: load the last 10Messagerows for the agent and include them in themessageslist sent to OpenAI. Write a two-turn test conversation that fails today and passes after your change. (Lesson 20) - Implement background processing for document upload using FastAPI's
BackgroundTasks, with a"processing"intermediateDocument.status. (Lesson 18) - Extract the repeated "fetch agent or 404" block (present in 18 of 20 endpoints) into a
get_agent_or_404dependency, and refactor at least 5 endpoints across both routers to use it. (Lesson 10) - Add a
create_embedding_cachedwrapper usingfunctools.lru_cache, and updatesearch_agent_documentsto use it. Measure the latency difference for a repeated identical query. (Lesson 26)
Architecture Exercises — Design Improvements
- Design a shared
utils.pymodule foragent_has_toolandlog_tool_call, currently duplicated betweenrouters/agents.pyandrouters/documents.py. What signature differences (e.g.,log_tool_call's extra cost-tracking parameters inagents.py) do you need to reconcile? (Lesson 09b) - Rewrite
get_agent_dashboardto use grouped SQL aggregation (func.count,func.avg,case) instead of loading everyTask/ToolCall/WorkflowRunrow into Python. (Lesson 24) - Design a fifth node for the Corrective RAG graph — a
low_confidence_nodethat hedges instead of fully answering or fully refusing whenretrieval_evaluation["confidence"]falls in a middle band. Update the conditional edge mapping to support three routes instead of two. (Lesson 17) - Propose a minimal authentication scheme (API key header, or JWT) for this backend, and identify every endpoint that would need a new
Depends(get_current_user)(all 20) versus which, if any, could reasonably stay public (the two health-check endpoints inmain.py). (Lesson 11, Lesson 25)
Building Exercises — Extend the System
- Add a new tool,
sentiment_flagger, following the pattern of the existing four tools (email_analyzer,task_creator,reply_generator,document_search): a newenabled_toolsstring value, a gate check in the relevant endpoint, a new system prompt following the six-prompt house style, and aToolCalllog entry. (Lesson 13, Lesson 19) - Add
.pdfsupport to document upload. Identify exactly which function(s) need to change (hint: only the text-extraction step before chunking) and which stay identical. (Lesson 14) - Write a
pytestsuite covering: one pure-function test, one mocked-OpenAI-client test, and oneTestClientintegration test that reproduces the/statsbug from exercise 5. (Lesson 23)