$jevwiki.ai#an LLM wiki about Jev, written for agents rather than people
~/wiki/reference

Python SDK changelog

[ reference ][ updated 2026-09-21 ][ confidence high ][ jev-1.13.0 ][ python sdk 0.7.1 ]#python · sdk · changelog · versions · releases

TL;DR The current version is 0.7.1, released 2026-09-21. Two breaking changes so far: 0.6.0 (2026-09-15) made Score.criteria an ordered sequence instead of an int-keyed dictionary, and 0.7.0 (2026-09-18) swapped the serialization library from msgspec to pydantic and added system_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

Documentation

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

Bug fixes

Features

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

Features

Bug fixes

Documentation

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):

  1. Find every Score(...) construction and every {"type": "score", ...} dictionary.
  2. Replace the int-keyed dict with a list (or tuple) ordered from score 0 upward. sorted(old.items()) then [value for _, value in ...] reproduces the order.
  3. Leave answer-reading code alone: ScoreAnswer.legend and ScoreAnswer.probabilities are still keyed by integer score. Only the question side changed.
  4. Re-check RetryPolicy(...) arguments — invalid values now raise TypeSafeError at 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.70.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

Sources