Skip to main content

kedi-typesafe

Framework-native integrations for using TypeSafe AI's Jev models with Kedi's supported agent frameworks. Core Jev schema translation and the Pydantic AI and LangChain integrations ship as one kedi-typesafe package.

Pydantic AI

Install the package and provide TYPESAFE_API_KEY in your environment:

pip install kedi-typesafe
export TYPESAFE_API_KEY="your-key"
from typing import Literal

from pydantic import BaseModel, Field
from pydantic_ai import Agent

from kedi_typesafe.integrations.pydantic import TypeSafeModel


class Triage(BaseModel):
    urgent: bool = Field(description="The request needs action today")
    route: Literal["billing", "support", "other"] = Field(
        description="Which team should handle the request?"
    )


model = TypeSafeModel("jev-latest")
agent = Agent(model, output_type=Triage)
result = agent.run_sync("I was charged twice. Please fix this today.")
print(result.output)

The initial surface supports booleans, finite string Literal/Enum values, constrained text extraction, and flat Pydantic models composed of those fields. Pydantic's native EmailStr and pydantic-extra-types PhoneNumber schemas are recognized automatically. A JSON Schema pattern is treated as a regex candidate extractor; other string fields can provide an explicit field extractor:

Install kedi-typesafe[email], kedi-typesafe[phone], or kedi-typesafe[all] when those optional Pydantic field types are used.

from kedi_typesafe import RegexExtractor
from kedi_typesafe.integrations.pydantic import TypeSafeModel

model = TypeSafeModel(
    text_extractors={"ticket_id": RegexExtractor(pattern=r"CASE-\d+")},
)

Candidate extraction is deterministic and Jev only selects among values found in state, following TypeSafe's pre-parsed extraction pattern. Jev is not a free-form text-generation model, so unconstrained strings, tool calling, streaming, arbitrary numbers, nested models, and optional fields are rejected before a provider request is made.

Boolean answers use Jev's Noul probability and a configurable threshold. The default decision is strictly probability > 0.5; the full probability remains available in model response metadata.

LangChain

Install kedi-typesafe[langchain] and use the native structured-output surface:

from typing import Literal

from langchain.agents import create_agent
from pydantic import BaseModel, Field

from kedi_typesafe.integrations.langchain import TypeSafeChatModel


class Triage(BaseModel):
    urgent: bool = Field(description="The request needs action today")
    route: Literal["billing", "support", "other"] = Field(
        description="Which team should handle the request?"
    )


agent = create_agent(TypeSafeChatModel("jev-latest"), response_format=Triage)
result = agent.invoke(
    {"messages": [{"role": "user", "content": "I was charged twice. Fix this today."}]}
)
print(result["structured_response"])

TypeSafeChatModel.with_structured_output(...) is also supported for direct LangChain model use. The same Jev schema restrictions described above apply. Free-form invocation, function tools, media/tool history, stop sequences, and arbitrary model settings fail before a provider request.

Email and Phone Extraction

Install the field validators:

pip install 'kedi-typesafe[email,phone]'
from pydantic import BaseModel, EmailStr, Field
from pydantic_ai import Agent
from pydantic_extra_types.phone_numbers import PhoneNumber

from kedi_typesafe.integrations.pydantic import TypeSafeModel


class Contact(BaseModel):
    email: EmailStr = Field(description="The current support email, not the archived address")
    phone: PhoneNumber = Field(description="The current support phone number")


agent = Agent(TypeSafeModel(), output_type=Contact)
result = agent.run_sync(
    "Archived contact: old@example.com. Current support: help@example.com, +1 202-555-0100."
)
print(result.output)

Email and phone candidates are extracted from the supplied text automatically. Jev selects the candidate matching the field description; Pydantic then validates the result. Phone numbers use Pydantic's normalized format, for example tel:+1-202-555-0100. Provide international numbers with a country code. Missing candidates or a no-match answer raise an extraction error rather than inventing a value. All fields in this initial integration must be required.

For LangChain, use the same Contact schema with create_agent(TypeSafeChatModel(), response_format=Contact) and install kedi-typesafe[langchain,email,phone].

Runnable Examples

After cloning this repository, run uv sync --all-extras and set TYPESAFE_API_KEY.

Example Command
Pydantic classification uv run examples/pydantic_agent.py
LangChain classification uv run examples/langchain_agent.py
Pydantic email and phone uv run examples/pydantic_contacts.py
LangChain email and phone uv run examples/langchain_contacts.py

These examples call the real TypeSafe API. An async context manager closes owned connections after use; it is optional for constructing the model. Reusing a model within the same event loop allows its HTTP connection to be reused.

Development

uv sync --all-extras --group dev
make prod

Normal tests use deterministic typed fakes and never call TypeSafe. Live API validation is kept separate so CI and local quality gates do not consume credentials or incur cost.

Release files for kedi-typesafe 0.1.0

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

Source distribution (sdist)

Source distribution for kedi-typesafe 0.1.0
File Size Uploaded
kedi_typesafe-0.1.0.tar.gz 155.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for kedi-typesafe 0.1.0
File Interpreter ABI Platform
kedi_typesafe-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 173.4 kB

Release files / kedi_typesafe-0.1.0.tar.gz

Download URL kedi_typesafe-0.1.0.tar.gz
Size 155.8 kB
Tags Source
SHA-256 checksum
How to use checksums
2772e1645ab779649cba11bbaef500b85119d15142046d4520fc3f785bc114b4
BLAKE2b-256 checksum
How to use checksums
ed6a6331133c90f8ff4dadd365161301d94d796471e9f26d58659e8b8f1cf054
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","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 / kedi_typesafe-0.1.0-py3-none-any.whl

Download URL kedi_typesafe-0.1.0-py3-none-any.whl
Size 17.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dd4a06f296e2944f1d91d583e7e544537b7c117139ae900d4d7a9cce7b85623c
BLAKE2b-256 checksum
How to use checksums
07870f6fd37ff62711a82e48d1a98136de529f65fc60a12f5fec48b760448514
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","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 history Release notifications | RSS feed

0.2.1

2 release files

This release

0.1.0 This release

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