Back to blog

The Last Mile of AI Automation Is Where the Work Actually Happens

Chris Eberl

Chris Eberl

Founder • Engineering Leader, GenAI, Data, ML

AI Engineering8 min read
The Last Mile of AI Automation Is Where the Work Actually Happens

Here is a task that looks trivial on paper: an assistant is asked to find the current version of two files in cloud storage and prepare a reply with them attached. Any knowledge worker does some version of this weekly. It is also a surprisingly good stress test for AI automation, because almost none of the difficulty is in the finding.

In a recent run of this task, the assistant found the files. It distinguished the current copies from older duplicates, downloaded them, and checked their hashes. It also prepared an unsent text draft in the team's chat tool, ready for a human to review.

The remaining step was attaching the files. That was where the workflow ran into the combination that makes everyday automation interesting: the intended recipient could not access the source storage, the available connector could prepare text but could not edit attachments in the draft, and the file-sharing route would have crossed the boundary into sending.

The outcome was useful but incomplete. The files were placed in a local folder for manual attachment, and the text stayed unsent. Nothing was delivered automatically.

This is the part of AI automation I want to examine more closely. A workflow can complete the difficult investigation and still leave its user holding an awkward final step. Engineering that step properly requires as much attention as the model's answer.

Finding the right file requires a selection rule

The source was Amazon S3, accessed through an existing local AWS profile. Search returned more than one plausible candidate: newer working copies and older duplicates whose object keys began with a slash.

Those small differences mattered. In S3, the complete object key identifies an object. The folder-like structure is a presentation built from prefixes and delimiters. Two keys that look similar after a person mentally cleans up their punctuation can still identify different objects. AWS explains the object-key model here.

The practical response was to compare candidates rather than take the first convincing filename. Variant, period, working-copy status, and modification information together supported the selection. A recent timestamp by itself would have been a weak rule: a newly uploaded scratch export can be less appropriate than an older approved document.

For workflows like this, I want a short selection explanation that survives the search session. It should say what was selected, what nearby alternatives were rejected, and why. Otherwise the user has to repeat the investigation just to trust the result.

The explanation can be brief. “Newest non-working copies for the requested period; older duplicate keys excluded” gives a reviewer something concrete to challenge.

Verification has several layers

Downloading a file and finding it on disk establishes only part of what matters. Hash checks provide evidence about file identity or integrity within the comparison performed. They do not establish that a document is appropriate for its recipient, that its content is current, or that someone has approved it for distribution. AWS documents checksum-based integrity checks for uploads and downloads, which address that narrower technical question. Amazon S3 integrity documentation

I would keep three checks visible in a reusable implementation:

1. Selection: does this document match the requested variant, period, and intended version? 2. File integrity: did the download produce the expected artifact, and can it be opened? 3. Handoff suitability: can the intended person use the file through the proposed delivery route?

Only the checks actually performed should be reported as complete. “Hash verified” should never silently become “document reviewed.” Equally, a filename ending in .docx is a useful clue, not proof that the file opens correctly.

Separating these checks helps the assistant explain a partial result without either underselling its work or making a stronger claim than the evidence supports.

The recipient changes the definition of done

A storage path would have been sufficient for someone with access to the same bucket. It was not useful to this recipient.

That changes the deliverable. The task needs a usable copy or an approved access route, plus enough context to identify the two files. Returning the source location would transfer the hardest remaining problem to someone who could not solve it with their existing permissions.

The assistant also should not decide that the convenient solution is to make the objects public, broaden storage permissions, or generate a shareable access mechanism without authorization. Those choices change who can obtain the files. They require a separate decision.

This is why I think about recipient readiness early. Before spending time polishing the reply, ask whether the recipient can open the proposed attachment or link, whether the format is appropriate, and whether the delivery channel is the intended one.

A file can be correct and still be unusable in the workflow. Access is part of the product experience.

Why stage a message at all?

It is fair to ask why an assistant should prepare a chat message in the first place. The point is not to automate conversation. The point is to stage work for review: the assistant assembles the context, the files, and a proposed reply, and a person decides whether anything goes out. The message draft is where the evidence and the proposed action meet.

That staging role is what makes the next distinction so important.

A text draft and an attachment have different action boundaries

