AI Hints
Home›Agentic AI Tutorial›Workflows Two
Agentic AI · Lesson 24 of 100

Choosing a Pattern

And gates in plain code.

⏱ 2 min read▶ Video at 43:10🎓 Free
Watch this lesson in the Agentic AI courseWatch on YouTube ↗Full Agentic AI course

Now you've got five workflow patterns, and an agent loop. So how do you choose? Here's a simple way to decide, and a technique that makes every one of them safer.

Choosing a Pattern
From the video: Choosing a Pattern
  • Five patterns and a loop
  • How do you choose?
  • One technique for all of them

Which pattern fits?

Fixed steps, use chaining. Different kinds of input, use routing. Independent checks, use parallelism. Subtasks that you can't predict, use orchestrator workers. Clear quality rules, use evaluator optimizer. And if you can't list the steps at all, use an agent. They also combine. Juno routes first, and then some routes run chains, and others run an agent.

Your situationPattern
Fixed stepsChaining
Different kinds of inputRouting
Independent checksParallelism
Unknown subtasksOrchestrator-workers
Clear quality rulesEvaluator-optimizer
Unknown stepsAgent

Gates in plain code

Whichever pattern you use, put hard rules in code. Here's a refund gate. Is the amount more than the order? Is the order too old? These aren't for the model to decide. Run it. A valid refund passes. Too much money gets refused. An old order gets refused. Whatever the model says, or however it's been tricked, this function won't change its mind.

gate.pypython
def can_refund(order, amount):
    if amount > order["price"]:
        return False, "More than the order total"
    if order["days_ago"] > 30:
        return False, "Outside the thirty-day window"
    return True, "OK"

from shop import get_order

print(can_refund(get_order("A17"), 40))
print(can_refund(get_order("A17"), 900))
print(can_refund(get_order("C09"), 40))
Output
(True, 'OK')
(False, 'More than the order total')
(False, 'Outside the thirty-day window')
Also uses shop.py
ORDERS = {
    "A17": {"item": "Carbon wheelset", "price": 640, "status": "delivered", "days_ago": 12},
    "B42": {"item": "Chain", "price": 28, "status": "shipped", "days_ago": 2},
    "C09": {"item": "Helmet", "price": 95, "status": "delivered", "days_ago": 45},
}
STOCK = {"Carbon wheelset": 3, "Chain": 14, "Helmet": 0}
REFUNDS = []

def get_order(order_id: str) -> dict:
    """Look up one order by its ID, such as A17."""
    return ORDERS.get(order_id, {"error": f"No order {order_id}"})

def check_stock(item: str) -> dict:
    """Return how many of an item are in stock."""
    return {"item": item, "in_stock": STOCK.get(item, 0)}

def refund(order_id: str, amount: float) -> dict:
    """Refund money to the customer for an order."""
    REFUNDS.append((order_id, amount))
    return {"refunded": amount, "order_id": order_id}
Also uses scripted.py
class Scripted:
    """A stand-in model that replays a fixed list of replies."""
    def __init__(self, replies):
        self.replies = list(replies)
        self.calls = 0

    def ask(self, messages):
        self.calls += 1
        return self.replies.pop(0)

The golden rule

Here's the golden rule of agent engineering. Use the least autonomy that solves the problem. Each step up in freedom costs you predictability, speed, and money. A good system is mostly plain code, with a little bit of model judgment at exactly the right places.

Plain codewherever you can
Workflowwhen judgment helps
Agentonly when you must
Gatesrules stay in code

Summary

Use the least autonomy that works, and keep hard rules in code. Next, a big step. Our agent has been forgetting everything. Let's give it a memory.

Key takeaways
  • Pick by the shape of the task
  • Patterns combine
  • Least autonomy that works
Next up: Conversation Memory — what happened so far