format_text
Apply bold, italic, or underline styling to exact matching text in Google Docs without altering content, even inside merged table cells. Returns proof of style changes.
Instructions
Apply character styling (bold/italic/underline) to a matched text span.
Use this tool when you need to style existing text in place — bold a
phrase, un-bold it, italicize it — without touching its content. Unlike
replace_text (which deletes and reinserts text and cannot express
styling), this tool compiles ONLY updateTextStyle requests, so it is
safe to use inside a table cell even when the table has hand-merged
cells: no delete/insert/merge request is ever compiled, and the response
reports every compiled_request_kinds entry so that claim is checked,
not just asserted.
Call list_tabs first to get the tab_id, then read_document to confirm the
text you want to style is present as-is. style maps any of
bold/italic/underline to true or false — e.g.
{"bold": true} to bold, {"bold": false} to un-bold. At least one
key is required.
Matching uses the same normalization ladder and match-count guard as
replace_text (exact → curly/straight quote equivalence → NBSP/whitespace
collapse → soft-hyphen strip; refuses unless the match count equals
expected_matches). If the matched text already carries every
requested style value, the call is a no-op: it returns
applied: true, style_mutated: false, and issues no write at all
(so an idempotent re-run does not create a new document revision).
The response includes, per matched span, the actual textRun style flags
before and after (runs_before/runs_after) — not a markdown or
plain-text diff, since genuine bold and a literal **word** both
render identically as text. content_mutated is always false,
proven by compiled_request_kinds containing only updateTextStyle.
Style reflects textRun.textStyle only: a heading rendered bold by its
named/paragraph style rather than an explicit run style will not show
bold: true here, matching every other style read in this server. A
pending style-only suggestion on the target span is allowed through (see
SUGGESTIONS_PRESENT below) and evidence reflects the base, non-suggested
style, same as every read in this server.
Set dry_run=True to preview the operation without writing; the
response carries applied: false and a predicted runs_after
(the requested fields overlaid on the current runs) but makes no API
call.
Errors are returned as typed envelopes with error_code, message,
diagnostics, and retryable so the caller can act on them precisely:
ZERO_MATCH – find string not found; near-miss span included
MATCH_COUNT_MISMATCH – wrong number of matches; all locations listed
STRUCTURAL_BOUNDARY – match crosses a paragraph or table-cell boundary
REVISION_CONFLICT – document changed mid-call; re-read and retry
VERIFICATION_FAILED – the write landed but could not be confirmed on
re-read; check diagnostics before assuming a
manual restore is needed — a concurrent edit
near the target text is a common, benign cause
INVALID_INPUT – empty find, or style is empty/unknown-key/non-bool
TAB_NOT_FOUND – tab_id not in document; available tabs listed
SUGGESTIONS_PRESENT – tab has a pending suggested insertion/deletion
(not a style suggestion); accept/reject it in the
Docs UI first, then retry
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| find | Yes | ||
| style | Yes | ||
| doc_id | Yes | ||
| tab_id | Yes | ||
| dry_run | No | ||
| expected_matches | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||