Skip to main content

OCR Text (Google Vision)

This document covers ocr_text, which returns the exact page-by-page text of a document using Google Vision. No LLM reads or rewrites the pages, so the output cannot truncate mid-schema, summarize, or hallucinate documents — the failure modes that make LLM-driven splitting fragile on large multi-document bundles. Use it when you need faithful page-addressed text for evidence lookup or citation, or when LLM-based splitting/parsing of a file fails and you still need its content.

Authentication and enablement

No integration binding and no user credentials. The tool downloads the file through the platform’s file storage and calls the deployment’s Google Vision credentials (google_vision.api_key), which are already covered by the outbound-call audit — using this tool adds no new outbound HTTP surface. DefaultEnabled is false: the tool must be explicitly enabled per agent. On a deployment where google_vision.api_key is unset, the tool still registers (so it is visible in the UI) but every call fails loudly rather than silently returning empty text.

Inputs

Omit both page fields to OCR the whole file. For large documents, window the work: pass start_page/end_page and call the tool once per window, the same way batched extraction does. Returned page numbers are always the original document’s page numbers, so citations stay addressable against the source file no matter how the document was windowed. end_page without start_page, a negative page number, end_page below start_page, or a page window on a non-PDF file are all rejected before any OCR runs.

Output

Structured content:
page_count is the number of pages in this call; total_pages is the whole document. start_page / end_page are the first and last original page numbers present in pages. total_chars counts runes, not bytes.

The result is stored as a variable

Each successful call registers its structured content as a task variable and the result carries the handle as output_variable. Reference it in a later tool’s arguments instead of copying the text into the call:
  • "ocr_result": "${VAR_5}" — the whole window, as JSON. Use this form for a string-typed field, which is what both current consumers declare.
  • "pages": "${VAR_5}.pages" — just the page array, for a field declared as an array.
Match the form to the field’s declared type. The accessor form strips the surrounding quotes and splices a raw JSON array, and binding coercion only converts string→other at the top level — never inside input. Handing an array to a type: string field means the tool receives a list where it expects a dict, its isinstance(...) check fails, and the OCR context comes through empty with no error. Always pass the reference rather than the text. A page window is 10–30KB, and a model that retypes it into the next call corrupts the JSON often enough to matter: on one production task, 3 of 5 downstream calls failed on a surplus brace or a stray escape, each failure silently dropping a 40-page window from the result. One variable is created per call, so a document OCR’d in ten windows produces ten variables. They are told apart by their metadata (filename and page range), which is shown next to each ${VAR_N} — the model can pick the right window without loading any of their text. Under harness_v2, an oversized result is collapsed in the model’s context to its ${VAR_N} plus a short preview. The text is still passable to any tool via the reference, and still readable on demand via request_variables. Agents that need the model itself to read the page text on every turn should not enable harness_v2. OCR variables are the one type not auto-injected into a bare python_code_tool call’s input dict. Other variables arrive there as input['VAR_N'] whether the program asked for them or not; a document’s page windows would be hundreds of KB of text the program mostly does not read. Pass the window you want explicitly — "ocr_result": "${VAR_5}" — and it arrives like any other argument.

Limits and behaviour

  • Cost: billed per call (flat), independent of page count. Window a large document to keep each call’s payload manageable, not to save money.
  • Malformed PDFs degrade rather than fail. If the page count cannot be read or the requested range cannot be sliced, the tool OCRs the whole file and filters down to the requested window. The output is the same; the call is slower and costs a full-document OCR.
  • Rotation: per-page rotation detected during a whole-file OCR is persisted to the source file for the review viewer. It is deliberately skipped for windowed calls, where the OCR engine’s page numbers are range-relative and would be recorded against the wrong pages.
  • Images have no page dimension and always come back as a single page numbered 1.
  • Word order within a page is Vision’s reading order. Layout, tables, and column structure are not reconstructed — if you need fielded data, use an extraction tool.

Errors

All of these come back as a normal tool error (isError: true) with a readable message, never a crash: A failed call registers no variable, so a downstream tool can never be handed an empty ${VAR_N} that reads as “the document was blank”. A call that succeeds but produces no pages (a fully blank window) likewise registers nothing.