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.
| 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.
pip install llm-safecall
# or for development / optional providers:
pip install -e ".[dev]"
pip install ".[openai]" ".[anthropic]"Requires Python β₯3.10.
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 infollm-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.
Policies can be defined in YAML or Python β enforcing safety both before and after LLM calls.
allowed_urls:
- "https://docs.mycompany.com"
disallowed_patterns:
- "os.system"
- "subprocess"
- "open('"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")- 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
- Retries with exponential jitter
- Circuit breaker with cooldown
- Timeout control
- Local caching for consistent results
- 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
- Optional daily budget caps
- Token bucket rate limiter
- Redaction + logging control for compliance
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.
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 | 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.
from llm_safecall import from_env
# env: LLM_PROVIDER=openai|anthropic|mock, LLM_MODEL=..., OPENAI_API_KEY=..., etc.
safe = from_env(output=None)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"))pytest -vpython -m build
twine upload dist/*Pull requests are welcome β new providers, richer policies, and better telemetry are encouraged.
- GitHub: https://github.com/VODuda/llm-safecall
- PyPI: https://pypi.org/project/llm-safecall
- License: MIT
- Author: https://github.com/VODuda
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.