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 with jq (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 a Traceback (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 a pyproject.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.

  1. 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”?
  2. In a request, where does an Authorization header live, and why must its value never be written into source code?
  3. 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?
  4. What does try / except let you do that a plain if cannot, and when would you reach for it?
  5. Which uv commands initialize a packaged project, add a dependency, and run a script inside its environment?
Check your recall 1. `GET` (fetch) and `POST` (send/create). `4xx` = client error (your request was wrong, e.g. 401/404); `5xx` = server error (Month 2). 2. In a request *header*; its value is a secret (a password). Committed secrets are scraped and permanently compromised — the Month-2 git-leak lesson. 3. A `dict`. Use `data.get("key")` (returns `None` if absent) rather than `data["key"]` (raises `KeyError`) (Month 3). 4. `try`/`except` catches an *exception* raised at runtime (e.g. a timeout, a bad parse) so the program can recover instead of crashing; an `if` only branches on a value you already have (Month 3). 5. `uv init --package`, `uv add `, `uv run

Table of contents