Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Agent Framework TypeSafe AI

Use TypeSafe AI System One models, including Jev, with Microsoft Agent Framework.

This alpha package adapts TypeSafe's structured decision API to the Agent Framework chat client contract. Jev evaluates application state against explicit typed questions and returns probabilities and scores. It does not generate ordinary chat text.

Installation

pip install agent-framework-typesafe --pre

Quick start

Set TYPESAFE_API_KEY, then create TypeSafe questions and run them through an Agent Framework Agent:

from agent_framework import Agent
from agent_framework_typesafe import TypeSafeChatClient
from typesafe_sdk import Choice, Noul

client = TypeSafeChatClient()
try:
    agent = Agent(
        client=client,
        name="TicketEvaluator",
        instructions="Evaluate the support request using the configured questions.",
    )
    response = await agent.run(
        "Our checkout has failed for three days and we are losing sales.",
        options={
            "response_format": {
                "department": Choice(
                    instructions="Which team should handle this request?",
                    criteria={"billing": None, "technical": None, "sales": None},
                ),
                "urgent": Noul(instructions="Does this request need urgent attention?"),
            },
        },
    )
    print(response.value)
finally:
    await client.close()

For this connector, Agent Framework's response_format option is the TypeSafe Questions mapping. The connector forwards it as the SDK's questions argument and internally uses SystemOneResponse as the actual response model.

AgentLoopMiddleware.with_judge(...) supports provider-specific structured judges through its response_format and verdict_parser arguments. Pass a TypeSafe Questions mapping as the response format and convert the returned SystemOneResponse into the framework's JudgeVerdict in the loop setup. This keeps the connector focused on TypeSafe response primitives instead of making it aware of framework-specific judge models.

Framework integrations with a fixed TypeSafe contract can configure default_questions on the client and omit per-call response_format. For example, SecureAgentConfig can use TypeSafeChatClient(default_questions=quarantine_questions) directly as its quarantine client; the framework's explicit tool_choice="none" forwarding is honored.

Supported options

Option Description
response_format Required non-empty TypeSafe Questions mapping containing Noul, Choice, or Score questions.
model Optional per-call model override.
instructions Agent instructions included in the structured state sent to TypeSafe.

Streaming, non-text message content, and generative settings such as temperature are rejected.

TypeSafeChatClient is the recommended client and layers function invocation, middleware, and telemetry over RawTypeSafeChatClient. Use the raw client only when composing a custom layer stack or intentionally opting out of those framework layers. The raw client can inspect compatible tools and emit Agent Framework function calls, but it does not execute them itself.

Function calling

TypeSafe converts tool selection and supported arguments into internal Choice and Noul questions, emits Agent Framework function calls, and lets the standard function-invocation loop execute them. The client defaults to one tool call per run; opt into sequential round trips with function_invocation_configuration={"max_function_calls": N}. Jev can select another tool call after seeing each result, or select no tool to finish.

This follows TypeSafe's Function calling cookbook: the model selects from closed sets, while application code owns validation and execution.

The terminal response text consolidates the current turn's tool results and any final TypeSafe Choice or Score decisions. The full terminal SystemOneResponse, including Noul answers, remains available through response.value.

Supported input-schema shapes:

  • Empty/zero-argument object schemas.
  • Fixed const values.
  • enum or Python Literal arguments.
  • Boolean arguments.
  • Arrays whose items are enum or Literal values. These are treated as set-like selections in schema order; duplicates and caller-defined ordering are not supported. Arrays with minItems, maxItems, uniqueness, prefix, or membership constraints are rejected because the connector cannot preserve those semantics. Every enum member must match the declared item type.
  • Optional versions of those shapes. A separate TypeSafe question decides whether to omit the argument so the function's default can apply.

Required free-form strings, numbers, nested objects, general arrays, and required nullable arguments are not supported. Schema constraints that the connector cannot preserve, such as allOf on the root object, an argument, or an array item, also exclude the entire tool. Assertion siblings beside $ref or nullable anyOf are rejected rather than merged in a way that could broaden the schema. A tool is excluded when any declared argument is unsupported, including optional arguments, so invocation never falls back to an unintended default. In automatic tool mode, unsupported tools are excluded with a warning. Required unsupported tools fail the request.

