07-tool-using-agent / src /tools /external_api.py
FlyingNunchucks's picture
Sync from GitHub via hub-sync
6bedc74 verified
Raw History Blame Contribute Delete
3.17 kB
from typing import Any, Dict, List
import requests
BASE_URL = "https://api.worldbank.org/v2/country"
def lookup_country(country_name: str) -> Dict[str, Any]:
"""
Retrieve basic country information from the World Bank Countries API.
This tool demonstrates controlled access to an external HTTP API
without requiring an API key.
"""
if not isinstance(country_name, str):
raise TypeError("country_name must be a string.")
country_name = country_name.strip()
if not country_name:
raise ValueError("country_name cannot be empty.")
if len(country_name) > 100:
raise ValueError("country_name is too long.")
try:
response = requests.get(
BASE_URL,
params={
"format": "json",
"per_page": 400,
},
timeout=10,
)
response.raise_for_status()
except requests.Timeout as exc:
raise RuntimeError(
"World Bank API request timed out."
) from exc
except requests.RequestException as exc:
raise RuntimeError(
f"World Bank API request failed: {exc}"
) from exc
try:
payload = response.json()
except ValueError as exc:
raise RuntimeError(
"World Bank API returned invalid JSON."
) from exc
if (
not isinstance(payload, list)
or len(payload) < 2
or not isinstance(payload[1], list)
):
raise RuntimeError(
"World Bank API returned an unexpected response."
)
countries: List[Dict[str, Any]] = payload[1]
normalized_query = country_name.casefold()
exact_matches = [
country
for country in countries
if country.get("name", "").casefold() == normalized_query
]
if exact_matches:
country = exact_matches[0]
else:
partial_matches = [
country
for country in countries
if normalized_query in country.get("name", "").casefold()
]
if len(partial_matches) == 1:
country = partial_matches[0]
elif len(partial_matches) > 1:
names = [
match.get("name")
for match in partial_matches[:10]
]
raise ValueError(
f"Country name '{country_name}' is ambiguous. "
f"Possible matches: {names}"
)
else:
raise ValueError(
f"No country found matching '{country_name}'."
)
region = country.get("region") or {}
income_level = country.get("incomeLevel") or {}
lending_type = country.get("lendingType") or {}
return {
"query": country_name,
"name": country.get("name"),
"iso2_code": country.get("iso2Code"),
"iso3_code": country.get("id"),
"capital": country.get("capitalCity"),
"region": region.get("value"),
"income_level": income_level.get("value"),
"lending_type": lending_type.get("value"),
"longitude": country.get("longitude"),
"latitude": country.get("latitude"),
}