Pydantic AI integration for the UniRate API — a drop-in currency-exchange toolset for Pydantic AI agents.
UniRate provides 593+ fiat, crypto, and commodity exchange rates. Latest rates, conversion, the currency list, and VAT rates are available on the free tier; historical and time-series endpoints require a Pro plan.
Pydantic AI has no built-in FX tool — most examples hand-roll one against
exchangerate-api.com or AlphaVantage. This package gives you a typed, tested
UniRateToolset (a subclass of pydantic_ai.toolsets.FunctionToolset, i.e. an
AbstractToolset) that plugs straight into an Agent, plus the underlying
async wrapper and tool functions if you want to compose your own toolset.
pip install pydantic-ai-unirateimport os
os.environ["UNIRATE_API_KEY"] = "..." # https://unirateapi.com
from pydantic_ai import Agent
from pydantic_ai_unirate import UniRateToolset
agent = Agent("openai:gpt-4o-mini", toolsets=[UniRateToolset()])
result = agent.run_sync("How many euros is 250 US dollars right now?")
print(result.output)The toolset registers four tools the model can call:
| Tool | Description |
|---|---|
get_rate |
Latest rate for a pair, or every rate for a base currency. |
convert |
Convert an amount from one currency to another. |
list_currencies |
Every currency code UniRate can convert between. |
get_vat_rates |
VAT rates for all countries, or one country. |
The transport layer is a standalone async client you can call without an agent:
import asyncio
from pydantic_ai_unirate import UniRateAPIWrapper
async def main() -> None:
async with UniRateAPIWrapper() as unirate:
print(await unirate.convert("USD", "EUR", amount=100)) # 92.5
print(await unirate.get_rate("USD", "GBP")) # 0.79
print((await unirate.get_supported_currencies())[:5])
print(await unirate.get_vat_rates("DE"))
asyncio.run(main())The tool functions are exported so you can register them on an existing
FunctionToolset or hand them to an agent individually. Each takes the
UniRateAPIWrapper as its first argument:
from pydantic_ai.toolsets import FunctionToolset
from pydantic_ai_unirate import UniRateAPIWrapper, convert, get_rate
wrapper = UniRateAPIWrapper()
toolset = FunctionToolset()
toolset.add_function(lambda from_currency, to_currency: get_rate(wrapper, from_currency, to_currency), name="get_rate")| Constructor arg | Env var | Default |
|---|---|---|
api_key |
UNIRATE_API_KEY |
— (required) |
base_url |
— | https://api.unirateapi.com |
timeout |
— | 30 (seconds) |
enable_historical |
— | False (Pro-gated; opt in) |
UniRateToolset(api_key=..., enable_historical=..., wrapper=...) forwards to
the wrapper; pass a pre-built wrapper= to share an httpx client.
Every failure raises a typed subclass of UniRateError:
| HTTP status | Exception | Meaning |
|---|---|---|
| 400 | InvalidRequestError |
Invalid request parameters |
| 401 | AuthenticationError |
Missing or invalid API key |
| 403 | APIError (status_code == 403) |
Endpoint requires a Pro subscription |
| 404 | InvalidCurrencyError |
Currency not found or no data available |
| 429 | RateLimitError |
Rate limit exceeded |
| 503 | APIError (status_code == 503) |
Service unavailable |
| transport | UniRateError |
Connection / timeout failure (wrapped) |
If you want to call the API directly from a non-Python application, there are official clients in Python, Node.js, Go, Rust, Java, Ruby, PHP, .NET, and Swift, plus a LangChain integration and an MCP server for Claude Desktop and other MCP hosts.
MIT — see LICENSE.