Problem
Producing a formatted Google Doc today takes the two-step flow the google-docs skill teaches: docs.writeText with plain text, then docs.formatText with hand-computed 1-based character indices. The skill spends most of its length teaching the model index arithmetic ("count the \n characters..."), and any miscount styles the wrong range. For agents, markdown is the native output format — the index math is pure failure surface.
Proposal
docs.appendMarkdown(documentId, markdown, tabId?): converts a markdown string to natively formatted Docs content in a single call.
- Supported: headings (
#–######), **bold**, *italic*, ~~strikethrough~~, `inline code`, [links](url), bullet (- ) and numbered (1. ) lists
- One
insertText with the plain text, then one batchUpdate with updateParagraphStyle / updateTextStyle / createParagraphBullets requests computed from parse offsets — no client-side index math ever reaches the model
tabId optional, default tab when omitted (same convention as docs.writeText)
- Not in scope for v1 (documented): tables, horizontal rules, images — they degrade gracefully to plain text / are skipped with counts in the response
No new OAuth scopes (documents already covers it). Complements rather than replaces docs.formatText, which remains the right tool for fine-grained edits to existing text.
I have a working implementation (pure parser module + service method) with Jest coverage ready to submit as a PR.
Problem
Producing a formatted Google Doc today takes the two-step flow the
google-docsskill teaches:docs.writeTextwith plain text, thendocs.formatTextwith hand-computed 1-based character indices. The skill spends most of its length teaching the model index arithmetic ("count the \n characters..."), and any miscount styles the wrong range. For agents, markdown is the native output format — the index math is pure failure surface.Proposal
docs.appendMarkdown(documentId, markdown, tabId?): converts a markdown string to natively formatted Docs content in a single call.#–######),**bold**,*italic*,~~strikethrough~~,`inline code`,[links](url), bullet (-) and numbered (1.) listsinsertTextwith the plain text, then onebatchUpdatewithupdateParagraphStyle/updateTextStyle/createParagraphBulletsrequests computed from parse offsets — no client-side index math ever reaches the modeltabIdoptional, default tab when omitted (same convention asdocs.writeText)No new OAuth scopes (
documentsalready covers it). Complements rather than replacesdocs.formatText, which remains the right tool for fine-grained edits to existing text.I have a working implementation (pure parser module + service method) with Jest coverage ready to submit as a PR.