Today's concept: Python basics for ML - lists, dicts, loops
Every call you'll ever make to an LLM API is a Python list full of dicts. That's it. Learn those two structures plus a for loop and you know the shape of agentic code before writing a line of it.
1) A list is an ordered box you access by position. A numbered coat rack: ["a", "b", "c"], and my_list[0] grabs the first coat. The order isn't decoration, it's the meaning: a conversation is a sequence.
2) A dict is a labeled box you access by name. A filing cabinet with labeled folders: {"role": "user", "content": "hi"}, and my_dict["role"] pulls out "user". Since Python 3.7, insertion order is an official part of the language spec: a cabinet that also remembers the order you filed things.
3) A loop does one action for every item in the box, in order. An agent loop is literally that: send the list, read what came back, append it, send again.
Every major chat API takes a flavor of this, and MCP servers speak JSON-RPC 2.0, so their tool definitions arrive as dicts too.
Where beginners crash: content isn't always a string. In Claude's Messages API it can be a plain string OR a list of content blocks, each its own dict with a "type" (text, image, tool_use, tool_result, thinking). A real agent is dicts nested in lists nested in dicts. Assume msg["content"] is text and your code breaks the moment a tool call shows up. Read block["type"] first.
Ordering is enforced, not stylistic: a tool result goes back as a user message, its tool_result blocks must come FIRST in that content list, and it must immediately follow the assistant turn that asked for the tool. Text ahead of them returns a 400.
The boring data structure is a cost lever too. Prompt caching (the KV-cache trick everyone's tuning now) only hits on a 100% identical prefix: append to the end of the list and everything before it is read from cache; re-word an earlier message and you invalidate it plus everything after. "Append, don't mutate" isn't style, it's your latency and your bill.
Second pressure on the same list: context windows are finite, so eventually you trim it or summarize the middle. Slice carelessly, orphan a tool_use from its tool_result, and yesterday's working request 400s. Most "context engineering" is surgery on one Python list.
Quick check before you scroll: You have messages = [{"role": "user", "content": "hi"}, {"role": "assistant", "content": "hello!"}]. How would you loop through it and print just the content of each message?
Full breakdown + the answer: frankduah.me/learnings/2026-08-19-python-basics-for-ml-lists-dicts-loops
New here? I post a bite-size AI / ML concept like this every day - follow me for the daily drop, and it compounds fast. Why I do it: https://lnkd.in/gK8knHDH
#Python #AI #LLM #AIAgents #MachineLearning
The answer
for msg in messages: print(msg["content"]) - the loop hands you each dict one at a time, and ["content"] pulls the value out of that dict by its label.