Funnels for agents: giving an LLM write access to your money path
Most AI in funnel software writes copy into a box. We exposed orders, pages and refunds as MCP tools, and the hard part was the permission model.
Nearly every funnel builder now advertises AI. Look at what the AI is allowed to do and it is almost always the same thing: it writes copy into a box you then approve. The model is a text generator wearing the interface of an assistant.
That is a reasonable product decision. It is also not what people keep asking me for. The question I get is some version of: can my agent just go do it? Read the funnel, notice step three is leaking, rewrite that page, and tell me what it did.
That requires the funnel to be an API surface an agent can operate. Autonnel ships one. This post is about the part that turned out to be hard, which was not the endpoints and was not the prompting.
Why hosted platforms will not ship this
This is not a capability gap. It is a business-model conflict, and it is worth naming plainly.
A hosted funnel platform’s moat is that your pages, your orders, and your customer list live inside their product. Every feature that makes those things easier to operate from outside the product weakens the moat. Handing a third-party agent a token that can read your orders and publish your pages is close to the exact opposite of that strategy.
So they will keep shipping the copy generator, and it will keep getting better, and it will keep being a text box. A self-hosted, permissively licensed tool can ship the other thing precisely because it has no lock-in to protect. That asymmetry is more durable than any individual feature.
What is actually exposed
Update, 2026-08-05. The tool list below has been corrected against the shipped server. The names this post originally used (
refund_order,publish_page,get_funnel_stats,list_media,generate_media,get_order) were from an earlier plan and are not what shipped: there is no refund tool at all, publishing is a flag onupdate_page, and funnel stats are oneget_statstool. The argument about where the guardrail lives is unchanged, but it is now written against verbs that exist.
Autonnel serves MCP over HTTP at /api/mcp, in the same Worker or Node process that serves the rest of the site. No separate daemon, no stdio binary. Any MCP client (Claude Desktop, Cursor, Windsurf, or something you built on the SDK) connects with a Bearer token:
{
"mcpServers": {
"autonnel": {
"url": "https://your-shop.com/api/mcp",
"headers": { "Authorization": "Bearer YOUR_KEY" }
}
}
}
The tools mirror the external REST API, one tool per action:
| Domain | Tools |
|---|---|
| Funnels | list_funnels, get_funnel, create_funnel, update_funnel, delete_funnel |
| Funnel steps | add_funnel_page, replace_funnel_page, remove_funnel_page, set_funnel_step_slug |
| Pages | list_pages, get_page, create_page, update_page |
| Page templates | list_templates, get_template |
| Catalog | list_products |
| Media | upload_media |
| Orders | list_orders, deliver_order |
| Stats | get_stats |
Read that list again, because the entries that matter most are delete_funnel and update_page with publish: true. One removes a live sales flow. The other pushes a draft onto a page that is taking money right now.
I could have left the write tools out and written a more comfortable blog post. But an agent that can read orders and not act on them is a dashboard with extra steps, and pretending the dangerous verbs do not exist does not make anyone safer. They exist. What makes this workable is not their absence, it is the gate in front of them.
The gate is a permission model, not a prompt
Here is the rule I would give anyone building this, and it is the one thing in this post I would defend hardest:
The guardrail must not live in the prompt. A prompt instruction is a request. A permission check is a wall. If the only thing between an agent and delete_funnel is a sentence asking it politely not to, you have not built a guardrail, you have written a note.
Autonnel’s actual model has two layers, and it is worth being precise because the details change how you should use it.
Layer one: an immutable write flag on the key.
writeAccess | Allowed methods |
|---|---|
false (default) | GET only |
true | GET, POST, PUT, DELETE |
It is set at creation and cannot be changed afterwards. To downgrade a key you revoke it and mint a new one. A read-only key genuinely cannot mutate anything, which makes “let the agent look around first” a real, enforceable posture rather than a promise.
Layer two: the creating user’s role features. A key’s effective permissions are the union of the role features held by the user who created it. Autonnel’s RBAC is feature-level and database-driven, so “can read orders, cannot issue refunds” is expressible. It is just expressible on the role, not on the key.
Which leads to the piece of advice this post exists to deliver:
Do not mint an agent key from your admin account. Create a dedicated user, give it a role with exactly the features the agent needs, and create the key as that user. An agent key minted from an owner account inherits owner powers, and delete_funnel is on the tool list.
The limitations, stated plainly
I would rather you hear these from me than find them.
There are no per-key scopes. Granularity lives entirely in roles. You cannot mint a narrow key from a broad account, which means the setup above is not optional hardening, it is the only mechanism.
Keys do not follow role changes. If you later tighten the role, keys created before that change keep their previous effective access until they are revoked and recreated. That is a genuine footgun. If you tighten a role for security reasons, revoke that user’s keys in the same sitting.
The in-editor agent edits in place. The Agent panel in the page editor reads the current layout plus the component catalog and rewrites the page directly, autosaving the draft. There is no separate “AI version” and no side-by-side diff view. If you want a checkpoint before letting it experiment, duplicate the page first. I would like a real diff UI here and we do not have one yet.
What does protect you there is the structure itself. Pages are stored as Puck component trees, not HTML blobs, so the model cannot smuggle arbitrary markup into your checkout. The in-editor path hands the model each component’s validPropNames and prop schema, and props outside that set are ignored by the renderer rather than applied. Be precise about the limit, though: that is not the same as rejection, and draftData written through the MCP API is not structurally validated at all - an unknown component name saves cleanly and renders blank. Take the shape from get_template and verify with get_page after writing.
Draft and published are separate states. Autosave writes drafts. Making a page live is a distinct action: update_page with publish: true, which is a write, which is behind the flag and the role. Keep publish out of the agent’s role until you have watched it work for a while.
The agent is good at mechanical work and mediocre at judgement. Restructuring a page, translating labels, summarising where a funnel leaks: reliable. Deciding which offer to make to which audience: not reliable, and I have not seen a configuration where it is.
Each run costs tokens. Every agent call ships the current page layout and the full component catalog to your configured LLM. Long iteration sessions add up. Check your provider pricing before you loop.
The loop that is actually useful
Not “write me a funnel”. The boring one:
get_statsto find which step is leaking.get_pageon the offending step.- The Agent panel rewrites that page with a specific hypothesis about the drop.
- A human looks at the canvas and publishes, or does not.
get_statsagain once the change has enough sample to mean anything.
Every step is a tool call an agent can make with a scoped key. None of it requires the model to be brilliant. It requires the funnel to be legible, which is why funnel-native analytics matters here: an agent asking “why is this underperforming” needs step-level conversion, not a page-views table it has to reason around sideways.
One more thing the model will not do for you: sample size is still sample size. An agent will cheerfully declare a winner off 40 sessions. The A/B machinery enforces minimums because the agent will not.
If you want to try it
- MCP server for the transport, the tool list, and client configuration
- API keys for the
writeAccessflag and how key scope is derived - Permissions for building the restricted role the agent should use
- SKILL.md reference for the workflows Claude picks up automatically
All of it runs in the self-hosted edition under Apache-2.0. There is no agent tier and there is not going to be one: charging for the API is the single move that would make the argument in this post dishonest. The same is true on Cloud, where the API is not a plan feature either.
The tool-by-tool overview of what an agent actually gets to call is on the MCP server for funnel orders page. If you are weighing this against a hosted platform, Autonnel vs ClickFunnels is the longer comparison, including the cases where the hosted option wins.
Boot it with docker compose up, create a restricted user, and point an agent at it. If you build something with this that I did not anticipate, I would like to see it.