There’s a version of “AI form building” that gets demoed a lot and used very little. You paste a key into a settings screen, type a sentence, and a form appears on your production site. It’s impressive for thirty seconds. Then you need a date picker, or a price that depends on three fields, or a repeater — and the textbox has nothing to offer, because the vendor only wired up the easy cases.
There’s a second version that’s less flashy and considerably more useful: give a coding agent the full authoring specification for your form plugin, let it build the form on your local install, verify it, and export the result as a single file you import on production.
That’s the workflow this article covers. It’s slower to set up and dramatically more capable, and it has a property the textbox version can never have: the agent never touches your live site. What reaches production is a file you reviewed.
The idea in one paragraph

CraftForms publishes its complete authoring specification — the AI Form Builder Guide. It’s about 12,000 words covering every block pattern, the form meta schema, conditional logic, template variables, and the WP-CLI commands to wire it all up. Hand that URL to an agent with shell access to a local WordPress install, describe the form you want, and it has everything it needs. When the form is built and verified, one button exports it to a portable file. Import that on production. Done.
No API key. No AI feature in the plugin. The “AI” is whichever agent you already use.
Why not just use the MCP abilities?
Fair question, and if you’ve read our MCP guide you’ve seen the other path: WordPress 6.9’s Abilities API, exposed as MCP tools, letting an agent call craftforms/create-form and craftforms/add-field directly.
That path is genuinely elegant, and it has a hard ceiling:
| MCP abilities | Guide + local build | |
|---|---|---|
| Field types | 7 basic (text, email, number, textarea, select, radio, checkboxes) | all of them — datepicker, file upload, repeater, range, color, payment, WooCommerce |
| Editing an existing form | no — append-only | yes |
| Pricing / smart variables | at create time only | any time |
| Conditional logic | no | yes |
| Requires | WP 6.9+, MCP Adapter plugin | nothing beyond WP-CLI |
| Touches production | yes, if that’s the site you connect it to | no — local only |

Use the abilities when you want an agent scaffolding simple intake forms in place. Use this workflow when you want a real form. In practice the two combine well: let the agent scaffold with create-form (which gets the post type and meta right with zero chance of error), then have it author the remaining blocks by hand from the guide.
Step 1 — Give the agent the guide
Whatever agent you’re using, the setup is the same: point it at the guide and give it shell access to a local install.
In Claude Code, that’s one sentence:
Read https://kb.craftformswp.com/documentation/for-developers/ai-form-builder-guide and follow it to build a CraftForms form on my local site. Ask me anything you need about the form before you start.
Two things make this work better than it has any right to:
The guide is written for machines. It’s not marketing documentation with a code sample at the end. It’s block-markup patterns, a meta schema reference, and a WP-CLI cheatsheet — the shape of thing an agent consumes well.
It leads with the failure modes. The guide opens with sections marked CRITICAL, covering the ways to produce a form that looks fine and isn’t. An agent that reads them doesn’t make those mistakes. We’ll come back to these, because they’re the whole reason this workflow is reliable.
Step 2 — Describe the form, not the markup
The point of handing over a specification is that you get to talk about the form, not the implementation. A useful prompt is closer to a brief than a spec:
A quote request form for a made-to-measure blinds company. Customer picks width and height in cm, a fabric from four options with different per-square-metre prices, and optional motorisation for a flat £85. Show the running total live as they change anything. Name and email required, phone optional. Email me the quote on submit.
That’s a form with a price formula, a lookup table keyed on fabric, a conditional add-on, and a live-updating total — four things that are entirely outside what any prompt-to-form textbox will give you, and all of which are documented in the guide.
The agent will do roughly this:
wp post create --post_type=craftforms_formfor the form post.- Set
_craftforms_form_metawith the formula, the fabric price table as atabletransformation, and the email submit action. - Author the field blocks into
post_contentfollowing the guide’s patterns. - Add an Infoblock bound to the form for the live total.
Step 3 — The three CRITICAL rules (read these even if the agent did)
This is the part worth understanding yourself, because it’s where a form silently breaks. All three are in the guide, and all three exist because WP-CLI bypasses the safety nets the editor and importer provide.
Rule 1 — Forms are craftforms_form posts, never pages
All form logic lives on the craftforms_form custom post type. A page never holds form markup directly. Saving a form auto-generates a synced pattern (CraftForms: <form title>), and the page holds only a reference to it — <!-- wp:block {"ref":PATTERN_ID} /--> — or the shortcode.
Writing form block HTML straight into a page with --post_content produces something that renders and does nothing: the meta is detached from the block, so no formula, no validation, no submit actions.
A related trap sits on the form post itself: its craftforms/form block needs "ref" set to the form’s own post ID. The editor adds it on first edit, so a form built entirely by CLI never gets one — and the form stays hidden on the page with no console error. The agent has to create the post, learn its ID, then write the ID back into the block. The guide covers this; it’s worth knowing why a CLI-built form can silently fail to appear.
Rule 2 — Form meta must be an array, not a JSON string
This is the one that catches everybody:
# WRONG — stores a string. Frontend works. Editor shows no formula, no smart variables.
wp post meta update 42 _craftforms_form_meta '{"formula":"width * height * price"}'
# RIGHT
wp post meta update 42 _craftforms_form_meta '{"formula":"width * height * price"}' --format=json
Without --format=json, WordPress stores the raw string. The frontend happens to survive it — the submission controller decodes strings defensively — so the form appears to work. But the block editor reads the meta as an array and finds nothing, so the Price Formula and Smart Variables panels come up empty. You’d conclude the build failed when the data is right there, in the wrong shape.
Rule 3 — Block HTML and block-comment attributes must agree
Gutenberg validates blocks by regenerating the saved markup from the block comment’s JSON attributes and comparing. Any mismatch produces “This block contains unexpected or invalid content.”
The canonical trap is a required message on a radio or checkbox group, which lives in two places at once:
<!-- wp:craftforms/radio-field {"name":"fabric","required":true,"requiredMessage":"This field is required"} -->
<div class="wp-block-craftforms-radio-field"
data-validate-minselected="1"
data-validate-minselected-message="This field is required">
Set one and not the other, or set them to different strings, and the block fails validation. Any hand-written data-validate-*-message needs its matching block-comment attribute at the same value.
Why this workflow is safe anyway: all three rules are checked by simply opening the form in the editor. A validation notice means rule 3. Empty formula panels mean rule 2. That’s a ten-second check, and it’s the reason building locally matters — you find these on your machine, not on a client’s site.

