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:

validate first, act second
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 work

Log 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:

a thin audit wrapper around the tool call
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 result

Keep 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:

📌Ship it safely
  1. Start read-only. Launch with no write/send tools; earn each dangerous capability.
  2. Sandbox first. Prove it against a test environment and fake data before real systems.
  3. Require sign-off. A human approves risky actions until you trust the track record.
  4. Log everything. Full audit trail from day one, stored out of the agent's reach.
  5. 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.