Skip to main content
Platform feature. Requires WANIWANI_API_KEY. Works whether your MCP server is self-hosted or on Managed Hosting. About the Platform.
Modules are capabilities you turn on per agent in the dashboard. The documents module reads a PDF or an image and gives you back the fields you asked for, shaped by a Zod schema. A document reaches your agent one of two ways. Either you already have a URL and hand it over, or a visitor attaches a file in the chat widget and the platform stores it for you.

Setup

The documents client sits on the Waniwani client instance:

Read a document you have a URL for

Describe what you want with a Zod schema and pass the URL:
filename is not decoration. It is how an unsupported type gets refused before anything is fetched.
Extraction runs in strict mode, so mark every field the document might not answer .nullable(). A field that is not nullable and not present makes the whole extraction fail rather than coming back empty.
The URL has to be publicly fetchable. Private and loopback addresses are refused.

What you get back

Read a file the visitor attached

Turn Modules → Documents on for the agent first. While it is off the widget shows no paperclip and the upload endpoint answers 403, so nothing arrives. With it on, the visitor gets a paperclip, a drop target and paste. The bytes go straight from the browser to storage, never through your server, and your tool call arrives with a handle instead of a file. Read it off the scoped client:
Each entry carries documentId, filename and mediaType. Only the id is load-bearing, and there is no filename to pass to extract() because the platform kept it.
Your agent needs a tool like this before the toggle does anything visible. The platform stores the file and hands over an id; reading it is the agent’s job.
Give the tool a description that names the case plainly, including screenshots and photos. A model that does not believe it can read images will refuse before it ever calls your tool.

On your own chat route

If you run the chat backend yourself rather than using the hosted widget, pull the same handles out of the request body:
It accepts the whole body, reads the documents array when the widget sent one, and otherwise falls back to the latest user turn in messages.

Read only some pages

Billing is per page processed, so narrow the range when you know where the answer is. Indexes are zero-based, and the option is ignored for images.

Limits

Both the size and page caps are the OCR vendor’s. A PDF is counted before the vendor is called, so an oversized document is refused rather than billed. After 7 days the stored file is gone and its documentId no longer resolves. Extract what you need and keep the fields, not the id.

Widget configuration

The hosted widget picks the module state up on its own, so WaniwaniChat and the script embed need no code for any of this. ChatEmbed, the bring-your-own-backend primitive, takes it as a prop instead, and can send the upload calls under a different credential than the chat. See Chat in React.