trustcall
Tenacious, validation-safe LLM tool calling and structured extraction built on LangGraph.
Repository Health
Technical Analysis
trustcall is a Python library that makes large-language-model structured output reliable. Instead of asking an LLM to emit a large, deeply nested JSON blob in one shot — a task where models frequently drop required fields or fail validation — trustcall asks the model to generate RFC 6902 JSON patch operations, a simpler, iterative task that can be retried against validation errors until the result conforms.
Built on LangGraph and pydantic, it exposes a single create_extractor entry point that wraps any LangChain-compatible chat model. It supports generating complex schemas from scratch, updating existing records without information loss, and running simultaneous inserts and updates across multiple tools, while automatically repairing validation failures along the way.
What You Get
- A single
create_extractorfunction that wraps any LangChain chat model for validated extraction - Automatic retry-on-validation-error using JSON patch operations rather than full regeneration
- Accurate updates to existing schemas that avoid unintended field deletions
- Support for pydantic models, schema dictionaries, and plain Python functions as tools
- Simultaneous insertion and update of multiple records across multiple tools in one call
Common Use Cases
- Extracting complex, deeply nested schemas that plain tool calling fails to populate
- Maintaining and updating long-lived agent memory or user profiles without data loss
- Building multi-step agents that must call several tools reliably in a single turn
Under The Hood
Architecture - trustcall is built as a LangGraph state machine assembled in trustcall/_base.py (~1,700 lines). The public create_extractor factory wires together nodes for initial extraction (_Extract), patch-based updates (_ExtractUpdates), and error repair (_Patch), routed by an enter node and looped through validate_or_retry/handle_retries until a _ExtendedValidationNode accepts the output. State classes (ExtractionState, ExtendedExtractState, DeletionState) carry messages and candidate documents through the graph, and filter_state shapes the final ExtractionOutputs.
Tech Stack - Pure Python (>=3.10), depending on langgraph (>=0.2.25) for orchestration, dydantic for dynamic pydantic model construction, and jsonpatch for applying RFC 6902 operations. Packaging is via setuptools with a uv lockfile; tooling includes ruff (pycodestyle, pyflakes, isort, pydocstyle with Google convention) and mypy, and it ships a py.typed marker for downstream type checking.
Code Quality - The library is fully type-annotated and documented with Google-style docstrings. Tests live under tests/ with unit_tests/ (extraction, strict-existing, utils) plus VCR-cassette-backed evals/ that record real model interactions, run under a strict pytest config. Naming is consistent and internal helpers are underscore-prefixed, though most logic is concentrated in one large _base.py module.
API Design - The developer-facing surface is deliberately minimal: a single create_extractor(llm, tools=..., tool_choice=...) call returns a runnable that drops into existing LangChain/LangGraph pipelines, accepting pydantic models, schema dicts, or functions as tools. This keeps onboarding boilerplate low while hiding the retry-and-patch machinery behind a familiar invoke interface.