Steering
1. Steering
In the last video, we built a customer service agent with skills for refunds, order tracking, and account troubleshooting. It works, but if you run it enough times, you'll eventually notice something frustrating. The agent doesn't always follow directions consistently. Sometimes it processes a refund without first checking whether the order is actually eligible. Other times it skips looking up the order history entirely and it just guesses. And sometimes the response tone is far too casual for a customer support interaction. This is one of the big challenges when building AI agents. Instructions can be there in the prompt and still not reliably be followed. As prompts and conversation history grow, important guidance can become less effective or get lost in the context window entirely. This is one of the reasons agent systems drift from expected behavior over time, especially for long-running tasks. One option is to abandon the model-driven approach entirely and hardcode every workflow into a deterministic graph. That can work for very rigid, happy path systems, but the moment a user asks something unexpected, the workflow starts breaking down because it wasn't designed for that scenario. That's one of the reasons Strands takes a model-driven approach. You still want the adaptability and reasoning capabilities of the model, but how do you keep that flexibility while still having the reliability and control you need for a production system? One pattern you can use to improve reliability is steering. Steering gives you a way to inspect and influence agent behavior while the agent is running. Steering is implemented as a plugin and relies on hooks under the hood. At specific points in the agent loop, steering logic evaluates the agent behavior and returns one of three outcomes: proceed, guide, or interrupt. Proceed allows execution to continue normally. Guide injects corrective feedback into the loop so the agent can self-correct. Interrupt pauses execution entirely and hands control back to your application or human operator using the same interrupt system we saw earlier with hooks. Let's add steering to our customer service agent. I'm going to show you two kinds of steering, deterministic steering around tool usage and LLM based steering for evaluating model responses. First up, tool steering. I built a refund workflow handler. This is a deterministic steering handler that enforces the order of operations before a refund can be processed. It extends the steering handler class and the main logic lives inside steer before tool. Every time the agent attempts to call the tool, this handler runs. For anything other than process refund, it simply returns proceed and gets out of the way. But when the agent attempts to process a refund, the handler starts evaluating what has already happened inside the loop. It does this by using an events ledger provided by Strands. The ledger automatically tracks tool calls, inputs, outputs, and execution status throughout the agent life cycle. Steering handlers can inspect that history to make decisions based on the full execution context. The handler validates that the required workflow steps happened in the correct order and that the refund request actually matches the underlying order data. This gives us a deterministic verification layer inside an otherwise model-driven loop. Even if the model hallucinates a refund amount or skips steps, the refund tool cannot execute unless the requirements are satisfied. Agents do hallucinate parameters, so this is important. When the handler returns guide, the tool call gets canceled and the feedback is injected back into the loop as additional context. The model reads the corrective guidance, adjusts its behavior, and tries again. In practice, models respond much more reliably to timely corrective feedback than to large static prompts filled with instructions that they saw several turns ago. Now, let's look at the second kind of steering, which is model steering. This is useful for situations where the rules are difficult to express as deterministic code. I built a tone guardrail handler, which extends the LLM steering handler base class. Instead of deterministic logic, this handler spins up a second agent that acts as a judge. Every time the customer service agent generates a response, the steering agent evaluates its communication policies defined in the steering prompt. This is one of the simplest examples of a multi-agent system. The main customer service agent performs the task, while a second agent evaluates the output before it reaches the user. The steering agent checks for things like over promising, failing to acknowledge customer frustration, or offering compensation outside of the allowed workflow. These are nuanced decisions that are difficult to validate reliably with simple if-else statements. If the steering agent determines the response violates policy, it returns guide with corrective feedback. The original response gets discarded before the customer ever sees it, and the customer service agent gets another opportunity to generate a better response. You can also configure retry limits, so the system doesn't loop forever trying to regenerate responses. This pattern is powerful because the steering agent doesn't have to use the same model as the primary agent. It's a totally separate agent with its own isolated context window. In some systems, you might even intentionally use a different model provider for verification. So, generation and evaluation aren't relying on the same exact model behavior or training patterns. You might also choose a model specifically optimized for critique, policy enforcement, or structured evaluation tasks. This can be very powerful, but the trade-off for this pattern is token consumption and latency because every steering pass adds another model invocation to the loop. But, for important workflows that reliability gains are often worth it. Now, let's wire these steering handlers into our customer service agent. When we create the agent, we compose both steering handlers alongside the skills plugin from the previous video. The skills plugin handles workflow instruction loading, the refund steering handler enforces deterministic workflow requirements, and the tone steering handler evaluates communication quality before responses reach the customer. Let's run it and see what happens. I'll say, "Help me return my order for customer order C1001." And we can see the agent is calling the tools to look at the customer. It's loading the skills, and then see here we have some output from our tone steering handler. It's evaluating the agent's response, and it comes back that it was approved. So, it's doing this for every turn of that agent loop. After the steering handler is done evaluating, it approves that final response, and I can then follow up and say, "I want to return the headphones." And it's asking me if I want to confirm that. I will say yes, and we can again see all of that steering output right here in the command line. And now we can also see here it calls the process refund tool and it's checking to ensure that the order of operations is correct. So that's our deterministic steering handler that just executed there. So now this is done and then I'll just type exit. If you step back and look at what we've assembled across these last few videos, models, tools, MCP integrations, hooks, plugins, skills and now steering, we're gradually building out a full agent harness around the model. But there's another problem we still haven't addressed. For long-running tasks or conversations, your agent is going to hit the context window limit and throw an error. In the next video, we'll tackle that problem with conversation managers.2. Final slide
With agent control covered, shift focus to memory and context engineering.Create Your Free Account
or
By continuing, you accept our Terms of Use, our Privacy Policy and that your data is stored in the USA.