← First Pair Library

19 Python Examples

The Python examples are the user-facing and notebook-facing complement to the Rust examples. They do not replace the Rust lakehouse loader. They make the warehouse, semantic sidecars, agent protocol, and audit trail easy to inspect, compose, and extend.

From the sister project:

cd ../qg-python
uv sync --extra test
uv run python -m pytest

The test suite checks both Python-only behavior and Rust equivalence for the semantic bundle. That matters because Python agents should speak the same semantic and security language as the Rust platform.

19.1 Build OSI from Semantic Croissant

examples/osi_semantic_croissant.py starts with a concrete Croissant dataset: files, record sets, fields, types, and semantic meanings. It then projects the dataset into an OSI model:

uv run python examples/osi_semantic_croissant.py

The result has:

This is the bridge from file metadata to business meaning. The agent does not need to guess that monthly_energy_cost belongs to an energy-burden concept. The OSI model says so.

19.2 Query Sail with PySpark

After the Rust loader has materialized the warehouse, start Sail:

cd ../qg-rust
sail spark server --port 50051

Register the data and audit tables from Python:

cd ../qg-python
uv sync --extra lakehouse
uv run querygraph lakehouse-register \
  --manifest ../qg-rust/.querygraph/lakehouse/manifest/load-report.json \
  --warehouse ../qg-rust/spark-warehouse

uv run querygraph audit-register \
  --warehouse ../qg-rust/spark-warehouse

Open a shell:

uv run pyspark --remote sc://127.0.0.1:50051

Example queries:

spark.sql("SELECT COUNT(*) AS rows FROM global_temp.government_finance__countydata").show()
spark.sql("SELECT COUNT(*) AS rows FROM global_temp.codata_constants_2022__codata_constants_2022").show()
spark.sql("SELECT quantity, value, unit FROM global_temp.codata_constants_2022__codata_constants_2022 LIMIT 5").show(truncate=False)
spark.sql("SELECT event_hash, event_type, job_name FROM global_temp.openlineage_events LIMIT 10").show(truncate=False)

This gives Python users direct inspection of both governed data and audit evidence.

19.3 Run TypeDID Agents with Pydantic

The Python QG Lakehouse story is:

uv run querygraph qglake-story --pretty

It creates the same cast as the Rust story: supervisor, finance, energy, mobility, climate-health, reference, restricted-data broker, and synthesis. Each request and response is a Pydantic TypeDID model. Each response carries a payload hash. The restricted broker returns a denial instead of leaking raw data. The final report includes OpenLineage and a DID-style attestation.

A minimal Python sketch looks like this:

from querygraph.typedid import TypeDidAgent

supervisor = TypeDidAgent.new("SupervisorAgent")
finance = TypeDidAgent.new("FinanceAgent")

request = supervisor.request(
    finance,
    action="summarize",
    resource="compartment:finance",
    payload={"question": "Where is fiscal stress highest?"},
)

response = finance.answer(
    request,
    status="allowed",
    summary="Fiscal stress summary over governed finance tables.",
)

assert request.verify_payload()
assert response.envelope.payload["requestSha256"] == request.payload_sha256

This is what Pydantic contributes: a natural Python object model that is still strict enough to validate, hash, serialize, and test.

19.4 Adapt a TypeDID Agent to LangChain

LangChain is useful when a planner should choose tools. Querygraph’s rule is that the tool must already be governed. The Python adapter turns a TypeDID agent into a LangChain StructuredTool:

uv sync --extra agents
uv run python examples/typedid_langchain_agents.py

Conceptually:

from querygraph.agents import TypeDidLangChainToolAdapter, deterministic_specialist
from querygraph.typedid import TypeDidAgent

finance = TypeDidAgent.new("FinanceAgent")
handler = deterministic_specialist(
    finance,
    summary="Fiscal capacity summary from governed Sail finance tables.",
    evidence=["global_temp.government_finance__countydata"],
)
tool = TypeDidLangChainToolAdapter(finance, handler).as_tool()

The LangChain planner can invoke the tool, but the tool returns a TypeDID response. The planner does not receive a secret back door into Sail.

19.5 Python as the Experiment Surface

Python is where new agent behavior can be prototyped quickly:

The ideal development loop is not Rust versus Python. It is Rust for the contract and Python for the exploration, both operating over the same Sail warehouse and the same semantic sidecars.