Build Your Own Agent Loop
Strip an "AI agent" of its mystique and this is what is left: a loop. Read the model’s next move — a tool call or a final answer — run the tool, feed the result back as an observation, repeat until it answers or the step cap trips. This is the ReAct inner loop, and it is a pure, testable function.
The problem
Implement agent_loop(model_outputs, tools, max_steps). Each step consumes the next entry of model_outputs: either {"type": "final", "text": …} (the agent is done) or {"type": "tool", "name": …, "arg": …} (call a tool). tools is a lookup of {name: {arg: result}}. Execute a tool by looking up its result and appending it to observations; if the tool name is unknown append "unknown_tool", if the name is known but the arg is not append "unknown_arg". Stop on a final (status "answered") or when steps reaches max_steps or model_outputs runs out (status "max_steps", answer stays None). Return {"answer", "steps", "observations", "status"}.
model_outputs=[{"type":"tool","name":"search","arg":"cats"}, {"type":"final","text":"felis catus"}], tools={"search":{"cats":"felis catus"}}, max_steps=5{'answer': 'felis catus', 'steps': 2, 'observations': ['felis catus'], 'status': 'answered'}model_outputs=[{"type":"tool","name":"calc","arg":"2+2"}], tools={"calc":{"2+2":"4"}}, max_steps=1{'answer': None, 'steps': 1, 'observations': ['4'], 'status': 'max_steps'}model_outputs=[{"type":"tool","name":"web","arg":"x"}, {"type":"final","text":"done"}], tools={"search":{"a":"b"}}, max_steps=5{'answer': 'done', 'steps': 2, 'observations': ['unknown_tool'], 'status': 'answered'}- One
model_outputsentry is consumed per step;stepscounts entries consumed (including the final). - Tool result:
tools[name][arg]when both exist;"unknown_tool"ifnameis absent;"unknown_arg"if the name exists but the arg does not. Append it toobservationsin order. - A
finalends the loop with status"answered"andanswerset to its text. - Ending any other way —
steps == max_stepsORmodel_outputsexhausted — is status"max_steps"withanswerleft asNone.
Your turn — write it
Edit the stub, hit Run (or ⌘/Ctrl + Enter), and watch the hidden tests. Stuck? the hints are right above and Reveal solution is one click away.
Implement agent_loop(model_outputs, tools, max_steps) — step through the model’s moves, execute tools into observations, and stop on a final answer or the step cap. Return the full result dict.
- Loop while steps < max_steps AND steps < len(model_outputs). Read model_outputs[steps], then increment steps.
- On {"type": "final"}, set answer to its text, status "answered", and break.
- On a tool: check name in tools first ("unknown_tool"), then arg in tools[name] ("unknown_arg"), else tools[name][arg]. Append whichever to observations.
- If the loop ends without a final, answer stays None and status is "max_steps" — this covers both hitting the cap and running out of moves.
Explore the topic
See this challenge alongside everything else on the same subject — handbooks, system designs, algorithms and tools, in one place.