JJoeven

Curriculum/Python

HTTP and APIs

You ask a server, it answers. Learn methods, status codes, JSON bodies, headers, and timeouts — with fake functions, no network.

intermediate20 min32 / 37

An API is a way one program asks another for data. HTTP is a set of rules for that ask. You send a request (you ask). The server sends a response (it answers).

You ask. The server answers.
RequestServerResponse

Method, path, headers, body go out. Status and body come back. No real network in this box.

You ask. The server answers.

Almost every agent tool is an HTTP API in disguise: search, tickets, email, even the model. Joeven blocks the network. We simulate with functions. No real URLs. No urllib. The shape is what you will keep when you later swap in a client on a laptop.

If you only memorize status codes, you can already branch a tool: 200 read the body, 400 do not retry, 429 retry later, 401 fix the key, timeout fail closed.

You ask, the server answers

A request has parts:

PartMeaningExample
MethodThe verbGET read, POST send
PathWhat you want/tools/search
HeadersExtra labelsAuthorization, Content-Type
BodyThe payloadJSON text

A response has a status code (a number) and a body.

python
request = {
    class="tok-s">"method": class="tok-s">"POST",
    class="tok-s">"path": class="tok-s">"/tools/search",
    class="tok-s">"headers": {class="tok-s">"Authorization": class="tok-s">"Bearer demo"},
    class="tok-s">"body": {class="tok-s">"q": class="tok-s">"rain"},
}
response = {class="tok-s">"status": 200, class="tok-s">"body": {class="tok-s">"hits": [class="tok-s">"bring a coat"]}}
print(request[class="tok-s">"method"], response[class="tok-s">"status"])

GET usually has no body. POST usually has a body. Agents POST JSON a lot: “here is my question.” The path is not the tool name the model sees. Your Python maps search(q) to POST /tools/search. The model should not pick raw paths.

Status codes

The status is the first branch in your tool:

CodeMeaningWhat you do
200OKRead the JSON body
400Bad requestYour args are wrong. Do not retry the same body.
401UnauthorizedMissing or bad key
404Not foundWrong path
429Too many requestsWait, then retry (next lesson)
500Server errorTheir fault. Retry later, or fail

400 means you sent a bad question. Sending it again will fail again. 429 means “slow down.” 500 means the server tripped. 401 means the key is missing or wrong — fix the key, do not keep sending the same call.

A 200 is not always a business win. Some APIs return {"ok": false} with HTTP 200. Read the body too. Branch on both: transport status and business ok.

Timeout is not always a number status. In our fake client it is the string "timeout". A real client raises or returns an error object. Normalize to a dict in one place.

JSON body

Agents usually send and receive JSON — text that looks like a Python dict. Content-Type: application/json is the header that says “this body is JSON.”

You already know json.dumps (Python → text) and json.loads (text → Python). A real client does that for you. Here we pass a dict and pretend. The lesson is the dict’s fields, not the bytes on the wire.

Empty body vs missing q is a 400 in the fake search. That is your validator sitting in front of the “server.” On a laptop the server might 400. Either way, do not retry.

Headers and timeouts

Headers are name tags on the request. Put API keys in Authorization. Never put keys in the prompt. Never put keys in a query string that gets logged. Bearer plus a token is a common pattern. The word Bearer is not the secret. The token is.

A timeout is a max wait. If the server is silent too long, you stop waiting. An agent with no timeout waits forever. In this editor we do not sleep. We compare a fake delay to the timeout and return "timeout".

Retry comes in the next lesson. For now, just see 429 and timeout as results you might retry later. See 400 as a result you must not retry.

A fake server in Python

A dict of (method, path) maps to a handler function. Your tool code should look the same when you later swap in a real HTTP client on your laptop: build a request, call request(...), branch on status.

The fake CALLS dict is global on purpose so you can see 429 after two searches. In a real client, the server owns that counter. Tests should reset state between runs. Here, re-run the box to reset. If you add a fourth search, it should still 429. That is rate limiting as data, not as a lecture.

Authorization is compared as a full string. Extra spaces fail 401. Strip headers if you accept user-supplied keys, but do not log them after strip. 404 means your path table missed. The model should not see 404 for search if your adapter maps names to paths. Map first, then request.

Common mistakes

  • Retrying 400.
  • Logging Authorization.
  • No timeout.
  • Treating 200 as success without reading ok.
  • Letting the model choose method and path.
Live PythonOpen full playgroundpython
Output
Run to execute this in your browser. Nothing is sent to a server.

Read each line. Match the status to the table. The third search is 429. The slow path is a timeout. The missing key is 401.

On a real machine you would write something like: post the URL, send JSON, set a timeout, then branch on the status code. The shape does not change.

Put API keys in headers from the environment. Never in the prompt. Never in logs.

How agents use this

The model endpoint is one more HTTP API: you POST messages, you get text or a tool call. Every other tool is the same shape with a different path. Your Python wraps status codes so the model sees search(q), not 429. If you can handle 200, 400, 401, 429, 500, and timeout, you can wrap the world — even when we fake the network.

Hide HTTP from the loop. The loop should receive {"ok": False, "error": "too many requests"} or a result payload. If the transcript is full of status numbers, the model will try to “fix” HTTP. That is not its job. Your adapter already knows 429.

Timeouts belong on every outbound call, including the model. An agent with an infinite wait is an agent you cannot budget. The fake delay > timeout check is that rule in arithmetic. On a laptop, pass timeout= into the client. Same idea.

Check your understanding

What does status 429 mean?