Thinwrap now speaks Python
· 3 min read
#announcement #python #release
Last time we said Python was next. It’s here, and it didn’t come alone.
Every Thinwrap scope now ships in four languages, and each scope is on the same version everywhere:
- Location 1.3.0: routing, matrix, geocoding, isochrone
- Notifications 1.2.0: email, SMS, push, chat
- LLM 1.1.0: chat and embeddings across 18 model providers
Python, the Thinwrap way
Python 3.10+, and zero runtime dependencies. Not “just httpx”. Zero. HTTP goes through the standard library’s urllib. The AWS request signing and the JWTs that FCM and APNs need are written in plain Python, so there’s no cryptography wheel to drag along. Prefer httpx or requests? Hand us a transport. We never import either.
from thinwrap.notifications import (
Email, EmailSendInput, SendgridConfig,
)
email = Email(SendgridConfig(api_key=KEY, from_="hi@acme.com"))
email.send(EmailSendInput(
to="you@example.com",
subject="Hi",
text="Hello from Python",
))
Same facade, same result shape, same provider ids as the other three languages. Every release is built and uploaded by CI with a PEP 740 attestation, so PyPI can show you exactly which workflow produced the file you installed.
One story from the road. Our first live check of the Python packages failed on Resend with a bare 403, before the request ever reached the API. The cause: Cloudflare blocks Python’s default Python-urllib user agent. Five of the vendors we wrap block it (Resend, Mailtrap, MailerSend, Discord and Groq), and no unit test would ever have caught it. The fix was one header. The lesson was older: test against the real thing. Every release in this round went through live checks against real vendor APIs before it shipped.
Location: your first real user is your best reviewer
This summer the location scope picked up its first production user, and they sent us a list. Thirteen asks became place details, country filters for autocomplete, a proper no_route error, sensible timeouts, and a hard look at what our defaults were costing people.
In a few places, the answer was “too much”:
- Traffic is opt-in. Traffic-aware routing is a pricier tier on Google and HERE, and we no longer turn it on just because you passed a departure time.
- Lean route lines by default: about 30× smaller on Mapbox and OSRM, with identical distances and durations.
- Session tokens for autocomplete. Without one, Google and Mapbox bill a search box once per keystroke.
Notifications: fewer surprises
1.2.0 is mostly the boring kind of good. Microsoft Teams Workflows webhooks no longer look like failures. OneSignal’s new API keys work. Twilio only offers regions that still exist. SES attachments no longer go through hand-built MIME. And a stray line break in a header gets stopped before it reaches the vendor.
LLM: keeping up with 2026’s models
Models move fast, and 1.1.0 catches up:
- Claude reasoning uses adaptive thinking, because every Claude 5 model rejects the old token-budget style.
- Gemini 3 tool loops keep their thought signatures, so the second turn no longer fails.
- OpenAI’s reasoning models now accept a max-tokens limit.
Token usage now counts what you’re actually billed for, including cache reads, cache writes and thinking.
A few of these changes break things at the edges, and each repo’s changelog spells out which ones.
Get started
npm install @thinwrap/llm # TypeScript
composer require thinwrap/llm # PHP
go get github.com/thinwrap/llm-go # Go
pip install thinwrap-llm # Python
Find your provider in the catalog, see what holds for each language on /python and its siblings, or come say hi on GitHub. It’s in the top menu now.
That’s the release. Go build, in whichever language you like.