Skip to main content

xstructured

CI Docs License: Apache-2.0 Python 3.12+

xstructured is a schema-guided structured output layer for LangChain v1 Runnables and agents. It wraps any chat model, create_agent agent, or custom Runnable so that its natural-language output is turned into a validated Pydantic v2 object, with conservative recovery from markdown fences and surrounding prose, an optional delimited envelope protocol for reliable extraction alongside free-form text, and ordered streaming of text and structured deltas.

It is not a replacement for create_agent's built-in output_schema and does not call an LLM provider itself: it composes with whatever Runnable you already have, focuses on making structured extraction robust to imperfect model output, and stays out of the way otherwise.

Installation

pip install xstructured

The Python import namespace is:

from xstructured import with_xstructured_output, XStructuredResult

Running the examples against a real LLM provider additionally requires the examples dependency group (LangChain, an OpenAI chat model, and optionally Deep Agents):

uv sync --group examples

Quickstart

from langchain.agents import create_agent
from langchain_core.messages import HumanMessage
from langchain_core.runnables import RunnableLambda
from pydantic import BaseModel

from xstructured import with_xstructured_output


class ContactInfo(BaseModel):
    name: str
    email: str


agent = create_agent(model="openai:gpt-4o-mini", tools=[])


def run_agent(messages):
    # create_agent's compiled graph takes/returns a {"messages": [...]} state,
    # so it is adapted to the plain-message Runnable contract xstructured expects.
    state = agent.invoke({"messages": list(messages)})
    return state["messages"][-1]


extractor = with_xstructured_output(RunnableLambda(run_agent), ContactInfo)

result = extractor.invoke(
    [HumanMessage(content="Reach Priya Shah at priya.shah@example.com.")]
)

print(result.structured)  # ContactInfo(name='Priya Shah', email='priya.shah@example.com')
print(result.content)     # the agent's natural-language reply, envelope stripped
print(result.raw)         # the original AIMessage

See Why xstructured? for ten practical use cases and guidance on when LangChain or LangGraph native features are the better choice.

with_xstructured_output composes with .invoke, .ainvoke, .batch, .abatch, .stream, and .astream, following native Runnable semantics throughout. Streaming yields ordered TEXT_DELTA, STRUCTURED_START, STRUCTURED_DELTA, STRUCTURED_END, and RESULT events so a UI can render prose and structured data as they arrive.

Lower-level building blocks are also public, for callers who want schema instructions, parsing, or fingerprinting without the Runnable wrapper:

from xstructured import StructuredParser, fingerprint_schema, schema_instructions

instructions = schema_instructions(ContactInfo, envelope="xstructured")
result = StructuredParser(ContactInfo).parse(model_output_text)
digest = fingerprint_schema(ContactInfo)

Offline benchmark

Compare plain JSON plus Pydantic, LangChain's JSON and Pydantic output parsers, and xstructured against the same local fixture corpus:

uv run python -m benchmarks --help
uv run python -m benchmarks

The benchmark performs no network calls and needs no API key. Its correctness criteria, corpus, and timing methodology are documented in docs/benchmarks.md.

Resource limits and strict JSON

ParserConfig bounds all untrusted response handling. Its defaults limit whole inputs, envelopes, and JSON payloads to 1,000,000 characters and JSON container nesting to 100 levels. The same configuration is used by StructuredParser and streaming wrappers.

from xstructured import ParserConfig, StructuredParser

parser = StructuredParser(
    ContactInfo,
    config=ParserConfig(
        max_input_chars=100_000,
        max_envelope_chars=50_000,
        max_payload_chars=40_000,
        max_nesting_depth=32,
    ),
)

JSON decoding rejects duplicate object keys and non-standard NaN, Infinity, and -Infinity constants. Envelopes that are incomplete or exceed their configured bounds fail explicitly rather than continuing to accumulate streamed content.

Examples

Runnable, environment-gated example scripts live in examples/:

Each script checks for EXPLABS_API_KEY and prints an explanation and exits instead of failing when it is not set, so they are safe to run in any environment. See examples/README.md for details.

Documentation

Full documentation, including user guides, architecture, security, benchmarks, and API reference, is published at https://xstructured.readthedocs.io and built from docs/ with MkDocs Material.

Development

uv sync
uv run ruff check .
uv run ruff format --check .
uv run flake8 .
uv run pyrefly check
uv run pytest -m "not live"

Documentation diagrams are Mermaid sources rendered to PNG with a pinned Mermaid CLI (see scripts/render-diagrams.mjs):

# Install this tooling globally; the Python package has no Node runtime dependency.
npm install --global @mermaid-js/mermaid-cli@11.17.0
node scripts/render-diagrams.mjs
node scripts/render-diagrams.mjs --check

node_modules/ is not required in the repository. The renderer uses a local CLI when present and otherwise resolves the pinned global Mermaid CLI.

See CONTRIBUTING.md for the full workflow.

The project requires Python 3.12 or newer and is licensed under Apache-2.0.

Release files for xstructured 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 xstructured 0.1.0
File Size Uploaded
xstructured-0.1.0.tar.gz 24.0 kB Details

Built distribution (wheel)

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

Total release size: 57.6 kB

Release files / xstructured-0.1.0.tar.gz

Download URL xstructured-0.1.0.tar.gz
Size 24.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e1e60345543124a630f2df478165c18481d77f93a7573d57b310abbb0068f125
BLAKE2b-256 checksum
How to use checksums
3f0189c5e8c64dcc9d54af34a63e091818660ec6ac8d17c3663afab515a4cfc5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / xstructured-0.1.0-py3-none-any.whl

Download URL xstructured-0.1.0-py3-none-any.whl
Size 33.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a239375eb6ae3e2cf7bbcd3cd7d9557d944c63aa9632e42e8a5133e5d3a03b22
BLAKE2b-256 checksum
How to use checksums
a6ed699517a2ad75019c541da15d8a7fbda70f8ba09a08f2e38c5d37d8f94259
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":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

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