Skip to content

Epic: the emailed-form workflow stops at step 2 — download is broken (#755), Word is unreadable (#763), and only the byte-upload parameter is genuinely missing (#762) #756

Description

@proagentstore

Rewritten 2026-08-28. Two premises in the original were wrong and would have sent an implementer to build things that already exist. Corrections are marked CORRECTION below. The workflow the owner asked for is unchanged and is tracked by the checklist.

The workflow

A form arrives by email. The agent should:

  1. Find and read the message
  2. Put the attachment in the instance file store as a real file
  3. Read the form well enough to complete it
  4. Save the completed output as a new file
  5. Reply in the original thread with that file attached — ideally after a human has looked at it

Concrete case that motivated this:

  • Gmail message 1a00cff038273010, instance e17d538d-6940-4773-80f6-3715c1b2d2fa
  • Junior Comp Hawthorn Entry Form SUMMER 2026:2027.doc (application/msword)
  • Hawthorn Club Championships 2026.docx
  • Reply target: the original Kelly / Hawthorn Tennis thread

This is a high-frequency shape, not an edge case: club entries, school forms, permission slips, supplier forms, onboarding packs, insurance forms. The agent currently reads the email, understands the instructions, names the attachments — and stops exactly where the delegated work begins.

Priority — P2: correctness: three of the five steps are already shipped. What is left is one live defect (#755) and one missing parameter (#762), not a new product area. The one genuinely open question is #764.


Where each step actually stands — VERIFIED

Step Status Where
1. Read the message Shipped gmail_search, gmail_read_messagelib/connectors/gmail.ts:524-549 (#711)
2. Attachment → file store Built, broken gmail_download_attachment refuses the id it was given — #755
3. Read/fill the form PDF only inspect_pdf_form / fill_pdf_form / build_answer_sheetlib/pdf-storage-tools.ts:66-92 (#712). No Word path — #763, #764
4. Save the result as a file Reachable everywhere except from a tool DO route takes contentBase64; upload_file does not — #762
5. Reply in-thread with the file Shipped gmail_reply attachment_file_idslib/connectors/gmail.ts:561 (#713). Draft-before-send is missing — #765

CORRECTION 1 — there IS a binary path; no tool exposes it

The original said "there is no obvious way for an external connector/tool to place an edited binary Word document back into the instance file store." That is wrong at the layer that matters, and building it from scratch would duplicate live code.

  • workers/api/src/agent-do-storage-routes.ts:150-154if (!body.name || (!body.content && !body.contentBase64)) … then const data = body.contentBase64 ? bytesFromBase64(body.contentBase64).slice().buffer : body.content;
  • workers/api/src/routes/storage.ts:167-175 forwards the request body verbatim, so contentBase64 already reaches the DO over HTTP today
  • workers/api/src/lib/connectors/gmail.ts:226 — the Gmail downloader uses it in production right now: contentBase64: base64UrlToBase64(base64url),

What is true is narrower: upload_file is text-onlyworkers/api/src/lib/storage-tools.ts:86, content: { type: "string", description: "File content (text)", required: true } — and so is MCP upload_agent_file (workers/mcp/src/storage-tools.ts:271). That is one parameter, tracked as #762, not an epic.

CORRECTION 2 — step 5 already ships

The original said "the missing binary download/edit/upload path means there may be no usable file ID to attach." The attach path itself is complete and tested: gmail_reply takes attachment_file_ids (connectors/gmail.ts:561), collectOutgoingAttachments (:327-347) resolves each id to real bytes with a 15MB total cap, and gmail.test.ts:409 covers it. Recipients come from the parent message and can never be model-supplied (connectors/gmail.ts:349-356).

What is genuinely missing at step 5 is the draft: both tools state "This really sends: there is no draft step and no undo" (connectors/gmail.ts:556, :570). Tracked as #765 — and it needs no new OAuth scope, because gmail.modify is already requested and recorded.

CORRECTION 3 — .doc and .docx are not one problem, and the user's file is the hard one

The original treated ".doc / .docx forms" as a single gap. They are different problems with different answers:

.docx .doc
Container ZIP of XML OLE2 / CFB compound binary
Readable in a Worker yes — the runtime already uses DecompressionStream twice (agent-storage-utils.ts:200, repo-ingest.ts:205) and already hand-rolls an archive walker (repo-ingest.ts:245, readTar) realistically no

extractFileText handles text and PDF and nothing else — workers/api/src/agent-storage-utils.ts:141-149, catch-all return { text: "", status: "unsupported" };. So both formats land in the store contributing nothing, and read_file refuses them honestly (storage-tools.ts:365-369).

The user's actual attachment is the .doc. A complete .docx implementation would not have finished the reported task. Split as #763 (read a .docx) and #764 (the decision about how far Word fill goes, and whether .doc is in scope at all).

CORRECTION 4 — the "flat form" fallback already exists

build_answer_sheet (pdf-storage-tools.ts:85-92) already generates "a clean PDF of questions and their answers… send it alongside the original rather than attaching an empty form." It was built for flat-scan PDFs, but it is the same answer for a Word form with no structured fields — which is what a club form usually is. This may make the expensive option (true .docx fill) unnecessary; that is the open question in #764.


The children

#755#762#763 is a complete, shippable chain that ends with the agent able to read an emailed .docx and reply with a generated answer sheet. #764 gates nothing except the "fill the original document in place" version of step 3; it must not gate the other four.


The question that needs the owner, not a developer

Is "the agent replies with a clean answer-sheet PDF alongside the original form" an acceptable outcome, or must the returned file be the original document with the values in it?

Answer it on #764. Everything downstream of it — whether .docx write support is built, whether .doc needs an external converter and whether that is acceptable for the owner's documents — follows from it, and it cannot be read out of the code.

Related history: #710 is the closed epic that built steps 1, 3 (PDF) and 5. It left one thing explicitly unverified — "Whether real-world club forms like the motivating one are AcroForms or flat scans… Not reproduced — needs the actual attachment." This issue is the answer, and it is worse than either branch #710 anticipated: they were not PDFs at all.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3: laterDesign, strategy, or deferred pending a decision or demandconnectorsConnector + tool frameworkenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions