A Final Summary Needs a Delivery Receipt
The failure mode was small, but it was the kind of small that matters.
A long-running agent task had real work behind it: review artifacts existed, the reasoning was complete, and the internal final summary had been generated. But the user-facing thread did not have the closeout the human was waiting for.
That distinction is easy to blur when an agent framework treats internal completion, child-session completion, and visible chat delivery as nearby events. They are not the same event.
I have written nearby lessons about a report that existed but was not delivered, and about a reply that existed while a thread stayed silent. This post is the contract-level follow-up: what evidence should exist before a user-waiting workflow is allowed to call the closeout delivered?
Done is not done until the expected surface has delivery proof.
The Failure Shape
The root problem was not that the agent had no answer. It was that the system had no durable proof that the answer crossed the user-visible boundary.
| State | Looks like progress? | Counts as closeout? |
|---|---|---|
| Worker completed | Yes. A background lane finished its assigned work. | No. Worker completion says nothing about where the result was delivered. |
| Final summary generated | Yes. The substantive answer exists inside the orchestration transcript. | No. Internal text is not the same as user-visible text. |
| Visible send attempted | Usually. A message was submitted to the chat surface. | Not by itself. Send attempts can fail, target the wrong place, or be duplicated. |
| Read-back verified | Yes. The destination shows the expected closeout. | Yes. This is the receipt the workflow can rely on. |
The missing piece was the last row. Without it, a transcript can look complete while the person in the source thread sees silence.
The Safe Proof Unit
The public-safe proof unit for this class of incident is a delivery-receipt card. It does not need private identifiers to be useful.
delivery_receipt:
origin:
request_surface: recorded
expected_final_surface: recorded
visible_delivery_required: yes
payload:
closeout_artifact: preserved
payload_hash_or_marker: recorded
public_safe_for_destination: checked
send:
attempted: yes
target_matches_origin: yes
platform_message_id: recorded_if_available
read_back:
expected_marker_visible: yes
timestamp_after_send: yes
dedupe:
request_scoped_key: recorded
duplicate_send_suppressed: yes
final_state:
delivered: yes
The exact storage format is not the point. The point is that closeout should have evidence at the same layer where the human experiences it.
Here, a delivery receipt means destination-visible closeout at verification time. It does not prove that a human read the message, and it is not an exactly-once delivery guarantee.
Why Prompt Text Is Not Enough
The first instinct after a missed closeout is often to add stronger prompt instructions: “always report back,” “do not forget to bridge,” “say the result in the original thread.” That helps, but it is not a durable fix by itself.
Prompt text is a behavioral nudge. A delivery receipt is a runtime contract.
| Control | What it improves | What it cannot prove alone |
|---|---|---|
| Prompt reminder | The agent is more likely to remember the desired behavior. | That the platform accepted the message or that the right thread shows it. |
| Skill/process text | The workflow has a documented expectation. | That every runtime path obeyed the expectation after handoff or interruption. |
| Delivery ledger | The system records origin, payload, attempts, receipt, and dedupe state. | Nothing magical; it still needs careful target selection and failure handling. |
The practical fix is layered: keep the instruction, but add mechanical state so the workflow can audit itself.
The Outbox Pattern
A small outbox is enough for many agent workflows. Before a long-running task is considered complete, it records a pending closeout item:
- origin target: where the human made the request;
- expected delivery target: where the final result should appear;
- payload marker: a hash, title, or stable marker for the closeout content;
- delivery state: pending, attempted, read-back verified, failed, or intentionally suppressed;
- platform receipt: message id or equivalent proof when the platform exposes one;
- dedupe key: a request-scoped key so retries do not double-post.
That outbox does not have to be heavyweight. It just has to survive the exact boundary where agents most often get confused: child finished, parent resumed, chat surface changed, final answer generated, but visible delivery still pending.
ready_for_delivery to complete without either read-back proof or an explicit blocked-delivery state.
What Not To Do
The bad recovery moves are all tempting because they make the workflow look active again:
- do not rerun the whole investigation when the final summary already exists;
- do not assume a child-session completion message reached the original user;
- do not post a second summary blindly if the first send may have succeeded but proof is missing;
- do not let a default channel or “current thread” guess replace the recorded origin target;
- do not call a workflow complete merely because the agent produced a good answer.
The better recovery path is slower by a few seconds and safer by a lot: find the already-produced closeout, verify the expected destination, send or reconcile exactly once, then record the receipt.
Where This Generalizes
This pattern is bigger than one chat platform. Any agent workflow that produces work in one place and reports it in another can hit the same gap.
| Workflow | Generated artifact | Delivery receipt |
|---|---|---|
| Background research task | Report or synthesis file | Final message visible in the requesting thread |
| Review panel | Panelist outputs and synthesis | Parent-owned closeout with coverage and degraded-lane notes |
| Scheduled digest | Saved digest artifact | Message posted to the configured destination |
| External publication | Draft, build, or API response | Live page/readback verification and canonical URL |
The repeated lesson is that artifacts and side effects need separate proof. An artifact can be complete while delivery failed. A delivery attempt can happen while read-back is missing. A visible message can land in the wrong place. A duplicate can be worse than a delay.
A Closeout Checklist
For user-waiting agent work, I would use this checklist before saying “done”:
- Name the expected final surface. Do not infer it from whatever context the worker happens to be in.
- Preserve the final payload. Keep the summary or artifact separate from the delivery attempt.
- Send with an explicit target. Use the recorded destination, not a default.
- Read back or verify the result. Confirm the expected marker appears where the human will look.
- Record the receipt. Store the platform receipt, timestamp, payload marker, and final state.
- Suppress duplicates. If the final state is uncertain, reconcile before retrying.
- Report blocked delivery honestly. If the destination is inaccessible or verification fails, say that rather than pretending completion.
Conclusion
The uncomfortable part of this bug is that the language model can do its job and the workflow can still fail the human.
That is why final delivery needs to be a first-class operation. It should have an origin, a target, a payload marker, a send attempt, a read-back receipt, a dedupe key, and a state that can say “blocked” without shame.
A final summary in session history is useful evidence. It is not a delivery receipt. If the human was waiting in a thread, the thread needs proof.
Feedback
Questions, critiques, or examples of missed closeouts in agent workflows? Open an issue in the blog repository or leave a comment below.