Skip to content
4 min read · 823 words

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

  1. Trace normalize_due_date("2020-01-01") by hand through every branch of the function. What does it return, and why? (Lesson 09a)
  2. 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)
  3. Read evaluate_node in rag_graph_service.py and explain, in one sentence, why it checks if not retrieved_chunks before calling evaluate_retrieved_context instead of always calling the evaluator. (Lesson 08e)
  4. 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

  1. The /stats bug. GET /agents/{agent_id}/stats queries models.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 and response_model suggest)? Implement whichever you choose correctly, matching schemas.AgentStatsResponse. (Lesson 09a)
  2. The double import. routers/documents.py imports generate_rag_answer from both openai_service and rag_graph_service, with the second shadowing the first. Clean up the import so only one, clearly-sourced name remains. (Lesson 09b)
  3. The empty-context crash. openai_service.generate_rag_answer assigns system_prompt and user_prompt inside its for loop over contexts. Call it directly with contexts=[] and observe the UnboundLocalError. Fix the function so it either raises a clear, intentional error for empty contexts or handles them gracefully. (Lesson 08e)
  4. The task ownership gap. PUT /tasks/{task_id}/status never 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

  1. Add a sixth environment variable, OPENAI_TEMPERATURE_OVERRIDE, that if set, overrides the hardcoded temperature= value in every chat.completions.create call. Decide whether this should apply uniformly or per-function, and justify your choice. (Lesson 19, Lesson 27)
  2. Give chat_with_agent real conversation memory: load the last 10 Message rows for the agent and include them in the messages list sent to OpenAI. Write a two-turn test conversation that fails today and passes after your change. (Lesson 20)
  3. Implement background processing for document upload using FastAPI's BackgroundTasks, with a "processing" intermediate Document.status. (Lesson 18)
  4. Extract the repeated "fetch agent or 404" block (present in 18 of 20 endpoints) into a get_agent_or_404 dependency, and refactor at least 5 endpoints across both routers to use it. (Lesson 10)
  5. Add a create_embedding_cached wrapper using functools.lru_cache, and update search_agent_documents to use it. Measure the latency difference for a repeated identical query. (Lesson 26)

Architecture Exercises — Design Improvements

  1. Design a shared utils.py module for agent_has_tool and log_tool_call, currently duplicated between routers/agents.py and routers/documents.py. What signature differences (e.g., log_tool_call's extra cost-tracking parameters in agents.py) do you need to reconcile? (Lesson 09b)
  2. Rewrite get_agent_dashboard to use grouped SQL aggregation (func.count, func.avg, case) instead of loading every Task/ToolCall/WorkflowRun row into Python. (Lesson 24)
  3. Design a fifth node for the Corrective RAG graph — a low_confidence_node that hedges instead of fully answering or fully refusing when retrieval_evaluation["confidence"] falls in a middle band. Update the conditional edge mapping to support three routes instead of two. (Lesson 17)
  4. 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 in main.py). (Lesson 11, Lesson 25)

Building Exercises — Extend the System

  1. Add a new tool, sentiment_flagger, following the pattern of the existing four tools (email_analyzer, task_creator, reply_generator, document_search): a new enabled_tools string value, a gate check in the relevant endpoint, a new system prompt following the six-prompt house style, and a ToolCall log entry. (Lesson 13, Lesson 19)
  2. Add .pdf support 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)
  3. Write a pytest suite covering: one pure-function test, one mocked-OpenAI-client test, and one TestClient integration test that reproduces the /stats bug from exercise 5. (Lesson 23)

← Back to Course Index · Interview Questions →