Skip to content

The Refraction API | Tool Calling

In the previous chapter, we discussed the basic form of the refraction API, where you have the catalog specs, and the generated tool call(s), in structured forms and you want to validate, and act upon the results of the validation, within an agentic system.

This chapter will describe a less invasive form where you can annotate tools directly for this purpose.

3.1 Decorating a Tool

Let's start with tool / function calls outside of existing agentic frameworks. Consider the following tools.

from refraction.integration import refract

@refract()
def SkyScrapperFlightSearch(
    originSkyId: str,
    destinationSkyId: str,
    originEntityId: str,
    destinationEntityId: str,
    date: str,
    returnDate: Optional[str] = None,
    cabinClass: Optional[str] = "economy",
    adults: Optional[int] = 1,
    ...
) -> Dict[str, Any]:
    return {...}


@refract()
def TripadvisorSearchLocation(
    query: str,
) -> Dict[str, Any]:
    return {...}


@refract(
    api="TripadvisorSearchHotels",
    use_given_operators_only=False,
    execute_if_fixed=True,
)
def search_hotels(**kwargs: Any) -> Dict[str, Any]:
    return {...}

A couple of things to notice here. The tools or function can be in two forms: either the signature itself contains what all it needs (if it wraps an API inside, then these would be the input specification of that API). This is not always possible, and so the refract decorator allows you to annotate with the name of the API it is wrapping instead.

3.1.1 Successful Call

This is a successful call (notice the extra inputs) and the function will execute as if nothing extra has happened!

flight_details = SkyScrapperFlightSearch(
    originSkyId="BOS",
    destinationSkyId="JFK",
    originEntityId="123",
    destinationEntityId="456",
    date="2024-05-09",
    # NOTE: Extra parameter
    refractor=refractor,
)

3.1.2 Faulty Call with Return

Now we have missed a parameter in the call.

flight_details = SkyScrapperFlightSearch(
    # missing parameter
    # originSkyId="BOS",
    destinationSkyId="JFK",
    originEntityId="123",
    destinationEntityId="456",
    date="2024-05-09",
    # NOTE: Extra parameters
    refractor=self.refractor,
)

The decorator will block the call and return a refraction result instead. As described in the previous chapter, you can use this to decide how to fix your call.

+ ask(originSkyId)
- var1 = SkyScrapperFlightSearch(destinationSkyId="JFK", originEntityId="123", destinationEntityId="456", date="2024-05-09")
+ var1 = SkyScrapperFlightSearch(destinationSkyId="JFK", originEntityId="123", destinationEntityId="456", date="2024-05-09", originSkyId="$originSkyId$")
?                                                                                                                          +++++++++++++++++++++++++++++

3.1.3 Faulty Call with Execution

If this call is fixable as is, then setting the following parameter, lets the fixed call to execute in place without returning back to the user, even if the original function call was incomplete / incorrect.

use_given_operators_only=False
memory = {"query": "London", "var1": {"geoId": "foo"}}

payload = {
    "checkIn": "2024-09-05",
    "checkOut": "2024-09-15",
}

result = search_hotels(
    **payload,
    refractor=refractor,
    memory=memory,
)
- var2 = TripadvisorSearchHotels(checkIn="2024-09-05", checkOut="2024-09-15")
+ var2 = TripadvisorSearchHotels(checkIn="2024-09-05", checkOut="2024-09-15", geoId="$var1.geoId$")
?                                                                           ++++++++++++++++++++++
Executing: TripadvisorSearchHotels(checkIn="2024-09-05", checkOut="2024-09-15", geoId="foo")

3.1.4 Recovery Call

Now we have messed up the call in a way that can be fixed by making an extra call! This will be allowed if you set the following parameter.

use_given_operators_only=False
memory = {
    "query": "London",
}

payload = {
    "geoId": "$var1.geoId$",
    "checkIn": "2024-09-05",
    "checkOut": "2024-09-15",
}

hotel_details = search_hotels(
     param="foo", **payload, refractor=refractor, memory=memory,
)

Notice the extra call! 🤯 You will now get the result of executing the whole sequence in response to making the original faulty call.

+ var1 = TripadvisorSearchLocation(query="$query$")
- var1 = TripadvisorSearchHotels(param="foo", geoId="$var1.geoId$", checkIn="2024-09-05", checkOut="2024-09-15")
?                                -------------

+ var1 = TripadvisorSearchHotels(geoId="$var1.geoId$", checkIn="2024-09-05", checkOut="2024-09-15")

Executing: var1 = TripadvisorSearchLocation(query="London")


  var1 = TripadvisorSearchLocation(query="London")

Executing: TripadvisorSearchHotels(param="foo", geoId="123", checkIn="2024-09-05", checkOut="2024-09-15")