Skip to main content

tswitch

Typesafe switch, score, and bool primitives for Python, powered by TypeSafe AI.

Installation

pip install tswitch

Set your API key (see typesafe.ai):

export TYPESAFE_API_KEY=apikey_...

Quickstart

from tswitch import tswitch

tone = tswitch(
    "I was charged twice and I am furious!",
    calm="Polite, measured, or friendly language.",
    angry="Hostile, frustrated, or expletive language.",
)
# tone == "angry"

Dispatch on structured state, then map case names to results:

from tswitch import tswitch

ticket = {"subject": "Refund please", "body": "You billed me twice this month."}

route = {
    "billing": ["billing-team@example.com", "P1"],
    "general": ["support@example.com", "P3"],
}[
    tswitch(
        ticket,
        billing="Problems with charges, invoices, refunds, or subscriptions.",
        general="Anything else.",
    )
]

Score a value on a spectrum

tscore returns a float position along your ordered levels — it can fall between two of them, so it maps onto a threshold:

from tswitch import tscore

frustration = tscore(
    "I was charged twice and I am furious!",
    "How frustrated does the customer appear?",
    ["Calm and neutral.", "Concerned but civil.", "Very angry or using strong language."],
)
if frustration >= 2:
    escalate_to_human()

Judge a yes/no statement

tbool returns True when the probability that your statement is true is at or above threshold (default 0.5), so it maps onto an if:

from tswitch import tbool

if tbool(
    "I was charged twice. Please refund the duplicate.",
    "Does the customer request a refund?",
    true="The customer wants money returned.",
    false="The customer is asking for information only.",
):
    issue_refund()

Phrase the statement so it is clearly true or false. If you want to measure a level of something ("how strong is this candidate in Python?"), use tscore with defined levels instead.

The value

The value may be text, a JSON-like dict or list (nested non-JSON objects are described by their repr), or any other Python object, which is described by its repr:

import datetime

tswitch(
    {"at": datetime.datetime(2026, 1, 1, 3, 0), "text": "URGENT: site is down"},
    urgent="Reports of outages or unavailable services.",
    routine="Ordinary questions or feature requests.",
)

Case descriptions

Each case is keyed by its name and valued by a description of what matches — a string, JSON-like content, or None for an undescribed label:

tswitch(
    "The plot dragged in the second act.",
    plot="Concerns about storyline or pacing.",
    cast="Concerns about acting or characters.",
    effects=None,
)

Descriptions don't have to be strings — any JSON-like value works, and non-JSON objects are described by their repr:

bugs = tswitch(
    {"error": "TypeError: 'NoneType' object is not iterable", "version": "1.4.2"},
    crash={"matches": "failures that stop the program", "signals": ["traceback", "exit code"]},
    cosmetic=("visual problems", "layout issues"),
    other=object(),  # described by repr(object())
)

Cases are keyword arguments, so names with dashes or spaces are unpacked from a dict:

tswitch(
    "The plot dragged in the second act.",
    **{"slow-burn": "Deliberate, gradual pacing.", "messy": "Confused or erratic pacing."},
)

Async

import asyncio
from tswitch import atswitch, atscore, atbool

async def main():
    tone = await atswitch(
        "Thanks, that solved it!",
        calm="Polite, measured, or friendly language.",
        angry="Hostile, frustrated, or expletive language.",
    )
    frustration = await atscore(
        "Thanks, that solved it!",
        "How frustrated does the customer appear?",
        ["Calm and neutral.", "Concerned but civil.", "Very angry."],
    )
    friendly = await atbool(tone, f"Is {tone!r} friendly language?")
    print(tone, frustration, friendly)

asyncio.run(main())

Every function has an async twin: atswitch, atscore, and atbool.

API

tswitch(value, /, *, model=None, api_key=None, client=None, **cases)str

Returns the name of the case matching value. Raises ValueError if no cases are supplied, and TypeSafeError if no API key is available.

tscore(value, instructions, levels, /, *, model=None, api_key=None, client=None)float

Returns the score of value along the ordered levels, from 0 to len(levels) - 1; it can fall between two levels. Raises ValueError if levels is empty.

tbool(value, instructions, /, *, true=None, false=None, threshold=0.5, model=None, api_key=None, client=None)bool

Returns whether instructions is true of value, using the optional true/false outcome descriptions and requiring a probability of yes at or above threshold. Raises ValueError if threshold is outside [0, 1].

atswitch, atscore, atbool

The async variants of the functions above, with identical signatures and results.

Options:

  • model — model name override (None uses the environment or account default).

  • api_key — API key override (None reads TYPESAFE_API_KEY).

  • client — a reusable TypeSafeClient / AsyncTypeSafeClient from typesafe-sdk. It is used for the call and never closed; without it a short-lived client is created per call, so pass your own client in hot loops:

    from typesafe_sdk import TypeSafeClient
    from tswitch import tswitch
    
    with TypeSafeClient() as client:
        for email in emails:
            kind = tswitch(email, sales="...", support="...", client=client)
    

Errors from the underlying SDK (TypeSafeAPIError and subclasses) propagate unchanged; see the typesafe-sdk docs for details.

Release files for tswitch 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tswitch 0.1.1
File Size Uploaded
tswitch-0.1.1.tar.gz 11.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tswitch 0.1.1
File Interpreter ABI Platform
tswitch-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 21.1 kB

Release files / tswitch-0.1.1.tar.gz

Download URL tswitch-0.1.1.tar.gz
Size 11.3 kB
Tags Source
SHA-256 checksum
How to use checksums
7c37fa0b0b4643bbd2fc9531e738f67f3eb85dffa6641e5d881db4344d42e63b
BLAKE2b-256 checksum
How to use checksums
59792588161aa340c313ab4fb638726dbf4a7ee9409d9bca85fbb5a651bb3655
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.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 Sep 18, 2026.

Transparency log

Release files / tswitch-0.1.1-py3-none-any.whl

Download URL tswitch-0.1.1-py3-none-any.whl
Size 9.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4dbae2b07c6cb54ef9baa915310c380a84be9c16a5a4187aa1b3dadaf43de6c9
BLAKE2b-256 checksum
How to use checksums
f09737190f25c835f714c96002c03079882824484e1bac7ad4ccd6a4c7e3aeb1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.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 Sep 18, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page