- Exception emails arrive classified, with shipment context attached, instead of as raw inbox items
- Read-only lookups automated; every state-changing action approved by a person
- Agent behaviour measured against a labelled set before each release
- Every run traceable from email to tool calls to the approved action
Anonymised composite. Client names, identifying details and confidential figures are withheld; public facts are cited in the references.
The situation
A logistics operator's customer service and operations teams handled shipment exceptions largely by email. A late container, a failed delivery, a missing customs document or an address query each arrived as free text, often with attachments, sometimes in a long thread. Staff read each message, worked out which shipment it concerned, looked it up in the transport management system (TMS), decided what to do and then did it, across several screens.
The work was repetitive but not trivial. The hard part of each email was usually the same: identify the shipment, understand the exception, gather the facts. The decision itself was often quick once the facts were on one screen.
What had to be true
- Structured, not chatty: every email becomes a typed exception record, or is routed to a person as unclassifiable.
- Governed tools: the agent reaches systems only through a defined, permissioned tool layer.
- Read freely, write with approval: lookups are automatic; anything with side effects needs a person.
- Inbound email is untrusted and never treated as instructions.
- Measured and traceable: behaviour evaluated before release, every run inspectable afterwards.
Architecture
The design favoured a defined workflow with agentic steps over an open-ended autonomous agent. Anthropic's guidance on building agents makes the same distinction, recommending the simplest pattern that works and adding autonomy only where it earns its keep1.
The data flow, end to end
- ReceiveEmail lands on a queue with its thread and attachments
- ClassifyException type, shipment references and key facts as a typed record
- MatchReferences resolved to a shipment; low confidence routed to a person
- Look upRead-only MCP tools fetch status, milestones and contacts from the TMS
- ProposeDraft action and reply prepared; workflow pauses for approval
- ActOn approval, write tool executes; outcome logged and thread updated
Classification and extraction used structured outputs, where the model's response is constrained to a supplied JSON schema5, so downstream steps receive valid records rather than prose. Approval pauses used LangGraph interrupts, which persist graph state while waiting for human input and resume with that input3. More in structured outputs for reliable LLM integration.
The hard part: tools you can trust an agent with
The model was rarely the weak point. The tool layer was where safety lived. The MCP specification describes tools as model-invoked and recommends that a human can always deny a tool invocation2. The design took that literally:
- Separate read and write servers, with write tools reachable only from the post-approval step of the workflow.
- Narrow tools: "get shipment milestones" and "request redelivery", not a general API passthrough.
- Service identity per tool, scoped to the minimum permissions in the TMS.
- Email as data: inbound text is passed as content to classify, never as instructions, because prompt injection and excessive agency both appear in the OWASP Top 10 for LLM applications4.
The checklist used is in securing MCP servers and prompt injection defence for agents.
Give an agent the narrowest tools that do the job, and put approval in the workflow, not in the prompt.
How it ran
- Classifies and extracts
- Looks up shipment state
- Drafts action and reply
- Reviews the case card
- Approves, edits or rejects
- Handles unclassified mail
- TMS via MCP tools
- Messaging via drafts
- Traces and audit log
- Exception taxonomy
- Labelled sample of emails
- Current handling steps
- Classification and matching
- Lookup tools
- Case cards in shadow
- Write tools behind approval
- Draft replies
- Evaluation gate
- More exception types
- Runbooks and owners
- Autonomy reviews
Evaluation followed evaluating AI agents for reliability, scoring classification, shipment matching and proposed actions separately, so a regression could be located rather than just noticed.
Key decisions and trade-offs
| Decision | Alternative | Why |
|---|---|---|
| Fixed workflow with agentic steps | Open-ended autonomous agent | Predictable, testable paths per exception type |
| MCP tool layer | Direct API calls from prompts | Standard, reusable tools with permissions in one place |
| Approval before side effects | Full autonomy | Trust earned with evidence, not assumed |
| Structured outputs everywhere | Free-text parsing | Typed records that downstream code can rely on |
| Separate scores per step | One end-to-end score | Regressions can be traced to a step |
What I'd do again, and differently
Again: start read-only, build the labelled set from real emails, and keep write tools behind approval. Differently: invest earlier in shipment matching. Ambiguous references caused more escalations than misclassification did, and better matching would have improved every downstream step.
If you are designing agents that touch operational systems, the AI architect page describes how I approach it, or analyse your challenge and bring the result to a call.
- 1Building effective agentsAnthropic
- 2Model Context Protocol specification: ToolsModel Context Protocol
- 3LangGraph interruptsLangChain
- 4OWASP Top 10 for LLM ApplicationsOWASP GenAI Security Project
- 5Structured outputsAnthropic