Skip to main content

Lanternfish docs

Build from first trace to first briefing

Browse documentation

Reference

SDK configuration

Everything the Python SDK reads and records. Most projects set two environment variables and call lanternfish.instrument() once.

instrument()

Every argument is optional when its environment variable is set.

ArgumentTypeIf omittedWhat it does
api_keystrLANTERNFISH_API_KEYProject API key from Settings → API keys. Sent only in the x-api-key header.
endpointstrLANTERNFISH_ENDPOINTBase URL of your Lanternfish API. There is no default destination.
agentstr—Agent name written on every run; the Agents page groups runs by it.
releasestrLANTERNFISH_RELEASE or CI commitVersion of the running code, written on every span. See Release detection.
environmentstrLANTERNFISH_ENVIRONMENTEnvironment name, for example production or staging.
includelist[str][]Extra integrations to turn on: "http", "sql", "redis".
capture_contentboolTrueRecord prompt and completion text of LLM calls. Set False for agents that handle personal data.
import lanternfish

lanternfish.instrument(
    agent="travel-agent",
    environment="production",
    include=["http"],   # also record outgoing HTTP calls
)

Environment variables

An argument passed to instrument() always wins over the environment variable.

VariableExampleUsed for
LANTERNFISH_API_KEYlfsk_…Used when api_key is not passed. record_deployment() reads it too.
LANTERNFISH_ENDPOINThttps://api.example.comUsed when endpoint is not passed.
LANTERNFISH_RELEASEv1.8.2Used when release is not passed; kept as written.
LANTERNFISH_ENVIRONMENTproductionUsed when environment is not passed.

Release detection

Each span carries the version of the code that produced it, so a change can be lined up with the release it started on. If you pass neither release nor LANTERNFISH_RELEASE, the SDK reads the first of these commit variables that your CI or host sets and keeps its first 12 characters:

  • GIT_COMMIT_SHA
  • GITHUB_SHA
  • VERCEL_GIT_COMMIT_SHA
  • RENDER_GIT_COMMIT
  • RAILWAY_GIT_COMMIT_SHA
  • HEROKU_SLUG_COMMIT
  • SOURCE_COMMIT

To mark the moment a release went live, also call record_deployment() from your deploy step.

Integrations

On by default, when the library is installed: OpenAI (and Azure OpenAI), Anthropic, Gemini, Groq, Ollama, LangChain/LangGraph, CrewAI, LlamaIndex, Haystack, OpenAI Agents SDK, Pydantic AI, AutoGen, MCP. A library that is not installed is skipped; the INFO log lists the integrations that were turned on.

Off unless included: HTTP (requests, httpx, aiohttp), SQL (SQLAlchemy, psycopg2, sqlite3) and Redis. Every query and request outside your agent would otherwise become a run of its own and count toward your plan.

pip install "lanternfish[openai]"        # one provider
pip install "lanternfish[openai,langchain]"
pip install "lanternfish[all]"           # every packaged provider

Send the same spans elsewhere

If your application sets up its own OpenTelemetry provider first, instrument() adds Lanternfish next to it instead of replacing it. The same spans then also reach your other exporter, for example an OTLP endpoint such as the Datadog Agent with OTLP ingest turned on.

from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
import lanternfish

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4318/v1/traces")))
trace.set_tracer_provider(provider)

lanternfish.instrument()  # adds Lanternfish to your provider

What is recorded

  • LLM calls: model, token counts, duration and errors, plus the prompt and completion text. Pass capture_content=False to keep the text out; everything else is still recorded.
  • @trace: the function's arguments, each cut to 500 characters. Use capture_args=False for functions that take personal data.
  • Failures: a step that raises is marked failed, with the exception type and message.
  • HTTP (if included): method, host, path and status code. Never the body, headers or query string.
  • SQL (if included): the statement with literal values replaced by ?; never parameter values.

Functions

FunctionWhat it does
instrument(...)Starts tracing. Call once at startup; a second call is ignored and logged.
flush(timeout_seconds=10)Sends waiting spans now. Call at the end of short scripts and serverless handlers.
shutdown()Sends waiting spans and stops tracing. Runs on process exit as well.
set_user(user_id, session_id=None, tags=None)Adds the end user to every span that follows. Use it as a with block per request.
@trace / @trace(name=..., capture_args=False)Records a function as a step, with its arguments unless capture_args=False.
span(name)Records a block or function as a step; you add attributes yourself.
reasoning(), decision(), planning(), tool_usage(), verification() …Records why the agent chose what it chose; shown in the run's explanation.
record_deployment(version, metadata=...)Records a release from CI so briefings can compare before and after it.

Errors

  • A missing key or endpoint, or an unknown include value, raises LanternfishConfigurationError at startup with the next step in the message.
  • Sending never raises into your code. A network error, 429 or 5xx is retried once after one second; after that the batch is dropped and a warning is logged.
  • A rejected batch is logged with its reason: an invalid or revoked key (401) or a reached plan limit (402).
  • An integration that fails to load is skipped with a warning; the others keep working.
  • record_deployment() raises LanternfishDeploymentError so your CI step fails visibly.
import logging

logging.basicConfig(level="INFO")   # shows the endpoint, the active integrations and every rejected batch