Tool reference
Wrap any method on NutrientViewer.Instance as a tool. The pattern is always the same: Define an input schema matching the method’s parameters, write an execute function that calls the SDK, and return a plain JavaScript object.
The SDK returns Immutable.js objects. Call .toJS() to convert them before returning to the model.
Reading document content
An agent typically reads the document before taking action, like searching for text, checking what annotations exist, or inspecting form fields.
Searching text
instance.search(term) finds all occurrences of a string across the document. Each result includes the page index and surrounding text, giving the agent context about where content appears:
async function execute({ query }, instance) { const results = await instance.search(query); return results.toJS();}Reading annotations
instance.getAnnotations(pageIndex) returns every annotation on a page: type, text content, bounding box, and ID. The agent uses this to understand what markup already exists before adding or modifying annotations:
async function execute({ pageIndex }, instance) { const annotations = await instance.getAnnotations(pageIndex); return annotations.toJS();}Inspecting forms
instance.getFormFieldValues() returns all field values as key-value pairs. instance.getFormFields() returns metadata: field names, types, and validation options. Together, these provide the form’s structure and current state:
async function execute(instance) { const values = await instance.getFormFieldValues(); const fields = await instance.getFormFields(); return { values: values.toJS(), fields: fields.toJS() };}The result includes field names, current values, and field types (text, checkbox, radio, dropdown). The agent uses the field names when calling setFormFieldValues() later.
Annotating documents
To add an annotation, the agent provides a page index, text content, and a bounding box. The execute function constructs the SDK annotation object from these plain values.
Bounding box coordinates are in PDF points. The origin is at the bottom-left of the page:
async function execute( { pageIndex, text, left, top, width, height }, instance,) { const annotation = new NutrientViewer.Annotations.TextAnnotation({ pageIndex, text: { format: "plain", value: text }, boundingBox: new NutrientViewer.Geometry.Rect({ left, top, width, height, }), }); const [created] = await instance.create(annotation); return { id: created.id };}The SDK supports many annotation types beyond text: ink, shapes, highlights, stamps, and more. See the annotations API reference for the full list. Each type has its own constructor parameters, but the wrapping pattern is the same: Build the SDK object from plain tool arguments, call instance.create(), and return the ID.
To modify an existing annotation, use instance.update(annotation). To remove one, use instance.delete(annotationId).
Working with forms
instance.setFormFieldValues(values) fills in fields by name. The agent passes an object mapping field names to values — the same names returned by getFormFieldValues():
async function execute({ values }, instance) { await instance.setFormFieldValues(values); return { updated: Object.keys(values) };}A typical agent workflow reads the form fields first to discover available field names, and then it fills them in.
Navigating the viewer
instance.setViewState(updater) controls the viewer’s current page, zoom, and layout. These tools help the agent guide the user to relevant content after searching or annotating:
async function execute({ pageIndex }, instance) { instance.setViewState((v) => v.set("currentPageIndex", pageIndex), ); return { navigatedTo: pageIndex };}Editing pages
instance.applyOperations() removes or rotates pages. These operations change the document structure and are irreversible:
async function execute({ pageIndexes }, instance) { await instance.applyOperations([ { type: "removePages", pageIndexes }, ]); return { removed: pageIndexes };}instance.applyRedactions() permanently removes redacted content. instance.exportPDF({ flatten: true }) burns annotations into the PDF. Both are irreversible.
Writing tool descriptions
The description determines when the model selects the tool. Include what the method does, what it returns, and any dependencies on other tools:
"Search the document for a text string. Returns matching locations with page index.""Add a text annotation to a page. Call get_page_info first to understand dimensions.""Remove pages from the document. Irreversible."
Mentioning prerequisites (like calling get_page_info before creating an annotation) helps the model plan multistep workflows.
See the Vercel AI SDK and LangChain pages for how to register these tools with a framework. Any method on NutrientViewer.Instance can be wrapped as a tool using the same pattern; refer to the API reference for the full list.