Python auto-instrumentation library for the TypeSafe AI Python SDK (typesafe-sdk).
Calls to TypeSafeClient.system_one and AsyncTypeSafeClient.system_one are traced and exported as OpenInference DECISION spans. A decision model scores or selects among the candidate options supplied in the request instead of generating free-form text, which is exactly what System One does: a request sends a state plus a map of typed questions (Noul, Choice, Score) and returns one typed answer per question, so the span records:
input.value: the request body (state, model, questions) as JSONllm.invocation_parameters: the call configuration, meaning the model and any extra_body fieldsoutput.value: the response body (model, answers, usage) as JSONdecision.system and decision.provider: both typesafedecision.request.model_name (for example jev-latest), decision.response.model_name (the resolved model, for example jev-1.13.0), and decision.model_name (the response model when reported, else the requested one)decision.token_count.input and decision.token_count.output, from the response’s usageThe model and its token usage are recorded under decision.* rather than llm.*, following the OpenInference decision span conventions, so decision model usage is not priced or counted as LLM usage.
A System One call is not a chat exchange, so the state and the answers are recorded only as input.value and output.value, not as llm.input_messages / llm.output_messages.
The state and the questions are recorded only in input.value, so TraceConfig(hide_inputs=True) keeps the whole request — caller data and question instructions alike — off the span, and hide_outputs=True does the same for the answers. llm.invocation_parameters holds no request content, only the model and any extra_body fields; mask it with hide_llm_invocation_parameters if those are sensitive.
These traces are fully OpenTelemetry compatible and can be sent to an OpenTelemetry collector for viewing, such as Arize Phoenix or Arize AX.
TypeSafeClient and AsyncTypeSafeClient)suppress_tracing()using_session, using_user, using_attributes, metadata, tags)TraceConfig (e.g. hide_inputs, hide_outputs)Requires typesafe-sdk >= 0.6.0.
pip install openinference-instrumentation-typesafe
pip install openinference-instrumentation-typesafe typesafe-sdk arize-phoenix opentelemetry-sdk opentelemetry-exporter-otlp
Start Phoenix as a collector (default http://localhost:6006), then:
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from openinference.instrumentation.typesafe import TypeSafeAIInstrumentor
endpoint = "http://127.0.0.1:6006/v1/traces"
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(SimpleSpanProcessor(OTLPSpanExporter(endpoint)))
TypeSafeAIInstrumentor().instrument(tracer_provider=tracer_provider)
Make a System One call. Set the TYPESAFE_API_KEY environment variable with your key.
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
client = TypeSafeClient()
response = client.system_one(
state={"document": "I was charged twice. Please fix this ASAP."},
questions={
"billing": Noul(instructions="Is this ticket about billing?"),
"tone": Choice(
instructions="What is the customer's tone?",
criteria={"calm": None, "frustrated": None, "angry": None},
),
"urgency": Score(
instructions="How urgent is this ticket?",
criteria=["can wait", "this week", "today"],
),
},
)
print(response.nouls["billing"].noul)
print(response.choices["tone"].choice)
print(response.scores["urgency"].score)
Runnable examples, including async usage and context attributes, are in the examples/ directory.