💰 Tip Calculator

custom @tool via Strands + Bedrock

Concept

A tool-enabled agent. Any phrasing of a tip question routes to the same calculate_tip tool — no regex or intent classifier needed. The @tool decorator is all that's needed to expose a Python function to the agent: Strands reads the type hints and docstring to build the tool's schema automatically.

Theory & Concepts

The Tip Calculator demo illustrates the core concept of Function Calling (or Tool Use). On its own, an LLM might struggle with precise arithmetic. By giving it access to a calculate_tip Python function, we empower the agent to offload math to deterministic code, ensuring absolute accuracy.

In our tip_agent.py, we simply define a function that takes a bill_amount, tip_percentage, and an optional num_people. The @tool decorator tells the Strands framework to expose this function to the Bedrock agent. When a user asks a tip-related question via the browser, the agent pauses its text generation, invokes calculate_tip with the extracted numbers, and then uses the returned dictionary (containing the exact tip, total, and per-person split) to formulate its final friendly response.

The standout feature of this approach is Semantic Intent. We didn't have to write any regex or intent classification logic to parse the user's question. Whether the user types "What's a 20% tip on $85?" or "Split a 50 dollar bill 3 ways with 15% tip", the LLM natively understands the intent. It extracts the correct parameters from the messy natural language and perfectly maps them to our tool's arguments, showcasing the flexibility of agent-driven routing.

Request flow

Browser question POST /tip
app.py tip_route tip_agent.py calculate()
Agent Bedrock decides to call calculate_tip
calculate_tip() returns dict Bedrock phrases answer
Browser JSON result

Code flow

flowchart TD A["Browser<br/>tip question"] -->|"POST /tip"| B["app.py<br/>tip_route"] B -->|"question"| C["tip_agent.py<br/>calculate"] C -->|"question + tools"| D["Bedrock<br/>Nova Pro"] D -->|"tool call: calculate_tip"| E["calculate_tip<br/>bill, %, people"] E -->|"tip + total + per_person"| D D -->|"answer text"| C C -->|"answer text"| B B -->|"JSON result"| A

Backend

tip_agent.py
"""Module 2 demo — a tool-enabled agent: the tip calculator.

The agent understands INTENT, not keywords: every phrasing of a tip question
routes to the same ``calculate_tip`` tool with no regex or intent classifier.
"""

from strands import Agent, tool
from strands.models.bedrock import BedrockModel

from config import MODEL_ID, agent_text


@tool
def calculate_tip(bill_amount: float, tip_percentage: float, num_people: int = 1) -> dict:
    """Calculate tip and split the bill among people.

    Args:
        bill_amount: Total bill amount in dollars
        tip_percentage: Tip percentage (e.g., 15, 18, 20)
        num_people: Number of people splitting the bill (default: 1)
    """
    tip = bill_amount * (tip_percentage / 100)
    total = bill_amount + tip
    per_person = total / num_people
    return {
        "bill": bill_amount,
        "tip": round(tip, 2),
        "total": round(total, 2),
        "per_person": round(per_person, 2),
    }


def calculate(question: str) -> str:
    """Answer a natural-language tip question using the calculate_tip tool."""
    agent = Agent(
        model=BedrockModel(model_id=MODEL_ID),
        tools=[calculate_tip],
        callback_handler=None,
    )
    return agent_text(agent(question))