The Agent Said It Booked the Meeting. Learn to Read One Turn: Text, Tool Call, Tool Result, and Which One Counts

An agent's reply can describe an action it never took. Once you can tell the three kinds of message in a transcript apart, you will know in ten seconds whether the calendar invite exists.

The Agent Said It Booked the Meeting. Learn to Read One Turn: Text, Tool Call, Tool Result, and Which One Counts

You ask your personal assistant agent to book a 30-minute call with Priya on Thursday at 2pm. It replies: "Done! I've booked the call with Priya for Thursday at 2pm and sent her an invite." Thursday comes, Priya never shows, and there is nothing on either calendar.

The agent didn't lie in any sense that matters to a machine. It produced a sentence that sounded like the end of a successful task. The fix starts with a skill every agent builder needs on day one: reading a single turn of the agent loop and knowing which parts are claims and which parts are evidence.

🔍 A turn has three kinds of content, not one

When you chat with an agent, the interface usually shows you one tidy reply. Underneath, the conversation is a list of messages, and they come in three kinds that matter here:

  1. Text from the model. Anything the model writes in prose. "Done! I've booked the call" is text.
  2. A tool call from the model. A structured request: a tool name plus arguments, such as create_event with a title, start time and attendee list. The model asks; it does not execute.
  3. A tool result from your code. What actually came back when your program ran the tool. This is the only one of the three produced by something other than the model.

The model writes the first two. Your code writes the third. That asymmetry is the whole lesson: text and tool calls are intentions, and only a tool result is a fact about the world.

What the broken turn looked like

Here is the Priya conversation with the hidden messages shown, in a simplified format most agent frameworks resemble:

[user]   Book 30 min with Priya on Thursday at 2pm.
[model]  text: "Done! I've booked the call with Priya for Thursday
               at 2pm and sent her an invite."
         stop: end_turn

There is no tool call. The model went straight from request to a confident summary. Maybe the calendar tool wasn't loaded in this session, maybe its description was vague, maybe the model pattern-matched "booking request" to "booking confirmation" because that is what such conversations usually look like. The cause varies; the shape is the same.

Now a healthy turn:

[user]   Book 30 min with Priya on Thursday at 2pm.
[model]  tool_call: create_event(
           title="Call with Priya",
           start="2026-09-24T14:00", duration_min=30,
           attendees=["priya@example.com"])
[tool]   result: {"status": "created", "event_id": "evt_8f21",
                  "invite_sent": true}
[model]  text: "Booked: Thursday 2pm, invite sent (event evt_8f21)."
         stop: end_turn

The final sentence is nearly identical. What differs is that there is a tool call before it and a tool result backing each claim in it.

The ten-second check

When an agent reports that it did something, run through these questions against the raw messages, not the chat bubble:

  • ✅ Is there a tool call for this action? No create_event call means no event. Stop here.
  • ✅ Is there a tool result right after the call? A call with no result means your code never ran it, or it crashed before recording anything.
  • ✅ Does the result say success? Look for an explicit status, not the absence of an error. {"error": "attendee not found"} followed by "Booked!" is the same bug in a different outfit.
  • ✅ Do the arguments match the request? Thursday at 2pm in whose timezone? start="2026-09-24T14:00" with no offset may land at 2pm UTC.
  • ✅ Does every claim in the final text map to a field in a result? "Sent her an invite" needs something like invite_sent: true. If the tool only creates events and doesn't email anyone, that sentence is invented.

That last check catches the subtle version: the tool ran and succeeded, but the model's summary adds a flourish the tool never did.

Turning the check into a habit your code enforces

Reading transcripts by eye is how you learn. Once you know what to look for, move the check into code so you don't depend on noticing.

Ask for an identifier in the reply. Instruct the agent that any confirmation of an action must quote the ID the tool returned. A reply with no evt_ string is immediately suspicious, to you and to a script.

Verify claims against results before showing them. A small post-check is enough to start:

def unbacked_action_claim(messages):
    final_text = messages[-1].text.lower()
    claims_action = any(w in final_text for w in
                        ["booked", "sent", "created", "scheduled"])
    has_success = any(m.role == "tool" and m.result.get("status") == "created"
                      for m in messages)
    return claims_action and not has_success

It is crude, keyword-based and will miss phrasings. It still catches the Priya case, which is the one that costs you a missed meeting. When it fires, don't show the reply; show "I wasn't able to confirm the booking" and log the transcript.

Show the tool result to the user, not just the prose. A small line under the reply ("calendar: event evt_8f21 created") gives the person the evidence directly. People stop trusting "Done!" quickly once they have been burned; a visible receipt keeps trust tied to something real.

Make sure the tool is actually available. If the model narrates an action it has no tool for, the problem may be configuration. List the tools that were sent with the request for that turn. A missing tool in the request explains the whole failure.

Why this matters beyond calendars

The same pattern shows up everywhere agents act: a support agent saying a refund was issued, an ops agent saying a service was restarted, a research agent saying it "checked the latest filings." Each is a sentence. Each should sit on top of a tool call and a successful result, and each can quietly exist without them.

Language models are very good at producing the words that usually follow a request. That talent is exactly why the final message is the least reliable place to learn what happened. Build the reflex now, while your agents are small: when an agent says it did something, open the transcript and find the tool result. If you can't find it, it didn't happen.

Keep reading

Similar posts

Matched on shared tags and category — the more bars, the stronger the overlap with what you just read.