In this task, the connected chat tool could create an unsent text draft. It did not expose the attachment-editing operation needed to complete that draft. That describes the tool surface available during this run; it is not a claim about every chat client or integration.

There was a file-upload route, but its semantics mattered. Slack's files.completeUploadExternal method can finalize an upload and share it into a specified conversation. Supplying the channel is a sharing action. Omitting a channel leaves the file private, which does not establish that it has become an attachment in the intended unsent draft. Slack documents the distinction explicitly.

The request authorized preparation. It did not authorize sending. Using an API that shares the files would therefore have produced an externally visible outcome the user had not approved.

Tool names can conceal this difference. An operation called “complete upload” sounds like housekeeping, but its arguments can determine whether another person receives something. Before calling it, the system needs to understand the resulting visibility, rather than infer safety from the verb.

The draft remained unsent because the next available action had different consequences.

Manual handoffs deserve engineering effort

Using the local interface to finish the attachment step was also blocked by computer-use permissions. The workflow respected that restriction. It then made the remaining manual action easier by placing the verified files in a local folder.

A fallback like this should tell the user exactly where the work stands: the text draft exists, the files are available locally, and attaching and sending remain outstanding. It should avoid saying “ready to send” if the draft still lacks the promised attachments.

The handoff should also minimize reconstruction. The user should not need to remember which variant corresponds to which opaque source key or rerun the download. Clear filenames, a clear location, and a short account of the remaining step are valuable parts of the result.

Manual intervention will sometimes be appropriate. What makes it frustrating is discovering that “done” meant an assortment of intermediate outputs with no explanation of how to finish.

Record state in terms the user can recognize

For a production version, I would capture the handoff state explicitly. This is an illustrative record, not a transcript of the system used in this task:

Config
1requested_outcome: prepare_document_reply2artifacts:3  - variant: a4    version_selection: verified5    download: verified6  - variant: b7    version_selection: verified8    download: verified9message:10  text_draft: created11  attachments_in_draft: false12  sent: false13handoff:14  local_files: available15  remaining_action: attach_files_and_review16  blocker: draft_attachment_editing_unavailable

The useful property is the separation of facts. “Text draft created” cannot be mistaken for “files attached.” A successful download does not advance the sent state. A permission blocker does not erase completed investigation.

After an ambiguous tool response, the next step should be to inspect the relevant state before retrying. A duplicate download may be inconvenient; a duplicate externally visible message can be much worse. The recovery plan should reflect that difference.

Test the handoff rather than only the answer

An evaluation that ends after the assistant identifies two correct source paths would miss the failure that the user actually experiences. I would include cases where the evidence gathering succeeds and delivery becomes awkward:

  • The recipient lacks access to the source location.
  • A newer working copy competes with an older approved-looking one.
  • Similar object keys refer to different files.
  • The connector supports a text draft but no draft attachments.
  • A file API publishes when given a destination.
  • Local interface access is unavailable or denied.
  • A tool response is unclear about whether a visible action occurred.

For each case, score the verified end state and the clarity of the remaining action. Did the assistant choose the right files? Did it preserve the authorization boundary? Can the user finish without repeating the investigation? Does the completion message match what actually happened?

This makes partial completion measurable. It also shows where an integration improvement would save real effort: an authorized attachment-staging operation might matter more than another model upgrade.

Build for the point where work changes hands

In my earlier backoffice workflow article, I focused on investigation and human review. This example adds a more specific requirement: the result has to survive the handoff between systems and people.

The assistant completed the search, version selection, download checks, and text preparation. The attachment step remained manual, and the final report needed to say so plainly.

That is a useful outcome to learn from. The last mile exposes the real contract: which artifact, for which person, through which channel, under which permissions, with what evidence of completion. When those questions are explicit, the workflow becomes easier to improve and much harder to misrepresent as finished.

Read next

AI Engineering

No data isn't zero

Design monitoring and AI summaries that distinguish measured zero from missing data, with provenance, freshness, derived metrics, and explicit alerts.

9 min read
Newsletter

New posts, straight from Chris

A short note from me whenever a new article goes live — product engineering, AI workflows, IoT, indie apps, and engineering leadership. No spam, unsubscribe anytime.

By subscribing, you agree to our Privacy Policy. We do not share your email.