ol-llm
The library every LLM call site at MIT Open Learning goes through. It owns the Opik integration (tracing, prompt management, evaluation), a single timeout and retry policy, and the attribution fields that let cost, quality, and traffic join across applications.
Importing ol_llm sets OPIK_SENTRY_ENABLE=false before anything imports the Opik SDK, which
otherwise replaces the host application's Sentry client with its own, so import it first.
The design is in mitodl/ol-infrastructure docs/plans/shared-llm-library-spec.md.
The rules the code follows are in docs/:
the error contract and the
attribution schema.
Usage
Declare each call site once, as a module-level constant, and build its agent from it:
from pydantic import BaseModel
import ol_llm
SUMMARY = ol_llm.UseCase(
app="mit-learn",
name="content-summary",
profile="batch",
model="openai:gpt-4o-mini",
fallback_models=("bedrock:global.anthropic.claude-haiku-4-5-20251001-v1:0",),
)
class Summary(BaseModel):
text: str
summarizer = ol_llm.build_agent(SUMMARY, output_type=Summary, instructions="Summarize.")
The agent's model has a timeout on every request, retries rate limits and outages and
nothing else, falls back once the primary has spent its retries, and raises LLMError
subclasses (LLMRateLimited, LLMUnavailable, LLMRejected, ...) with the provider's
exception as the cause. Build agents once, not per request: each build creates new provider
clients.
Set OL_LLM_ENVIRONMENT, or call ol_llm.configure(ol_llm.Settings(environment=...)) at
startup. Provider credentials are each SDK's own (OPENAI_API_KEY, ANTHROPIC_API_KEY, the AWS
and Google default credential chains, and so on). Operators can change a use case's limits
without a release, e.g. OL_LLM_CONTENT_SUMMARY_TIMEOUT_SECONDS=120.
Call sites not built on PydanticAI (LangGraph, a plain SDK) apply the same numbers with
ol_llm.resolve_policy(use_case), which needs no extra.
Run the agent with ol_llm.run, or ol_llm.run_sync in a Celery task or Dagster asset:
result = ol_llm.run_sync(
summarizer,
text,
attribution=ol_llm.Attribution(user_id=user.global_id, run_id=task_id),
)
result.output # a Summary
result.degraded # True when a fallback model answered
Each run is one Opik trace in the app's project, tagged with the use case and environment,
with the model calls, token usage, and cost inside it. Model failures raise LLMError
subclasses, and invalid output after its retries raises LLMInvalidOutput.
A run inside the application's own @opik.track function becomes a span of that function's
trace, in that function's project: Opik files a span under its trace's project, and the model
spans follow. The use case's tags go on the outer trace so tag filters still find it; the
attribution metadata stays on the run's span.
run_stream and the single-call complete are not released yet.
Tracing
Tracing reads the variables the Opik SDK reads, so the SDK and the span exporter always send to the same instance:
| Variable | Meaning |
|---|---|
OPIK_URL_OVERRIDE |
the Opik API, e.g. https://opik-qa.ol.mit.edu/api |
OPIK_WORKSPACE |
default on our instances |
OPIK_KEYCLOAK_TOKEN_URL, OPIK_KEYCLOAK_CLIENT_ID, OPIK_KEYCLOAK_CLIENT_SECRET |
the Keycloak client the app authenticates to Opik with; OPIK_KEYCLOAK_SCOPE if it needs one. Leave OPIK_API_KEY unset |
OPIK_TRACK_DISABLE |
true turns tracing off, for local development without an Opik |
OL_LLM_TRACE_CONTENT |
false keeps prompts, completions, and tool arguments out of traces. On by default until the data-handling policy decides |
Without a call, tracing reads these the first time an agent is built or a run starts. A host
that configures in code calls ol_llm.configure_tracing(ol_llm.TracingConfig(...)) at
startup, before anything else touches the Opik SDK (the SDK reads the Keycloak hook when it
first builds its HTTP client) and before building agents (an agent keeps the instrumentation
it was built with). Once tracing has been used, a different configuration raises
RuntimeError and the one in effect stays. Short-lived processes should call
ol_llm.tracing.flush() before they exit. An app that registers its own Keycloak hook on the SDK (learn-ai's
opik_keycloak_auth) should drop it when it adopts the library.
Testing
ol_llm.testing.override_models makes build_model and build_agent use PydanticAI's
TestModel or FunctionModel in place of a provider, still under the library's retry and
error handling. Set OPIK_TRACK_DISABLE=true for a test suite that should send nothing, or
use ol_llm.testing.tracing_disabled around one test. opik.record_traces_locally()
captures the root traces a test produces. Script responses and failures with
FunctionModel; do not commit recorded provider responses.
Extras
The base install is the Opik SDK and OpenTelemetry, which every call site needs. Everything else is opt-in:
| Extra | Installs | For |
|---|---|---|
pydantic-ai |
pydantic-ai-slim |
The default construction path for agents and single calls |
openai, anthropic, bedrock, google, mistral |
the matching pydantic-ai-slim extra |
A provider SDK; each also installs PydanticAI |
harness |
pydantic-ai-harness |
In-session memory, compaction, and conversation search. Each harness release pins PydanticAI exactly |
memory |
hindsight-client |
The shared memory service's client. Provisional: the backend is still being evaluated |
For example, ol-llm[bedrock,harness].
Installing without the Opik SDK's heavy dependencies
The opik package hard-requires litellm, openai, pytest, and several other packages the
tracing and prompt paths never import. uv consumers can drop them:
[tool.uv]
override-dependencies = [
"boto3-stubs; sys_platform == 'never'",
"click; sys_platform == 'never'",
"litellm; sys_platform == 'never'",
"openai; sys_platform == 'never'",
"pytest; sys_platform == 'never'",
"rapidfuzz; sys_platform == 'never'",
"tree-sitter; sys_platform == 'never'",
"tree-sitter-javascript; sys_platform == 'never'",
"tree-sitter-typescript; sys_platform == 'never'",
"watchfiles; sys_platform == 'never'",
]
Drop openai from that list if the application uses the openai extra. Opik's evaluation
metrics need litellm, so the overrides belong in runtime images, not in an environment that
runs evaluations. CI checks this exact list on every change (python/smoke/).
Applications that cap how new a dependency may be (exclude-newer in uv) should exempt this
package so releases are usable the day they ship:
[tool.uv.exclude-newer-package]
ol-llm = "0d"
Metadata
Release files for ol-llm 0.0.2
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 | |
|---|---|---|---|---|
| ol_llm-0.0.2.tar.gz | 120.1 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ol_llm-0.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 163.9 kB
Release files / ol_llm-0.0.2.tar.gz
| Download URL | ol_llm-0.0.2.tar.gz |
|---|---|
| Size | 120.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4c055a0321235b7a1dae78797f8c23b6aa89983e5a21cbba39937618c604d51b
|
|
BLAKE2b-256 checksum How to use checksums |
8a61e254be362d1a0acb4a75c9abe9cbd62006ec488ba646707204f4f9da212a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logRelease files / ol_llm-0.0.2-py3-none-any.whl
| Download URL | ol_llm-0.0.2-py3-none-any.whl |
|---|---|
| Size | 43.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a08e8fe7c950558898f653fdf282fbd2c287079622416ccfac5da8196401e80e
|
|
BLAKE2b-256 checksum How to use checksums |
98b3c2367c5b3bc0930986115f6b4c9b33dd341f5822a4084485c21786f67cb0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logSecurity for ol-llm 0.0.2
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ol_llm-0.0.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logA 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.