AI Hints
Agentic AI · Lesson 91 of 100

Capstone: Juno's Tools

The reliable layer.

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

Everything reliable lives in plain code. So we'll build that first, and test it, with no model at all. When you get to the model, you'll know that the ground beneath it is solid.

Capstone: Juno's Tools
From the video: Capstone: Juno's Tools
  • Reliable things live in code
  • Test with no model
  • Solid ground first

The tools file

Here's the reliable layer. Get order has a helpful error. Check stock is simple. Search policy has fixed answers here, but it could use real search. Then the most important function in the project. The refund gate. It returns blocked, auto, or needs human, and no model can influence it. And clean removes card numbers from incoming text, and it limits the length.

juno_tools.pypython
import re
from shop import ORDERS, STOCK

AUDIT = []

def get_order(order_id: str) -> dict:
    """Look up one order by ID, such as A17. Use before answering about any order."""
    return ORDERS.get(order_id, {"error": f"No order {order_id}. Ask the customer to check."})

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

def search_policy(topic: str) -> dict:
    """Search store policies. Topics: returns, warranty, refunds."""
    rules = {"returns": "Free within thirty days if unused.",
             "warranty": "Wheelsets have a two-year warranty for manufacturing faults.",
             "refunds": "Refunds reach the card within five working days."}
    return {"policy": rules.get(topic, "Unknown topic")}

def refund_gate(order_id: str, amount: float) -> str:
    order = ORDERS.get(order_id)
    if order is None:
        return "blocked: unknown order"
    if amount > order["price"] or order["days_ago"] > 30:
        return "blocked: outside policy"
    return "auto" if amount <= 50 else "needs_human"

def clean(text: str) -> str:
    return re.sub(r"\b\d(?:[ -]?\d){12,15}\b", "[CARD]", text)[:2000]

Testing without a model

Before any AI, we test it all directly. Run it. An unknown order gives a helpful error. A small refund is automatic. A large refund needs a person. Too much is blocked. An old order is blocked. And the card number's gone. In seconds, and for free, we've proved that our most important rules work.

test_tools.pypython
from juno_tools import clean, get_order, refund_gate, search_policy

print(get_order("Z99"))
print(search_policy("warranty"))
print("Small refund:", refund_gate("A17", 40))
print("Large refund:", refund_gate("A17", 640))
print("Too large:   ", refund_gate("A17", 900))
print("Too old:     ", refund_gate("C09", 40))
print(clean("Card 4111 1111 1111 1111 please"))
Output
{'error': 'No order Z99. Ask the customer to check.'}
{'policy': 'Wheelsets have a two-year warranty for manufacturing faults.'}
Small refund: auto
Large refund: needs_human
Too large:    blocked: outside policy
Too old:      blocked: outside policy
Card [CARD] please
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 juno_tools.py
import re
from shop import ORDERS, STOCK

AUDIT = []

def get_order(order_id: str) -> dict:
    """Look up one order by ID, such as A17. Use before answering about any order."""
    return ORDERS.get(order_id, {"error": f"No order {order_id}. Ask the customer to check."})

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

def search_policy(topic: str) -> dict:
    """Search store policies. Topics: returns, warranty, refunds."""
    rules = {"returns": "Free within thirty days if unused.",
             "warranty": "Wheelsets have a two-year warranty for manufacturing faults.",
             "refunds": "Refunds reach the card within five working days."}
    return {"policy": rules.get(topic, "Unknown topic")}

def refund_gate(order_id: str, amount: float) -> str:
    order = ORDERS.get(order_id)
    if order is None:
        return "blocked: unknown order"
    if amount > order["price"] or order["days_ago"] > 30:
        return "blocked: outside policy"
    return "auto" if amount <= 50 else "needs_human"

def clean(text: str) -> str:
    return re.sub(r"\b\d(?:[ -]?\d){12,15}\b", "[CARD]", text)[:2000]

Summary

The reliable layer is finished, and tested. Next, the agent itself.

Key takeaways
  • Build the reliable layer first
  • The gate is the key function
  • Test it without a model
Next up: Capstone: Juno's Graph — wiring up the brain