Kensa turns observed behavior into evals. Trace evidence reaches Kensa two ways: imported from an observability provider or export file, or captured locally from an instrumented run. Either way you end up with bounded local evidence under .kensa/traces/ that your coding agent can mine into evals.
.kensa/traces/ is local evidence, not an observability backend. Kensa imports bounded exports to build CI regression tests; it does not stream or store your production telemetry.
Importing from a provider
Langfuse is supported as a live connection. Connect once, then import.
kensa connect langfuse # verify credentials, save non-secret metadata
kensa import --from langfuse --since 7d --limit 200
kensa connect saves connection metadata to .kensa/connections/<provider>.json. API keys are read from environment variables (or a configured dotenv) at run time and are never written to that file. By default connect verifies access before saving; pass --configure-only to skip the check.
| Provider | Connect | Key env vars |
|---|
| Langfuse | kensa connect langfuse | LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY |
See the CLI reference for every connect and import flag.
Importing from a file
You do not need a live connection. kensa import reads bounded export files in several formats:
kensa import --from json --source traces.json
kensa import --from jsonl --source spans.jsonl
kensa import --from otlp --source otlp-export.json
kensa import --from langfuse --source langfuse-export.json
--from | Source |
|---|
json | A JSON array of spans |
jsonl | One span per line |
otlp | OpenTelemetry Protocol export |
langfuse | A Langfuse export file (or a live connection) |
Imports are normalized to a common span schema and written to .kensa/traces/imports/<provider>-<timestamp>.jsonl, with a .manifest.json recording provenance and redaction, and a latest.json pointer.
Redaction
Imports are redacted before they touch disk. The --redact mode defaults to keys:
| Mode | Behavior |
|---|
off | No redaction |
keys (default) | Redact values for keys matching secret, token, password, api_key, authorization, credential |
strict | Also scan free-text values for PII (requires the optional redaction extra) |
kensa import --from jsonl --source spans.jsonl --redact strict
Capturing traces locally
If you do not have an observability provider, instrument your agent and let Kensa record spans directly. The recording helpers are exported from the top-level package:
from kensa import instrument, record_tool_call, record_llm_call, record_span
instrument() # set up OpenTelemetry span capture
with record_tool_call("lookup_customer"):
customer = lookup(order_id)
with record_llm_call(provider="openai", model="gpt-5.4-mini"):
reply = client.responses.create(...)
Set KENSA_TRACE_DIR so spans are written to disk, then import them like any other JSONL source:
KENSA_TRACE_DIR=.kensa/traces python my_agent.py
kensa import --from jsonl --source .kensa/traces/spans.jsonl
Inside an eval, the same helpers feed the live kensa_trace fixture — your kensa_run harness wraps real tool and model calls with record_tool_call / record_llm_call so trace assertions have something to assert on. See Pytest plugin.
From traces to evals
Once evidence is imported, your coding agent turns it into evals. The kensa-inspect skill reads the redacted evidence and proposes reviewable eval ideas as a YAML queue under .kensa/inspect/, which the CLI can read and validate:
kensa traces list # list imported trace IDs
kensa traces sample # preview one trace
kensa inspect list # read the eval-idea review queue
kensa inspect lint # validate the queue against the imported traces
Approve the ideas worth keeping (change status: pending to status: approved), then the kensa-generate skill materializes them as tests/evals/test_<id>.py. No traces yet? Capture a local run (below), or let the skill seed a first eval from one realistic prompt.
OpenTelemetry compatibility
Spans are standard OpenTelemetry. Kensa annotates them with kensa.span.kind, kensa.tool.name, and kensa.llm.provider / kensa.llm.model attributes, and reads cost and token counts from LLM spans. Anything that emits OTLP can be exported and imported with --from otlp.