Chapter 6 · Part 3
Verify, log & ship
Two habits turn all these defenses into something you can operate, then a checklist to deploy it.
Validate at the boundary
Every tool is an entry point, and the arguments are untrusted. Check them at the top of the tool, before doing anything — the right type, the right range, on the allow-list — and refuse clearly otherwise:
def charge_card(amount, order_id):
if not isinstance(amount, (int, float)) or not (0 < amount <= 1000):
return "Refused: amount must be between 0 and 1000."
if order_id not in known_orders:
return "Refused: unknown order id."
... # only now do the real workLog every action
You will not catch every attack. So make sure you can see what the agent did — record each tool call, its arguments, and whether it was approved. An audit log is how you notice something wrong, review it, and roll it back:
import logging, json
def run_tool(name, args):
logging.info("tool_call %s", json.dumps({"tool": name, "args": args}))
result = TOOL_FUNCTIONS[name](**args)
logging.info("tool_result %s -> %s", name, str(result)[:200])
return resultKeep these logs somewhere the agent can't reach or edit — an injection that can rewrite the audit trail defeats the point.
The deploy checklist
The pattern teams use to put an agent into production in 2026:
- Start read-only. Launch with no write/send tools; earn each dangerous capability.
- Sandbox first. Prove it against a test environment and fake data before real systems.
- Require sign-off. A human approves risky actions until you trust the track record.
- Log everything. Full audit trail from day one, stored out of the agent's reach.
- Monitor and cap. Watch the logs, alert on anomalies, and keep the loop and spend limited.
How it all fits: breaking the trifecta
Every defense in this course removes a leg of the lethal trifecta — and you only need to remove one:
- Least privilege, secrets host-side → cut the private-data leg (a fooled agent can't reach much).
- Allow-lists, approvals, sandboxing → cut the action leg (it can't do the dangerous thing).
- No default egress, confined tools → cut the exfiltration leg (it has nowhere to send it).
Prompt injection will keep coming; you've made it land on an agent that can't do harm. That's what "secure" means for an agent — not unfoolable, but safe to trust with real data and real tools.
You've now built an agent, given it a standard interface with MCP, and locked it down. That's the full arc from a toy loop to something you could actually run.