| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| langroid-0.65.9-py3-none-any.whl | 2026-07-12 | 452.5 kB | |
| langroid-0.65.9.tar.gz | 2026-07-12 | 402.0 kB | |
| 0.65.9 -- Precise MCP tool-parameter types, and fail-fast on non-retryable LLM errors source code.tar.gz | 2026-07-12 | 58.7 MB | |
| 0.65.9 -- Precise MCP tool-parameter types, and fail-fast on non-retryable LLM errors source code.zip | 2026-07-12 | 59.2 MB | |
| README.md | 2026-07-12 | 4.0 kB | |
| Totals: 5 Items | 118.8 MB | 2 | |
0.65.9 — Precise MCP tool-parameter types, and fail-fast on non-retryable LLM errors
Two improvements this release, both originally contributed by @alexagr: MCP tool parameters now map to precise Python types — so they validate correctly and the LLM sees accurate schemas — and the LLM retry logic now fails fast on non-retryable 4xx errors instead of retrying them with exponential backoff.
:::bash
pip install -U langroid
Precise MCP tool-parameter types (#1059)
When Langroid builds a ToolMessage from an MCP tool,
FastMCPClient._schema_to_field converts each parameter's JSON Schema into a
Python type. Several common constructs were previously dropped — falling
through to a plain scalar or to Any — so the generated tool lost type
information both for validation and in the schema the LLM sees. They now map to
precise types:
enum/const→typing.Literal.anyOf/oneOf→typing.Union; a{"type": "null"}branch (or an optional parameter) makes itOptional— the commonOptional[...]shape fastmcp emits.allOfwith a single subschema → that subschema; a multi-schema intersection falls back toAny.$refinto the tool's$defs(pydantic-model params, including inside unions and array items) → a nested pydantic model, with reference cycles degrading the cyclic edge toAny.
This release also fixes a Pydantic v1→v2 regression in
ToolMessage.llm_function_schema(): the nested-model schema cleanup keyed off
v1's "definitions", but v2 emits "$defs", so under Langroid's v2 the cleanup
silently no-op'd — leaking purpose / id / exclude and an unconstrained
request into nested ToolMessage schemas sent to the LLM. It now tracks the
v2 key.
Why it matters:
- Validation — out-of-set
enumvalues and wrong-type union values now raiseValidationErrorinstead of being silently accepted. - Better LLM grounding — pydantic re-emits
enum,anyOf, and nullability in the schema, so the model receives exact parameter types instead of"string"/"any".
Behavior change: MCP tools with enum / union / nested-model params are now
strictly validated; a value that violates a (previously dropped) constraint now
raises ValidationError. Well-formed calls are unaffected.
Fail fast on non-retryable 4xx LLM errors (#1058)
The retry decorators (retry_with_exponential_backoff and its async variant)
decided non-retryability by substring-matching str(e). But a native
OpenAI-SDK error stringifies to Error code: 404 - ..., which does not
contain the class name, so native 403 / 404 errors — e.g. a retired or
unknown model on an OpenAI-compatible endpoint such as Gemini — slipped past the
guard and were retried with exponential backoff instead of failing immediately.
A type-based guard now catches the non-retryable 4xx errors
(BadRequestError 400, AuthenticationError 401, PermissionDeniedError 403,
NotFoundError 404, UnprocessableEntityError 422) in both the sync and async
paths and raises them immediately. This also closes two latent gaps: the async
path was missing 422 handling and neither path handled 403. Retryable errors
(429, 5xx, timeouts) are unaffected, and the substring guard is retained as a
fallback for LiteLLM-proxy-wrapped errors.
Behavior change: a non-retryable 4xx error now fails fast instead of after several backoff retries — faster, clearer failures, with no change for transient (retryable) errors.
Credit
Both improvements were originally contributed by @alexagr in #1055 and #1057; this release ships them with added hardening, tests, and docs.
Upgrade
:::bash
pip install -U langroid
Full changelog: 0.65.8...0.65.9