langchaint
langchaint is a provider-neutral Python client for LLM applications. It provides fully typed, asynchronous APIs for generation, streaming, embeddings, tools, retries, and billing. The application owns the agent loop.
Alpha: the API may change without notice.
Why langchaint
- Consistent API. Bind request fields once with
LLM.bind(), then callgenerate_one(),generate_many(), orstream_one()on the resultingBoundLLM. - Useful type annotations. For example,
llm.bind(response_format=Answer)typesgeneration.outputasAnswer. - Outcome variants with autocomplete. Match on
.kindwith editor autocomplete and no class imports. - Coordinated retries. Share concurrency limits, request-start pacing, and provider-directed pauses across models using one rate-limit quota.
- Complete billing.
GenerationandGenerationErrorvalues retain provider-reported usage from every recorded request, including billed retries. - Streaming.
stream_one()returns an async context manager and async iterator.final()returns the typed generation with its usage. - Agent loops in Python. Provider-neutral messages, typed tools with argument validation, concurrent dispatch, and explicit outcome variants support async control flow.
Install
langchaint requires Python 3.13 or newer.
Install the extra for each backend you use:
pip install "langchaint[openai]"
| Backend | Class | Install |
|---|---|---|
| Anthropic | Anthropic |
langchaint[anthropic] |
| Anthropic on Amazon Bedrock | AnthropicBedrock |
langchaint[anthropic-bedrock] |
| Cohere embeddings on Amazon Bedrock | CohereBedrock |
langchaint[cohere-bedrock] |
| DeepSeek | DeepSeek |
langchaint[deepseek] |
| Gemini | Gemini |
langchaint[gemini] |
| OpenAI | OpenAI |
langchaint[openai] |
| OpenAI embeddings | OpenAI |
langchaint[openai-embedding] |
| OpenAI on Amazon Bedrock | OpenAIBedrock |
langchaint[openai-bedrock] |
Install langchaint[tracing] for OpenTelemetry tracing.
Generate a typed output
import asyncio
from pydantic import BaseModel
from langchaint.openai import OpenAI
class Answer(BaseModel):
answer: str
confidence: float
async def main() -> None:
assistant = (
OpenAI()
.llm("gpt-5.6-terra")
.bind(
system_prompt="Answer clearly and concisely.",
response_format=Answer,
)
)
generation = await assistant.generate_one("Why is the sky blue?")
print(generation.output.answer)
print(generation.usage.cost_in_usd)
asyncio.run(main())
The Pydantic model validates the provider response.
generate_many() returns generations in input order, or raises GenerationError after cancelling and awaiting unfinished inputs.
generate_many_records() returns one normalized record per input, including generation failures.
Pass resume_path to persist records and resume interrupted batches.
Coordinate retries across a rate-limit quota
Create one SharedBackoff for each rate-limit quota, and pass it to every backend that sends requests against that quota. Models from one OpenAI share its SharedBackoff:
from langchaint import SharedBackoff
openai = OpenAI(
shared_backoff=SharedBackoff(max_concurrent_requests=8, max_request_starts_per_second=50.0),
)
fast_model = openai.llm("gpt-5.6-luna")
strong_model = openai.llm("gpt-5.6-sol")
A rate-limit response pauses request starts across the shared quota. After a transient failure local to one request, langchaint waits and retries that request.
Stream with an explicit lifetime
text_assistant = OpenAI().llm("gpt-5.6-terra").bind()
async with text_assistant.stream_one("Explain photosynthesis.") as stream:
async for item in stream:
# Without tools, every item is str | ReasoningDelta
if isinstance(item, str):
print(item, end="", flush=True)
generation = await stream.final()
final() consumes the remaining stream and returns the assembled generation.
Build agent loops
The application controls turn limits, state, approvals, model changes, and persistence.
messages: list[Message] = [UserMessage(content=prompt)]
for _ in range(max_turns):
generation = await bound.generate_one(messages)
match generation.kind:
case "tool_call":
messages.append(generation.assistant_message)
outcomes = await bound.tool_manager.dispatch_many(generation.tool_calls)
messages.extend(outcome.tool_message for outcome in outcomes)
case "plain":
return generation.output
raise RuntimeError("model did not finish within max_turns")
ToolManager.dispatch_many() runs tool calls concurrently and preserves their order.
See examples/02_tool_loop.py for a complete typed tool loop.
Account for every request
generation.usage.cost_in_usd includes every billed retry recorded for the input.
GenerationError.usage preserves the recorded cost of a failed input.
More examples
See examples/README.md for complete examples.
License
Metadata
Release files for langchaint 0.33.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| langchaint-0.33.0.tar.gz | 180.2 kB | Without provenance | Details for langchaint-0.33.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| langchaint-0.33.0-py3-none-any.whl | Python 3 | none | any | Details for langchaint-0.33.0-py3-none-any.whl |
Total release size: 380.8 kB
Release files / langchaint-0.33.0.tar.gz
| Download URL | langchaint-0.33.0.tar.gz |
|---|---|
| Size | 180.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f2f286c5482968efa050ffca4f9b7648167d795e63a4865bef0014a2a9d852a8
|
|
BLAKE2b-256 checksum How to use checksums |
5e77b393431c4da7c71145631e5e03387957cf431828ff8d857b6eb0f3509439
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / langchaint-0.33.0-py3-none-any.whl
| Download URL | langchaint-0.33.0-py3-none-any.whl |
|---|---|
| Size | 200.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
88cd15eefa9396176ea86c1370c3ee09cf15b7d066383edde5b43ae2699f230a
|
|
BLAKE2b-256 checksum How to use checksums |
835d952537ee79c25286b95e510ea60456754546a4a5e6f500e9bf3fa42163b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for langchaint 0.33.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.