Skip to main content

Step-By-Step Instruction Following

Sometimes we need an agent to follow a very strict script. For example, when troubleshooting a router, the agent must ask the customer to unplug it, wait 60 seconds, and then plug it back in. If the agent skips the wait, the fix won’t work. LLMs (Large Language Models) can get distracted or try to be “helpful” by skipping steps. To prevent this, we use a State Machine.

What is a State Machine?

Think of a State Machine like a digital bookmark in a book.
  • The Book is your script (the instructions).
  • The Bookmark is the “State” (where you are right now).
The agent is only allowed to read the page with the bookmark. It cannot flip ahead to the end of the book. It must finish the current page before moving to the next one.

How to Build One

To make an agent follow a script, we need three things:
  1. The Script (Flow Definitions): A list of steps the agent must take.
  2. The Tracker (State): A variable that remembers the current step.
  3. The Tools: Functions the agent calls to “turn the page”.

1. The Script

We define our script as a simple list of steps. Each step has an ID and instructions.
// This is our "Book"
const routerFixFlow = [
  {
    id: "step_1_unplug",
    title: "Unplug Router",
    instruction: "Ask the customer to unplug the power cable."
  },
  {
    id: "step_2_wait",
    title: "Wait 60 Seconds",
    instruction: "Tell the customer to wait. Do not continue until 60 seconds pass.",
    requiresWait: true // Special rule: Agent must wait!
  },
  {
    id: "step_3_plug_in",
    title: "Plug In",
    instruction: "Ask the customer to plug the cable back in."
  }
];

2. The Tracker

We need a way to track which step is active.
// This is our "Bookmark"
let currentStepIndex = 0; // We start at the first step (Index 0)

function getCurrentStep() {
  return routerFixFlow[currentStepIndex];
}

3. The Tools

Instead of giving the agent the whole script at once, we give it tools to ask “What do I do next?” and “I’m done”.

Tool A: get_current_step

The agent calls this to see what it should do right now.
// Agent calls this to read the current page
function get_current_step() {
  const step = getCurrentStep();

  if (!step) {
    return "You are done! Great job.";
  }

  return {
    step_id: step.id,
    instruction: step.instruction,
    status: "pending" // Tells the agent it hasn't started this yet
  };
}

Tool B: start_step

The agent calls this to say “Okay, I am doing this step now.”
// Agent calls this to say "I'm starting"
function start_step(step_id: string) {
  const current = getCurrentStep();

  if (step_id !== current.id) {
    return "Error: You cannot start that step. You are on " + current.id;
  }

  return "Step started. Follow the instructions: " + current.instruction;
}

Tool C: complete_step

The agent calls this when the customer has finished the action. This is where the magic happens. This function moves the bookmark forward.
// Agent calls this to say "We finished this step"
function complete_step(step_id: string) {
  const current = getCurrentStep();

  if (step_id !== current.id) {
    return "Error: Wrong step.";
  }

  // Move the bookmark forward!
  currentStepIndex = currentStepIndex + 1;

  // Return the NEXT step immediately so the agent keeps going
  const nextStep = getCurrentStep();
  return {
    status: "Step completed",
    next_step: nextStep ? nextStep.instruction : "Flow finished"
  };
}

Putting It All Together

When the agent runs, the conversation looks like this:
  1. Agent: “System, what is my current step?” (Calls get_current_step)
  2. System: “Your step is step_1_unplug. Instruction: Ask customer to unplug.”
  3. Agent: “Hello customer, please unplug your router.”
  4. Customer: “Okay, it’s unplugged.”
  5. Agent: “System, I finished step_1_unplug.” (Calls complete_step)
  6. System: “Marked as done. Moving bookmark to step_2_wait. Instruction: Wait 60 seconds.”
  7. Agent: “Okay customer, now we must wait 60 seconds…”
By using this pattern, the agent cannot forget to wait, because the system won’t give it the instructions for Step 3 until Step 2 is marked as complete.