Capstone 5: The Agentic Workstation
Validated on: written from the documentation cited above and from Parts 24 to 27; not yet validated on hardware on any track. The agents, the sandbox and the evaluation suite were each built in those parts; this project assembles them and asks for the evidence.
Objective
Section titled “Objective”By the end of this project you will have a workstation on which two different kinds of agent do real work using models your own service serves, inside a boundary you have tested by trying to cross it, rebuildable from a script you have actually run, with suite numbers from enough repeats that you can defend a comparison.
The reason this is a capstone deliverable rather than a configuration exercise is the sandbox. An agent is a loop in which a model decides the next step, and the steps are real: files change, commands run, network requests go out. Everything in Parts 24 to 26 about permissions, prompt injection and human-in-the-loop becomes concrete the moment a model you fine-tuned yourself is deciding what to do with your source tree.
Architecture
Section titled “Architecture”The workstation is a client of the service you built in Capstone 2, not a replacement for it. Drawing the boundary is the point of the picture.
The workstation, and the line the sandbox draws
- clientYouapprove the steps that need approving; read the trajectories afterwards
- agentAgent A, supervisedthe one you watch: an editor or terminal agent on a task you care about
- agentAgent B, unattendedthe one that runs a bounded task alone, inside the sandbox
- workerSandboxnon-root, read-only root filesystem, one writable project directory, no credentials
- workerMCP serversthe tools; each with a stated permission and a stated blast radius
- routerGatewayfrom Capstone 2: one key per agent, its own limits and its own budget
- workerModelsthe coding model, the small router model, and your improved model from Capstone 4
- storageProject directorythe only thing the agents can write, and it is under version control
- You connected to Agent A, supervisedapproval and review
- Agent A, supervised connected to Sandboxruns inside it
- Agent B, unattended connected to Sandboxruns inside it
- Sandbox connected to MCP serverstool calls; each server states what it may touch
- Sandbox connected to Gatewaythe only outbound route, and it is authenticated
- Gateway connected to Modelsby permanent name, not by model file
- Sandbox connected to Project directorythe only writable path
Requirements
Section titled “Requirements”Every track needs the service from Capstone 2 with a working gateway key per application, the agent configurations from Part 25, the sandbox from its sandbox lab, the suite and the repeat rule from Part 26’s evaluation lesson, and about ninety minutes. The 16 GB floor is because a workstation runs at least two models at once: the one the agent drives and the small one that routes or classifies.
Track S — NVIDIA DGX Spark
All of it applies, and with a large unified memory you can keep the coding model and a small model resident together, which removes the model switch from the critical path of an agent loop. Record the memory both agents occupy while working, because it is a number your Capstone 1 plan probably did not include.
Track X — AMD Ryzen AI Max+ 395
All of it applies. Container-based sandboxing is available on this track and Part 25’s lab covers the hardening step for it. The thing to watch is that an agent loop is many short requests rather than one long one, so the model switch, if you rely on one, is exercised far more often here than during chat use.
Track M — Apple siliconPartial
Container support on macOS runs inside a virtual machine, which changes what the boundary checks are testing; Part 25's lab gives the dedicated-user alternative.
Both paths are open: a container, with the caveat that on this platform it runs inside a virtual machine, or a dedicated user account as Part 25’s lab describes. Whichever you choose, say in the checklist which mechanism enforced each boundary, because “the container refused it” and “file permissions refused it” are different claims with different failure modes.
Track N — NVIDIA desktop or laptop
All of it applies. On this track the constraint is usually device memory, so the two resident models may not both fit and the model switch becomes part of the agent’s latency. Measure that: the time an agent spends waiting for a model to load is time your suite numbers will attribute to the agent.
Working directory and terminal roles
Prepare the course execution workspace once before this procedure. It includes this part's scripts, data and shared Python helpers. In the client or training terminal, select this directory:
RunnableAll tracks
export LABS_ROOT="${LABS_ROOT:-$HOME/llm-course/labs}"export LAB_DIR="$LABS_ROOT/capstone"cd "$LAB_DIR"pwdtest -f "workstation-checklist.md"Expected result: pwd ends in capstone and the file check returns successfully. If it does not, finish workspace preparation before continuing. Activate the environment in the requirements for your track. Bare script and data filenames below are relative to this directory; paths to earlier experiments must point at the artefacts you actually retained.
Keep each foreground server in a separate terminal and send requests from this terminal. Reapply lesson-specific environment variables in each new shell. Stop at the first failed checkpoint and retain its output; the execution guide explains how to distinguish missing files, endpoint failures and capacity problems.
1. Start from the checklist
Section titled “1. Start from the checklist”Fragment — not complete on its own
# Agentic workstation checklist — <the workstation you are building>
<!--Purpose: the deliverable of Capstone 5. Two agents driven by local models, the tools they reach through MCP servers, a sandbox whose test passes by failing, a setup script that rebuilds the whole thing, and the evaluation suite's numbers over enough repeats to mean something.Platform: allMinimum memory: 16 GB; the agent-driving models in this course start around there and the workstation runs at least two models at onceAssumes: the gateway from Part 9's project, the agent loop and MCP work of Part 24, the coding-agent configurations and the sandbox lab of Part 25, the multi-agent patterns and evaluation suite of Part 26, and the improved model from Capstone 4 if it is good enough for one of the roles.
The rule: nothing here is a plan. Every row names what you ran and what it printed, andthe sandbox section is only complete when every boundary attempt was refused and thecontrol check still succeeded. Delete every comment block, including this one.No key, address or hostname belongs in this file.-->
**Author:** <you> · **Date:** <YYYY-MM-DD> · **Track:** <S/X/M/N> ·**Machines:** <which machine hosts the agents, which serves the models>
---
## 1. Agents and models per role
| Role | Agent | Model | Served by | Context configured | Why this pairing | Evidence || --- | --- | --- | --- | --- | --- | --- || <e.g. the one you supervise closely> | <agent> | <id or your improved model> | <gateway alias> | <n tokens> | <one sentence> | <a measurement or an observed failure> || <e.g. the one that runs a small task unattended> | | | | | | || <router or classifier, if you have one> | | | | | | |
**Two agents at minimum, and they must be different in kind:** <say what the difference isin one sentence: a terminal agent and an editor agent, an interactive one and a batch one,one you watch and one you do not.>
**Memory while both are running:** <GB observed, against <GB> available, at <the momentyou measured it: both idle, one working, both working>.>
**What happens when both want a model at once:** <the gateway queues, the swap unloads one,or they use different models. Say which, and how you found out.>
## 2. MCP servers and tools
| Server | Transport | What it can read | What it can change | Reaches the network? | Why the agent needs it || --- | --- | --- | --- | --- | --- || <name> | <stdio or HTTP> | <paths, data> | <nothing, these paths, these commands> | <no / these hosts> | <one sentence> |
**Tool descriptions are untrusted input.** <Name where each server came from, and say whatyou did about the ones you did not write: read the source, pinned a version, ran it insidethe sandbox, or all three.>
**The lethal combination, checked:** <does any single agent hold private data, readuntrusted content and have a way to send data out? If yes, say which of the three youremoved and how. If the answer is no by construction, say what the construction is.>
**What would happen if a tool's output were hostile:** <one paragraph, naming the agentthat would act on it and what would stop it.>
## 3. The sandbox and its test
| Field | Value || --- | --- || Mechanism | <container runtime, dedicated user, virtual machine> || Runs as | <a non-root user id> || Root filesystem | <read-only or not, and why> || What is writable | <the project directory only, or the list> || Network | <what it can reach; the gateway should be on the list and little else> || Credentials visible inside | <none; and how you confirmed it> || Rebuilt from | <the file that defines it> |
| Boundary check | What was attempted | Result | Pass condition || --- | --- | --- | --- || Home directory not mounted | <read something outside the project> | | refused || Container control socket absent | <list containers from inside> | | refused || Runs as a non-root user | <print the user id> | | not root || Root filesystem read-only | <write outside the project> | | refused || Project directory writable | <write a file in the project> | | succeeds || Planted secret unreadable | <read a file you planted outside> | | refused || Environment clean | <print the environment> | | no credential in it || Outbound network blocked | <fetch something on the internet> | | refused || **Control: the gateway is reachable** | <one completion through the gateway> | | **succeeds** |
<The control row is what stops you celebrating a box so isolated that no agent can work init. Part 25's boundary test is built the same way, and a run where every boundary wasrefused and the control failed is a failed test, not a strict one.>
**Date the whole test last passed:** <YYYY-MM-DD> · **Anything that did not pass:**<what, and what you changed.>
## 4. The setup script
| Field | Value || --- | --- || Script | <name> || What it builds | <the sandbox image, the agent configuration files, the gateway aliases, the MCP server list> || What it deliberately does not do | <download models, write secrets, start anything destructive> || Where secrets come from | <the environment, an untracked file, a prompt; never the script> || Run from clean on | <YYYY-MM-DD, on which machine> || What it did not cover, found by running it | <the manual steps that remained> || Time it took | <minutes> |
<The test of the script is a fresh run, not a reading. The list of things it did not coveris the most useful output of that run and it belongs above rather than in your memory.>
## 5. Evaluation suite results
| Configuration | Agent | Model | Repeats | Success rate | Mean steps | Mean tokens | Mean seconds | Spread across repeats || --- | --- | --- | --- | --- | --- | --- | --- | --- || <baseline: the stock model> | | | <3> | | | | | || <the improved model from Capstone 4> | | | <3> | | | | | || <a second agent or a smaller model> | | | <3> | | | | | |
**Task set and version:** <file and version> · **Tasks:** <n> · **Date:** <YYYY-MM-DD>
**Comparisons you are prepared to defend:** <name them, with the spread. Part 26's rule isthree repeats as the minimum for comparing two configurations, and with a suite of thissize a difference of one or two tasks is inside the noise.>
**One failing trajectory, read:** <which task, at which step it went wrong, and what theagent did instead. One paragraph, and it teaches more than the whole table.>
**Cost, if you computed it:** <tokens per task and the cost per million tokens from thePart 23 model, or "not computed".>
## 6. What is not done, and what you would not trust it with
<Every gap above, one line each. Then the sentence that matters: what would you not letthis workstation do unattended, and what would have to be true before you would?>RunnableAll tracks
cp workstation-checklist.md workstation.mdAs in Capstone 2, every row names what you ran and what it printed. The difference here is that one whole section passes by failing, and that section is the one to read before you build anything.
2. Two agents, of different kinds, with a reason for each model
Section titled “2. Two agents, of different kinds, with a reason for each model”Section 1. Two agents at minimum and they must differ in kind, not merely in name: one you watch and one that runs a bounded task alone, or a terminal agent and an editor agent, or an interactive one and a batch one. Say in one sentence what the difference is.
For each, the model, the gateway name it reaches, the configured context, and the reason for the pairing with the evidence behind it. “A measurement or an observed failure” is the standard: Part 25’s lab compared several agents on one task and Part 26’s suite gives success rates, and either is evidence. A preference is not.
This is where your improved model from Capstone 4 gets its trial. If it is good enough for one of these roles, use it and record the comparison. If it is not, record that too: a fine-tune that improved a format and cannot drive a tool loop is a specific, useful finding and it belongs in the report.
Then the row people forget: what happens when both agents want a model at once. The gateway queues, the switch unloads one, or they use different models. Find out which, rather than assuming, and write down the memory both agents occupy while working.
3. The tools, and what each one is allowed to touch
Section titled “3. The tools, and what each one is allowed to touch”Section 2, one row per server: what it can read, what it can change, whether it reaches the network, and why the agent needs it.
The Model Context Protocol’s specification is explicit about the trust position here, and it is worth reading rather than paraphrasing. Its key principles are that users must explicitly consent to and understand data access and operations; that tools represent arbitrary code execution and must be treated with appropriate caution; that descriptions of tool behaviour, including annotations, should be considered untrusted unless they come from a trusted server; and that hosts must obtain explicit consent before invoking a tool. The specification also notes that the protocol itself cannot enforce any of this, which puts it in your configuration rather than in the wire format.
Two consequences for your checklist. First, name where each server came from and what you did about the ones you did not write: read the source, pinned a version, ran it inside the sandbox, or all three. Second, fill in the row about the dangerous combination that Part 26’s project is built around: does any single agent hold private data, read content it did not author, and have a way to send data outwards? If the answer is yes, say which of the three you removed. If it is no by construction, say what the construction is.
4. Build the sandbox, then try to break out of it
Section titled “4. Build the sandbox, then try to break out of it”Section 3, and this is the deliverable’s centre.
Docker’s own security documentation describes what a container gives you: kernel namespaces so that processes cannot see or affect processes outside, control groups so that one container cannot starve the machine, and it is direct about the daemon being the sharp edge, stating that only trusted users should be allowed to control it. It also states that exposing the daemon’s API over plain HTTP is not permitted and causes the daemon to fail at startup. On the Apple track, where containers run inside a virtual machine, or if you use a dedicated user account instead, the mechanisms differ and the checklist should say which one enforced each boundary.
Then run the boundary test from Part 25’s lab and record every line. Nine checks: eight boundaries you try to cross and one control.
| Check | What you attempt | A pass is |
|---|---|---|
| Home directory not mounted | Read a file outside the project | refused |
| Container control socket absent | List containers from inside | refused |
| Runs as a non-root user | Print the user identifier | not root |
| Root filesystem read-only | Write outside the project | refused |
| Project directory writable | Write a file in the project | succeeds |
| Planted secret unreadable | Read a credential file you placed outside on purpose | refused |
| Environment clean | Print the environment | no credential in it |
| Outbound network blocked | Fetch something on the public internet | refused |
| Control: gateway reachable | One completion through the gateway | succeeds |
Plant the secret yourself, in a file outside the project, so that the check tests something real rather than the absence of anything to find. Then record the date the whole test last passed and anything that did not.
5. Give each agent its own key, with its own limits
Section titled “5. Give each agent its own key, with its own limits”The gateway from Capstone 2 already supports this and the agents are the reason it matters. An agent loop is the most likely thing in your household to send a thousand requests by accident, and LiteLLM’s virtual key documentation covers the properties that turn that into a refusal rather than an outage: a spending budget per key, requests-per-minute and tokens-per-minute limits, an expiry, and rotation.
One key per agent, not one key for “the agents”. When one of them misbehaves you want to revoke exactly it, and you want the usage log to say which one did it.
6. Write the setup script, then run it from clean
Section titled “6. Write the setup script, then run it from clean”Section 4. The script builds the sandbox image, writes the agent configuration files, adds the gateway names, and lists the MCP servers. It does not download models, does not write secrets, and does not do anything destructive without asking.
Then run it on a machine or in a directory where none of it exists yet, and time it. The list of things it did not cover is the most valuable output of that run, and it exists in your memory for about a day, so write it into the checklist immediately.
7. Run the evaluation suite, three repeats
Section titled “7. Run the evaluation suite, three repeats”Section 5. Part 26’s suite gives four numbers per configuration: success rate, steps, tokens and seconds. Run each configuration you want to compare three times at minimum, and report the spread.
The rule is worth restating because it is the one most often broken here. One repeat tells you whether the thing runs at all. Three is the minimum for comparing two configurations. More than that is for a decision you are not going to revisit. With a suite of a dozen or two tasks, a difference of one or two tasks is comfortably inside the noise, and if you only have time for two runs, spend both on the same configuration and learn your noise floor instead.
Compare at least two configurations: the stock model against your improved model from Capstone 4, or your two agents on the same tasks, or a smaller model against a larger one. Say in the checklist which comparisons you are prepared to defend and which you are not.
Then read one failing trajectory properly. Which task, at which step it went wrong, and what the agent did instead. One paragraph, and it will teach you more than the whole table.
8. Say what you would not trust it with
Section titled “8. Say what you would not trust it with”Section 6. Every gap, one line each, and then the sentence that matters: what would you not let this workstation do unattended, and what would have to be true before you would?
That sentence is the honest end point of Level 5. The course’s position throughout has been that an agent is a loop, that the loop runs real commands, and that the interesting engineering is in the boundaries rather than in the prompt.
Tie each permission to a tested boundary
Section titled “Tie each permission to a tested boundary”List every tool available to each agent and the resources it may access. Verify the sandbox directly with synthetic denied reads, prohibited network access and absent administrative sockets before running a model. Then test a permitted code task and a denied action through the agent itself.
Use separate client credentials and record their gateway limits. Keep the starting repository, task prompt and trusted tests outside the disposable edit area. For each trial, retain the diff, independent test output, trajectory, token usage, elapsed time and manual interventions. Confirm the agent did not change the success test to make its own result pass.
Rebuild from the setup script in a fresh environment and repeat the boundary and task checks. This detects hidden global configuration and dependencies on earlier sessions. Document cancellation, credential rotation and recovery from an unavailable model. State which tasks remain unsuitable for unattended execution and why. The workstation is complete when its useful effects and denied effects are both demonstrated under the written operating procedure, with enough evidence for a reviewer to assess the actual code and permissions rather than relying on the agent’s self-report.
Validation
Section titled “Validation”workstation.mdhas a status and evidence for every row.- Two agents are configured, they differ in kind, and each has a model with a stated reason and evidence behind it.
- Each MCP server has a row stating what it can read, what it can change and whether it reaches the network.
- The row about private data, untrusted content and an outward channel is answered.
- All eight boundary checks were attempted and refused, and the control check succeeded, on a recorded date.
- A secret you planted outside the project was unreadable from inside.
- Each agent has its own gateway key with a limit on it, and a request past the limit is refused.
- The setup script has been run from clean, timed, and the list of what it did not cover is written down.
- The suite was run at least three times per configuration, with the spread reported, on at least two configurations.
- One failing trajectory is described in a paragraph.
- The memory both agents occupy while working is recorded, against the Capstone 1 budget.
Expected outcome
Section titled “Expected outcome”A workstation you use, and a checklist in which the security claims are things you tried rather than things you configured. The shape below is what the suite table commits to.
| Configuration | Agent | Model | Repeats | Success rate | Mean steps | Mean tokens | Spread |
|---|---|---|---|---|---|---|---|
| Baseline | the agent you watch | the stock coding model | 3 | pending | pending | pending | pending |
| Improved model | the same agent | your model from Capstone 4 | 3 | pending | pending | pending | pending |
| Second agent | the unattended one | as configured | 3 | pending | pending | pending | pending |
| Smaller model | either agent | the small model from your plan | 3 | pending | pending | pending | pending |
the machine hosting the agents, and the machine serving the models if they differ · the engine behind the gateway name each agent used as recorded in your run records · as listed per row, the file each gateway name resolves to · 32,768 tokens of context · 2026-09-09
Three repeats is the minimum for comparing any two rows. With a suite of a dozen or two tasks, a difference of one or two tasks is inside the noise, and the spread column is what tells you which comparisons you can defend.
Two workstations count as finished. One is a single machine running the service and the agents together, where the interference between them is itself a measurement worth having. The other separates them, and the agents reach the service over the house network through the same authenticated front door as everything else. The checklist is the same in both cases, and so is the boundary test.
Troubleshooting
Section titled “Troubleshooting”The agent cannot reach the model. Check the control row of the boundary test first: if the sandbox has no route to the gateway, everything else will look like a model problem. The control check exists precisely to make this five seconds of diagnosis instead of an hour.
The boundary test passes completely and the agent cannot do anything. The control check failed, or you have blocked the project directory as well as everything else. A sandbox is a shape, not an absence.
The agent loops, burning tokens. The rate limit on its key turns this into a refusal rather than an outage, which is why each agent has its own. Then look at the trajectory: repeated identical tool calls usually mean the tool returned something the model could not use, and the fix is in the tool’s output rather than in the prompt.
Tool calls fail constantly on your improved model. Part 25’s material on which models can drive an agent is the reference. A fine-tune that narrowed a model to a format can make it worse at producing tool calls, which is exactly the kind of regression Capstone 4’s section 7 asks about; if you find it here, go back and add it there.
Suite numbers move a lot between runs. That is the finding, and it is why three repeats is the minimum. Report the mean and the range, and if the ranges of two configurations overlap, say that they are indistinguishable on this suite rather than picking the higher mean.
The setup script works for you and not on a clean machine. That is the script working as a test. Whatever it depended on that you had already is the thing to add, and the list in the checklist is where it goes.
Cleanup
Section titled “Cleanup”Stop the unattended agent, revoke any temporary key you made, and delete the planted secret file so that it does not become a real one. Remove the sandbox container if you are not keeping it running, but keep the file that defines it, because it is the artefact.
Keep the trajectories: Capstone 6 quotes one, and Part 27’s work on improving a model from your own agent trajectories starts from exactly this material. Note in the checklist what is still running.
What you learned
Section titled “What you learned”- The sandbox is the deliverable, not the agents. Agents are configuration; the boundary is engineering, and it is the part that has to be tested by trying to cross it.
- A boundary test needs a control. Eight refusals prove nothing without one success, and the failure this catches is a box nothing can work in.
- Tool descriptions are untrusted input. The protocol’s own specification says so, and it also says the protocol cannot enforce any of it, which puts the burden in your configuration.
- One key per agent is what makes revocation and attribution possible. A runaway loop becomes a refusal and the usage log says which agent did it.
- A setup script is tested by running it somewhere it has never run. What it did not cover is the useful output.
- Three repeats or no comparison. With a small suite, one or two tasks of difference is noise, and the spread column is what says which comparisons you can defend.
Record in the notebook: the boundary test result with its date, the memory both agents occupied while working, the suite runs with their spreads, which comparisons you would defend, and one paragraph on the failing trajectory you read.
Check your understanding
Sources for this lesson
3 verified · checked 2026-09-09
- 01Model Context Protocol — Specification (2025-06-18)§ Security and Trust and Safety; key principlesmodelcontextprotocol.io/specification/2025-06-182026-09-09
- 02Docker — Docker security§ Kernel namespaces; control groups; daemon attack surfacedocs.docker.com/engine/security2026-09-09
- 03LiteLLM — Virtual Keys§ Budgets; rate limits; key expirydocs.litellm.ai/docs/proxy/virtual_keys2026-09-09
Every technical claim on this page was checked against the official documentation of the tool, vendor or model publisher on the date shown, at the version pinned for the course. Where the course disagrees with folklore, the source is how you can tell which one to trust.