Static dataset query

A common mistake is to jump straight to tool calling for a simple lookup. For data you own, a plain Python function is faster, more reliable, and easier to debug. The graph calls the function, the function returns a list, and the next node proposes options from it.

Catalog lookup as a plain function

The search node calls a deterministic repo function. No tool calling, no LLM roundtrip.

flight_repo.py
python
def search_flights(
    origin: str,
    destination: str,
    depart_date: str,
    limit: int = 3,
) -> List[Dict[str, Any]]:
    """Return up to `limit` flight offers stamped with the requested depart date."""
    origin_u = (origin or "").upper().strip()
    dest_u = (destination or "").upper().strip()
    matches: List[Dict[str, Any]] = []
    for f in _FLIGHTS:
        if f["origin"] == origin_u and f["destination"] == dest_u:
            offer = dict(f)
            offer["depart_date"] = depart_date
            matches.append(offer)
        if len(matches) >= limit:
            break
    return matches

The repo is the boring part, which is the point. A list comprehension in disguise: match origin and destination, stamp the requested date, return up to the limit. Swap this for a real GDS or database call without touching the graph.

Tool calling makes sense when the LLM needs to decide whether to call something, or when the arguments are hard to pin down. Here, once the router has origin, destination, and date, there is nothing to decide. Running a deterministic function is cheaper and cannot hallucinate. Reserve tool calling for when the model actually needs agency.

Quiz: Quiz

Loading practice…