Step 4 — Verify, then export
Open the form in the block editor. No validation notice, formula and variables visible in the panels, fields render — that’s the build confirmed.
Now, in the form editor sidebar, open the Export panel and click Export Form. You get form-{id}.craftform.html.
Do not let the agent hand-write this file. Export it. The distinction is not stylistic — the export pipeline is a normalisation pass that fixes things:
- It repairs string meta. If rule 2 was violated, export decodes the string and writes clean JSON into the file. The imported copy comes back as a proper array. Export literally heals the most common mistake in this workflow.
- It strips the
refattribute from the form block.refis the form’s own post ID and is meaningless on another install; import re-assigns it. - It embeds images as base64 in a
<!--craftforms-assets-->block, so the file is self-contained and images sideload (deduplicated) on import. - It re-serialises from the database, so the file reflects what the editor actually read — not what you hoped you wrote.
The result is one readable file:
<!--
Name: Blinds Quote Request
Description: Exported from CraftForms
Type: form
Version: pro
UUID: form_6a95425107d97
CraftForms-Version: 1
-->
<!--craftforms-meta
{
"sendEmails": true,
"createEntries": true,
"formula": "width * height / 10000 * fabric_price + motorised",
"transformations": [ ... ],
"submitActions": [ ... ]
}
-->
<!-- wp:craftforms/form {"layout":{"type":"constrained"}} -->
...

Treat a clean export as your conformance check. If it exports and the file looks right, it will import.
One portability gotcha: the Version line
Version: is set by feature detection, not your licence. A form is tagged pro if it has a price formula, transformations, conditional-logic rules, a user-registration or create-post submit action, or a file-upload field. Otherwise free.
A pro file is refused on import into a free install. So the blinds form above — which has a formula — is not portable to a free site no matter where it was exported from. Worth knowing before you promise a client a file.
Step 5 — Import on production
On the target site: CraftForms → Add New Form, then Import from file in the starter modal. Same UI that installs the bundled starters, because it’s the same format.
The importer loads the blocks and the <!--craftforms-meta--> settings into the new form and sideloads any embedded images into the media library. Publish it, then place it on a page by inserting its synced pattern (CraftForms: Blinds Quote Request) or with the shortcode, and you’re live.
The new form takes its name from the file, so there’s nothing to retype.
To ship a new version later, don’t create another form. Open the existing form on production, find Starters & Import in the sidebar, click Choose starter or import, and import the new file. It replaces that form’s blocks and settings in place and keeps the same form, so every page that embeds it picks up the change as soon as you click Update.
That’s what makes this a repeatable deployment path rather than a one-shot migration: iterate locally, re-export, import over the form on production.
Why this beats the textbox
Nothing proprietary in the chain. The guide is a public document. The agent is whichever one you already pay for. Swap models freely; the specification doesn’t care.
The deliverable is a file. You can read it, diff it, commit it, code-review it, and roll it back. Compare that with an AI feature that mutates your production database and leaves you an undo button.
No ceiling. Anything documented in the guide is in scope, which is everything the plugin does.
It scales sideways. Ten department contact forms for one client, or the same intake form across fifteen sites, is one build and fifteen imports. Drop the file into the plugin’s starters/forms/ folder and it shows up as a starter in the UI — but that folder lives inside the plugin, so a plugin update replaces it. Keep your copies in version control.
Production stays clean. The agent works on localhost. A human reviews a file. That’s a review gate no in-plugin AI feature gives you.
The honest limits
- You need a local WordPress install with WP-CLI, and an agent that can run shell commands. That sounds like more than it is. Claude Code, Cursor, and similar coding agents run shell commands out of the box, and most local dev tools (Local, DDEV, wp-env) include WP-CLI. If you already have a coding agent and a local site, you have the whole setup. If you don’t, the MCP path or the editor is a lower bar.
- The agent still needs supervision. It won’t produce invalid markup if it follows the guide, but it can absolutely build the wrong form correctly. Read the brief back before you accept it.
- Complex pricing deserves a real test. Submit the form once on local and confirm the total. CraftForms recalculates price server-side rather than trusting the browser, so a formula wrong in both places is still wrong.
- Free/Pro portability is feature-detected, per the
Versionnote above. - This is a build workflow, not a sync workflow. Importing over an existing form updates it in place, but there’s no continuous two-way sync between environments.
Try it
- Local WordPress with CraftForms and WP-CLI.
- Tell your agent: read the AI Form Builder Guide and build me a form that does X.
- Open the form in the editor — no validation notice, formula visible.
- Export Form in the sidebar.
- Import the file on production.
The interesting thing isn’t that an AI built a form. It’s that the output is a file you own, produced by an agent you chose, from a specification anyone can read.
Related: How to Use MCP to Build and Fill WordPress Forms · AI Form Builder Guide (docs)

