pydantic-ai-unirate
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.
Why this package
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.
Install
pip install pydantic-ai-unirate
Quick start
import 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. |
Direct use of the wrapper
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())
Composing your own toolset
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")
Configuration
| 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.
Error handling
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) |
Related UniRate clients
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.
License
MIT — see LICENSE.
Metadata
Release files for pydantic-ai-unirate 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pydantic_ai_unirate-0.1.0.tar.gz | 50.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pydantic_ai_unirate-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 60.6 kB
Release files / pydantic_ai_unirate-0.1.0.tar.gz
| Download URL | pydantic_ai_unirate-0.1.0.tar.gz |
|---|---|
| Size | 50.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a4d3c0912a037a1f559a61d6a98fac7c7a26d2821361940f768970e9bc1d8876
|
|
BLAKE2b-256 checksum How to use checksums |
e591ff42bdc5ee1452ef9616cc4995ceea2e98a499f4d10b7d516ee3205c71e4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 25, 2026.
Transparency logRelease files / pydantic_ai_unirate-0.1.0-py3-none-any.whl
| Download URL | pydantic_ai_unirate-0.1.0-py3-none-any.whl |
|---|---|
| Size | 10.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5c1bec94979338c5819e1e110b544be055b648108d08ddbe8b63208487b7731d
|
|
BLAKE2b-256 checksum How to use checksums |
8f8bb8f5cfdefad4db70018477b8201c97d12b3ef55cab23b221f41586896067
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 25, 2026.
Transparency log