Half of the loop I wrote to Agent is guardrails
Dedicated domain Agent series 02. The foundation of Wild Run Y is a model-driven cycle. This article opens up how it works in the code, why it can't be written into the assembly line, and the most strenuous guardrails: blocking text, removing tools, confirming before issuing reports, changing your brain to check for hard injuries, and closing the clock.
The previous article talked about the foundation of Wild Travel Y, which is a model-driven cycle. This article takes this piece out separately and explains clearly how it works in the code and how I wrote it.
First look at the skeleton of this cycle, it is a bit unreasonably simple:
As long as it is not finished yet: Feed the model everything it knows now, and it decides which tool to call next, execute which tool, stuff the results back, and go back to the beginning.
The model makes only one decision per round: what to do next with this information now. It may be searching for a destination, it may be asking you a few days, it may be estimating how long this section of the road will take, or it may be that the itinerary has been scheduled and a report should be issued. The tool's results come back into the context, it sees the results, and then decides the next step. This is the core of Wild Y, and the code is in the main loop of loop.py. It doesn't care about "what to do in the next few steps", it just feeds the context, takes the action, executes it, and feeds it back again until the model itself calls the submit_plan submission process.
When many people do "AI itinerary planning" for the first time, their first reaction is to build an assembly line: extract destinations, check air tickets, check hotels, schedule every day, make them into itineraries, and output them. This line can run, but it runs quite smoothly in the demo. But when placed in front of a real person, it will break when touched.
Broken down in the real planning process is never a straight line. Someone tells you that he wants to go to the plateau to drive by himself. You have to ask him a few days, how many people, and what car he drives. But maybe he can say everything in one sentence, so you shouldn't ask. You found out that Daocheng Aden takes more than eight hours to drive back to Chengdu, and it can't be completed in one day. You have to turn back and divide the day into two days with an accommodation point in between. When you check your ticket, you find that there is no direct flight to a certain place at all, so you have to change your mind. The user suddenly changed his mind in the middle of the conversation and said that he would not go to the plateau and change to the island. The whole line would have to be restarted, but everything he had confirmed before could not be lost.
Turn around, change paths, start over. The assembly line cannot handle these three things. You can only push if-else in until it becomes a state machine that no one dares to touch, change one branch, and bug in three places.
The cycle changed its mind. There is no concept of "what step" in it, only "current status" and "next decision." When the user changes his mind, new messages enter the context, and the model naturally follows the new intention in the next round. The driving time was too long and the sky would be demolished. The model saw that the road had returned for eight hours, so it decided to add an additional accommodation point. There is no direct flight to a certain place, and the tool returns no data. When it sees it, it changes its strategy. Rules are moved from code to model judgment. I no longer maintain a huge state machine. What I maintain is what tools, what contexts, and what constraints are given to the model.
Speaking of this, it sounds like leaving all the work to the model and it will do it itself. When you really run, you will find that things are not so beautiful.
A naked while cycle can cause two types of accidents. The first is that it does not restrain itself, keeps searching and checking, goes around in circles, just does not submit, and you wait nearby and get angry. The other type is that it goes astray. The user clearly said that it was afraid of high-altitude reactions, but it also connects to a long-distance pass of 4,700 yuan; the user brings the elderly, and it gives you eight hours a day to drive.
Therefore, the loop of wild travel Y does not look elegant at all. It has a large part of the code, which is at the bottom of the pocket model. Let me pick a few real guardrails to talk about.
Does it want to fool the itinerary with a large paragraph of text and ignore the tools? Stop it. There is a counter in the code to stare at it. Before the report is released, it will spit out a large piece of text, and the reply is "Don't use pure text, you must call submit_plan to produce a formal report" to force it to produce structured things in a regular manner. Weak models like to be so lazy.
It is addicted to searching information. After searching three or four times, it is still flipping through travel notes and refusing to get to the point? Just remove the search tool from its eyes. The search tool couldn't be seen, so it could only go down to arrange a line. This hand is more effective than just relying on text prompts. If the tool is not in your hand, it cannot be circumvented even if it wants to.
Does it want to report directly? No. Before issuing a report, you must first show the main line skeleton for you to confirm, and the person must be in the ring. The code stipulates: If submit_plan has not been confirmed once before, call it back and show it to you first.
And before showing it to you, there is a check to change your mind. The model has just finished arranging the main line, and I dare not let it check itself. The context is full of reasons for "why do I arrange this way". Ask it to self-examine, it will be easy for it to confirm itself and feel that the arrangement is very good. So open a clean sub-agent, just take your original requirements and this version of the main line, and check one by one whether there are any flaws: afraid of high revolvers but went to a high altitude? Taking an old man with you but going berserk in a single day? Is one of the three people's must-go points missed? Find out the hard injury and correct it again. It connects before you see the main line, so you can't see the problematic version at all and have been stopped and rearranged.
For self-driving trips, the daily driving hours must be calculated before reporting. Otherwise, weak models will love to skip this step and give you a ghost route of driving for twelve hours and more than a thousand kilometers a day. It is also mandatory in the code: if you want to submit it before you have counted the driving, you will call it back.
Finally, there is a wall clock gate. The guardrail of the upper limit of steps is no longer in name under the slow model. One step may wait for more than 100 seconds. If the number of steps is not used up, the external time will have long expired. So I added another timer: No matter where it reaches five minutes, no matter where it reaches, I will force it to finish with the real place name that it has verified. It is better to have a shorter trip than to timeout, giving users a white screen.
Have you noticed that the most strenuous part of making an agenic loop is not the beautiful sentence "Let the model decide freely", but the pile of guardrails behind it that "Don't let it go too freely". Let it be free is one line of while, and let it be chaotic is hundreds of lines. To make an agency loop, the energy is mainly spent on this guardrail. No matter how smart the model is, it can sometimes be stupid. The system must still be decent and end up at those moments.
This is the cycle of Wild Travel Y: a model-driven main cycle, surrounded by a circle of guardrails. It is the engine of the entire Agent, and every piece behind it hangs on it.
In the loop, the actions that the model can adjust in each round, such as searching for destinations, estimating driving times, checking aircraft and wine, and submitting itineraries, have a unified name called tools. The collection of tools defines what the Agent can and cannot do. The next article will talk about how to design tools.