Month 04 — Python Meets the Network: APIs as a First-Class Citizen
Phase: Foundations
Overview
This is the month the two halves of your foundation fuse. In Month 2 you learned to speak HTTP — you poked at APIs with curl and HTTPie, you read response status codes, you sliced JSON with jq. In Month 3 you learned to write Python — programs, data structures, file I/O, error handling, and a packaged CLI. But you have never once made an HTTP call from inside your own code. That wall comes down now. By the end of the month, the request/response cycle in Python will be muscle memory.
The reason this matters far beyond this month is simple: an agent is a program that talks to a network in a loop. Every model SDK you will use from Month 6 onward — Anthropic, OpenAI, Ollama’s HTTP API — is, underneath the sugar, a POST request with a JSON body and an Authorization header, whose response you parse and act on. Tool use, retrieval, function calling, multi-step agent loops: all of it is HTTP from Python. If you can call the GitHub API end-to-end, handle its failures, and respect its rate limits, you can call any model API. We deliberately practice on a non-AI API first so the network mechanics are solid before the LLM’s nondeterminism is added on top.
So we keep the network honest and visible. You will use the requests library — the de facto standard, readable and synchronous — and take a short look at httpx so you recognize the async future. You will manage secrets correctly with a .env file and python-dotenv, never committing a credential, reusing the git-leak check from Month 2. And — crucially — you will learn that the network fails: connections time out, servers return 500s, and APIs say “slow down.” Production agents that run for hours unattended live or die on how they handle that. So you will hand-roll a retry loop with exponential backoff and jitter — not import one from a library — because understanding the mechanism is the point, and you will reimplement it inside every agent harness later.
The month ends with GitHub Pulse: a real, installable CLI that turns a GitHub username into a Markdown activity report, reads its token from .env, survives rate limits with your own backoff, ships with a small pytest suite, and installs with uv tool / pipx. It is the first program in this course that reaches out into the world and comes back with something useful.
Here is the whole month in one picture — the request/response cycle you will make muscle memory:
flowchart LR
A["Your Python program"] --> B["requests.get / .post"]
B --> C["The network and the API"]
C --> D["Response object"]
D --> E{"Status OK?"}
E -->|"2xx"| F["Parse .json() and use it"]
E -->|"429 / 5xx / timeout"| G["Retry with backoff"]
G --> B
E -->|"4xx (401/404)"| H["Fail fast, do not retry"]
Notice: the same loop powers every model API later — the only thing that changes is the URL and the JSON body.
Prerequisites
Coming in, you should be able to do everything from Months 1–3:
- Speak HTTP and JSON at the conceptual level: methods (
GET/POST), request and response headers, status-code families (2xx/3xx/4xx/5xx), and what a JSON object/array looks like; pretty-print and slice JSON withjq(Month 2). - Run the git-leak check and understand why a committed secret is permanently compromised (Month 2).
- Write and run Python programs: functions, the four core data structures, comprehensions,
try/except, reading aTraceback(Month 3). - Read and write files and round-trip JSON with the standard library (Month 3).
- Build and package a CLI with
uv:uv init --package,uv add,uv run,argparse,[project.scripts]entry points, reading apyproject.toml(Month 3).
You also need a free GitHub account (from Month 1). No paid services and no LLM access are required this month.
Warm-Up: Retrieve Before You Begin
Before reading on, answer these from memory — no peeking at earlier months. This pulls forward the prior skills this month builds on.
- Name the two HTTP methods you used most in Month 2 and what each is for. What status-code family means “you made a mistake” versus “the server broke”?
- In a request, where does an
Authorizationheader live, and why must its value never be written into source code? - In Python, which data structure does a parsed JSON object become, and how do you safely pull a key out of it when it might be missing?
- What does
try/exceptlet you do that a plainifcannot, and when would you reach for it? - Which
uvcommands initialize a packaged project, add a dependency, and run a script inside its environment?