Use when adding user, session, environment, or version context to MLflow traces — Python or TypeScript. Covers the reserved metadata fields (`mlflow.trace.user`, `mlflow.trace.session`), auto-populated environment metadata (`mlflow.source.*`, Git provenance, model id), the `APP_ENVIRONMENT` override pattern for production, custom deployment metadata, and how this composes with `client_request_id` and `gen_ai.*`. Foundation Step 2c. Sibling to F2 (Python tracing) and F2b (TS tracing).
Scanned 9/12/2026
Install to Claude Code
npx -y skills add databricks-solutions/vibe-coding-workshop-template --skill 02c-trace-context-and-environments --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of 02c Trace Context And Environments?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/databricks-solutions-02c-trace-context-and-environments)More formats (shields.io, HTML) on the badges page.
---
name: 02c-trace-context-and-environments
description: >
Use when adding user, session, environment, or version context to MLflow
traces — Python or TypeScript. Covers the reserved metadata fields
(`mlflow.trace.user`, `mlflow.trace.session`), auto-populated environment
metadata (`mlflow.source.*`, Git provenance, model id), the
`APP_ENVIRONMENT` override pattern for production, custom deployment
metadata, and how this composes with `client_request_id` and `gen_ai.*`.
Foundation Step 2c. Sibling to F2 (Python tracing) and F2b (TS tracing).
license: Apache-2.0
clients: [ide_cli, genie_code]
bundle_resource: none
deploy_verb: none
deploy_note: "Trace-context metadata configuration (user/session/environment/version) — no deployed resource; identical on both clients. See `skills/genie-code-environment`."
coverage: full
metadata:
last_verified: "2026-04-15"
volatility: medium
upstream_sources: []
author: "prashanth-subrahmanyam"
version: "1.0.0"
domain: "genai-agents"
pipeline_position: "F2c"
consumes: "tracing_config"
produces: "trace_context_metadata"
grounded_in: "docs.databricks.com/aws/en/mlflow3/genai/tracing/add-context-to-traces, docs.databricks.com/aws/en/mlflow3/genai/tracing/track-environments-context, docs.databricks.com/aws/en/mlflow3/genai/tracing/prod-tracing"
---
# Trace context and environments — users, sessions, deployment metadata
## When to Use
Use this skill when you need to:
- Attribute traces to a **user** (`mlflow.trace.user`).
- Group traces from a multi-turn conversation under one **session**
(`mlflow.trace.session`).
- Tag traces with the **deployment environment** (`development`,
`staging`, `production`) and the **app version** so you can debug
regressions and compare cohorts.
- Search traces programmatically by user, session, or environment.
- Pair trace-side user attribution with end-user feedback collection
(see [`sdlc/04c-end-user-feedback`](../../sdlc/04c-end-user-feedback/SKILL.md)).
This skill applies to **both** Python ([F2](../02-experiment-tracing-and-uc-storage/SKILL.md))
and TypeScript ([F2b](../02b-typescript-tracing/SKILL.md)) tracing. The
concepts are identical; the call sites differ.
Prerequisites:
- Foundation Step 1 (MLflow environment, tracking URI, auth).
- Foundation Step 2 or 2b (tracing already wired — `@mlflow.trace`,
`mlflow.openai.autolog()`, or `tracedOpenAI`).
- **MLflow 3** required (`mlflow[databricks]>=3.1`). Context tracking
is not supported on MLflow 2.x.
> **Source:** [Add context to traces](https://docs.databricks.com/aws/en/mlflow3/genai/tracing/add-context-to-traces?language=Production).
## Tags vs metadata — pick the right bucket
`mlflow.update_current_trace(tags=..., metadata=...)` accepts both. The
two buckets serve different purposes and the Databricks UI treats
reserved metadata fields specially.
| Property | Tags | Metadata |
|---|---|---|
| **Mutability after log** | Mutable (you can update them later) | **Immutable** once the trace is logged |
| **UI affordances** | Filter columns | Filter columns + first-class facets for reserved keys (`mlflow.trace.user`, `mlflow.trace.session`) |
| **Best for** | Routing dimensions that may change during the trace (`feature_flag_active`, `retry_count`, `degraded_mode`) | Stable identifiers and version pins (`mlflow.trace.user`, `mlflow.trace.session`, `agent_version`, `deployment_id`) |
| **Typical examples** | `domain`, `team`, `sla_tier`, `experiment_arm` | `mlflow.trace.user`, `mlflow.trace.session`, `mlflow.source.type`, `agent_version`, `deployment_region` |
**Rule of thumb:** if the value is **the identity of something** (a user,
a session, a build), use metadata. If it's **a label you might revisit**,
use tags.
## Track users and sessions
MLflow defines two reserved metadata fields. Use these — not custom keys —
so the UI's filter / group / cohort views light up.
| Field | Purpose |
|---|---|
| `mlflow.trace.user` | Authenticated user id (email, SP id, OBO-resolved username). |
| `mlflow.trace.session` | Conversation / multi-turn session id. |
### Python (`@mlflow.trace`-wrapped handler)
```python
import mlflow
@mlflow.trace(name="answer", span_type="AGENT")
def answer(question: str, *, user_id: str, session_id: str) -> str:
mlflow.update_current_trace(
metadata={
"mlflow.trace.user": user_id,
"mlflow.trace.session": session_id,
},
)
return _plan_and_execute(question)
```
Call `update_current_trace(metadata=...)` **inside** an active trace
context — typically as the first statement in your request handler,
before any LLM call. Calling it before the trace opens is a no-op.
### TypeScript (`mlflow-tracing` SDK)
```ts
import * as mlflow from "mlflow-tracing";
mlflow.update_current_trace({
session_id: req.headers["x-session-id"] as string,
user_id: resolvedUserId,
});
```
The TS SDK's `session_id` / `user_id` shorthand keys map to the same
reserved metadata fields (`mlflow.trace.session` / `mlflow.trace.user`).
See [F2b § Sessions and users](../02b-typescript-tracing/SKILL.md#sessions-and-users)
for the full handler shape.
> **Why metadata, not tags?** The doc explicitly recommends metadata
> because: (a) these IDs are immutable identifiers — they should not
> change after the trace is logged; and (b) MLflow treats them as
> first-class facets only when stored as metadata under the reserved
> keys. Older code that placed them under tags works for read but
> loses the UI affordances.
## Track environments and versions
### Auto-populated metadata
MLflow auto-fills several metadata fields from your runtime. You don't
have to set these — but you should know what's there so you don't
double-write.
| Field | Set automatically from |
|---|---|
| `mlflow.source.name` | Script filename, notebook name. |
| `mlflow.source.git.commit` | Current Git commit hash, if running in a Git repo. |
| `mlflow.source.git.branch` | Current Git branch. |
| `mlflow.source.git.repoURL` | Git remote URL. |
| `mlflow.source.type` | `NOTEBOOK` (Jupyter / Databricks notebook), `LOCAL` (Python script), or `UNKNOWN`. **Override this in deployed apps.** |
| `mlflow.sourceRun` | The MLflow run id, if the trace was created inside `mlflow.start_run()`. |
| `metadata.mlflow.modelId` | The active `LoggedModel` id (from `MLFLOW_ACTIVE_MODEL_ID` or `mlflow.set_active_model()`). |
### Override `mlflow.source.type` from `APP_ENVIRONMENT`
In production, `mlflow.source.type` defaults to `LOCAL` or `UNKNOWN`,
which is misleading. Override it from an environment variable that the
deployment sets:
```python
import os
import mlflow
def trace_environment_metadata() -> dict[str, str]:
return {
"mlflow.source.type": os.getenv("APP_ENVIRONMENT", "development"),
}
@mlflow.trace(name="answer", span_type="AGENT")
def answer(question: str, *, user_id: str, session_id: str) -> str:
mlflow.update_current_trace(
metadata={
"mlflow.trace.user": user_id,
"mlflow.trace.session": session_id,
**trace_environment_metadata(),
},
)
return _plan_and_execute(question)
```
Set `APP_ENVIRONMENT` per deployment via `databricks.yml` (Model Serving)
or `app.yaml` (Databricks Apps) — see
[`references/prod-tracing-deployment.md`](../02-experiment-tracing-and-uc-storage/references/prod-tracing-deployment.md)
for the full env-var matrix.
```yaml
# app.yaml fragment
env:
- name: APP_ENVIRONMENT
value: "production"
```
> **Don't hard-code environment names** in the application source.
> Pulling from an env var means the same image runs in dev / staging /
> prod with different `mlflow.source.type` values.
## Custom deployment metadata
Add app-specific metadata for routing, version pinning, and audit. Pull
values from env vars, not literals, so the same code works across
deployments.
```python
import os
import mlflow
def deployment_metadata() -> dict[str, str]:
return {
"mlflow.source.type": os.getenv("APP_ENVIRONMENT", "development"),
"agent_version": os.getenv("AGENT_VERSION", "unknown"),
"deployment_id": os.getenv("DEPLOYMENT_ID", "unknown"),
"deployment_region": os.getenv("DEPLOYMENT_REGION", "unknown"),
"feature_flags": os.getenv("FEATURE_FLAGS", ""),
}
mlflow.update_current_trace(metadata=deployment_metadata())
```
Recommended custom-metadata keys:
| Key | Purpose |
|---|---|
| `agent_version` | Semantic version of the agent code (build tag). |
| `deployment_id` | Unique id per deploy (CI run id, asset bundle deployment id). |
| `deployment_region` | AWS region / Azure region where the workload runs. |
| `feature_flags` | Comma-separated active feature flags. Use tags instead if these change mid-trace. |
## Production package choice
| Environment | Install | Why |
|---|---|---|
| **Production** (Model Serving, Databricks Apps, batch jobs) | `pip install --upgrade mlflow-tracing` | Tracing-only, smaller dependency footprint, faster cold start, fewer transitive risks. |
| **Development** (notebooks, local CLI, eval runs that also need full MLflow features) | `pip install --upgrade "mlflow[databricks]>=3.1"` | Full SDK: experiments, runs, models, evaluation, registry. |
`mlflow-tracing` is API-compatible with `mlflow[databricks]` for the
tracing surface (`mlflow.trace`, `mlflow.update_current_trace`,
`mlflow.start_span`, `mlflow.search_traces` for tracing-only usage).
Use it on the deployed side; use `mlflow[databricks]` everywhere
else.
> MLflow 3 is required for context tracking. MLflow 2.x is **not
> supported** for `mlflow.trace.user` / `mlflow.trace.session` due to
> performance limitations and missing trace-info fields.
## Coexistence with `client_request_id` and `gen_ai.*`
Trace context is **layered** — these are not alternatives, they are
different scopes:
| Layer | Field | Where it lives | What it answers |
|---|---|---|---|
| Request correlation | `client_request_id` | `TraceInfo` (set via `mlflow.update_current_trace(client_request_id=...)`) | Which HTTP request produced this trace? |
| User attribution | `mlflow.trace.user` (metadata) | Trace root | Who triggered this trace? |
| Session grouping | `mlflow.trace.session` (metadata) | Trace root | Which conversation does this trace belong to? |
| Environment | `mlflow.source.type`, `agent_version`, `deployment_id` (metadata) | Trace root | Where / what version produced this trace? |
| Per-call OTeL | `gen_ai.operation.name`, `gen_ai.system`, `gen_ai.request.model`, `gen_ai.usage.*` (span attributes) | Each LLM / tool span | What did this specific LLM call do? |
Set them all on the **same** trace. Reserved metadata + auto-populated
metadata + `client_request_id` go on the trace root (one
`update_current_trace` call). `gen_ai.*` go on the spans
(`span.set_attributes(...)` inside each LLM/tool call).
The composed call site looks like:
```python
import mlflow
import os
@mlflow.trace(name="answer", span_type="AGENT")
def answer(
question: str,
*,
user_id: str,
session_id: str,
client_request_id: str,
) -> str:
mlflow.update_current_trace(
client_request_id=client_request_id,
metadata={
"mlflow.trace.user": user_id,
"mlflow.trace.session": session_id,
"mlflow.source.type": os.getenv("APP_ENVIRONMENT", "development"),
"agent_version": os.getenv("AGENT_VERSION", "unknown"),
},
tags={
"domain": "billing",
"sla_tier": "gold",
},
)
return _plan_and_execute(question)
```
For `client_request_id` request-correlation patterns and the
frontend-handshake details, see
[`sdlc/04c-end-user-feedback`](../../sdlc/04c-end-user-feedback/SKILL.md).
For the `gen_ai.*` semantic-convention attributes, see
[F2 § OTeL GenAI Semantic-Convention Attributes](../02-experiment-tracing-and-uc-storage/SKILL.md#otel-genai-semantic-convention-attributes).
## Search traces by metadata
Once metadata is on the trace, search by it with `mlflow.search_traces`.
The result is a pandas DataFrame; metadata appears in the `metadata`
column.
```python
import mlflow
# All traces from a specific user in production
df = mlflow.search_traces(
experiment_names=["/Shared/skyloyalty/agent"],
filter_string=(
"metadata.`mlflow.trace.user` = 'alice@example.com' "
"AND metadata.`mlflow.source.type` = 'production'"
),
max_results=200,
)
# All traces in one conversation, ordered chronologically
df = mlflow.search_traces(
experiment_names=["/Shared/skyloyalty/agent"],
filter_string="metadata.`mlflow.trace.session` = 'sess-2026-04-24-abc'",
order_by=["timestamp ASC"],
)
# Per-trace access from Trace objects
trace = mlflow.get_trace(trace_id)
print(trace.info.trace_metadata["mlflow.trace.user"])
print(trace.info.tags.get("domain"))
```
The DataFrame columns expose `metadata` (immutable, includes the
reserved keys) and `tags` (mutable). Filter by metadata for stable
identifiers; filter by tags for routing dimensions.
## DO / DON'T
| DO | DON'T |
|---|---|
| Put `mlflow.trace.user` / `mlflow.trace.session` under **metadata**. | Put them under tags — you lose the immutability guarantee and the UI's first-class filter/group affordances. |
| Override `mlflow.source.type` from `APP_ENVIRONMENT` in deployed code. | Hard-code `"production"` in the source. The same image should produce different traces in dev / staging / prod. |
| Pull `agent_version` / `deployment_id` from env vars set at deploy time. | Pin them as Python constants — they go stale at the next release. |
| Install `mlflow-tracing` in production images. | Install full `mlflow[databricks]` everywhere — slower cold start, larger image, more transitive deps. |
| Set metadata once at the top of the request handler, before any LLM call. | Sprinkle `update_current_trace` calls across child spans — wastes work and can race. |
| Use **metadata** for stable IDs and version pins; **tags** for routing dimensions that may change. | Mix the two — `mlflow.trace.user` belongs to metadata, `feature_flag_active` belongs to tags. |
| Compose user/session/environment metadata with `client_request_id` and `gen_ai.*` (they're layered, not alternatives). | Treat them as competing — they answer different questions. |
## Validation checklist
- [ ] `mlflow.trace.user` and `mlflow.trace.session` set under **metadata** (not tags) on the trace root, once per request.
- [ ] Set as the **first** call inside the traced request handler, before any LLM/tool call.
- [ ] `mlflow.source.type` overridden from `APP_ENVIRONMENT` env var in deployed code.
- [ ] `APP_ENVIRONMENT` set in `databricks.yml` (Model Serving) or `app.yaml` (Apps) per deployment.
- [ ] `agent_version` and (optional) `deployment_id` / `deployment_region` populated from env vars.
- [ ] Production image installs `mlflow-tracing` (not full `mlflow[databricks]`) for footprint.
- [ ] MLflow runtime version is **3.1+**.
- [ ] If the agent collects end-user feedback, `mlflow.trace.user` is set at request time (not just `AssessmentSource.source_id` at feedback time). See [04c](../../sdlc/04c-end-user-feedback/SKILL.md).
- [ ] `client_request_id` set on the same trace root via `mlflow.update_current_trace(client_request_id=...)` for request correlation.
- [ ] `gen_ai.*` attributes set on individual LLM / tool **spans** (not on trace metadata).
- [ ] `mlflow.search_traces(filter_string="metadata.`mlflow.trace.user` = ...")` returns expected traces in dev before deploy.
## References
### Official documentation
- [Add context to traces](https://docs.databricks.com/aws/en/mlflow3/genai/tracing/add-context-to-traces?language=Production) — primary source for this skill.
- [Track environments and context](https://mlflow.org/docs/latest/genai/tracing/track-environments-context/) — auto-populated metadata, reserved tags, override patterns.
- [Tutorial: Trace and analyze users and environments](https://mlflow.org/docs/latest/genai/tracing/track-environments-context/) — end-to-end example.
- [`mlflow.search_traces` API](https://mlflow.org/docs/latest/api_reference/python_api/mlflow.html#mlflow.search_traces) — filter syntax for metadata and tags.
- [Trace agents deployed on Databricks](https://docs.databricks.com/aws/en/mlflow3/genai/tracing/prod-tracing) — production env-var matrix.
### Related skills
- [Foundation Step 2: Python tracing](../02-experiment-tracing-and-uc-storage/SKILL.md) — `@mlflow.trace`, `update_current_trace`, manual spans, UC OTEL storage.
- [Foundation Step 2b: TypeScript tracing](../02b-typescript-tracing/SKILL.md) — Node sibling, `mlflow.update_current_trace({ session_id, user_id })`.
- [Production tracing deployment reference](../02-experiment-tracing-and-uc-storage/references/prod-tracing-deployment.md) — `ENABLE_MLFLOW_TRACING`, `MLFLOW_EXPERIMENT_ID`, `APP_ENVIRONMENT`, SP `CAN_EDIT`.
- [Trace context patterns reference](../02-experiment-tracing-and-uc-storage/references/trace-context-patterns.md) — full tag taxonomy, search examples, dashboard SQL.
- [Autolog integrations](../02-experiment-tracing-and-uc-storage/references/autolog-integrations.md) — auto-instrument 20+ libraries (token counts, span tree).
- [`sdlc/04c-end-user-feedback`](../../sdlc/04c-end-user-feedback/SKILL.md) — companion: tag the trace with the user **and** attach feedback to the same user.
- [`sdlc/06-deployment-and-automation`](../../sdlc/06-deployment-and-automation/SKILL.md) — `databricks.yml` / `app.yaml` env wiring including `APP_ENVIRONMENT`.
## Version history
| Version | Date | Changes |
| --- | --- | --- |
| 1.0.0 | 2026-04-24 | Initial skill: tags-vs-metadata decision matrix, reserved metadata fields (`mlflow.trace.user` / `mlflow.trace.session`), auto-populated environment metadata table, `APP_ENVIRONMENT` override pattern, custom deployment metadata (`agent_version`, `deployment_id`, `deployment_region`), `mlflow-tracing` vs `mlflow[databricks]` package choice, coexistence layering with `client_request_id` and `gen_ai.*`, search-by-metadata examples, validation checklist, DO/DON'T table. Sourced from [Add context to traces](https://docs.databricks.com/aws/en/mlflow3/genai/tracing/add-context-to-traces?language=Production). |
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!