The One Where We Make Contact

Last time on Obi the Explorer, the agent learned. It remembered regulars, kept track of what they liked, and wrote it all down once each conversation was over. I closed on Ava from Ex Machina, and the idea that the dangerous part isn't knowing someone. It's acting on it without asking.
This week, the agent finally acts. Not on you, thankfully. On the kitchen.
If you've watched The Bear, you'll know the sound. An order gets called, and the whole line shouts "yes, chef!" before anyone has touched a pan. Once an order is fired, it's happening. Ingredients come out, prep starts, and someone's evening now revolves around that dish. You can't really un-fire it.
That's the moment this post is about.
It was the same at work. Party bookings sometimes came with food ordered in advance. I'd take it down on the call, then walk it over to the kitchen so they could plan. Now and then, the kitchen came back short on something, and I'd be back on the phone apologising and offering an alternative.
The new requirement
Customers should be able to pre-order dishes for a future reservation. Before anything is confirmed, the system checks the inventory to ensure every ingredient will be available. The kitchen gets to plan, and customers aren't left disappointed.
What it replaces
For pre-orders:
- The host notes the pre-order in the reservation book
- The host tells the chef or kitchen manager manually
- The kitchen checks the current inventory for the ingredients
- For speciality items, the chef orders ingredients specifically for that booking
- If something can't be sourced, the host calls the customer back with alternatives
- The kitchen keeps a separate calendar of special orders
For inventory:
- Kitchen staff count stock daily
- The chef projects what's needed based on reservations and history
- Orders go out to suppliers
- Last-minute adjustments happen when something runs short
Same exercise as always. Step 3 is retrieval. Step 5 is reasoning, working out a decent alternative and phrasing it nicely. But look at step 2 of the first list.
Nothing is being fetched or remembered. The host is telling another team to go and do something. Which, if you've worked in hospitality, can be very annoying. Hopefully, you have a great manager.
The thing that actually changed
Up to now, the agent has only worked inside its own world. It read from and wrote to its own databases. Even the Learning module from last week only wrote to a profile that the agent owns.
Iteration 4 is the first time the agent reaches outside and makes something happen in a system it doesn't own. We're finally ready to make contact with the outside world! The kitchen doesn't hand back data for reasoning. It receives an instruction, and then real people start doing real work.
Obviously, this is where I insert what movie or show my study reminded me of. Today, that's Arrival, one of the best alien invasion movies I've ever seen. Except, it's more of a language lesson. The heptapods turn up, and the whole film is about two completely different worlds trying to make contact without getting each other catastrophically wrong.
That's this iteration. For three weeks, the agent has stayed inside its own walls. Now it has to reach out to a world it doesn't control, one with its own rules and its own way of doing things. Get the message wrong, and something real happens on the other side.
I hate spoilers, so I'm not going to subject you to any. (Yes, I know. Ex Machina. Last week. I've grown since then.) What's important is that you should watch this!!!!!
Back to being serious...
Introducing Tool Integration, everyone. For the uninitiated, a tool is anything that lets the agent do something in the outside world, rather than just read or generate text. Calling an API, sending a notification, writing to someone else's system. In this case, telling the chef to start prepping.
What changed from iteration 3
| Component | Change |
|---|---|
| Semantic Router | Upgraded: now handles a fourth intent, pre-order requests |
| Retrieval — Inventory DB | New: check the ingredients are in stock |
| Decision — can we fulfil it? | New: enough stock or not |
| Tool — Kitchen Notification | New: send the pre-order to the kitchen and alert the chef |
| Reasoning — substitutes | New: suggest alternatives when stock is short |
| Learning module | Upgraded: now also stores pre-order history |
| Everything else | Carried over untouched |
Four new components, and one of them is the first box in this series that can't be undone.
The pre-order path
Router → Pre-order path
→ Check the Inventory DB
→ Enough stock for every dish?
→ Yes → Notify the kitchen → Confirm the pre-order → Learning
→ No → Find substitutes in the Menu KB
→ Suggest them to the customer
→ Loop back
%%{init: {"flowchart": {"curve": "linear", "htmlLabels": true, "nodeSpacing": 36, "rankSpacing": 44, "padding": 12, "useMaxWidth": true}}}%%
flowchart TD
INPUT([Customer Message]) --> GROUND
subgraph GROUND["Grounding Module"]
G1["Parse natural language input<br>Extract intent signals + field values"]
end
GROUND --> STM
subgraph STM["Short-Term Memory"]
M1["Conversation state<br>Track intent + fields + preferences + pre-order details"]
end
STM --> CUST_RET
subgraph CUST_RET["Retrieval Module - Customer Profile DB"]
CR1["Look up customer<br>Fetch: preferences · dietary needs · past orders · reservations"]
end
CUST_RET --> ROUTER
subgraph ROUTER["Semantic Router - LLM"]
SR1["Classify intent:<br>Reservation · Menu Inquiry · Seasonal Query · Pre-order Request"]
end
ROUTER -->|Menu or Seasonal Inquiry| RET_MENU
ROUTER -->|Reservation Request| FIELD_CHECK
ROUTER -->|Pre-order Request| RET_INV
subgraph RET_MENU["Retrieval Module - Menu KB + Seasonal Calendar"]
RM1["Fetch dish details + cross-check seasonal availability"]
end
RET_MENU --> REASON_MENU
subgraph REASON_MENU["Reasoning Module - LLM"]
R_M1["Generate personalised menu answer<br>Highlight seasonal items"]
end
REASON_MENU --> LEARN
REASON_MENU --> MENU_OUT([Menu response sent to customer])
FIELD_CHECK{All required<br>reservation fields<br>present?}
FIELD_CHECK -->|Missing fields| REASON_FOLLOWUP
subgraph REASON_FOLLOWUP["Reasoning Module - LLM"]
R_F1["Generate personalised follow-up question"]
end
REASON_FOLLOWUP --> LOOP_BACK([Loop back to customer message])
FIELD_CHECK -->|All fields collected| RET_SEASON
subgraph RET_SEASON["Retrieval Module - Seasonal Calendar"]
RS1["Check seasonal dishes for booking date"]
end
RET_SEASON --> RET_AVAIL
subgraph RET_AVAIL["Retrieval Module - Reservation DB"]
RA1["Check slot availability: date + time + party size"]
end
RET_AVAIL --> AVAIL_CHECK{Slot<br>available?}
AVAIL_CHECK -->|Yes| DEC_BOOK
subgraph DEC_BOOK["Decision Module"]
D1["Confirm booking + generate reference number"]
end
AVAIL_CHECK -->|No| RET_ALT
subgraph RET_ALT["Retrieval Module - Reservation DB"]
RA2["Query next available slots"]
end
RET_ALT --> REASON_ALT
subgraph REASON_ALT["Reasoning Module - LLM"]
R_A1["Generate alternative slot suggestions"]
end
REASON_ALT --> OFFER([Offer alternatives<br>then loop back])
DEC_BOOK --> LTM_RES
subgraph LTM_RES["Long-Term Memory - Reservation DB"]
LM1["Write booking record"]
end
LTM_RES --> LEARN
subgraph RET_INV["Retrieval Module - Inventory DB"]
INV1["Check ingredient stock levels<br>for all requested pre-order dishes"]
end
RET_INV --> STOCK_CHECK{Sufficient<br>stock for all<br>dishes?}
STOCK_CHECK -->|Yes| KITCHEN_TOOL
subgraph KITCHEN_TOOL["Tool Module - Kitchen Notification System"]
KT1["Write pre-order to kitchen management system<br>Alert chef · schedule prep · log against reservation ref"]
end
STOCK_CHECK -->|Insufficient stock| RET_ALTS
subgraph RET_ALTS["Retrieval Module - Menu KB"]
RAS1["Fetch substitute dishes<br>that match dietary needs + current stock"]
end
RET_ALTS --> REASON_SUBS
subgraph REASON_SUBS["Reasoning Module - LLM"]
R_S1["Generate personalised substitute suggestions<br>Explain unavailability diplomatically"]
end
REASON_SUBS --> SUB_OFFER([Offer substitutes<br>then loop back])
KITCHEN_TOOL --> DEC_PREORDER
subgraph DEC_PREORDER["Decision Module"]
DP1["Confirm pre-order<br>Attach to reservation record"]
end
DEC_PREORDER --> LEARN
DEC_PREORDER --> PREORDER_OUT([Pre-order confirmation sent to customer])
subgraph LEARN["Learning Module"]
L1["Update Customer Profile DB<br>Store: preferences · visit history · pre-order history"]
end
%% Role colours come from docs/stylesheets/mermaid.css (light + dark).
class INPUT source
class GROUND,STM,CUST_RET,ROUTER,RET_MENU,REASON_MENU,REASON_FOLLOWUP,RET_SEASON,RET_AVAIL,RET_ALT,REASON_ALT,DEC_BOOK,LEARN,RET_INV,KITCHEN_TOOL,RET_ALTS,REASON_SUBS,DEC_PREORDER process
class FIELD_CHECK,AVAIL_CHECK,STOCK_CHECK control
class MENU_OUT,LTM_RES,PREORDER_OUT,LOOP_BACK,OFFER,SUB_OFFER outcome
Three decisions worth arguing about
Why is the kitchen notification a Tool and not Retrieval?
Both of them talk to another system, so it would be easy to call them both "integrations" and move on.
I nearly did, but they're different. Retrieval is read-only. It pulls information into the agent's context, and if it fails, you try again, and nothing in the external world has changed. A tool produces a material change. If it fails halfway through, you might not know whether the chef got the message. Retry mindlessly, and the kitchen might prep the same order twice.
Different failure modes, retry rules, and things to watch for. Calling them by the same name hides all of that. Moreover, not acknowledging the difference is how you end up with two birthday cakes and a very confused customer. Yes, I've caused my fair share of confusion. We all learn from mistakes.
Why check inventory before notifying the kitchen?
This one seems obvious once it's written down, but it's probably the rule I'll lean on most for the rest of the series. Never take an irreversible action before all preconditions have been checked.
Reads are cheap. You can check the inventory ten times, and nothing happens. In this scenario, telling the kitchen is not cheap. You can end up with the wrong order or quantity, wasting everyone's time. Once the chef has been told, the order has been fired, and we're back to "yes, chef."
So the agent checks stock first, and it only touches the kitchen once all dishes on the pre-order have cleared. Think of it as checking the fridge before asking someone to start cooking. You'd think that goes without saying, but I can't tell you how many times I've been psyched to cook something, only to find out I don't have the ingredients.
Why do substitutes go back to the customer instead of being swapped in?
When the stock runs short, the agent could pick the closest dish and carry on. It has the menu and the customer's dietary needs from last week, and it could make a decent choice.
It doesn't. It suggests substitutes and hands the decision back.
You may recognise where this comes from. Last week ended with the problem of acting on someone without asking. This is where that line gets drawn in the architecture. The agent is allowed to tell the kitchen what to do because the kitchen belongs to the restaurant, which has approved it. It isn't allowed to decide what the customer eats.
At least, that's how I have chosen to design this.
The capability so far
Four iterations in, and each one has added a different kind of capability:
- Iteration 1: The agent executes a task
- Iteration 2: The agent routes between tasks
- Iteration 3: The agent remembers across tasks
- Iteration 4: The agent acts outside itself
That fourth one is the first where a mistake has real repercussions. A bad booking record is annoying, but the wrong instruction to the kitchen costs ingredients, time, and somebody's patience.
It's also the first path where the order of the steps genuinely can't change. Check the stock, then notify the kitchen, then confirm. If you swap any two, the workflow breaks. Keep that in mind, because it comes back once things start running in parallel.
What's still missing
The agent now reads from five sources, writes to two of its own, and sends instructions to one that isn't internal.
But every answer it gives still comes out in one go. It writes a response and sends it. Nothing checks the work. What happens when it suggests a steak as a substitute to a vegetarian? Or vice versa? Personally, I will shed a tear if a salad is ever suggested to me instead of meat. And what about when it treats an anniversary dinner exactly like a Tuesday lunch?
In a real kitchen, that's what the pass is for. Nothing leaves until someone has looked at the plate. The agent doesn't have a pass yet.
My anniversary is in less than a week. So I'll take this opportunity to shout out to my girl. Love you, babe! (Crisis averted).
Which leaves me with a question I'm still chewing on (get it? I just giggled). If the agent learns to check its own work, who checks the checker?
Next time, it's special occasions, and the agent learns to check its own homework. That story is The One With The Critic.
If you're building agents and trying to figure it out, I'd genuinely like to hear about it.
-
Let's have a virtual coffee together!
Want to see if we're a match? Let's have a chat and find out. Schedule a free 30-minute strategy session to discuss your AI challenges and explore how we can work together.