llm-seam
Unified LLM abstraction with a provider pattern — one interface, five backends, automatic fallback and retry.
Note on the name: this package was llm-base until 2026-08-21. It was
renamed to llm-seam because the PyPI name llm-base belongs to an
unrelated, older project — no relation to this package.
What's in the box
| Module | What it gives you |
|---|---|
llm_seam.client |
LLMClient — auto-selects a provider from the environment (Anthropic, then OpenAI, then a mock fallback), or accepts an explicit provider name/instance |
llm_seam.providers.base |
LLMProvider — the Protocol every provider implements (complete, get_name, supports_streaming) |
llm_seam.providers.anthropic |
AnthropicProvider — wraps the anthropic SDK |
llm_seam.providers.openai |
OpenAIProvider — wraps the openai SDK |
llm_seam.providers.claude_cli |
ClaudeCLIProvider — shells out to the Claude Code CLI |
llm_seam.providers.agent_sdk |
AgentSDKProvider — wraps claude-agent-sdk (requires the [sdk] extra); supports an optional can_use_tool security callback (see below) |
llm_seam.providers.ollama |
OllamaProvider — local models via Ollama's OpenAI-compatible API (uses the openai SDK, no extra required) |
llm_seam.providers.mock |
MockProvider — fixed-response provider for tests and offline use |
llm_seam.fallback |
FallbackChain — tries a list of providers in order, raises AllProvidersFailed only if every one of them fails |
llm_seam.retry |
with_retry — decorator with exponential backoff, retries on RateLimitError by default (configurable) |
llm_seam.tool_guards |
path_scoped_tool_guard — ready-made can_use_tool callback for AgentSDKProvider; confines a tool's path arguments to an allowlist of directories, resists .. traversal, symlink escapes, and absolute paths outside the allowlist |
llm_seam.exceptions |
LLMError (base), RateLimitError, TokenLimitError, TimeoutError, AllProvidersFailed |
Design
One interface, provider-agnostic callers. LLMClient and every provider
implement the same three-method LLMProvider protocol (complete,
get_name, supports_streaming), so a caller can swap Anthropic for a local
Ollama model, the Claude CLI, or a mock in tests without touching call sites.
Auto-selection is a convenience, not a requirement. LLMClient() with no
arguments picks Anthropic if ANTHROPIC_API_KEY is set, else OpenAI if
OPENAI_API_KEY is set, else falls back to MockProvider. Pass an explicit
provider= name or instance to bypass auto-selection entirely.
Provider-name convention. When constructing by name string, this
portfolio distinguishes two Claude transports: "claude-sdk" selects
AgentSDKProvider (the claude-agent-sdk package, preferred for new
scheduled work — see libs/CLAUDE.md), and "claude-cli" selects
ClaudeCLIProvider (shells out to the installed Claude Code CLI). "claude-sdk"
is only registered as a valid name if claude-agent-sdk is installed (the
[sdk] extra); otherwise constructing by that name raises ValueError.
AgentSDKProvider's can_use_tool is a security boundary, not a hygiene
knob. It threads straight to ClaudeAgentOptions.can_use_tool. If a caller
passes a callback and the installed claude-agent-sdk can't accept the
field, the call raises LLMError rather than silently proceeding ungated —
a caller that believes tool calls are being permission-checked must never
find out otherwise the hard way. Use
tool_guards.path_scoped_tool_guard(allowed_dirs) rather than hand-rolling
path checks.
Fallback and retry compose, they don't replace each other. FallbackChain
moves between providers; with_retry retries a single call on a
transient error (rate limits by default). Wrap a FallbackChain's
.complete in with_retry, or use either alone.
Install
pip install llm-seam
Optional extras:
pip install "llm-seam[sdk]" # AgentSDKProvider (claude-agent-sdk)
Usage
from llm_seam import LLMClient, FallbackChain, with_retry
# Auto-select a provider from the environment
client = LLMClient()
response = client.complete("Hello, world!")
# Explicit provider by name
client = LLMClient(provider="anthropic")
# Fall back through providers in order
chain = FallbackChain(providers=[
LLMClient(provider="claude-cli").provider,
LLMClient(provider="anthropic").provider,
])
response = chain.complete("Hello")
# Retry a call with exponential backoff on rate limits
@with_retry(max_retries=3, initial_delay=1.0)
def call():
return client.complete("Hello")
Testing
cd llm-seam
pytest tests/
Dependencies
anthropic>=0.122.0,<2(1.0.0+ removedtemperature/top_p/top_kfromMessages.create;AnthropicProvider.complete()drops those three and emits aUserWarningif you pass them — useextra_body={"temperature": ...}if the target model still accepts it)openai>=3.1.0(also used byOllamaProvider, which talks to Ollama's OpenAI-compatible API — no extra required)claude-agent-sdk>=0.2.139(optional,[sdk]extra)
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llm_seam-0.3.0.tar.gz.
File metadata
- Download URL: llm_seam-0.3.0.tar.gz
- Upload date:
- Size: 27.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63c3e104809364fcba697989f70c9d7419ac9fa1e9f91468b1b6b7c5db0e821e
|
|
| MD5 |
15becdf82496bdfe8867a55957cbc485
|
|
| BLAKE2b-256 |
92cbcb1eeaa5c6b72537dd0aee50794d2ce1fca1142556948cac172b5c186820
|
Provenance
The following attestation bundles were made for llm_seam-0.3.0.tar.gz:
Publisher:
release-llm-seam.yml on m0j0d/libs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llm_seam-0.3.0.tar.gz -
Subject digest:
63c3e104809364fcba697989f70c9d7419ac9fa1e9f91468b1b6b7c5db0e821e - Sigstore transparency entry: 2645587551
- Sigstore integration time:
-
Permalink:
m0j0d/libs@95a261f8035257feb221466303155be138927594 -
Branch / Tag:
refs/tags/llm-seam-v0.3.0 - Owner: https://github.com/m0j0d
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-llm-seam.yml@95a261f8035257feb221466303155be138927594 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file llm_seam-0.3.0-py3-none-any.whl.
File metadata
- Download URL: llm_seam-0.3.0-py3-none-any.whl
- Upload date:
- Size: 26.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba1d320531fb670876b0aa1a299e36ade8ea641045f18ccffd518f1e36e36154
|
|
| MD5 |
1e4c8522f35d71f5e7a53fc01a71a295
|
|
| BLAKE2b-256 |
d9a6ef83c6aaad21fe0c6030d1f1e77606f6e7721f6d3196327593d6f763a64b
|
Provenance
The following attestation bundles were made for llm_seam-0.3.0-py3-none-any.whl:
Publisher:
release-llm-seam.yml on m0j0d/libs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llm_seam-0.3.0-py3-none-any.whl -
Subject digest:
ba1d320531fb670876b0aa1a299e36ade8ea641045f18ccffd518f1e36e36154 - Sigstore transparency entry: 2645587701
- Sigstore integration time:
-
Permalink:
m0j0d/libs@95a261f8035257feb221466303155be138927594 -
Branch / Tag:
refs/tags/llm-seam-v0.3.0 - Owner: https://github.com/m0j0d
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-llm-seam.yml@95a261f8035257feb221466303155be138927594 -
Trigger Event:
workflow_dispatch
-
Statement type: