Okay, let's give this a go. We're gonna write a Slack message to our boss. We get the first draft, we get a load of feedback, we get another draft, and then we get some feedback, and then we get the same draft.
Could we chat briefly when you have a moment? Could we chat briefly when you have a moment?
Yep, we're streaming the most recent draft down as the final result. We can see too that our loop goes through two iterations, this first draft and feedback, and then this draft and the feedback. The code looks like this. We are writing the start part manually.
Then we start our step as zero, and we initialize the mostRecentDraft and the mostRecentFeedback.
Then we do our logic inside the while loop. We write our slack message here and then we stream it to the front end and then we take that initial draft that's been streamed and we save it into mostRecentDraft.
We then pass that mostRecentDraft into the evaluation as well as any previous feedback too which in the first loop through will be empty but in later loops will have feedback in.
We then stream that feedback to the front end, save it in the mostRecentFeedback and then increment the step counter at the end.
Finally, once that loop is finished, we get out here, we take the mostRecentDraft, and we stream it to the front end using text-start, text-delta, and text-end parts.
So that's it, we have created a loop. And while this first loop that we've created is quite humble, quite simple. This idea of having full control over the loop is incredibly powerful. And I'm gonna show you why in the next exercise. Oh, it's rare I get to leave a cliffhanger at the end of this.
Nice work, and I will see you in the next one!
writer.write({type: "start",})
let step = 0let mostRecentDraft = ""let mostRecentFeedback = ""
while (step < 2) {// Write Slack messageconst writeSlackResult = streamText({model: google("gemini-2.0-flash-001"),system: WRITE_SLACK_MESSAGE_FIRST_DRAFT_SYSTEM,prompt: `Conversation history:${formatMessageHistory(messages)}Previous draft (if any):${mostRecentDraft}Previous feedback (if any):${mostRecentFeedback}`,})const draftId = crypto.randomUUID()let draft = ""for await (const part of writeSlackResult.textStream) {draft += partwriter.write({type: "data-slack-message",data: draft,id: draftId,})}mostRecentDraft = draft// ...}
// ... in while loopconst evaluateSlackResult = streamText({model: google("gemini-2.0-flash-001"),system: EVALUATE_SLACK_MESSAGE_SYSTEM,prompt: `Conversation history:${formatMessageHistory(messages)}Most recent draft:${mostRecentDraft}Previous feedback (if any):${mostRecentFeedback}`,})// end of while loop
while (step < 2) {// ... in while loopconst feedbackId = crypto.randomUUID()let feedback = ""for await (const part of evaluateSlackResult.textStream) {feedback += partwriter.write({type: "data-slack-message-feedback",data: feedback,id: feedbackId,})}mostRecentFeedback = feedbackstep++}
writer.write({type: "text-start",id: textPartId,})writer.write({type: "text-delta",delta: mostRecentDraft,id: textPartId,})writer.write({type: "text-end",id: textPartId,})