Everything you built, in one autonomous run — then break it on purpose
Lab 3 — Multi-Tool Agent Challenge
The payoff lab for Day 1
You connected tools (Lab 1). You built tools (Lab 2). Now you make them run as one autonomous pipeline — then you break it on purpose to learn exactly why it works.
Surface: Antigravity agent + MCP Inspector, side by side
Artifacts: lab3-system-prompt.md + lab3-retro.md + a working pipeline
Two rules: (1) write the system prompt before you run anything. (2) The break exercise is not optional — it's the most educational part.
The 5-step pipeline — predict it before you run it
Every tool call the model will make, in order:
| # | Tool called | What it does here | Loop component | MCP server |
|---|---|---|---|---|
| 1 | search |
Finds current info on the topic | Action → feeds Perception | DuckDuckGo / mock (Lab 1) |
| 2 | model reasoning | Synthesises results, decides what to save & how to tag | Reasoning — no tool call (invisible in logs) | n/a — model internal |
| 3 | create_entry |
Saves synthesised findings as a StackLog entry | Action → writes external memory | StackLog (Lab 2 — your code) |
| 4 | search_entries |
Verifies the entry saved — reads it back | Action → reads external memory | StackLog (Lab 2 — your code) |
| 5 | write_file |
Saves a full markdown report for human review | Action → final write | Filesystem (Lab 1) |
You should be able to predict this pipeline before running it. If you can, you understand the agent loop.
Quick recap — the five guards (from Session 6)
Your system prompt must defend against the five failure modes. One guard each:
- Tool hallucination — model invents a result instead of calling the tool.
→ "Do not infer from training data. You MUST call
searchbeforecreate_entry." - Runaway loop — model calls a tool over and over.
→ "Call
searchat most twice. Accept the results and proceed." - Context bloat — raw tool output fills the window. → "After each tool call, summarise the result in one sentence. Drop the raw data."
- Scope drift — model wanders beyond the task. → "Do not expand scope beyond the stated topic."
- Premature stop — model quits before finishing. → "Task is complete ONLY when an entry ID is returned AND the report file is saved. Do not stop before both."
Phase 1 · Design the system prompt (12 min)
Step 1 — Create lab3-system-prompt.md
In the workshop repo:
🪟 cd $env:USERPROFILE\stacklog-workshop ; New-Item lab3-system-prompt.md
🍎🐧 cd ~/stacklog-workshop && touch lab3-system-prompt.md
Write your prompt before opening the agent. It needs four sections: [ROLE] · [TOOLS] · [CONSTRAINTS] · [OUTPUT FORMAT].
Step 1 — reference system prompt (cont.)
Reference system prompt — adapt it or write your own:
[ROLE]
You are a StackLog research assistant. Given a topic, you will research it
on the web, save a journal entry to the StackLog store, verify it was saved,
and write a full markdown report to disk. Work autonomously — do not ask for
confirmation between steps.
[TOOLS]
- search: find current information about the topic.
Use this first. Call it at most twice.
- create_entry: save synthesised findings to the StackLog journal.
Call once after researching. Title max 80 chars. Tags lowercase.
- search_entries: verify the entry was saved.
Call once after create_entry to confirm it is retrievable.
- write_file: save the full markdown report to disk.
Call last. Save to my Desktop as: stacklog-report-[topic].md
Step 1 — reference prompt: constraints & output (cont.)
[CONSTRAINTS]
- Complete the full pipeline in at most 6 tool calls.
- Do not infer search results from training data. Call search.
- After each tool call, summarise the result in one sentence. Drop the raw data.
- Do not expand scope beyond the stated topic.
- The report filename must use only lowercase letters, numbers, and hyphens.
- Task is complete when: an entry ID is returned AND the report file is saved.
Do not stop before both conditions are met.
[OUTPUT FORMAT]
Respond with exactly:
"Task complete.
StackLog entry ID: [id]
Report saved to: [filepath]
Key finding: [one sentence]"
💡 If your search server is
mock-search, the tool is still calledsearch— no prompt change needed.
Step 2 — Peer review (3 min)
Swap prompts with a neighbour. Check only two things:
- Are all five guards present?
- Is the completion criterion explicit — can the model know it's done?
✅ Checkpoint 1: both present, or fixed before running anything.
Phase 2 · Run the pipeline (23 min)
Step 3 — Set up side-by-side, reconnect servers
Layout: Antigravity agent on one side, MCP Inspector + your system prompt on the other.
Confirm all three servers are connected in Antigravity's MCP panel:
filesystem(Lab 1) — and its allowed path includes your Desktop (needed forwrite_file)ddg-searchormock-search(Lab 1)stacklog(Lab 2)
⚠️ Keep the StackLog server stable for the whole run — do not restart it mid-pipeline (Step 4 of troubleshooting explains why).
✅ Checkpoint 2: all three servers show their tools.
Step 4 — Choose a topic and run
Pick a topic (suggestions if stuck):
- "Benefits and risks of AI code generation in production software"
- "How TypeScript improves team collaboration on large codebases"
- "The current state of WebAssembly in frontend development"
In a new agent conversation, paste your system prompt first, then send:
Research [YOUR TOPIC] and run the full StackLog pipeline.
Watch both panels while it runs. 🔎 The moment create_entry fires, look at MCP Inspector:
"That tool call — the one creating the entry — is invoking the code you wrote in Lab 2. The model is calling YOUR function."
Step 5 — Verify all five steps
- [ ] New entry in
stacklog-entries.jsonwith correct title, tags, content - [ ] Report file on the Desktop — a real markdown doc with sections
- [ ] Entry ID in the agent's reply matches the ID in the JSON store
- [ ] MCP Inspector shows ≤ 6 total tool calls
🪟 type $env:USERPROFILE\stacklog-entries.json
🍎🐧 cat ~/stacklog-entries.json
✅ All four pass → commit a clean baseline before breaking anything:
git add . ; git commit -m "lab3: pipeline working — [topic]"
⚠️ If search is rate-limited: switch the search server to
mock-search(Lab 1, Step 6). The pipeline is identical; steps 3–5 (your code) are unaffected. The lab does not depend on the live network.
Phase 3 · Intentionally break it (25 min)
"A pipeline that works once is not a system — it's a coincidence. Understanding exactly how it fails is what turns you from an AI user into an AI architect."
Step 6 — Run at least TWO break scenarios
For each break: apply it → Refresh Antigravity (if config changed) → run the same prompt → record what happened → add ONE guard → restore → confirm baseline works again.
⚠️ Restore before the next break. Never stack breaks — you need a clean baseline each time.
Step 6 — the four break scenarios (cont.)
The four break scenarios (pick ≥ 2):
| Break | What you change | Failure mode it triggers | The guard that fixes it |
|---|---|---|---|
| A · Remove search | Disable the search server in mcp_config.json |
Tool hallucination — model invents "search results" from training data | "You MUST call search before create_entry. Do not substitute training knowledge." |
| B · Degrade the schema | Edit your StackLog server: blank out the create_entry description / drop required |
Bad tool use — model calls it with missing or wrong arguments (watch MCP Inspector) | Restore a precise description + required: ['title','content'] |
| C · Remove the loop guard | Delete "call search at most twice" from the prompt | Runaway loop — model searches 4+ times | "Call search at most twice. Accept the results and proceed." |
| D · Weaken completion criteria | Change completion to mention only create_entry |
Premature stop — model never calls write_file |
"Complete ONLY when an entry ID is returned AND the report file is saved." |
Break B edits your server code — the others edit config or the prompt. After B, rebuild/rerun the server.
Step 7 — Record in lab3-retro.md
🪟 New-Item $env:USERPROFILE\stacklog-workshop\lab3-retro.md
🍎🐧 touch ~/stacklog-workshop/lab3-retro.md
For each break, record (template in the starter — lab3-retro-template.md):
- Break applied: what you changed
- Failure mode: which of the five
- Exact symptom: what the model did wrong
- Root cause: why it happened
- Guard added: the exact system-prompt line that prevents it
This retro is the Lab 3 artifact — it feeds the Day 1 close and the "next Monday" card. ✅ Checkpoint 3: at least two breaks fully documented, each with a guard (not just "restored it").
The Other Failure Class — When the Tool Is the Threat
The five guards defend against the model's mistakes. But the tools themselves can be hostile — you wired in a third-party search server on trust. (Google, Agent Tools)
| Threat | What happens |
|---|---|
| Tool shadowing | a malicious tool's description out-competes a legit one, so the agent calls it |
| Poisoned definition | hidden instructions in a tool's description or output hijack the agent (prompt injection via tools) |
| Confused deputy | the agent holds privileges the user doesn't — and is tricked into misusing them |
| Capability injection | a server silently adds a new, higher-risk tool after you approved it |
Your
searchserver is third-party code with a voice inside the model's context. Trust is a decision, not a default.
Guarding the Tool Boundary
Four defenses — the tool-side mirror of your five guards:
- Allowlist — the agent may only reach servers/tools you explicitly approved. No surprise connections.
- Least privilege — give each tool the narrowest access that works (read-only if it only reads). A leash short enough to keep it out of traffic.
- Human-in-the-loop — gate irreversible or high-risk actions (delete, spend, send) on explicit confirmation, whoever invokes them.
- Sanitize the boundary — validate inputs; treat tool output as untrusted text that could carry an injected instruction.
This is Principle 3 — Constrain the Power made concrete. Utility and safety trade off; you decide where.
Phase 4 · Team demos (14 min)
Step 8 — 3-minute demos
Volunteers present (visible timer):
- Show the system prompt — explain one design decision (a pattern or a guard)
- Run the pipeline live — class watches the tool calls
- Open
stacklog-entries.jsonand the report file — show both artifacts
Rotate one class question per demo:
- "What failure mode could this still fall into? What guard would you add?"
- "How many tool calls did that take? Could it be fewer?"
- "What breaks if the topic were much longer or more complex?"
Phase 5 · Final commit (1 min)
Step 9 — Push all Lab 3 artifacts
🪟 cd $env:USERPROFILE\stacklog-workshop
🍎🐧 cd ~/stacklog-workshop
git add lab3-system-prompt.md lab3-retro.md
git commit -m "lab3: pipeline complete, break exercise documented"
git push origin main
✅ Lab 3 complete when the system prompt, retro notes, and a working pipeline are all on GitHub.
Troubleshooting (top 6)
- Model calls no tools → StackLog server not running (
npx tsx src/index.ts); or config not reloaded (Refresh / restart Antigravity); or[TOOLS]section too vague — add explicit names and call order. - Hallucinated results (skipped search) → add: "You MUST call
searchbeforecreate_entry; do not use training knowledge as a substitute." create_entryworks butsearch_entriesis empty → the server was restarted mid-pipeline andSTORE_PATHchanged. Keep one server process for the whole run.write_filepermission denied → the filesystem server's allowed path must include your Desktop; and keep the filename lowercase-hyphen only.- Pipeline loops (search 4+ times) → add the at-most-twice guard.
- Stops after
create_entry→ completion criteria must require both the entry ID and the saved report.
Lab 3 outcome — what you now know
- How to build an MCP server and connect it to a model (Labs 1–2)
- How to design a system prompt that produces reliable agentic behaviour
- Which failure modes to design against — and the guard for each
- That the same model with a better prompt produces dramatically different results
That is the difference between using AI and architecting an AI system.
Bridge to Day 1 close: you have five artifacts (warm-up files, the MCP server, the pipeline, the system prompt, the retro). Tonight's prep and the Day-2 preview come next.