Capstone: build an agent controller
Write the controller that runs a scripted agent safely - budgets, stuck detection, approvals - then summarize its trace.
- Combine step budgets, stuck detection and approval gates in one controller
- Simulate an environment whose results change as the agent acts
- Summarize a run trace into an operator report
Time to build the part of an agent that you own: the controller. The model’s decisions are given as a script, so you can focus on what the controller must enforce on every step:
- Stop on a final answer.
- Stop when the step budget is used up.
- Gate consequential actions on approval.
- Execute against the environment and record the result.
- Stop when the same action keeps returning the same result.
Then write the report an operator would want after the run: steps, errors, time, slowest call, tools used and why it stopped.
1results = {"run_tests()": ["1 failing", "all pass"]}
2calls = {}
3for _ in range(3):
4 index = calls.get("run_tests()", 0)
5 calls["run_tests()"] = index + 1
6 print(results["run_tests()"][min(index, 1)])1 failing all pass all pass
Key takeaways
The controller enforces budgets, approvals and stuck detection on every step.
Results come from the environment, which changes as the agent acts.
Every run ends with a clear stop reason and a report.
Lesson quiz
5 questions · pass with 4 correct · up to 50 XP
Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.
Practice: write Python
Write Python in the editor and run it against sample inputs. Python runs locally in your browser using a WebAssembly runtime.
Step 1: the controller
Line 1: JSON config {"max_steps", "stuck_threshold", "approvals"} (approvals maps tool names to true/false). Line 2: JSON environment mapping each call to a list of results - the Nth call returns the Nth result (the last one repeats). Then one proposed action per line.
For each action, in order:
answer: TEXT→ printfinal: TEXTand stop.- If
max_stepssteps already ran → printstopped: step budget reachedand stop. - If the tool (the name before
() is inCONSEQUENTIALand its approval isn’t true → printstep N: ACTION -> blocked: needs approvalandstopped: approval denied for TOOL, and stop. - Run it: print
step N: ACTION -> RESULT(error: unknown tool callif not in the environment). - If this action has now returned this result
stuck_thresholdtimes → printstopped: stuck on ACTIONand stop.
If the actions run out, print stopped: no answer.
- Fixes the bug
- Gets stuck
- Blocked deploy
Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.
Step 2: the operator report
Each line is a JSON event {"step", "action", "status", "ms"}, except the last, which is {"stop": REASON}. Print:
1steps: N
2errors: E
3total time: T s (1 decimal)
4slowest: ACTION (X s) (1 decimal; first one on ties)
5tools: NAME COUNT, ... (tool = name before "(", sorted by name)
6stop: REASON- A stuck run
Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.
Questions about this lesson
Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.
Loading posts…