Python SDK for Ledda — prompt management for LLM applications
Project description
ledda
Python SDK for Ledda — resilient prompt management for LLM applications.
Install
pip install ledda
Quick Start
from ledda import Ledda
ledda = Ledda(api_key="ldda_ak_...")
prompt = ledda.get_prompt("welcome",
fallback={
"messages": [{"role": "system", "content": "You are a helpful assistant."}],
},
)
# Use the prompt with your LLM
response = openai.chat.completions.create(
messages=prompt.messages,
**prompt.config,
)
Features
- Never stalls your app — 3-second timeout, automatic fallback on any failure
- Built-in caching — bounded LRU cache with configurable TTL, stale-while-revalidate
- Sync + Async —
Leddafor sync code,AsyncLeddafor FastAPI/async frameworks - Template variables —
{{var}}placeholders with.compile(var="value") - Strict mode — raises exceptions in dev/test to catch misconfigurations early
- OpenTelemetry — optional span attribute injection for trace linking
Usage
Basic
from ledda import Ledda
# The SDK never raises in default mode — always returns usable content
ledda = Ledda(api_key="ldda_ak_...")
prompt = ledda.get_prompt("welcome",
fallback={ # used when API is unreachable
"messages": [{"role": "system", "content": "You are a helpful assistant."}],
},
label="production", # environment (default: "production")
attributes={"tenant_id": "acme"}, # for routing rules
routing_key="user-12345", # for A/B test bucketing
)
print(prompt.messages) # [{"role": "system", "content": "..."}]
print(prompt.config) # {"model": "claude-sonnet-4-20250514", "temperature": 0.7}
print(prompt.version) # 5
print(prompt.is_fallback) # False
print(prompt.source) # "api" | "cache" | "fallback"
The fallback must be a dict with a messages list — the same shape as a prompt. This ensures your code works identically whether using a live prompt or a fallback.
# Multi-message fallback with config
prompt = ledda.get_prompt("welcome",
fallback={
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "{{question}}"},
],
"config": {"model": "claude-sonnet-4-20250514", "temperature": 0.7},
},
)
Template Variables
prompt = ledda.get_prompt("welcome",
fallback={
"messages": [{"role": "system", "content": "You are a helpful assistant."}],
},
)
compiled = prompt.compile(
persona="a friendly onboarding assistant",
task="account setup",
)
# compiled.messages → [{"role": "system", "content": "You are a friendly onboarding assistant..."}]
Async (FastAPI)
from ledda import AsyncLedda
ledda = AsyncLedda(api_key="ldda_ak_...")
@app.post("/chat")
async def chat():
prompt = await ledda.get_prompt("welcome", fallback={
"messages": [{"role": "system", "content": "You are helpful."}],
})
# ...
Cache Warming
# Pre-fetch on startup to avoid cold-start latency
ledda.prefetch(["welcome", "summarizer", "classifier"])
Strict Mode (Development)
from ledda import Ledda, PromptNotFoundError
ledda = Ledda(api_key="ldda_ak_...", strict_mode=True)
try:
prompt = ledda.get_prompt("typo-name", fallback={
"messages": [{"role": "system", "content": "fallback"}],
})
except PromptNotFoundError:
print("Prompt doesn't exist — fix the name!")
CI/CD Validation
assert ledda.validate_prompt("welcome", label="production")
OpenTelemetry Integration
# Auto-inject span attributes
ledda = Ledda(api_key="ldda_ak_...", enable_otel_injection=True)
# Or manually
prompt = ledda.get_prompt("welcome", fallback={
"messages": [{"role": "system", "content": "fallback"}],
})
span.set_attributes(prompt.span_attributes)
Context Managers
# Sync
with Ledda(api_key="ldda_ak_...") as ledda:
prompt = ledda.get_prompt("welcome", fallback={
"messages": [{"role": "system", "content": "fallback"}],
})
# Async
async with AsyncLedda(api_key="ldda_ak_...") as ledda:
prompt = await ledda.get_prompt("welcome", fallback={
"messages": [{"role": "system", "content": "fallback"}],
})
Resilience
The SDK is designed so that Ledda downtime never becomes your downtime:
| Scenario | Behavior |
|---|---|
| API reachable | Returns prompt, caches it |
| API down, cache warm | Returns cached prompt (even if stale) |
| API down, cache cold | Returns your fallback |
| Network timeout (3s) | Returns cached or fallback |
In default mode, get_prompt() never raises an exception. Every failure path returns usable content.
Configuration
ledda = Ledda(
api_key="ldda_ak_...",
base_url="https://edge.ledda.ai", # default
cache_ttl=60, # seconds, default 60
cache_max_size=1000, # max cached prompts, default 1000
default_label="production", # default environment
enable_otel_injection=False, # auto-inject OTel span attributes
strict_mode=False, # raise on errors (for dev/test)
debug=False, # verbose logging
)
License
MIT
Project details
Release history Release notifications | RSS feed
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 ledda-0.0.1.tar.gz.
File metadata
- Download URL: ledda-0.0.1.tar.gz
- Upload date:
- Size: 40.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a2684e803a94422051e578e96abf959cf3aa6b3aa7503f4269360c0545f32937
|
|
| MD5 |
2d7f2c21a7409d75a8c3dbd17e2d16cf
|
|
| BLAKE2b-256 |
c76e1d6d32a8acd7c52dfe5e59593001293f75410af6b0af99882ceb44361685
|
Provenance
The following attestation bundles were made for ledda-0.0.1.tar.gz:
Publisher:
publish.yml on LeddaAI/ledda-sdk-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ledda-0.0.1.tar.gz -
Subject digest:
a2684e803a94422051e578e96abf959cf3aa6b3aa7503f4269360c0545f32937 - Sigstore transparency entry: 1180524641
- Sigstore integration time:
-
Permalink:
LeddaAI/ledda-sdk-python@65c9b79be99ed54c0e2a222e6968ad22c6bc349b -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/LeddaAI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@65c9b79be99ed54c0e2a222e6968ad22c6bc349b -
Trigger Event:
release
-
Statement type:
File details
Details for the file ledda-0.0.1-py3-none-any.whl.
File metadata
- Download URL: ledda-0.0.1-py3-none-any.whl
- Upload date:
- Size: 12.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1c15b2ba1f97e806aad8182183458d80fe26c1b7853b7827a99772b7795ce05
|
|
| MD5 |
4b2c87a54d7873aa18685dca3dcb7007
|
|
| BLAKE2b-256 |
db2b90a5a7c510829655da9bff97b3870dd72ff85ac23fc36e2238908fb6ae90
|
Provenance
The following attestation bundles were made for ledda-0.0.1-py3-none-any.whl:
Publisher:
publish.yml on LeddaAI/ledda-sdk-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ledda-0.0.1-py3-none-any.whl -
Subject digest:
e1c15b2ba1f97e806aad8182183458d80fe26c1b7853b7827a99772b7795ce05 - Sigstore transparency entry: 1180524645
- Sigstore integration time:
-
Permalink:
LeddaAI/ledda-sdk-python@65c9b79be99ed54c0e2a222e6968ad22c6bc349b -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/LeddaAI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@65c9b79be99ed54c0e2a222e6968ad22c6bc349b -
Trigger Event:
release
-
Statement type: