---
title: "Governing what AI Assistant agents can do to a document"
canonical_url: "https://www.nutrient.io/blog/ai-assistant-agent-governance/"
md_url: "https://www.nutrient.io/blog/ai-assistant-agent-governance.md"
last_updated: "2026-10-02T18:14:32.916Z"
description: "Control what an AI agent can access and do to a document with Nutrient AI Assistant: Reusable agent configurations, scoped delegation, and access rules."
---

**TL;DR**

- **Nutrient AI Assistant** embeds a document-aware AI agent in an application that can answer questions about a document. In Nutrient Web SDK’s editing mode, it can also edit the document directly. AI Assistant 2.4.0 adds three ways to control and prove what that agent is allowed to do.

- **Saved agents** turn an agent’s configuration into a reusable, versioned resource on the server instead of a payload resent on every request.

- **Subagents** let one agent delegate part of a task to a narrower, separately scoped agent, instead of one agent’s toolset growing without limit.

- Two JSON Web Token (JWT) claims restrict which documents, layers, and saved agents a given request can even reach.

- A security or compliance team can now see which agent configuration touched a document, what it was allowed to access, and whether that’s still true. Before, the answer was “check the code that called it.”

**Call to Action**

Explore Nutrient AI Assistant

[Learn More](https://www.nutrient.io/sdk/ai-assistant/)

Under the hood, AI Assistant connects a large language model to a document. In a chat-style, read-only mode, end users can ask it questions across Web, iOS, Android, and Nutrient’s other SDK-based viewers. In Nutrient Web SDK’s editing mode, an agent goes further: Describe an edit in plain language, and it makes the edit directly. It can fill a form, redact a clause, or add an annotation. Every one of these capabilities runs as a configured “agent.” An agent is a system prompt, a set of tools the model can call, and rules for which calls need a human’s approval first.

An agent’s tool-calling and delegation decisions are the least predictable part of the system, because they’re the model’s judgment call, not fixed application code. More autonomy is only worth granting with a clear answer to who configured the agent, what it’s allowed to touch, and whether that configuration changed. That echoes [the case Nutrient’s CTO made in May](https://www.nutrient.io/blog/cto-ai-playbook-accountability-architecture.md) that autonomy and accountability should scale together. A January post, [introducing agentic document editing](https://www.nutrient.io/blog/introducing-agentic-document-editing-for-web-applications-with-ai-assistant/), listed workflow templates among the areas it was exploring next: “preconfigured agent behaviors for common use cases.”

AI Assistant 2.4.0 delivers on that in three parts. Saved agents make a preconfigured behavior a real, reusable resource. Subagents give delegation a boundary instead of letting one agent’s scope grow indefinitely. And a pair of JWT claims decide which documents and which saved agents a request can reach in the first place. [Studio](https://www.nutrient.io/guides/ai-assistant/changelog.md#2.4.0) is a new built-in screen for configuring and testing an agent. It’s where a saved agent gets created, edited, and versioned without writing JSON by hand.

## What this looks like end to end

Take a contract-review tool as an example. Someone configures a `contract-review` saved agent once: a legal-analyst prompt, with reads allowed by default and any edit held for approval. Every reviewer’s session points at that one versioned resource from then on.

When a reviewer opens a specific contract, the application doesn’t hand the agent access to the whole deployment. Instead, it issues a JWT scoped with `allowed_documents` to that one document. On [Document Engine](https://www.nutrient.io/sdk/document-engine/), Nutrient’s self-hosted document server, that scoping goes one level deeper, down to the reviewer’s own layer. Two people marking up the same contract never see each other’s edits. An `agents` claim grants `run` and `read` on `contract-review` alone — whatever else lives in the saved-agent catalog, this token can’t reach it.

Inside the run, when `contract-review` needs to cross-reference a clause, it delegates that lookup to a `researcher` subagent. The subagent can only read, never write, and it’s restricted to a single Model Context Protocol (MCP) server instead of the reviewer’s full toolset. The main agent gets back an answer, not a transcript of how the subagent got there. When `contract-review` is ready to act on its findings, filling a field or flagging a clause for redaction, that write pauses for the reviewer’s approval. That follows the approval policy the saved agent defines.

Those are the three pieces working as one workflow. Every reviewer points to a versioned configuration, and a narrower delegate can’t write. The token can’t reach past the one document, one layer, and one saved agent it was actually issued for. The rest of this post is that same workflow, one layer down.

## A saved agent is a resource, not a prompt

An integration selects a built-in agent with `agentId`: `chat`, `agentic`, or `base`. It can layer a custom configuration on top by sending `agentConfiguration` on every request. That works, but the configuration lives only in application code. There’s nothing to point to when someone asks which version of the `contract-review` agent ran last Tuesday, or what its instructions actually said.

Saved agents fix that by moving the configuration onto the server, where it has an ID and a version history. The following request creates one:

```bash

curl -X POST "$BACKEND_URL/inference/api/v2/agents" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "contract-review",
    "context": {
      "systemPromptTemplate": "You are a legal document analyst. Cite the clause number for every finding.",
      "toolApproval": { "defaults": { "default": "allow", "write": "ask" } }
    }
  }'

```

`toolApproval` is the setting that decides which of the agent’s actions need a human to confirm before they run. Here, anything the agent reads is automatic, but anything it writes to the document pauses for approval. The client selects the saved agent exactly like a built-in preset:

```js

PSPDFKit.load({
  aiAssistant: {
    sessionId: 'session123',
    jwt: 'your-jwt-token',
    backendUrl: 'http://localhost:4000',
    agentId: 'contract-review',
  },
});

```

Every update creates a new version and makes it current, so an earlier configuration can be inspected or restored instead of overwritten silently. That replaces “some code somewhere sends this prompt” with “here’s exactly what version of the `contract-review` agent was live on any given day.”

## Delegation with a fence around it

A single agent whose tools, prompt, and scope keep expanding is the specific risk named above. Past a certain point, nobody can reason about what it might do. Subagents are the alternative. A subagent is a named, separately configured agent with its own narrower instructions and limits. The main agent can hand it part of a task:

```json

{
  "subagents": [
    {
      "name": "researcher",
      "description": "Searches documents. Cannot modify them.",
      "mcps": [{ "transport": "inmemory", "name": "nutrient-ai-assistant" }],
      "toolApproval": { "defaults": { "default": "deny", "read": "allow" } }
    }
  ]
}

```

This hands research off to a subagent named `researcher`. Its `toolApproval` denies everything but reads, and `mcps` narrows it to one MCP server instead of the main agent’s full toolset. MCP is a standard way of exposing a defined set of tools to an AI model.

A subagent inherits every field it doesn’t declare. Declaring a field replaces the inherited value rather than merging with it, so `researcher` has only the listed MCP server and approval policy. That holds regardless of the main agent’s permissions. The isolation runs deeper than tool access: The main agent only ever sees the subagent’s final answer, not its intermediate steps.

An inline subagent can’t declare subagents of its own, though a saved agent it references can. That’s how a bounded delegation tree gets built instead of an unbounded one. References nest up to five levels deep, with up to 64 subagents in a single run.

## Scoping access before a tool ever runs

Saved agents and subagents govern what happens once a request is already running. Two JWT claims decide whether it should be running at all.

`allowed_documents` limits a token to specific documents and, in Document Engine mode, to specific layers of those documents. A layer is a distinct set of changes, such as annotations or form fields, stored alongside the same underlying document. Independent reviewers can each work in a separate layer without seeing each other’s edits.

The claim resolves like this:

- An entry with no layer authorizes only that document’s default layer. Any other layer of that document is rejected unless the layer itself is also listed.

- The literal string `"any"` grants access to every document.

- An empty array (`[]`) grants access to none; omitting the claim entirely behaves like `"any"`.

The `agents` claim does the same for saved agents themselves. `create` is a standing, collection-wide grant, while `access` maps specific `agent_id` values to `read`, `run`, `update`, and `delete`. These don’t imply each other: A token with `run` access to `contract-review` still can’t list its version history unless `read` is granted too. Built-in presets stay readable and runnable regardless of this claim; they just can’t be created, updated, or deleted.

The `agents` claim is strictly validated: An unrecognized property, an unsupported action, or a value of the wrong type doesn’t get silently ignored. Validation rejects the token with a `401`.

## Why this matters beyond the API

None of the three additions change what a model decides to do with a document. They change what’s true about the request before the model ever sees it, and that’s where the real payoff sits.

For a developer, it means an agent’s configuration, its delegation, and its access are now the same kind of resource as the document itself. Each is versioned, addressable, and scoped, instead of implicit in application code. For a security or compliance reviewer, it’s the difference between a demo and something a production review will actually sign off on. The reviewer gets a written answer on file, not a promise to go check the code.

## Getting started

- [AI Assistant developer guides](https://www.nutrient.io/guides/ai-assistant.md) — The full guide index, including setup, model providers, and viewer integration.

- [Agents](https://www.nutrient.io/guides/ai-assistant/features/agents.md) — Select a built-in agent or create and version a saved one.

- [Subagents](https://www.nutrient.io/guides/ai-assistant/features/subagents.md) — Configure delegation, inheritance, and tool scoping.

- [Generate a JWT](https://www.nutrient.io/guides/ai-assistant/viewer-integration/client-authentication/generate-a-jwt.md) — The full claim reference for `allowed_documents` and `agents`.

**Call to Action**

Get started with Nutrient AI Assistant

[Learn More](https://www.nutrient.io/sdk/ai-assistant/getting-started.md)

## FAQ

#### What is AI Assistant?

AI Assistant is a Nutrient SDK capability that embeds a document-aware AI agent in an application. It can answer questions about a document in a read-only chat mode, available across Web, iOS, and Android. In Nutrient Web SDK’s editing mode, it can also make edits directly, such as filling a form or redacting a clause.

#### Does a saved agent replace <code>agentConfiguration</code>?

No. `agentConfiguration` still works for a one-off configuration sent from the client on a single session. A saved agent is for a configuration used repeatedly. Create it once on the server, and select it with `agentId` the same way a client selects a built-in preset.

#### Can a subagent have its own subagents?

An inline subagent can’t declare subagents of its own. A subagent that references a saved agent can, because the saved agent may itself have saved subagents. References nest up to five levels deep, with up to 64 subagents in a single run.

#### Is the <code>document_ids</code> claim still supported?

It’s deprecated in favor of `allowed_documents`. Omitted or empty values behave the same way in both claims. A token that carries both `document_ids` and `allowed_documents` is rejected with a `401`.

#### Does granting <code>run</code> access to a saved agent also grant <code>read</code> access?

No. `read`, `run`, `update`, and `delete` are independent grants in the `agents` claim’s `access` map. A token needs each action listed for every saved agent it should reach, unless the `"*"` action grants them all.
---

## Related pages

- [The business case for accessibility: Five ways it drives enterprise value](/blog/5-ways-accessibility-drives-enterprise-value.md)
- [Accessibility Untangled Why It Matters Guide](/blog/accessibility-untangled-why-it-matters-guide.md)
- [Advanced Techniques For React Native Ui Components](/blog/advanced-techniques-for-react-native-ui-components.md)
- [`vector_store` holds your indexed documents (see the multimodal RAG post](/blog/agentic-rag.md)
- [How to build an AI agent for contract redlining against a compliance playbook](/blog/ai-contract-redlining-compliance-playbook.md)
- [Ai Document Automation Extraction To Action](/blog/ai-document-automation-extraction-to-action.md)
- [Ai Document Workflows Ocr Compliance Heavy Teams](/blog/ai-document-workflows-ocr-compliance-heavy-teams.md)
- [Ai Legal Assistant Document Authoring](/blog/ai-legal-assistant-document-authoring.md)
- [Ai Schema Generator Document Extraction](/blog/ai-schema-generator-document-extraction.md)
- [Amazon Textract Alternatives](/blog/amazon-textract-alternatives.md)
- [Start (clears any prior buffer), navigate the document, then stop into a file.](/blog/android-faster-pdf-rendering.md)
- [Android Pdf Out Of Memory Handling](/blog/android-pdf-out-of-memory-handling.md)
- [Angular File Viewer Pdf Image Office Files](/blog/angular-file-viewer-pdf-image-office-files.md)
- [Approval Workflow Software](/blog/approval-workflow-software.md)
- [Approvals Matrix](/blog/approvals-matrix.md)
- [Apryse To Nutrient Migration](/blog/apryse-to-nutrient-migration.md)
- [Auto Tagging And Document Accessibility In Dotnet Sdk](/blog/auto-tagging-and-document-accessibility-in-dotnet-sdk.md)
- [Simple PII redaction.](/blog/automated-pii-removal.md)
- [Azure Document Intelligence Alternatives](/blog/azure-document-intelligence-alternatives.md)
- [Best Ai Document Workflow Platforms](/blog/best-ai-document-workflow-platforms.md)
- [Best Document Ai Platforms](/blog/best-document-ai-platforms.md)
- [Best Document Classification Platforms](/blog/best-document-classification-platforms.md)
- [Best document parser for RAG: LlamaParse vs. Unstructured vs. Reducto vs. Nutrient](/blog/best-document-parser-llamaparse-unstructured-reducto.md)
- [Best Document Parsing Apis](/blog/best-document-parsing-apis.md)
- [Best Document Viewers](/blog/best-document-viewers.md)
- [Best Llm Document Understanding Platforms](/blog/best-llm-document-understanding-platforms.md)
- [Best Multilingual Ocr Software](/blog/best-multilingual-ocr-software.md)
- [Best Pdf Parsers For Rag](/blog/best-pdf-parsers-for-rag.md)
- [Best Salesforce Document Generation Apps](/blog/best-salesforce-document-generation-apps.md)
- [Best Secure Document Collaboration Platforms](/blog/best-secure-document-collaboration-platforms.md)
- [Bpm Guide](/blog/bpm-guide.md)
- [Bpm Tools](/blog/bpm-tools.md)
- [Build Vs Buy Document Extraction](/blog/build-vs-buy-document-extraction.md)
- [Business Automation](/blog/business-automation.md)
- [Capex Vs Opex](/blog/capex-vs-opex.md)
- [The CEO’s AI playbook: Why decision architecture beats model selection](/blog/ceo-ai-playbook-decision-architecture.md)
- [1. Extract and chunk the PDF.](/blog/chat-with-pdf.md)
- [Complete Guide To Pdfjs](/blog/complete-guide-to-pdfjs.md)
- [Construction Document Data Extraction](/blog/construction-document-data-extraction.md)
- [Convert One Drive Files To Pdf In Sharepoint](/blog/convert-one-drive-files-to-pdf-in-sharepoint.md)
- [Create And Edit Pdfs In Flutter](/blog/create-and-edit-pdfs-in-flutter.md)
- [Create Pdfs With React](/blog/create-pdfs-with-react.md)
- [Creating A Document Scanner With Ocr In Python](/blog/creating-a-document-scanner-with-ocr-in-python.md)
- [Creating And Filling Pdf Forms Programmatically In Javascript](/blog/creating-and-filling-pdf-forms-programmatically-in-javascript.md)
- [The CTO’s AI playbook: Why accountability architecture beats orchestration](/blog/cto-ai-playbook-accountability-architecture.md)
- [Digital Signatures](/blog/digital-signatures.md)
- [Digital Workflow Automation](/blog/digital-workflow-automation.md)
- [Docling Alternatives](/blog/docling-alternatives.md)
- [Document Ai Vs Ocr](/blog/document-ai-vs-ocr.md)
- [Document Authoring Audit Trail](/blog/document-authoring-audit-trail.md)
- [Document Extraction Confidence Scores](/blog/document-extraction-confidence-scores.md)
- [Document Extraction For Underwriting](/blog/document-extraction-for-underwriting.md)
- [Document Viewer](/blog/document-viewer.md)
- [Document Watermarking](/blog/document-watermarking.md)
- [Emerging threats: Your logging system may be an agentic threat vector](/blog/emerging-threats-your-logging-system.md)
- [Extend Alternatives](/blog/extend-alternatives.md)
- [Extract Patient Data On Premises](/blog/extract-patient-data-on-premises.md)
- [app.py](/blog/extract-text-from-pdf-using-python.md)
- [Fillable Pdf](/blog/fillable-pdf.md)
- [Google Document Ai Alternatives](/blog/google-document-ai-alternatives.md)
- [How To Add Digital Signature To Pdf Using React](/blog/how-to-add-digital-signature-to-pdf-using-react.md)
- [How To Build A Dotnet Maui Pdf Viewer](/blog/how-to-build-a-dotnet-maui-pdf-viewer.md)
- [How To Build A Flutter Pdf Viewer](/blog/how-to-build-a-flutter-pdf-viewer.md)
- [or](/blog/how-to-build-a-javascript-pdf-viewer-with-pdfjs.md)
- [or](/blog/how-to-build-a-javascript-pdf-viewer.md)
- [How To Build A Nextjs Pdf Viewer](/blog/how-to-build-a-nextjs-pdf-viewer.md)
- [How To Build A Powerpoint Viewer Using Javascript](/blog/how-to-build-a-powerpoint-viewer-using-javascript.md)
- [Using Yarn](/blog/how-to-build-a-react-excel-viewer.md)
- [How To Build A React Native Pdf Viewer](/blog/how-to-build-a-react-native-pdf-viewer.md)
- [How To Build A React Powerpoint Viewer](/blog/how-to-build-a-react-powerpoint-viewer.md)
- [How To Build A Reactjs File Viewer](/blog/how-to-build-a-reactjs-file-viewer.md)
- [or](/blog/how-to-build-a-reactjs-pdf-viewer-with-react-pdf.md)
- [or](/blog/how-to-build-a-reactjs-pdf-viewer.md)
- [How To Build A Reactjs Viewer With Pdfjs](/blog/how-to-build-a-reactjs-viewer-with-pdfjs.md)
- [How To Build A Vuejs Pdf Viewer With Pdfjs](/blog/how-to-build-a-vuejs-pdf-viewer-with-pdfjs.md)
- [How To Build A Vuejs Pdf Viewer](/blog/how-to-build-a-vuejs-pdf-viewer.md)
- [How To Build An Android Pdf Viewer](/blog/how-to-build-an-android-pdf-viewer.md)
- [How To Build An Angular Pdf Viewer With Ng2 Pdf Viewer](/blog/how-to-build-an-angular-pdf-viewer-with-ng2-pdf-viewer.md)
- [How To Build An Angular Pdf Viewer With Pdfjs](/blog/how-to-build-an-angular-pdf-viewer-with-pdfjs.md)
- [How To Convert Docx To Pdf Using Javascript](/blog/how-to-convert-docx-to-pdf-using-javascript.md)
- [How To Convert Docx To Pdf Using Python](/blog/how-to-convert-docx-to-pdf-using-python.md)
- [How To Convert Html To Pdf Using Html2pdf](/blog/how-to-convert-html-to-pdf-using-html2pdf.md)
- [How To Convert Html To Pdf Using React](/blog/how-to-convert-html-to-pdf-using-react.md)
- [How To Convert Html To Pdf Using Wkhtmltopdf And Csharp](/blog/how-to-convert-html-to-pdf-using-wkhtmltopdf-and-csharp.md)
- [or](/blog/how-to-convert-html-to-pdf-using-wkhtmltopdf-and-python.md)
- [How To Convert Html To Pptx](/blog/how-to-convert-html-to-pptx.md)
- [Quarterly report](/blog/how-to-convert-pdf-to-markdown-using-python.md)
- [How To Convert Word To Pdf In Nodejs](/blog/how-to-convert-word-to-pdf-in-nodejs.md)
- [or](/blog/how-to-create-a-react-js-signature-pad.md)
- [How To Create Pdfs With React To Pdf](/blog/how-to-create-pdfs-with-react-to-pdf.md)
- [How To Edit Pdfs Using Ios Pdf Library](/blog/how-to-edit-pdfs-using-ios-pdf-library.md)
- [How To Embed A Pdf Viewer In Your Website](/blog/how-to-embed-a-pdf-viewer-in-your-website.md)
- [How To Extract Tables From Pdf And Images](/blog/how-to-extract-tables-from-pdf-and-images.md)
- [How To Generate Pdf From Html With Nodejs](/blog/how-to-generate-pdf-from-html-with-nodejs.md)
- [base_url tells WeasyPrint where to resolve relative asset paths](/blog/how-to-generate-pdf-reports-from-html-in-python.md)
- [How To Merge Pdfs Using Javascript](/blog/how-to-merge-pdfs-using-javascript.md)
- [How To Ocr Pdfs In Linux](/blog/how-to-ocr-pdfs-in-linux.md)
- [How To Print Pdf In Csharp](/blog/how-to-print-pdf-in-csharp.md)
- [How To Programmatically Create And Fill Pdf Form In Angular](/blog/how-to-programmatically-create-and-fill-pdf-form-in-angular.md)
- [Open an image.](/blog/how-to-use-tesseract-ocr-in-python.md)
- [From an HTML string.](/blog/html-in-pdf-format.md)
- [Html To Pdf In Javascript](/blog/html-to-pdf-in-javascript.md)
- [Intelligent Data Extraction](/blog/intelligent-data-extraction.md)
- [Invoice Approval Software](/blog/invoice-approval-software.md)
- [Javascript Document Editor](/blog/javascript-document-editor.md)
- [Javascript Pdf Editors](/blog/javascript-pdf-editors.md)
- [Javascript Pdf Libraries](/blog/javascript-pdf-libraries.md)
- [Landing Ai Alternatives](/blog/landing-ai-alternatives.md)
- [Langextract Vs Llamaindex Extraction Comparison](/blog/langextract-vs-llamaindex-extraction-comparison.md)
- [Linearized Pdf](/blog/linearized-pdf.md)
- [Uses OpenAI by default — set OPENAI_API_KEY.](/blog/llamaindex-vs-langchain-rag.md)
- [Llamaindex Vs Langchain Vs Haystack](/blog/llamaindex-vs-langchain-vs-haystack.md)
- [Llamaindex Workflows Vs Langgraph](/blog/llamaindex-workflows-vs-langgraph.md)
- [Llamaparse Alternatives](/blog/llamaparse-alternatives.md)
- [Low Code No Code Document Integrations](/blog/low-code-no-code-document-integrations.md)
- [Material Requisition](/blog/material-requisition.md)
- [or](/blog/merge-pdfs.md)
- [Swift Package Manager](/blog/mobile-pdf-sdk.md)
- [`elements` come from your document parser — each has a type and content.](/blog/multimodal-rag.md)
- [Nutrient Flutter 6 Bindings Api](/blog/nutrient-flutter-6-bindings-api.md)
- [Nutrient Flutter Bindings Architecture](/blog/nutrient-flutter-bindings-architecture.md)
- [Nutrient Vs Conga Composer](/blog/nutrient-vs-conga-composer.md)
- [Ocr Api Comparison](/blog/ocr-api-comparison.md)
- [Online Document Viewer](/blog/online-document-viewer.md)
- [Open Pdf In Your Web App](/blog/open-pdf-in-your-web-app.md)
- [PDF accessibility for developers: Meeting WCAG 2.2, Section 508, and PDF/UA with an SDK](/blog/pdf-accessibility.md)
- [Extract data from PDF files: A developer guide to structured data from PDFs and scans](/blog/pdf-data-extraction-developer-guide.md)
- [Pdf Extraction Benchmark Opendataloader Bench](/blog/pdf-extraction-benchmark-opendataloader-bench.md)
- [Pdf Extraction Document Case Studies](/blog/pdf-extraction-document-case-studies.md)
- [Pdf Page Labels](/blog/pdf-page-labels.md)
- [Pdf Sdk Compliance Security Checklist](/blog/pdf-sdk-compliance-security-checklist.md)
- [Pdf Sdk Performance Benchmark](/blog/pdf-sdk-performance-benchmark.md)
- [Pdf Ua Compliance Guide](/blog/pdf-ua-compliance-guide.md)
- [Pdf Ua Validation](/blog/pdf-ua-validation.md)
- [Pdfjs Accessibility Structtree Printing](/blog/pdfjs-accessibility-structtree-printing.md)
- [Pdfjs Advanced Loading Streaming Workers](/blog/pdfjs-advanced-loading-streaming-workers.md)
- [Pdfjs Annotation Editor Layer](/blog/pdfjs-annotation-editor-layer.md)
- [Pdfjs Area Annotations Canvas Capture](/blog/pdfjs-area-annotations-canvas-capture.md)
- [Pdfjs Coordinate Systems Pdf To Screen](/blog/pdfjs-coordinate-systems-pdf-to-screen.md)
- [Pdfjs Document Outline Bookmarks Metadata](/blog/pdfjs-document-outline-bookmarks-metadata.md)
- [Pdfjs Eventbus Guide](/blog/pdfjs-eventbus-guide.md)
- [macOS](/blog/pdfjs-file-format-conversion-to-pdf.md)
- [macOS](/blog/pdfjs-generating-pdf-thumbnails-pdf2pic.md)
- [Pdfjs Limitations Commercial Upgrade](/blog/pdfjs-limitations-commercial-upgrade.md)
- [Pdfjs Native Annotation Layer Forms](/blog/pdfjs-native-annotation-layer-forms.md)
- [Pdfjs Navigation Zoom Rotation](/blog/pdfjs-navigation-zoom-rotation.md)
- [Pdfjs Pdf Page Manipulation Pdf Lib](/blog/pdfjs-pdf-page-manipulation-pdf-lib.md)
- [Pdfjs React Viewer Setup](/blog/pdfjs-react-viewer-setup.md)
- [Pdfjs Rendering Overlays React Portals](/blog/pdfjs-rendering-overlays-react-portals.md)
- [Pdfjs Server Side Text Extraction](/blog/pdfjs-server-side-text-extraction.md)
- [Pdfjs Sticky Note Annotations](/blog/pdfjs-sticky-note-annotations.md)
- [Pdfjs Text Highlight Annotations](/blog/pdfjs-text-highlight-annotations.md)
- [Pdfjs Text Search Pdffindcontroller](/blog/pdfjs-text-search-pdffindcontroller.md)
- [Pdfjs Thumbnail Sidebar](/blog/pdfjs-thumbnail-sidebar.md)
- [People Process Tools](/blog/people-process-tools.md)
- [Process Flows](/blog/process-flows.md)
- [React Native Pdf Annotation](/blog/react-native-pdf-annotation.md)
- [React Pdf Annotation Layer Forms](/blog/react-pdf-annotation-layer-forms.md)
- [React Pdf Custom Rendering Hooks](/blog/react-pdf-custom-rendering-hooks.md)
- [Using Yarn](/blog/react-pdf-editor.md)
- [React Pdf Loading States Errors Passwords](/blog/react-pdf-loading-states-errors-passwords.md)
- [React Pdf Non Latin Fonts Special Pdfs](/blog/react-pdf-non-latin-fonts-special-pdfs.md)
- [React Pdf Outline Table Of Contents](/blog/react-pdf-outline-table-of-contents.md)
- [React Pdf Performance Optimization](/blog/react-pdf-performance-optimization.md)
- [React Pdf Setup Basic Rendering](/blog/react-pdf-setup-basic-rendering.md)
- [React Pdf Text Layer Custom Renderer](/blog/react-pdf-text-layer-custom-renderer.md)
- [React Pdf Thumbnails Page Navigation](/blog/react-pdf-thumbnails-page-navigation.md)
- [Reducto Alternatives](/blog/reducto-alternatives.md)
- [Requisition System](/blog/requisition-system.md)
- [labels.py](/blog/route-documents-automatically-classify-api.md)
- [or](/blog/sample-blog-updated.md)
- [Sdk Product Updates Q2 2026](/blog/sdk-product-updates-q2-2026.md)
- [System Of Record Vs Source Of Truth](/blog/system-of-record-vs-source-of-truth.md)
- [Add DWS MCP Server to your Claude Code project.](/blog/teaching-llms-to-read-pdfs.md)
- [Open an image file.](/blog/tesseract-python-guide.md)
- [The Six Best Pdf Generator Apis](/blog/the-six-best-pdf-generator-apis.md)
- [Define the HTML part of the document.](/blog/top-10-ways-to-generate-pdfs-in-python.md)
- [Top 5 Javascript Pdf Viewers](/blog/top-5-javascript-pdf-viewers.md)
- [or](/blog/top-js-pdf-libraries.md)
- [Top Ten Ways To Convert Html To Pdf](/blog/top-ten-ways-to-convert-html-to-pdf.md)
- [Unstructured Alternatives](/blog/unstructured-alternatives.md)
- [Vector Pdf](/blog/vector-pdf.md)
- [Wcag2 Accessibility Requirements Documents](/blog/wcag2-accessibility-requirements-documents.md)
- [Web Sdk Is Now Headless](/blog/web-sdk-is-now-headless.md)
- [What Are Annotations](/blog/what-are-annotations.md)
- [What Is A Vpat](/blog/what-is-a-vpat.md)
- [What Is Business Logic](/blog/what-is-business-logic.md)
- [What Is Document Processing](/blog/what-is-document-processing.md)
- [What Is Intelligent Document Processing](/blog/what-is-intelligent-document-processing.md)
- [What Is Ocr Invoice Processing](/blog/what-is-ocr-invoice-processing.md)
- [What Is Pdf Ua](/blog/what-is-pdf-ua.md)
- [Why Pdfium Is A Trusted Platform For Pdf Rendering](/blog/why-pdfium-is-a-trusted-platform-for-pdf-rendering.md)
- [Why Your Ai Agent Hallucinates Pdf Table Data](/blog/why-your-ai-agent-hallucinates-pdf-table-data.md)

