Blog
Releases
Puck AI 0.9: Custom AI agents, user field types & localization
Fede Bonel TozziFede Bonel Tozzi
Nov 10, 2026

Puck AI 0.9 lets you build custom AI agents, supports user field types in design mode, adds localization, and includes several other API improvements.

See the AI overview for more information on Puck AI.

In this post, we’ll go over everything new in Puck AI 0.9 and how you can start using it:

You can also find in-depth documentation in our AI docs.

What’s new in Puck AI 0.9

Custom AI interfaces

The new usePuckAi hook lets you build your own UI for Puck AI. Use it to hold a conversation, request a single change to the current page, or integrate Puck AI with your own agent.

import { usePuckAi } from "@puckeditor/plugin-ai";
 
function AiChat() {
  const { chat } = usePuckAi();
  const [input, setInput] = useState("");
 
  const messages = chat.messages.map((message) =>
    message.parts.map((part, i) =>
      part.type === "text" ? <p key={i}>{part.text}</p> : null
    )
  );
 
  return (
    <div>
      {messages}
 
      <form
        onSubmit={(e) => {
          e.preventDefault();
          chat.sendMessage(input);
          setInput("");
        }}
      >
        <input value={input} onChange={(e) => setInput(e.target.value)} />
        <button>Send</button>
      </form>
    </div>
  );
}

The hook can be used anywhere the Internal Puck API is available. See the custom agents guide for more details.

Stream changes from your server

It’s now possible to stream AI changes from your own server-sided agent.

The headless server-side generate now exposes each AI Part through onPart. These parts can be sent to the client and applied to the editor using usePuckAi().applyPart:

// server side
await generate({
  prompt: "Create a page about dogs",
  config,
  pageData,
  onPart: (part) => {
    // send part to browser, or save it for later
  },
});

Apply each part when the editor receives it:

const { applyPart } = usePuckAi();
 
// get the parts from the server
// const parts = ...
 
for await (const part of parts) {
  await applyPart(part);
}

By default, headless generations run for one iteration. Set maxIterations to allow more iterations and configure onPart to process requests from the agent.

Multi-step headless generation

generate can now iterate during page generation to review its work and make further changes.

To enable this, set maxIterations in the options object and respond to data-client-request parts with onPart:

await generate({
  prompt: "Create a page about dogs",
  config,
  maxIterations: 10,
  onPart: (part, respond) => {
    if (part.type === "data-client-request") {
      if (data.action === "getPageData") {
        // Provide the latest page data via respond(pageData)
      }
 
      // handle other actions
    }
  },
});

See the onPart documentation for more details on handling data-client-request parts.

New user field type API

Puck AI now supports user field types in both assembly mode and design mode, letting you define their schema once and use them when assembling pages or designing new components.

Assembly mode

To use user field types in assembly mode, define them with the fieldTypes prop when creating your AI plugin:

const aiPlugin = createAiPlugin({
  fieldTypes: {
    cta: {
      description: "Renders a branded call-to-action button",
      schema: {
        type: "object",
        properties: {
          label: { type: "string" },
          href: { type: "string" },
          variant: { type: "string" },
        },
      },
    },
  },
});

Design mode

Combine user field types with field transforms to let Puck AI include your components in the new components it designs:

const aiPlugin = createAiPlugin({
  fieldTypes: {
    cta: {
      description: "Renders a branded call-to-action button",
      schema: {
        type: "object",
        properties: {
          label: { type: "string" },
          href: { type: "string" },
          variant: { type: "string" },
        },
      },
    },
  },
});
 
const fieldTransforms = {
  cta: ({ value }) => (
    <Button href={value.href} variant={value.variant}>
      {value.label}
    </Button>
  ),
};

See AI configuration for more details.

Localization

The AI plugin introduces a new label prop and new keys for Puck’s dictionary prop, letting you replace every string shown in the UI:

const aiPlugin = createAiPlugin({ label: "IA" });
 
<Puck
  plugins={[aiPlugin]}
  dictionary={{
    "plugin-ai-prompt-placeholder": "¿Qué quieres construir?",
    "plugin-ai-chat-msg-thinking": "Pensando...",
  }}
  config={config}
  data={data}
/>;

See the localization guide for more details, and the AI plugin dictionary reference for the full list of strings.

Other changes

New default model

Assembly mode now uses openai/gpt-5.6-luna by default, matching design mode. Set ai.model to use a different model.

New puckHandler option: ai.maxIterations

puckHandler now accepts ai.maxIterations, which limits how many times the AI can iterate on a request:

puckHandler(request, {
  ai: {
    maxIterations: 10,
  },
});

Paste files into chat

Users can now paste files, including screenshots, straight into the chat input. Pasted files follow your chat.attachments settings.

Force design mode with one option

Setting ai.mode to "design" now enables design mode for every request without also setting designMode.allowed:

puckHandler(request, {
  ai: {
    mode: "design",
  },
});

Use designMode.allowed only when users need to toggle design mode in the plugin interface.

puckHandler and generate now await onFinish

puckHandler and generate now wait for async onFinish callbacks. generate rejects if its callback fails, while puckHandler logs the failure.

Full changelog

Features

  • Add usePuckAi() for custom AI interfaces
  • Stream and iterate headless generate() requests
  • Support user field types in assembly and design modes
  • Add localization to the AI plugin
  • Allow pasting files into the AI chat
  • Let ai.mode force design mode without designMode.allowed
  • Use openai/gpt-5.6-luna as the default assembly model
  • Support checkbox fields in Puck AI
  • Wait for async onFinish callbacks

Bug Fixes

  • Opt into BYOK when providerApiKey is set without a model
  • Prevent design-mode config data from breaking defaultProps
  • Avoid clipping screenshots when the page body has an explicit height
  • Skip empty screenshots instead of failing the request
  • Strip values that cannot be serialized before sending a config to Puck Cloud
  • Preserve numeric option values
  • Ignore option fields with no options
  • Respect Puck’s theme in the AI plugin
  • Include Zod as a dependency of @puckeditor/ai-types and @puckeditor/cloud-client
  • Stop requiring React at runtime in @puckeditor/cloud-client
  • Bind dotted field paths correctly in design mode
  • Reject unsafe design-mode field names
  • Preserve Headers instances returned from prepareRequest

How to upgrade

Upgrading Puck

Run the following command to install the latest Puck AI packages:

npm install @puckeditor/cloud-client@latest @puckeditor/plugin-ai@latest

No stable Puck AI APIs were removed or deprecated in this release.

Try Puck AI

Puck AI is available now. Sign up.