AI Retries / Prompt Edits
Sometimes quick manual edits of (AI-generated) content are the best way to get the result you want. And that's what our in-place editing is for. But other times you need broader changes of a text, or manual edits are simply not an option - think images, videos, or audio.
By enabling retry buttons for a field, you can let your reviewers request changes - by retrying or even changing a given prompt.
Enable retry buttons
In your review template, you can enable retries in the settings of most field types like text, images, or markdown.

Requesting retries during reviews
In the review UI, this will add retry controls below the field.

The chat button will open a modal where the reviewer is able to iterate on the field's content (i.e. the artifact) by retrying or changing the prompt.
They can always go back and forth between different generated versions of the artifact, so they can safely give it another try without losing previous results.

Connect to your workflow
To make the AI retry feature work, you need to support the webhook that is triggered when a reviewer requests a retry. After regenerating the artifact, you'll need to update the review request with the new artifact.
Allow editing the prompt (optional)
For the prompt to show up in the chat and to allow editing it, you need to pass it in your review request in the following format:
{
...
"fields": {
...
"blog": {
"ai": {
"prompt": "Write a blog post about the following..."
},
"content": "..." // the value(s) you'd usually send for this field
}
}
}
This can simply be the initial prompt, even when you're updating the review request after a prompt edit by the reviewer (s. below). We are only processing this for the initial request.
Handle retry webhook
Clicking the retry button or editing the prompt will trigger the webhook you set up for this review template with a "type": "chat"
. If you passed a prompt in your review request, the webhook will also include a messages
array with the (maybe edited) prompt as the first message. Until we support full chat conversations, this is the only message you'll get.
Our n8n node handles the webhook internally, so the webhook data below will be the output of the node.
[
{
"type": "chat",
"event": "retry",
"accountId": "hlSXkGN5z6CxsSA48IYj",
"formId": "OuIlLGMQCcBtwkwbZmKn",
"reviewId": "lBkTFbmXN2YfA1tCMYHm",
"fieldId": "postDraft",
"createdAt": "2025-08-12T22:27:39.051Z",
"messages": [
{
"role": "human",
"content": "You will be passed a scraped article from a company blog. I'm a fan of their product and will write a LinkedIn post for every news that is coming out. Please write an engaging post based on the article."
}
],
"gthLinkToReview": "https://app.gotohuman.com/accounts/hlSXkGN5z6CxsSA48IYj/reviews/lBkTFbmXN2YfA1tCMYHm"
}
]
Update review request
After regenerating the artifact (content) of this field in response to the retry webhook, you need to update the review request with the new artifact. For simplicity you can send the same request as for your inital request for review, only adding the ID of the review to update.
- n8n
- Make
- Python SDK
- JS/TS SDK
- HTTP
Select Additional Fields > Add Field and add the field Update for Review ID, where you can enter or map the ID of the review to update.
Your flow will typically look like this:

Switch node with these rules:
{{ $json.response }}
is equal to "approved"{{ $json.response }}
is equal to "rejected"{{ $json.type }}
is equal to "chat"
"Retry" Set Fields node (Manual mapping):
- "prompt" (String) =
{{ $json.messages[0].content }}
- "reviewToUpdate" (String) =
{{ $json.reviewId }}
AI Draft Node:
- It can simply reference
{{ $json.prompt }}
because the "Set Initial Prompt" node and the "Retry" node both expose a "prompt" field
gotoHuman node:
- "Update for Review ID" =
{{ $('Retry').isExecuted ? $('Retry').item.json.reviewToUpdate : null }}
Read more in our n8n integration guide.
Select Show advanced settings to show the field Update for Review ID, where you can enter or map the ID of the review to update.
Read more in our Make integration guide.
review = gotoHuman.create_review("ib41P20UBPLpEfwH7CkL") // ID of form/review template
review.update_for_review("iVcm4fwRPihAdVnZ7v0d") // <-- ID of the review
review.add_field_data("blog", "My blog post regenerated by the LLM to be shorter.")
review.add_field_data("imageOptions", [
{
"url": "https://cdn.example.com/my-regenerated-image3.jpg"
},
{
"url": "https://cdn.example.com/my-regenerated-image4.jpg"
}
])
// add other fields
try:
response = review.send_request()
print("Review sent successfully:", response)
except Exception as e:
print("An error occurred:", e)
Create a request with the formId of the form you created.
Pass the field values and optionally some meta data.
const reviewRequest = gotoHuman.createReview("ib41P20UBPLpEfwH7CkL") // ID of form/review template
.updateForReview("iVcm4fwRPihAdVnZ7v0d") // <-- ID of the review
.addFieldData("blog", "My blog post regenerated by the LLM to be shorter.")
.addFieldData("imageOptions", [
{
"url": "https://cdn.example.com/my-regenerated-image3.jpg"
},
{
"url": "https://cdn.example.com/my-regenerated-image4.jpg"
}
])
// add other fields
await reviewRequest.sendRequest()
The structure of your API request is
{
"formId": "ib41P20UBPLpEfwH7CkL", // ID of form/review template
"updateForReviewId": "iVcm4fwRPihAdVnZ7v0d", // <-- ID of the review
"fields": {
"blog": "My blog post regenerated by the LLM to be shorter.",
"imageOptions": [
{
"url": "https://cdn.example.com/my-regenerated-image3.jpg"
},
{
"url": "https://cdn.example.com/my-regenerated-image4.jpg"
}
],
// add other fields
}
}