🧠 llm-safecall (Python)
Secure, fail-safe, and observable LLM calls for Python.
llm-safecall is a framework-agnostic, enterprise-grade safety and observability layer for interacting with large language models (LLMs).
It enforces policy guardrails, validates structured outputs, scans for secrets, applies circuit breakers and retries, and guarantees fail-safe operation.
Fail-safe by default. Secure by design. Enterprise ready.
🚀 Why use llm-safecall
| Problem | Solution |
|---|---|
| Prompt injection or data exfiltration | Policy engine with prompt heuristics, secret scanning, and sanitization |
| Invalid or unstructured outputs | Schema-based validation (Pydantic v2) with auto-repair and JSON-only enforcement |
| Hallucinated shell commands or URLs | Output sanitization + URL allowlists |
| Sensitive data exposure | Automatic redaction and structured logs |
| Network instability | Retries with jitter + circuit breaker |
| High latency or cost | Local caching + budget & rate limiting |
| App-breaking exceptions | Fail-safe mode ensures graceful recovery |
Predictable. Auditable. Secure.
⚙️ Installation
pip install llm-safecall
# or for development / optional providers:
pip install -e ".[dev]"
pip install ".[openai]" ".[anthropic]"
Requires Python ≥3.10.
✨ Quickstart
from pydantic import BaseModel
from llm_safecall import SafeCall, OpenAIProvider, PolicyEngine, PolicyConfig
class Output(BaseModel):
title: str
summary: str
policy = PolicyEngine(PolicyConfig(
outbound_url_allowlist=["https://docs.company.com/"],
allow_shell_output=False,
))
safe = SafeCall(
llm=OpenAIProvider(model="gpt-4o-mini"),
output=Output,
policy=policy,
timeout_s=15,
retries=2,
redact=["email", "phone"],
)
result = safe.generate("Return a JSON with keys title and summary.")
print(result.model_dump()) # validated Output
print(result._report.model_dump()) # observability info
🔒 Fail-Safe Guarantee
llm-safecall never breaks your code.
| Scenario | Result |
|---|---|
| Validation fails | Returns {} or fallback value |
| Provider error | Returns safe fallback |
| Policy violation | Returns sanitized fallback |
| Redaction triggered | Sensitive data removed |
| All fails | Returns quietly, logs structured event |
Worst case: nothing happens.
Best case: you get a secure, validated, policy-compliant result.
🧱 Policy Engine
Policies can be defined in YAML or Python — enforcing safety both before and after LLM calls.
Example YAML
allowed_urls:
- "https://docs.mycompany.com"
disallowed_patterns:
- "os.system"
- "subprocess"
- "open('"
Example Python config
from llm_safecall import PolicyEngine, PolicyConfig
policy = PolicyEngine(PolicyConfig(
outbound_url_allowlist=[
"https://intranet.company.com/",
"https://docs.company.com/",
],
allow_shell_output=False,
max_input_chars=20000,
max_output_chars=10000,
))
Load from file:
from llm_safecall import load_policy
policy = load_policy("policy.yml")
🧩 Key Features
✅ Safety & Policy
- Prompt-injection detection (
reveal system prompt,ignore instructions, etc.) - Secret scanning (AWS/GCP keys, Slack tokens, GitHub PATs)
- Output sanitization (blocks shell commands, restricts URLs)
- Redaction for sensitive fields (e.g. phone numbers, emails)
- JSON-only enforcement when schema is defined
⚙️ Reliability
- Retries with exponential jitter
- Circuit breaker with cooldown
- Timeout control
- Local caching for consistent results
📊 Observability
- Structured JSON logs (
event=llm_call_start|end|error|cache_hit) - Unique
call_idper call - Attached
CallReport(latency, tokens, model) - SIEM/ELK-friendly log output
💰 Governance
- Optional daily budget caps
- Token bucket rate limiter
- Redaction + logging control for compliance
🌊 Streaming (guarded)
for chunk in safe.stream_generate("Explain quantum encryption."):
print(chunk, end="", flush=True)
If any error or policy violation occurs, it yields a fallback token and ends gracefully — no crash, no broken coroutine.
🤖 For Agents & Copilots
⚠️ Mandatory wrapper for copilots and orchestrators
All AI agents and code copilots must route LLM calls through
SafeCall.
This enforces policy compliance, prevents unsafe tool calls, blocks secret leakage, and guarantees JSON correctness.
safe = SafeCall(OpenAIProvider(model="gpt-4o-mini"), fail_safe=True)
res = safe.generate("Suggest a shell command to deploy my app.")
print(res.value)
If the response violates your org policy or produces disallowed content, you get a safe fallback — your copilot continues running safely.
🧰 Provider Adapters
| Provider | Model | Package | Status |
|---|---|---|---|
| OpenAI | gpt-4o-mini |
openai |
✅ |
| Anthropic | claude-3-5-sonnet-20240620 |
anthropic |
✅ |
| Mock | local dev / CI | built-in | ✅ |
Pass API keys via environment variables (
OPENAI_API_KEY,ANTHROPIC_API_KEY)
or directly in constructor.
⚡ Environment-based Setup
from llm_safecall import from_env
# env: LLM_PROVIDER=openai|anthropic|mock, LLM_MODEL=..., OPENAI_API_KEY=..., etc.
safe = from_env(output=None)
🧪 Tool Sandbox Example
from pydantic import BaseModel
from llm_safecall import ToolRunner, PolicyEngine, PolicyConfig
class Args(BaseModel):
url: str
def fetch(url: str) -> str:
return f"Fetched {url}"
tr = ToolRunner(PolicyEngine(PolicyConfig(outbound_url_allowlist=['https://example.com/'])))
tr.register("fetch", fetch, Args, None)
print(tr.call("fetch", url="https://example.com/ok"))
🧩 Development & Contribution
Run tests
pytest -v
Build & publish
python -m build
twine upload dist/*
Contribute
Pull requests are welcome — new providers, richer policies, and better telemetry are encouraged.
📦 Repository & Metadata
- GitHub: https://github.com/VODuda/llm-safecall
- PyPI: https://pypi.org/project/llm-safecall
- License: MIT
- Author: https://github.com/VODuda
🧩 Summary
llm-safecall is a drop-in safety, observability, and compliance layer for LLM applications.
Fail-safe by default.
Secure by design.
Observable and auditable.
Enterprise ready.
Release files for llm-safecall 0.2.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 | |
|---|---|---|---|
| llm_safecall-0.2.2.tar.gz | 19.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| llm_safecall-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 41.8 kB
Release files / llm_safecall-0.2.2.tar.gz
| Download URL | llm_safecall-0.2.2.tar.gz |
|---|---|
| Size | 19.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0b515090b977281abdda25a49dc040d5e9ed189a5ce5d0329b85fb7431d8eb85
|
|
BLAKE2b-256 checksum How to use checksums |
75005975aa64bc8189b4391d9afbedb91a5246032aa0e74354fbdb12883c0241
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / llm_safecall-0.2.2-py3-none-any.whl
| Download URL | llm_safecall-0.2.2-py3-none-any.whl |
|---|---|
| Size | 22.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6ad9dabf5dbf7def461c101ab1accfeaa585ae796dd94c08b5142d955b8540f5
|
|
BLAKE2b-256 checksum How to use checksums |
0cbeb874dcf5cb5fc007694c9671519f16692ec12f82615ecf3902a0cc7fb994
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|