Lists
A list is a row of values you can change. Index, slice, append, pop, and keep an agent's step memory without losing order.
A list is a row of values. You write it with square brackets and commas. Values keep their order. You can change a list later: add a value, take one off, or replace one. That is why agents use lists as memory. Here, memory means a log of steps. Each thought, tool call, and result can be one item in the list.
A list can hold mixed types, but you usually should not. A list of step strings is clear. A list that mixes numbers, dicts, and None is hard to print and hard to test. Pick one kind of item, or later use a list of dicts with the same keys.
A list keeps order. Append adds a box at the end. That row is the agent's memory.
Memory is a row of boxesMake a list
Values sit in order. The first value is on the left.
memory = [class="tok-s">"user: book a flight", class="tok-s">"thought: need dates"]
tools = [class="tok-s">"search", class="tok-s">"read"]
empty = []
print(memory)
print(len(empty))An empty list is []. Start there, then add steps as the agent works. len(empty) is 0. len counts items, not characters. For a list of strings, len(memory) is how many steps, not how long the text is.
You can write a list across several lines. The commas still separate items. A trailing comma after the last item is allowed and often nicer when you add a row later.
Read, add, and remove
An index is a position number. Counting starts at 0, not 1. So memory[0] is the first item. memory[-1] is the last item. memory[-2] is the second last.
A missing index crashes with IndexError. empty[0] fails. Check len or use a slice when the list might be empty.
| Code | What it does |
|---|---|
memory[0] | First item |
memory[-1] | Last item |
memory[1:] | From index 1 to the end (a slice, a piece) |
len(memory) | How many items |
"search" in tools | True if that value is in the list |
memory.append(x) | Add x at the end |
memory.pop() | Take off the last item and give it back |
memory[0] = "new" | Replace the first item |
append changes the list. It does not give you a new list. It gives you None (Python's "nothing"). Never write memory = memory.append(x). That name would then hold None, and the next append would crash because None has no append.
pop() removes the last item and returns it. pop(0) removes the first item. Popping an empty list raises IndexError. If you need to undo only when there is something to undo, check if memory: first.
in on a list checks values with ==. It scans from the left. For a few tool names it is fine. For a large allowlist, a set (next lessons) is faster. For a log, in asks “did this exact step string already appear?”
memory = [class="tok-s">"user: book a flight"]
memory.append(class="tok-s">"thought: need dates")
print(memory[0])
print(len(memory))
print(class="tok-s">"thought: need dates" in memory)
last = memory.pop()
print(last)
print(memory)If you need the last five steps, use a slice: memory[-5:]. That is a simple memory rule. If the list has fewer than five items, you just get them all. Slices do not crash.
A list of steps
Each turn, append what happened. The list grows. That log is the agent's memory. Print it when you debug. Save it when you test.
You can also pop the last step to undo a bad action. Undo is not magic. It only works if the world outside the list can also be undone. Popping “sent email” from memory does not unsend the email. Use undo for thoughts and uncommitted drafts, not for irreversible tools.
Replace one slot when you correct a field: memory[1] = "thought: need dates and city". The rest of the list stays.
Start with memory = []. After the user message, append. After a thought, append. After a tool result, append. Print len(memory) if you are lost. The length should grow by one per event. If it grows by two, you appended twice. If it stays the same, you printed but did not append, or you appended to a different list.
in checks equality of whole items. "flight" in memory is False if the item is "user: book a flight". Searching inside each string is a loop, not list membership. Keep those two ideas apart.
Lists inside lists
A nested list is a list inside another list. Read it with two indexes: first the outer item, then the inner one.
step = [class="tok-s">"action", [class="tok-s">"search", class="tok-s">"weather"]]
print(step[0]) class="tok-c"># action
print(step[1][0]) class="tok-c"># search
print(step[1][1]) class="tok-c"># weatherKeep this light. Real agent logs usually nest dicts (named fields), not only lists. Named fields are easier to read than “the thing at index 1 of index 1.” Nested lists still show up in tables and in some tool results.
Common mistakes
memory = memory.append(x)storesNone.- Assuming the first item is index 1.
popon an empty list.- Using a list as an allowlist of thousands of names (a set is better).
- Sharing one list across two agents by assignment (
b = a). The next lesson on copies goes deeper; know thatb = adoes not copy. - Forgetting that
appendreturnsNone, then printing that return and thinking the list vanished.
Run to execute this in your browser. Nothing is sent to a server.
Add another append, run, then pop twice. Watch the list grow and shrink. The prints are the story of memory: first, last, count, then a change.
How agents use this
An agent keeps a list of steps. Each turn it appends what it thought, what tool it called, and what it saw. You debug by printing that list. You shorten cost by keeping only the last few items: memory = memory[-8:]. That assignment replaces the name with a shorter list. The old long list is dropped if nothing else points at it.
When people say the agent has memory, they often mean this list was not thrown away between turns. A function that creates a new [] every call has no memory. A function that receives memory, appends, and returns it does. You will write that pattern in the functions lessons. The list is the data. The loop is the user of the data.
Order matters. A set of steps would lose duplicates and order. “search, fail, search again” is a different story from one search. Keep the log as a list. Use other collections for uniqueness and for named fields.
Check your understanding