Python SDK changelog
TL;DR The current version is
0.7.1, released 2026-09-21. Two breaking changes so far:0.6.0(2026-09-15) madeScore.criteriaan ordered sequence instead of an int-keyed dictionary, and0.7.0(2026-09-18) swapped the serialization library frommsgspectopydanticand addedsystem_one(..., response_model=...). Write new code against 0.7.1.
Release table
| Version | Date | Kind | Headline |
|---|---|---|---|
0.7.1 |
2026-09-21 | patch | API key validated early and excluded from logged exceptions; AI-gateway usage examples |
0.7.0 |
2026-09-18 | minor, breaking | ser/de moves from msgspec to pydantic; new response_model argument on system_one; str subclasses serialize correctly |
0.6.0 |
2026-09-15 | minor, breaking | Score.criteria becomes an ordered sequence; abstract input types; richer errors; RetryPolicy validation; picklable exceptions and responses |
0.5.7 |
2026-09-14 | initial public release | First published SDK |
0.0.1a0 |
— (date not captured) | pre-release placeholder | Reserves the typesafe-sdk name on PyPI; no documented content |
The upstream changelog (both the docs page and docs/changelog.md in the repo) covers 0.7.1, 0.7.0, 0.6.0 and 0.5.7. 0.0.1a0 appears in the PyPI release listing collected 2026-09-17 and has no changelog entry; the PyPI listing has not been re-collected since, so 0.7.0 / 0.7.1 are confirmed from the changelog and pyproject.toml rather than from PyPI.
Repository state captured for this wiki: https://github.com/typesafe-ai/typesafe-sdk-python at commit 0ffd094c72ed9445223060b24ffd7a56aa781fb4, captured 2026-09-21 (raw/MANIFEST.json). pyproject.toml at that commit declares version = "0.7.1". The previous snapshot in this wiki was commit 420ef4ffb612d5a539a1e0f0fe883ff6770340af ("Release v0.6.0", 2026-09-15).
v0.7.1 (2026-09-21)
Verbatim from the upstream changelog:
Bug fixes
- validate the API key early and exclude the value from logged exceptions
Documentation
- add examples for usage with AI gateways
What that means in code: TypeSafeClient(api_key=...) now resolves and validates the key inside the constructor (resolve_and_validate_api_key in _core/config.py), so a missing, empty, non-ASCII, or whitespace-containing key raises TypeSafeError before any HTTP request — "Invalid API keys raise TypeSafeError during client creation, before any request or retry." Separately, _core/logging.py:redact_exception rewrites transport exceptions (message, __cause__/__context__ chain, and __notes__) replacing every secret-header value with ***, and detaches the unredacted original so it cannot resurface through implicit exception chaining.
The gateway examples are the OpenRouter and Vercel AI Gateway blocks now in the usage guide — reproduced in Python SDK: install, clients, system_one().
v0.7.0 (2026-09-18)
Verbatim from the upstream changelog:
Breaking Changes
- ser/de library has been changed from
msgspectopydantic
Bug fixes
strsubclasses are now correctly serialized as strings instead of lists of characters
Features
- the
system_onemethod now accepts a newresponse_modelargument that can be set to a desiredpydanticmodel for additional type-safety
What the breaking change means in code
| Change | 0.6.0 | 0.7.0 |
|---|---|---|
| Runtime dependency | msgspec>=0.21.1 |
pydantic>=2.12.0 + pydantic-core>=2.41.1 |
| Serialize a response | msgspec.json.encode(response) |
response.model_dump_json() |
| Response/question base | msgspec.Struct |
pydantic.BaseModel |
| Decode failure type inside the SDK | msgspec.DecodeError / msgspec.ValidationError |
pydantic.ValidationError |
| Question objects with unknown kwargs | tolerated by the wire struct | ConfigDict(extra="forbid") → pydantic.ValidationError |
Question TypedDicts |
extra_items=JSONValue | None |
closed=True |
JSONValue / JSONContent |
TypeAlias |
TypeAliasType |
from typesafe_sdk import Noul, NoulAnswer, SystemOneResponse, TypeSafeClient
class BillingResponse(SystemOneResponse):
billing: NoulAnswer
with TypeSafeClient() as client:
result = client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
response_model=BillingResponse,
)
assert result.billing == result.nouls["billing"]
The full migration checklist is in Python SDK: install, clients, system_one() under "Migrating from 0.6.0". The 0.6.0 Score.criteria sequence rule is unaffected and still applies.
v0.6.0 (2026-09-15)
Verbatim from the upstream changelog:
Breaking Changes
- accept
Score.criteriaas an ordered sequence instead of a dictionary keyed by integers
Features
- improve type annotations on SDK inputs to accept abstract types like
MappingandSequence - improve error messages to include http details and metadata
Bug fixes
- handle invalid values in
RetryPolicy - make exceptions and responses picklable
Documentation
- link more concepts from main docs
What the breaking change means in code
from typesafe_sdk import Score
# 0.6.0 and later
Score(instructions="How urgent is this ticket?", criteria=["can wait", "this week", "today"])
# pre-0.6.0 shape — an int-keyed dict; no longer the documented form
# Score(instructions="How urgent is this ticket?",
# criteria={0: "can wait", 1: "this week", 2: "today"})
Migration steps when upgrading from 0.5.7 (still required on 0.7.x — the sequence form is unchanged):
- Find every
Score(...)construction and every{"type": "score", ...}dictionary. - Replace the int-keyed dict with a list (or tuple) ordered from score
0upward.sorted(old.items())then[value for _, value in ...]reproduces the order. - Leave answer-reading code alone:
ScoreAnswer.legendandScoreAnswer.probabilitiesare still keyed by integer score. Only the question side changed. - Re-check
RetryPolicy(...)arguments — invalid values now raiseTypeSafeErrorat construction instead of being accepted silently.
See Python SDK question types (Noul, Choice, Score) for the current question contract and Python SDK responses, answers, usage, models for the answer side.
Where each change is visible in the API
| Change | Observable effect | Page |
|---|---|---|
Score.criteria sequence |
Score(criteria=Sequence[JSONContent]); empty sequence raises TypeSafeError |
Python SDK question types (Noul, Choice, Score) |
| Abstract input types | state, questions, criteria, headers accept Mapping/Sequence, not just dict/list |
Python SDK: install, clients, system_one() |
| Richer error messages | TypeSafeAPIError.endpoint, and __str__ renders endpoint: status message (request_id=…) |
Python SDK retries, exceptions, constants |
RetryPolicy validation |
__post_init__ raises TypeSafeError for bad max_retries, backoff values, jitter, or timeout |
Python SDK retries, exceptions, constants |
| Picklable exceptions and responses | In 0.6.0 via Response.__copy__ / __reduce__ carrying request_id and the raw HTTP response; TypeSafeAPIResponseValidationError.args is set explicitly. 0.7.0 deleted both dunders when Response became a BaseModel — Pydantic's own copy/pickle support took over, and the transport metadata still lives in the instance __dict__ |
Python SDK responses, answers, usage, models |
v0.5.7 (2026-09-14)
Verbatim: "This is the initial public release of TypeSafe Python SDK. Learn more in the documentation."
No itemized changes are published for this release. The version number starting at 0.5.7 rather than 0.1.0 is not explained upstream; the Python and JavaScript SDKs share the 0.5.7 → 0.6.0 sequence, which suggests a shared internal release train (inferred).
v0.0.1a0
Listed on PyPI among the typesafe-sdk releases (0.0.1a0, 0.5.7, 0.6.0) as collected on 2026-09-17. No changelog entry, no release date captured, and no documentation references it. Treat it as a name-reservation pre-release; do not install it.
Related packages
| Package | Version | Note |
|---|---|---|
typesafe-sdk |
0.7.1 (2026-09-21) | The SDK. Import as typesafe_sdk. |
typesafe-ai |
0.1.0 | Redirect shim that simply depends on typesafe-sdk. |
typesafe |
0.9.1 | Unrelated third-party package — not TypeSafe AI. |
@typesafe-ai/sdk (npm) |
0.6.0 (2026-09-15); 0.5.7 on 2026-09-12 | The JavaScript SDK. The two SDKs moved in lockstep through 0.6.0, but the JS SDK has not followed Python to 0.7.x — see JavaScript SDK changelog. |
system-one-adapter |
0.2.0 (2026-09-18) | Requires typesafe-sdk>=0.7.0; 0.1.5 pinned >=0.6.0,<0.7.0. See system-one-adapter: LLM-backed drop-in for TypeSafeClient. |
Version pinning
The SDK is pre-1.0 and has shipped a breaking change in each of its last two minor bumps (0.6.0, 0.7.0), so pin conservatively:
# pyproject.toml
dependencies = ["typesafe-sdk>=0.7.1,<0.8"]
uv add "typesafe-sdk>=0.7.1,<0.8"
Check the installed version at runtime:
from typesafe_sdk import __version__
print(__version__) # resolved via importlib.metadata.version("typesafe-sdk")
Related
- Python SDK: install, clients, system_one() — install, clients,
system_one(), and the 0.6.0 → 0.7.x migration - Python SDK question types (Noul, Choice, Score) — the current
Score.criteriacontract - Python SDK responses, answers, usage, models — answers, usage, models
- Python SDK retries, exceptions, constants —
RetryPolicyvalidation and richer errors - JavaScript SDK changelog — the JS SDK's parallel release line
- Versions and timeline (models, SDKs, API, company) — models, SDKs, API and company timeline
- typesafe-ai GitHub organisation and repos — the
typesafe-aiGitHub organisation
Sources
- raw/docs/sdk__python__changelog.md (https://docs.typesafe.ai/sdk/python/changelog.md)
- raw/github/typesafe-sdk-python/docs/changelog.md, pyproject.toml (https://github.com/typesafe-ai/typesafe-sdk-python @ 0ffd094c72ed9445223060b24ffd7a56aa781fb4, captured 2026-09-21)
- raw/github/typesafe-sdk-python/src/typesafe_sdk/_core/{config,logging,json,schemas/base}.py — the 0.7.x mechanisms described above
- raw/github/system-one-adapter-python/docs/changelog.md, pyproject.toml — the adapter's matching 0.2.0 release
- PyPI release listing for
typesafe-sdk(0.0.1a0, 0.5.7, 0.6.0) and thetypesafe-aishim, collected 2026-09-17 and recorded in CLAUDE.md