Skip to main content
PandaProbe supports attaching session_id and user_id to traces. Use this to group related traces into conversations and to associate activity with specific users or accounts.
Session and user identifiers are strings you control. They are echoed on exported traces and in the UI so you can join to your own identity store or conversation store.

Context managers (scoped)

import pandaprobe

with pandaprobe.session("conversation-123"):
    with pandaprobe.user("user-abc"):
        # All traces created in this scope inherit session_id and user_id
        with pandaprobe.start_trace("my-agent", input={"messages": [...]}) as t:
            ...

Imperative API (global)

pandaprobe.set_session("conversation-123")
pandaprobe.set_user("user-abc")

# All subsequent traces inherit these values
The imperative API sets session and user globally for the current context. It does not automatically reset. Prefer the context manager API when possible.

Explicit parameters (highest precedence)

When using decorators or context managers, explicit parameters always take precedence over scoped or global values:
@pandaprobe.trace(session_id="explicit-session", user_id="explicit-user")
def my_agent(query: str):
    ...

with pandaprobe.start_trace("agent", session_id="explicit") as t:
    ...

Precedence rules

  1. Explicit parameters passed to @trace, start_trace(), or integration constructors
  2. Context manager scope (pandaprobe.session() / pandaprobe.user())
  3. Imperative setting (pandaprobe.set_session() / pandaprobe.set_user())

Works across all layers

Session and user IDs propagate to wrappers, integrations, and manual instrumentation. Integration constructors also accept session_id and user_id:
from pandaprobe.integrations.langgraph import LangGraphCallbackHandler

handler = LangGraphCallbackHandler(session_id="conv-1", user_id="user-1")

Multi-turn conversation example

import pandaprobe
from pandaprobe.wrappers import wrap_openai
from openai import OpenAI

client = wrap_openai(OpenAI())
history = []

with pandaprobe.session("conversation-123"), pandaprobe.user("user-abc"):
    while True:
        user_input = input("You: ")
        if user_input.lower() == "quit":
            break
        history.append({"role": "user", "content": user_input})
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=history,
        )
        assistant_msg = response.choices[0].message.content
        history.append({"role": "assistant", "content": assistant_msg})
        print(f"Assistant: {assistant_msg}")