Local tools can use inferred schemas or Pydantic input models:

from typing import Literal

from agent_framework import Agent, FunctionTool
from agent_framework_typesafe import TypeSafeChatClient
from pydantic import BaseModel
from typesafe_sdk import Noul


class WeatherArguments(BaseModel):
    city: Literal["Seattle", "Paris"]
    detailed: bool


weather = FunctionTool(
    name="weather",
    description="Get weather for a supported city.",
    func=lambda city, detailed: f"Weather for {city}; detailed={detailed}",
    input_model=WeatherArguments,
)
agent = Agent(client=TypeSafeChatClient(), tools=[weather])
response = await agent.run(
    "Give me detailed Seattle weather.",
    options={"response_format": {"succeeded": Noul(instructions="Did the tool result indicate success?")}},
)

MCP tools are supported through Agent, which connects to the server and expands discovered MCP functions into FunctionTool objects before TypeSafe routing:

from agent_framework import Agent, MCPStdioTool
from agent_framework_typesafe import TypeSafeChatClient

mcp = MCPStdioTool(name="my-server", command="my-mcp-server")
agent = Agent(client=TypeSafeChatClient(), tools=[mcp])

Only discovered MCP functions whose JSON schemas fit the supported subset are routable. Use tool_choice.allowed_tools to narrow large MCP servers; a request supports at most 32 routable tools, 64 properties per tool, 64 enum members per argument, and 128 generated internal questions. The routable-tool limit is checked after tool-choice filtering and before any tool schemas are compiled. An exact cumulative question budget is reserved before question objects are constructed, so schemas that would exceed 128 questions fail without materializing the excess. An explicitly empty allowed_tools list denies every tool. Routing criteria always include the exact function name and its optional description so identically described tools remain distinguishable.

Configuration and lifecycle

The internally created TypeSafe SDK client reads:

  • TYPESAFE_API_KEY - required API key.
  • TYPESAFE_DEFAULT_MODEL - optional default model; the SDK defaults to jev-latest.
  • TYPESAFE_BASE_URL - optional API root override.

Constructor values take precedence over an explicitly selected .env file and process environment variables. Credential requirements are evaluated only after those sources are resolved. When async_client is supplied, the injected client is authoritative and no API key, endpoint, or environment-resolved model is applied by the connector. An explicitly passed per-request or constructor model can still override the injected client's default.

For advanced SDK configuration, inject a configured AsyncTypeSafeClient:

from agent_framework_typesafe import TypeSafeChatClient
from typesafe_sdk import AsyncTypeSafeClient

sdk_client = AsyncTypeSafeClient(timeout=60)
client = TypeSafeChatClient(async_client=sdk_client)

Injected SDK clients remain caller-owned. Use close() or async with to close clients created by TypeSafeChatClient.

See the package sample for a runnable direct-client and Agent example.

Metadata

Release files for agent-framework-typesafe 1.0.0a261002

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

Source distribution (sdist)

Source distribution for agent-framework-typesafe 1.0.0a261002
File Size Uploaded
agent_framework_typesafe-1.0.0a261002.tar.gz 17.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-framework-typesafe 1.0.0a261002
File Interpreter ABI Platform
agent_framework_typesafe-1.0.0a261002-py3-none-any.whl Python 3 none any Details

Total release size: 37.0 kB

Release files / agent_framework_typesafe-1.0.0a261002.tar.gz

Download URL agent_framework_typesafe-1.0.0a261002.tar.gz
Size 17.6 kB
Tags Source
SHA-256 checksum
How to use checksums
52f94aff074c53530fe001d4675c3a2ae6aad52e164f02b3eeb79b9a79b011ec
BLAKE2b-256 checksum
How to use checksums
4169d8cc212d9db33511dfaef96a99599da69371e8e0f36c0d07aa85b1a6ec15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / agent_framework_typesafe-1.0.0a261002-py3-none-any.whl

Download URL agent_framework_typesafe-1.0.0a261002-py3-none-any.whl
Size 19.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dbd7e4f812697fc716445df2c369ea18c77a38aa76cfb3121facfde0a08903cf
BLAKE2b-256 checksum
How to use checksums
bcaf8e81b2a33f81c53099b90ff96d6790733b76fd7787c77cd86abbd4aafda8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
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