TL;DR: A Make.com AI prompt is not a chat prompt. Nobody reads the answer; it flows straight into the next module. So the output contract is the whole job: exact JSON keys, a closed list of allowed values with a mandatory fallback, and a defined response to empty or unreadable input. Below are 26 templates built that way.
Scenarios do not usually break because the model was wrong. They break because the model was right in the wrong shape. It returned a friendly sentence where the next module expected a field. It wrapped valid JSON in a code fence. It answered a three-way classification with a fourth category nobody had built a route for. The model did something reasonable and the automation fell over.
That is why the templates below are organised by scenario shape rather than by topic, and why every one of them carries an explicit output contract.
What makes a Make.com AI prompt different from a chat prompt?
Three things, and all three are structural rather than stylistic. Nobody reads the output before it moves on, the module runs once per bundle rather than once per conversation, and the answer has to satisfy a machine that has no tolerance for a preamble.
In a chat window you are the error handler. You read a bad answer, notice the missing field, ask again. Inside a scenario there is no you. The output becomes the input of a Sheets row, a filter condition, a router branch, or an HTTP body, at three in the morning, with nobody watching.
The second difference is volume. Make's own Operations documentation puts it plainly: "An operation is a single module run to process data or check for new data." Modules process each bundle separately, and Make notes that "bundles in earlier modules have a multiplying effect on the operations in the rest of the scenario". A trigger returning ten items means the AI module runs ten times with ten different inputs, one of which will be the awkward one.
The third is that you rarely see the failure directly. You see a spreadsheet with a column full of Sure! Here's the JSON you asked for: and a week of downstream rows that quietly went nowhere.
What exactly is an output contract?
An output contract is the part of the prompt that describes the response as a data structure rather than as a request. It has four components, and the fourth is the one almost every template on the internet omits.
- The exact keys. Named, spelled, ordered, and typed. Not "return the details as JSON".
- Closed value lists. Every enum field states its permitted values in full.
- A mandatory fallback value. Every closed list ends with
"other"or"unknown", so the router always has somewhere to send the bundle. - A rule for empty or unreadable input. A literal object to return when the input is blank, whitespace, or garbage.
That last one is the most commonly missed and the most common cause of a 2am failure. Empty input is not rare. A CRM field is null. A webhook fires early. An email is an image with no text layer. Without an instruction, the model improvises, and improvisation is exactly what you removed the human to avoid.
Which Make modules actually take a prompt in 2026?
Make's OpenAI app is currently listed in the Apps Documentation as OpenAI (ChatGPT, Sora, Whisper). If your notes or a tutorial say DALL-E, they predate the current page. Verified at apps.make.com/openai-gpt-3 on 27 August 2026.
| Module | What it is for | Output shape control |
|---|---|---|
| Simple text prompt | Model plus prompt, no other setup | None. Free text out |
| Generate a response | The Responses-style module, most options | Output Format Type: Text, JSON schema, JSON object |
| Generate a completion | The chat completions module | Response Format field |
| Transform text to structured data | Field extraction with a typed definition | Structured Data Definition: name, description, data type, required |
| Make an API call | Arbitrary authorised call to OpenAI | Whatever you send |
Three details from that page are worth knowing before you write a single prompt.
Simple text prompt needs no connection. Make's app page carries a note headed "Get started easily—no OpenAI account or API key required" for that module. It is the fastest way to test a prompt, and the least controllable, because it exposes no output format field at all.
The JSON options are real, and conditional. On Generate a response, the Output Format Type offers Text, JSON schema, and JSON object, and Make's own field description states that when JSON object is selected, "the prompt must include the word json". Miss that and you get an error rather than an answer.
Make warns about the whitespace trap by name. On Generate a completion, the Response Format field description says that if you select JSON Object without instructing the model to produce JSON, "the model can generate an unending stream of whitespace until it reaches the token limit". That is a stuck run and a token bill, not a clean failure.
None of this makes the output trustworthy. A JSON schema constrains shape, not sense. The model can return perfectly valid JSON whose category field is confidently wrong, and a schema will pass it straight through. Structured output is a floor, not a guarantee.
How should you handle the model's answer once it lands?
Parse it, then validate it, then route it. In that order, in separate modules, so that each failure is visible on its own.
Make's JSON app page documents Parse JSON's behaviour clearly enough to plan around. If you leave the Data structure blank, "you may manually run the module and Make will build the structure from the provided JSON". More importantly for scenario design, a JSON string containing a collection produces a single bundle, while an array means "the output will be a series of bundles, each bundle containing one array's item".
That second sentence is a cost decision hiding in a formatting decision. Ask the model for an array of ten classifications and Parse JSON hands the next module ten bundles, which is ten module runs. Ask for one object per input bundle and you keep the arithmetic flat.
What Make does not publish on that page is a named error code for malformed JSON. So do not state one. What the docs do show is that a Parse JSON failure behaves like any other module error: Make's Throw page uses a deliberately misconfigured Parse JSON module as the recommended way to raise a BundleValidationError on purpose, then attaches an error handler to it. That tells you everything you need. Parse JSON is your validation gate, and its failure is catchable.
What happens to a scenario when the AI module fails?
By default, it stops and reverts. Make documents Rollback as the behaviour you get for free: it "is the default error handling if you don't set any error handling" while incomplete executions stay disabled, and the run ends with an error status.
There are five error handlers, and their current names matter because two of them changed. Verified at help.make.com/error-handlers on 27 August 2026.
| Feature | Scenario stopped | Run status |
|---|---|---|
| Skip — drops the failing bundle, continues with the next | No | Success |
| Retry — stores the bundle as an incomplete execution, retries | No | Warning |
| Resume — substitutes an output you define, carries on | No | Success |
| Commit — stops, keeps changes made so far | Yes | Warning |
| Rollback — stops, reverts transactional changes (default) | Yes | Error |
If you have read an older Make tutorial, you have read about Ignore and Break. Make's Fix missing data errors page carries two inline notes stating that the Ignore error handler shown in its screenshots has been renamed to Skip, and the Break error handler to Retry. Make's release notes index dates that change to 6 June 2026. Same behaviour, different labels in the interface.
For a classification module, Skip and Resume are usually the honest choices. Skip when a lost bundle costs nothing. Resume when you would rather push a placeholder through, which is exactly what an "unknown" fallback in your output contract gives you: a valid substitute the rest of the scenario can handle.
There is also automatic behaviour you do not configure. Make retries ConnectionError and ModuleTimeoutError using exponential backoff, on a published schedule that starts at one minute and, with incomplete executions disabled, stretches to 24 hours by the eighth rerun. After the eighth failed attempt Make disables scheduling for the scenario.
Does a retry loop cost you operations?
The handler itself does not. The reruns do, because reruns are module runs.
Make's error handling overview states that "When an error handler activates, it doesn't consume operations." That is the error handling route, not the retried work. When Retry completes an incomplete execution later, the remaining modules run, and module runs are operations.
The billing vocabulary has also changed, which is worth knowing before you read any older article about Make costs. The Credits page opens with the line "Credits replaced operations as the term for Make's billing unit." It sets out that non-AI apps count one operation as one credit, that third-party AI apps such as OpenAI, Anthropic Claude, and Gemini also count one operation as one credit, and that Make's own built-in AI features can consume credits based on tokens as well as operations.
I am not going to quote a price or a plan allowance here, because those change and this page will not. Read them on make.com/en/pricing at the moment you need them.
The design consequence is simple: a prompt that returns one clean object per bundle is cheaper than a prompt that returns an array someone has to iterate, and far cheaper than a prompt that fails intermittently and drags a retry schedule behind it.
The 26 templates
Every template below follows the same skeleton. Replace {{1.field}} with the mapping pill you drag in from the previous module; Make's own docs use that notation for placeholder mappings. Every contract names a fallback value and a rule for empty input.
Classify and route
The output feeds a router. The number of allowed values must equal the number of routes, plus a fallback.
1. Support ticket triage
You are a support triage classifier inside an automated workflow. No human reads your reply.
TICKET
<<<
{{1.body}}
>>>
Return one JSON object and nothing else. No prose. No markdown. No code fence.
Keys, all required:
"category" exactly one of: "billing" | "technical" | "account" | "other"
"urgency" exactly one of: "high" | "normal" | "low"
"reason" string, maximum 100 characters
If TICKET is empty, whitespace, or unreadable, return exactly:
{"category":"other","urgency":"normal","reason":"empty or unreadable input"}
Never return a category outside the list. Never add keys.
2. Inbound email intent
Classify the intent of this email for routing. Automated pipeline; no human reads this.
EMAIL
<<<
{{1.text}}
>>>
Return one JSON object, nothing else.
"intent" one of: "sales_enquiry" | "support" | "invoice" | "recruitment" | "spam" | "other"
"needs_reply" boolean
"confidence" number 0.00 to 1.00
Empty or unreadable EMAIL:
{"intent":"other","needs_reply":false,"confidence":0}
If two intents fit equally, choose "other". Do not guess between them.
3. Lead qualification tier
Score this inbound lead for routing to a sales queue.
LEAD
<<<
Company: {{1.company}}
Role: {{1.role}}
Message: {{1.message}}
>>>
Return one JSON object, nothing else.
"tier" one of: "enterprise" | "mid_market" | "self_serve" | "unknown"
"signals" array of strings, maximum 3 items, each maximum 40 characters
"reason" string, maximum 120 characters
If any of the three LEAD fields is empty, still classify from what remains.
If all three are empty or unreadable:
{"tier":"unknown","signals":[],"reason":"insufficient data"}
4. Content moderation gate
Decide whether this user-submitted text may be published automatically.
TEXT
<<<
{{1.content}}
>>>
Return one JSON object, nothing else.
"decision" one of: "allow" | "review" | "block"
"category" one of: "clean" | "profanity" | "personal_data" | "spam" | "unclear"
"note" string, maximum 100 characters
If TEXT is empty or unreadable:
{"decision":"review","category":"unclear","note":"empty or unreadable input"}
When uncertain, choose "review". Never choose "allow" to resolve ambiguity.
Extract structured fields from unstructured input
The output feeds a database write. Missing beats invented.
5. Invoice header extraction
Extract invoice fields. Automated pipeline. Do not explain.
DOCUMENT TEXT
<<<
{{1.text}}
>>>
Return one JSON object, nothing else.
"invoice_number" string or null
"issue_date" string in YYYY-MM-DD, or null
"total_amount" number, or null
"currency" ISO 4217 code as a string, or "unknown"
"vendor_name" string or null
Use null for any field not clearly present in the text. Never estimate a total.
If DOCUMENT TEXT is empty or unreadable, return every field as null except
"currency", which must be "unknown".
6. Contact details from an email signature
Extract contact details from this signature block.
SIGNATURE
<<<
{{1.signature}}
>>>
Return one JSON object, nothing else.
"full_name" string or null
"job_title" string or null
"company" string or null
"email" string or null, must contain "@" if not null
"phone" string or null, digits and + only
"confidence" one of: "high" | "medium" | "low"
Empty or unreadable SIGNATURE: all fields null, "confidence":"low".
Do not infer an email address from a company name.
7. Meeting notes to action items
Extract action items from these notes.
NOTES
<<<
{{1.notes}}
>>>
Return one JSON object, nothing else.
"items" array, maximum 10 entries, each an object with:
"task" string, maximum 120 characters
"owner" string or "unassigned"
"due" string in YYYY-MM-DD, or null
"has_items" boolean
If no action items are present, or NOTES is empty or unreadable:
{"items":[],"has_items":false}
Never invent an owner. Use "unassigned" when the notes do not name one.
8. Product attributes from a description
Extract product attributes for a catalogue record.
DESCRIPTION
<<<
{{1.description}}
>>>
Return one JSON object, nothing else.
"product_name" string or null
"colour" string or "unspecified"
"size" string or "unspecified"
"material" string or "unspecified"
"category" one of: "apparel" | "homeware" | "electronics" | "other"
Empty or unreadable DESCRIPTION:
{"product_name":null,"colour":"unspecified","size":"unspecified",
"material":"unspecified","category":"other"}
Summarise to a fixed length
The output goes into a field with a limit. Say the limit in characters, not "briefly".
9. Ticket summary for a Slack message
Summarise this support ticket for a Slack alert.
TICKET
<<<
{{1.body}}
>>>
Return one JSON object, nothing else.
"summary" string, 20 to 200 characters, plain text, no line breaks
"truncated" boolean, true if you had to omit material detail
If TICKET is empty or unreadable:
{"summary":"No readable ticket content.","truncated":false}
Never exceed 200 characters. Never start with "This ticket".
10. Article abstract for a CMS field
Write an abstract for this article.
ARTICLE
<<<
{{1.body}}
>>>
Return one JSON object, nothing else.
"abstract" string, 200 to 320 characters, one paragraph, no markdown
"language" ISO 639-1 code as a string, or "unknown"
If ARTICLE is empty or unreadable:
{"abstract":"","language":"unknown"}
Do not add a title. Do not use the words "delve", "landscape" or "dive".
11. Call transcript digest
Digest this call transcript for a CRM note field.
TRANSCRIPT
<<<
{{1.transcript}}
>>>
Return one JSON object, nothing else.
"digest" string, maximum 500 characters
"next_step" string, maximum 100 characters, or "none stated"
"sentiment" one of: "positive" | "neutral" | "negative" | "unclear"
Empty or unreadable TRANSCRIPT:
{"digest":"","next_step":"none stated","sentiment":"unclear"}
Report only what was said. Do not infer a next step that nobody proposed.
Draft a reply for human approval
Never send these automatically. The contract includes a flag that forces review.
12. Support reply draft
Draft a reply to this ticket. A human will review it before sending.
TICKET
<<<
{{1.body}}
>>>
KNOWN FACTS
<<<
{{2.facts}}
>>>
Return one JSON object, nothing else.
"draft" string, maximum 900 characters
"requires_human" boolean, always true
"unsupported_claims" array of strings, each a statement in your draft that
KNOWN FACTS does not support; empty array if none
If TICKET is empty or unreadable:
{"draft":"","requires_human":true,"unsupported_claims":[]}
Use only KNOWN FACTS. Do not promise refunds, dates, or discounts.
13. Sales follow-up draft
Draft a follow-up email. It will be reviewed before sending.
CONTEXT
<<<
Last contact: {{1.last_contact}}
Their message: {{1.message}}
>>>
Return one JSON object, nothing else.
"subject" string, maximum 70 characters
"body" string, maximum 800 characters
"requires_human" boolean, always true
Empty or unreadable CONTEXT:
{"subject":"","body":"","requires_human":true}
No pricing. No commitments. No claims about product features.
14. Review response draft
Draft a public response to this review. A human approves before posting.
REVIEW
<<<
Rating: {{1.rating}}
Text: {{1.text}}
>>>
Return one JSON object, nothing else.
"response" string, maximum 500 characters
"tone" one of: "apologetic" | "appreciative" | "neutral"
"escalate" boolean, true if the review alleges harm, fraud, or legal issues
"requires_human" boolean, always true
Empty or unreadable REVIEW:
{"response":"","tone":"neutral","escalate":true,"requires_human":true}
Enrich a record
The riskiest shape, because the model will happily fill a blank field with plausible fiction.
15. Company categorisation
Categorise this company from the supplied text only.
SOURCE TEXT
<<<
{{1.about}}
>>>
Return one JSON object, nothing else.
"industry" one of: "software" | "retail" | "manufacturing" | "services"
| "finance" | "healthcare" | "other"
"b2b_or_b2c" one of: "b2b" | "b2c" | "both" | "unknown"
"evidence" string, maximum 120 characters, quoted from SOURCE TEXT
If SOURCE TEXT is empty or unreadable:
{"industry":"other","b2b_or_b2c":"unknown","evidence":""}
Use no outside knowledge. If SOURCE TEXT does not say it, you do not know it.
16. Job title normalisation
Map this job title to a seniority band.
TITLE
<<<
{{1.job_title}}
>>>
Return one JSON object, nothing else.
"band" one of: "ic" | "manager" | "director" | "vp" | "c_level" | "unknown"
"function" one of: "engineering" | "sales" | "marketing" | "operations"
| "finance" | "other"
Empty or unreadable TITLE:
{"band":"unknown","function":"other"}
Do not guess a band from company size or from the person's name.
17. Support ticket tagging
Assign tags to this ticket from a fixed vocabulary.
TICKET
<<<
{{1.body}}
>>>
ALLOWED TAGS: login, billing, export, import, performance, mobile, api, other
Return one JSON object, nothing else.
"tags" array of strings, 1 to 3 items, each from ALLOWED TAGS
"notes" string, maximum 80 characters
If nothing matches, return ["other"]. If TICKET is empty or unreadable:
{"tags":["other"],"notes":"empty or unreadable input"}
Never invent a tag outside ALLOWED TAGS.
Translate and normalise
Formatting jobs where determinism matters more than fluency.
18. Tone-preserving translation
Translate the text. Automated pipeline; the result is written straight to a field.
SOURCE
<<<
{{1.text}}
>>>
TARGET LANGUAGE: {{1.target_lang}}
Return one JSON object, nothing else.
"translation" string
"source_language" ISO 639-1 code as a string, or "unknown"
"untranslatable" array of strings: product names or terms you left as-is
Empty or unreadable SOURCE:
{"translation":"","source_language":"unknown","untranslatable":[]}
Preserve line breaks. Do not add explanations or alternatives.
19. Address normalisation
Normalise this address into fields.
ADDRESS
<<<
{{1.address}}
>>>
Return one JSON object, nothing else.
"line1" string or null
"line2" string or null
"city" string or null
"postal_code" string or null
"country_code" ISO 3166-1 alpha-2 as a string, or "XX"
Empty or unreadable ADDRESS: all fields null except "country_code":"XX".
Never infer a country from a postal code format alone.
20. Date and currency normalisation
Normalise the values found in this text.
TEXT
<<<
{{1.text}}
>>>
Return one JSON object, nothing else.
"dates" array of strings in YYYY-MM-DD; omit ambiguous dates entirely
"amounts" array of objects: {"value": number, "currency": "ISO code or UNKNOWN"}
"ambiguous" array of strings: the raw fragments you refused to normalise
Empty or unreadable TEXT:
{"dates":[],"amounts":[],"ambiguous":[]}
A date like 03/04/2026 is ambiguous. Put it in "ambiguous", not in "dates".
Score or prioritise
Numeric outputs. Bound the range and define the scale, or you get a different scale every run.
21. Ticket priority score
Score this ticket's priority.
TICKET
<<<
{{1.body}}
>>>
SCALE: 1 = cosmetic, 3 = degraded, 5 = blocked, cannot work
Return one JSON object, nothing else.
"score" integer 1 to 5
"driver" one of: "outage" | "data_loss" | "billing" | "usability" | "unclear"
"rationale" string, maximum 100 characters
Empty or unreadable TICKET:
{"score":3,"driver":"unclear","rationale":"empty or unreadable input"}
Return an integer, never a decimal, never a range.
22. Lead fit score
Score how well this lead matches the ideal customer profile.
ICP
<<<
{{2.icp}}
>>>
LEAD
<<<
{{1.lead}}
>>>
Return one JSON object, nothing else.
"score" integer 0 to 100
"band" one of: "strong" | "possible" | "weak" | "unknown"
"missing" array of strings: ICP criteria you could not assess
If LEAD is empty or unreadable:
{"score":0,"band":"unknown","missing":["all criteria"]}
Score only against ICP. Do not apply your own idea of a good customer.
23. Content quality gate
Score this draft against the checklist before it goes to a human editor.
DRAFT
<<<
{{1.draft}}
>>>
Return one JSON object, nothing else.
"readability" integer 1 to 5
"on_brief" integer 1 to 5
"blockers" array of strings, maximum 5, each maximum 80 characters
"verdict" one of: "pass" | "revise" | "reject" | "unscored"
Empty or unreadable DRAFT:
{"readability":1,"on_brief":1,"blockers":["empty draft"],"verdict":"unscored"}
Deduplicate and match
Comparison jobs. The failure mode is a confident merge of two different people.
24. Record match decision
Decide whether these two records describe the same entity.
RECORD A
<<<
{{1.record_a}}
>>>
RECORD B
<<<
{{2.record_b}}
>>>
Return one JSON object, nothing else.
"match" one of: "same" | "different" | "uncertain"
"confidence" number 0.00 to 1.00
"evidence" array of strings, maximum 3, each maximum 60 characters
If either record is empty or unreadable:
{"match":"uncertain","confidence":0,"evidence":["missing record"]}
Choose "uncertain" rather than "same" whenever the only shared field is a name.
25. Duplicate ticket detection
Decide whether the new ticket duplicates any candidate.
NEW TICKET
<<<
{{1.body}}
>>>
CANDIDATES
<<<
{{2.candidates}}
>>>
Return one JSON object, nothing else.
"duplicate_of" string: a candidate id, or "none"
"confidence" number 0.00 to 1.00
"reason" string, maximum 100 characters
If NEW TICKET or CANDIDATES is empty or unreadable:
{"duplicate_of":"none","confidence":0,"reason":"insufficient data"}
Only return an id that appears verbatim in CANDIDATES.
26. Field-level conflict resolution
Two systems disagree on a field. Report the disagreement. Do not resolve it.
FIELD: {{1.field_name}}
VALUE FROM SYSTEM A: {{1.value_a}}
VALUE FROM SYSTEM B: {{2.value_b}}
Return one JSON object, nothing else.
"conflict" boolean
"same_meaning" one of: "yes" | "no" | "unclear"
"recommend" one of: "system_a" | "system_b" | "human_review"
If either value is empty:
{"conflict":false,"same_meaning":"unclear","recommend":"human_review"}
When "same_meaning" is "unclear", "recommend" must be "human_review".
How do you test one of these before it runs unattended?
Run the ugly inputs first, not the clean one. A prompt that works on your best example tells you nothing you did not already assume.
- Run the AI module alone with a normal input. Right-click and use Run this module only.
- Run it with an empty string. Confirm you get the exact fallback object from the contract.
- Run it with garbage: a base64 blob, a different language, an HTML fragment.
- Run it with an input designed to invite a fourth category. Confirm you get the fallback value.
- Attach Parse JSON and confirm it builds the data structure from your output.
- Attach the router. Confirm the fallback route catches every case from steps 2 to 4.
- Add an error handler to the AI module and to Parse JSON. Decide deliberately between Skip and Resume rather than accepting Rollback by default.
- Only then connect the module that writes, sends, or charges anything.
Make's Overview of error handling is worth reading in full before step seven, because the choice between the five handlers changes whether a bad night is a queue of incomplete executions or a disabled scenario.
What can go wrong that no prompt can fix?
Non-determinism, and it is not a bug you can write your way out of. The same prompt with the same input can return a differently shaped result on run 400 after 399 clean ones. Sampling is probabilistic; a lower temperature narrows the distribution without collapsing it.
This is why the entire structure above exists. You are not trying to make the model perfect. You are building a scenario where an imperfect answer is caught by Parse JSON, sorted by a fallback route, and parked in a queue that a person looks at, rather than written into a customer record at three in the morning. Validate before you route. Never trust the model as the last checkpoint.
Two honest limits. I have no reliability figures for these templates, and anyone quoting a percentage for how often a model returns valid JSON is quoting a number from a different model, version, and dataset than yours. And anything customer-facing gets a human approval step, because the cost of the one bad draft is asymmetric.
One more piece of honesty, since this page has our name on it. Prompt Architects generates the prompt, not the scenario. There is no Make.com connector on our integrations page and I am not implying one exists.
For the same discipline applied to a different automation platform, the n8n node templates cover the equivalent ground there. If you want the reasoning behind the contract format itself, JSON prompts explained and the free JSON prompt generator go deeper on schema validation. When a model ignores a format you specified clearly, this diagnostic covers the usual causes. And if the variation between runs is what is biting you, why you get a different answer every time explains the mechanism.
Stop rewriting prompts. Start shipping.
Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 5.0★ on the Chrome Web Store.
Create An AccountSources
All verified on 27 August 2026.
- Make Apps Documentation, OpenAI (ChatGPT, Sora, Whisper) and OpenAI modules — app name, module list, Output Format and Response Format fields.
- Make Apps Documentation, JSON — Parse JSON, data structures, collection versus array output.
- Make Help Center, Error handlers, Overview of error handling, Exponential backoff, Throw.
- Make Help Center, Operations and Credits — operation definition, bundle multiplication, credit terminology.
- Make Help Center, Router — fallback routes, sequential route processing.