AI agents

Quickstart

Last updated on

Give an agent the Paradoc tools and have it fill a real form

In this quickstart, an agent fills a pet addendum to a lease from one message and saves it as a PDF. The form comes from the Paradoc public registry, so you do not write a form first.

You need Node.js 22.13 or newer, a project with "type": "module" in its package.json, and an OpenAI API key in OPENAI_API_KEY. To use a different model, change the model line. Any model that can call tools works.

Install and write the agent

Pick your framework. Each tab is a complete program.

npm install @paradoc/ai-sdk ai @ai-sdk/openai zod
agent.ts
import { writeFile } from "node:fs/promises"
import { openai } from "@ai-sdk/openai"
import { paradocTools } from "@paradoc/ai-sdk"
import { generateText, isStepCount } from "ai"

const result = await generateText({
  model: openai("gpt-4o"),
  tools: paradocTools({ defaultRegistryUrl: "https://public.paradoc.dev" }),
  stopWhen: isStepCount(10),
  system: [
    "You fill documents with the Paradoc tools.",
    "Leave registry_url out: the tools use the configured registry.",
    "Call get_artifact first and follow its agent instructions.",
    "Pass the data from the last fill result to render.",
    "The app gives the user the PDF. Do not write links to it.",
  ].join("\n"),
  prompt:
    "Fill the pet-addendum form. My dog Rex weighs 30 lbs and is vaccinated. " +
    "I am Jane Doe, the tenant. The landlord is Acme Properties LLC. " +
    "Then render it as a PDF.",
})

for (const step of result.steps) {
  for (const call of step.toolCalls) console.log("tool:", call.toolName)
}
console.log(result.text)

const pdf = result.steps
  .flatMap((step) => step.toolResults)
  .find((r) => r.toolName === "render" && r.output.mime_type === "application/pdf")
if (pdf?.toolName === "render" && pdf.output.content) {
  await writeFile("pet-addendum.pdf", Buffer.from(pdf.output.content, "base64"))
}

generateText stops after one step unless you set stopWhen. Without it, the agent calls one tool and stops.

The system prompt tells the model four things:

  • Leave registry_url out. defaultRegistryUrl is only a fallback. If the model writes a URL of its own, the tools use it.
  • Read the agent instructions. get_artifact returns instructions that the form's author wrote for agents: the order to ask questions in, how to check values, and which layer to render.
  • Pass the draft to render. fill returns the draft in data. render without data renders an empty form.
  • The app delivers the PDF. The model sees only a short copy of each tool result. Your code gets the full result.

Run it

npx tsx agent.ts

The agent calls three tools, then answers:

tool: get_artifact
tool: fill
tool: render
The Pet Addendum form has been filled with the following details:

- Pet Name: Rex
- Species: Dog
- Weight: 30 lbs
- Vaccinated: Yes
- Tenant: Jane Doe
- Landlord: Acme Properties LLC

The form has been rendered as a PDF, ready for signature.

The model writes its own answer, so the text changes from run to run. Sometimes the model calls a tool twice: when a value is in the wrong shape, the tool returns an error that says why, and the model tries again.

Open the PDF

pet-addendum.pdf is in the current folder, with the values filled in. It is not signed. Paradoc can seal it for signing.

What happened

  1. get_artifact loaded the pet-addendum form from https://public.paradoc.dev, with its agent instructions.
  2. fill checked the values against the form and returned a draft. If a value was wrong, such as a species the form does not list, fill returned an error, and the model could fix it or ask you.
  3. render filled the form's PDF layer with the draft.

In this quickstart, the message gives every value at once. A real form needs a conversation: the agent asks for what is missing, one question at a time. That is the next guide.

Next

On this page