How lemon-code keeps telemetry disabled by default, uses a local Collector and omits prompt, response and file content
Published: November 4, 2026
Reading time: 8 min
Series: lemon-code in 30 days, part 8 of 13
lemon-code's telemetry ships disabled. When enabled, its default endpoint is localhost. The instrumented signals do not include prompts, responses, tool arguments or file paths.
It still answers useful questions: how long each turn took, how often it fell back and why that model was chosen.
estimated_cost is an observability estimate; local SQLite remains the canonical source.A plane has two data sources. The black box records everything, stays on board and is the source of truth. The panel and the tower link show a live summary. If the link drops, the plane keeps flying and the black box keeps recording.
In lemon-code, local SQLite is the black box. OpenTelemetry is the tower link: an extra output that recomputes nothing, replaces nothing and must never block an execution.
lc config set telemetry.endpoint http://localhost:4318
lc config set telemetry.exportIntervalMs 60000
lc config set telemetry.enabled true
And the pattern that keeps telemetry from ever taking the agent down (rewritten and simplified):
// export without ever blocking the turn (illustrative)
import { metrics } from "@opentelemetry/api";
const meter = metrics.getMeter("lemon-code");
const tokens = meter.createCounter("gen_ai.client.token.usage");
export function recordTurn(t: { provider: string; model: string; input: number; output: number }) {
try {
const attrs = { "gen_ai.system": t.provider, "gen_ai.request.model": t.model };
tokens.add(t.input, { ...attrs, "gen_ai.token.type": "input" });
tokens.add(t.output, { ...attrs, "gen_ai.token.type": "output" });
// no prompt, response, path or tool argument here
} catch {
// telemetry is best-effort: failing here must not affect the agent
}
}
Attributes are identifiers and numbers only.
Free and paid products to turn ideas into a foundation you can actually ship.
13 products availableContinue exploring similar topics
For HTTP-provider routes, lemon-code records score factors. This teaching example shows how to read the sum and distinguish it from the JEV layer.

Seis meses depois, alguém pergunta por que o sistema classificou aquele caso assim. Se a resposta depende de lembrar qual prompt estava no ar, você não tem sistema auditável — tem folclore.

Preço por token é o número do fornecedor. Custo por tarefa concluída é o seu. Entre os dois existem retries, tarefas que falham, contexto que cresce e um nível de esforço que ninguém varre.
A practical checklist to validate security, cost, evals, and observability before you ship your AI app to production.
Production-tested templates trusted by developers. Save weeks of setup on your next project.
| Default | Reason |
|---|---|
telemetry.enabled=false | no exporter runs by default |
endpoint http://localhost:4318 | local Collector over OTLP/HTTP; the endpoint is configurable |
| export every 60 s | periodic metrics export |
| no content | prompts, responses, tool args and results, paths and secrets stay out |
Collector auth headers go in OTEL_EXPORTER_OTLP_HEADERS, never in the repo.
gen_ai.client.token.usage and gen_ai.client.operation.duration.lemon.gen_ai.executions, lemon.gen_ai.fallbacks, lemon.gen_ai.estimated_cost.invoke_agent span with provider, model, outcome, tokens, estimated cost and local correlation IDs.lemon.dispatch.task.score, lemon.prompt.quality.score and lemon.resource.utilization.Prompt quality is a local deterministic heuristic. It doesn't call an LLM and isn't answer quality.
lemon.gen_ai.estimated_cost is an observability estimate, not a complete accounting record. Local SQLite remains the canonical source for executions and usage.
Double-counted usage. Some providers send cumulative usage in the last streaming chunk and again in the tool-use result. lemon-code counts once per call and reuses the last total.
Observing an agent doesn't require attaching conversation content to telemetry. Numbers, identifiers and scores help track duration, fallback and routing. SQLite remains the local black box.
Friday's post wraps up the engineering side with lessons from building the CLI and native app together.
If your team needs observability for agents or LLM features without exposing user data, that's work I do at LEMON.DEV.