Four weeks, twenty functions. Week 1 read search. Week 2 added an agent. Week 3 sharpened retrieval. Week 4 wired full RAG with structured output. The capstone is one function that takes a question and gives back a researched, graded answer. What moves do you expect it to make?
Fan out across a handful of query phrasings, dedupe by domain so the agent sees diverse sources, then run the whole set through a structured Pydantic output with answer plus confidence?
Exactly the arc. Three queries, merged retrieval, dedup, structured synthesis. Everything this track taught, composed:
from pydantic import BaseModel
from typing import Literal
class Report(BaseModel):
answer: str
sources: list
confidence: Literal["high", "medium", "low"]So the function takes a list of queries, runs a loop, dedupes the merged results, then hands them as context to an agent with result_type=Report. And the sources list gets overwritten from my Python, not the model.
Exactly. The pattern you learned on Day 25 — let the model produce prose, let your Python own the URLs. Put it together:
def research_assistant(queries: list) -> dict:
seen = set()
merged = []
for q in queries:
for r in search(q, count=3):
domain = r["url"].split("/")[2]
if domain not in seen:
seen.add(domain)
merged.append(r)
context = " ".join(r["snippet"] for r in merged)
urls = [r["url"] for r in merged]
agent = Agent(model, result_type=Report, system_prompt="Answer and rate confidence.")
prompt = f"Context: {context} Queries: {queries}"
data = agent.run_sync(prompt).output.model_dump()
data["sources"] = urls
return dataThe whole function is fifteen lines. Twenty small functions across four weeks, and the capstone is one tight composition.
That's the design lesson: small, single-responsibility pieces compose easily. Dedup is a loop and a set. Retrieval fan-out is a loop of searches. Structured output is Pydantic. Each piece you already know — the capstone is the wiring, not new concepts.
And the output is a deployable research assistant. A caller sends a list of queries, receives a structured report with answer, sources, and confidence — all in one call.
Exactly. Deploy this behind an API and you have a research endpoint. Next week — ai-for-makers — agents start remembering between calls. This capstone is stateless; the next track adds memory.
TL;DR: multi-query retrieval + domain dedup + Pydantic Report + overwritten sources = full research agent.
url.split('/')[2] in a seen setresult_type=Report — answer + sources + confidence| Week | Technique |
|---|---|
| 1 | search(), URL extraction |
| 2 | Agent(model, result_type=...) |
| 3 | dedup + merge |
| 4 | structured RAG output |
Deploy behind an API and the function becomes a research endpoint.
Four weeks, twenty functions. Week 1 read search. Week 2 added an agent. Week 3 sharpened retrieval. Week 4 wired full RAG with structured output. The capstone is one function that takes a question and gives back a researched, graded answer. What moves do you expect it to make?
Fan out across a handful of query phrasings, dedupe by domain so the agent sees diverse sources, then run the whole set through a structured Pydantic output with answer plus confidence?
Exactly the arc. Three queries, merged retrieval, dedup, structured synthesis. Everything this track taught, composed:
from pydantic import BaseModel
from typing import Literal
class Report(BaseModel):
answer: str
sources: list
confidence: Literal["high", "medium", "low"]So the function takes a list of queries, runs a loop, dedupes the merged results, then hands them as context to an agent with result_type=Report. And the sources list gets overwritten from my Python, not the model.
Exactly. The pattern you learned on Day 25 — let the model produce prose, let your Python own the URLs. Put it together:
def research_assistant(queries: list) -> dict:
seen = set()
merged = []
for q in queries:
for r in search(q, count=3):
domain = r["url"].split("/")[2]
if domain not in seen:
seen.add(domain)
merged.append(r)
context = " ".join(r["snippet"] for r in merged)
urls = [r["url"] for r in merged]
agent = Agent(model, result_type=Report, system_prompt="Answer and rate confidence.")
prompt = f"Context: {context} Queries: {queries}"
data = agent.run_sync(prompt).output.model_dump()
data["sources"] = urls
return dataThe whole function is fifteen lines. Twenty small functions across four weeks, and the capstone is one tight composition.
That's the design lesson: small, single-responsibility pieces compose easily. Dedup is a loop and a set. Retrieval fan-out is a loop of searches. Structured output is Pydantic. Each piece you already know — the capstone is the wiring, not new concepts.
And the output is a deployable research assistant. A caller sends a list of queries, receives a structured report with answer, sources, and confidence — all in one call.
Exactly. Deploy this behind an API and you have a research endpoint. Next week — ai-for-makers — agents start remembering between calls. This capstone is stateless; the next track adds memory.
TL;DR: multi-query retrieval + domain dedup + Pydantic Report + overwritten sources = full research agent.
url.split('/')[2] in a seen setresult_type=Report — answer + sources + confidence| Week | Technique |
|---|---|
| 1 | search(), URL extraction |
| 2 | Agent(model, result_type=...) |
| 3 | dedup + merge |
| 4 | structured RAG output |
Deploy behind an API and the function becomes a research endpoint.
Create a free account to get started. Paid plans unlock all tracks.