SpendLens AI

Python SDK

Existing application? Add one decorator.

Keep your standard OpenAI or Anthropic client. Mark an AI workflow with @spendlensai.observe, then refine individual calls only when needed.

Add one decorator

Set the SpendLens AI environment variables, then decorate the business workflow that makes supported OpenAI or Anthropic calls. The provider client remains unchanged.

SPENDLENS_PROJECT must match an existing dashboard project name or slug. A typo does not create a project: the provider request continues, while telemetry is dropped with a warning.

SPENDLENS_API_KEY=sli_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SPENDLENS_PROJECT=shopping-assistant
SPENDLENS_API_BASE_URL=https://spendlensai.dev/backend
SPENDLENS_PROMPT_SAMPLING=template_only
SPENDLENS_DISABLE=0
Only lines marked ADD are new
import spendlensaifrom openai import OpenAI client = OpenAI() @spendlensai.observe(workload="customer-support-reply")def generate_customer_reply(message: str):    return client.chat.completions.create(        model="gpt-6.1-sol",        messages=[            {"role": "system", "content": "Give concise, accurate billing help."},            {"role": "user", "content": message},        ],    )

Only two lines are new: the SpendLens AI import and the decorator. Your provider client and model call do not change.

A bare @spendlensai.observe derives a stable workload name from the Python module and function. Use workload="..." when you want an explicit business-friendly name.

Supported automatic coverage

Decorator mode supports official Python OpenAI chat.completions.create and responses.create calls and Anthropic messages.create calls, including supported sync and async variants. It does not inspect arbitrary HTTP traffic or direct REST calls, and SpendLens AI does not proxy model traffic.

Test the top three models in staging

After SpendLens AI recommends three candidates in Model recommendations, turn on Compare Mode for the same workload.

@spendlensai.observe(
    workload="customer-support-reply",
    compare_mode=True,
)
def generate_customer_reply(message: str):
    return client.chat.completions.create(...)

Add the candidate provider keys to your staging application. Candidate calls run separately from the original response using those local keys. SpendLens AI stores aggregate cost, latency, token and success totals, not candidate prompts, responses or provider keys. Optional quality evaluation runs on SpendLens AI infrastructure with the redacted template and safe generated data.

# Set only the keys required by your campaign candidates.
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
DEEPSEEK_API_KEY=sk-...
MISTRAL_API_KEY=...
GOOGLE_API_KEY=...       # Gemini (GEMINI_API_KEY is also accepted)
DASHSCOPE_API_KEY=...    # Qwen

You only need keys for candidates selected in the campaign. Provider keys stay in your staging process and are separate from SPENDLENS_API_KEY.

Read the Compare Mode guide →

Precision tracking with track() and client.tag()

Use the tracked-client API when one function makes multiple unrelated model calls or you need a business-friendly workload name or dynamic metadata. Explicit client tags override decorator context, which overrides inferred callsite information.

with client.tag(workload="recommend-products"):
    response = client.chat.completions.create(...)

with client.tag(workload="recommend-products"):
    response = client.messages.create(...)

Automatic callsite capture

Inside client.tag(), the SDK records provider, model, token usage, available OpenAI or Anthropic cache counters, latency, Python function name, file name, and line number. Without a workload name, the workload key looks like shopping/recommendations.py::recommend_products.

track(...) options

Environment variables are the recommended configuration path. These explicit parameters remain available for existing tracked-client integrations.

client = track(
    openai_client,
    project="shopping-assistant",
    api_key="sli_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    api_base_url="https://spendlensai.dev/backend",
    provider="openai",
    prompt_sampling="template_only",
    debug=False
)
client = track(
    anthropic_client,
    project="shopping-assistant",
    api_key="sli_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    api_base_url="https://spendlensai.dev/backend",
    provider="anthropic",
    prompt_sampling="template_only",
    debug=False
)
ParameterRequired?What it does
projectRecommendedExisting dashboard project name or slug, for example shopping-assistant.
api_keyYesYour SpendLens AI API key. Use sli_test_... for testing and sli_live_... for production.
api_base_urlRecommendedThe SpendLens AI API URL. For production use https://spendlensai.dev/backend. Do not add /v1.
providerOptionalUse only if auto-detection fails. Valid values are openai and anthropic.
prompt_samplingOptional, legacyAccepted for configuration compatibility. All values currently emit metadata only.
debugOptionalSet to True while troubleshooting SDK setup. It does not log API keys or full prompts.

Environment variables

The SDK reads process environment variables. Local .env files must be loaded by your application or runtime; production secrets should be injected by the deployment platform.

SPENDLENS_API_KEY=sli_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SPENDLENS_PROJECT=shopping-assistant
SPENDLENS_API_BASE_URL=https://spendlensai.dev/backend
SPENDLENS_PROMPT_SAMPLING=template_only
SPENDLENS_DISABLE=0

Set SPENDLENS_DISABLE=1 to temporarily return the original OpenAI or Anthropic client unchanged and stop SpendLens AI network calls.

Name a workload

Use any stable business name that makes sense to your team. Good examples are recommend-products, classify-review, or summarize-ticket. SpendLens AI handles internal classification.

with client.tag(workload="recommend-products"):
    response = client.chat.completions.create(...)

with client.tag(workload="recommend-products"):
    response = client.messages.create(...)

Add safe metadata

Use metadata for low-risk operational labels such as customer tier, region, experiment name, or request type. Do not put prompts, API keys, emails, or personal data in metadata.

with client.tag(
    workload="recommend-products",
    metadata={"customer_tier": "enterprise", "region": "us"}
):
    response = client.chat.completions.create(...)

Metadata-only tracking

Current SDK releases send metadata only. Legacy template_only and redacted_sample settings remain accepted for compatibility, but no prompt, response, tool or message content leaves your application.

client = track(
    openai_client,
    project="shopping-assistant",
    api_key="sli_test_xxx...",
    api_base_url="https://spendlensai.dev/backend",
    prompt_sampling="off"
)

Send queued events immediately

Use client.flush() for short scripts, tests, jobs, and notebooks.

The SDK batches events in the background. Long-running web apps usually flush automatically, but short processes can exit before the batch is sent. Calling client.flush() sends queued SpendLens AI events immediately.

with client.tag(workload="recommend-products"):
    response = client.chat.completions.create(...)

# Recommended for short scripts, tests, jobs, and notebooks.
client.flush()

Cache Efficiency

When a provider returns cache usage, SpendLens AI records it automatically. OpenAI uses prompt_tokens_details.cached_tokens; Anthropic uses cache_read_input_tokens and cache_creation_input_tokens. The dashboard separates actual cache savings from Avoidable Uncached Spend, shows the cache hit rate, and estimates how many reuses recover a cache write. If the provider response has no cache fields, SpendLens AI shows the unsupported state rather than assuming zero cache reads.

Cost calculations apply reported cache reads and writes, Batch or Flex discounts, Fast or Priority premiums, and supported long-context rates. Regional adjustments are applied only when an explicit provider multiplier is available; SpendLens AI does not infer a region from aggregate billing data.