Acceldata
AIO

Last updated: Oct 06, 2026 15:42 UTC

Track users and sessions

Attach a session id and a user id to each unit of work so that AIO groups related traces into one session.

Prerequisites

  • The Python SDK is installed, and aio.init() runs at startup. For setup steps, see Instrument your code.

Attach session and user ids in code

A session is every trace that shares one conversation id. Each trace in a session is a turn. To group traces into a session, wrap each unit of work in aio.root_span() and pass it the same conversation_id on every turn.

  1. Call aio.init() once at startup, before you create any HTTP or model clients.
  2. For each chat turn, workflow run, or scheduled job, open a with aio.root_span(conversation_id, ...) block.
  3. Pass the same conversation_id for every turn of one conversation.
  4. Pass user_id to record who the turn belongs to.
  5. Pass input_preview with the user's message, so the UI can show it as the turn's message.

The following example sends two turns of one conversation. Before you run it, set the environment variables that Instrument your code describes, and replace the ids with your own values.

import acceldata_aio_tracer as aio
aio.init(service="support-bot")
def answer(message: str) -> str:
    # Call your model here.
    return f"You asked: {message}"
def handle_message(conversation_id: str, user_id: str, message: str) -> str:
    with aio.root_span(
        conversation_id,
        user_id=user_id,
        input_preview=message,
        name="handle_message",
    ):
        return answer(message)
handle_message("conv-1234", "user-42", "How do I reset my password?")
handle_message("conv-1234", "user-42", "And how do I change my email address?")

Both calls use conv-1234, so their traces appear as two turns of one session.

Every span you start inside the root_span block, including model and tool calls, carries the same conversation id and user id.

Parameters of aio.root_span

Parameter

What it does

conversation_id

The session id. Traces that share it group into one session.

user_id

The user id for the root span and every span inside it.

input_preview

Text the UI shows as the turn's message. It's cut to 2000 characters.

name

The root span's name. The default is handle_message.

tenant_id

Overrides the process-wide tenant for spans inside the block.

project_id

Overrides the process-wide project for spans inside the block.

Use a fixed label for name, such as handle_message, rather than text that changes with each request.

When you nest root_span blocks, tenant_id, project_id, and user_id apply to the inner block only. The outer values come back when the inner block exits.

Important

AIO only understands the conversation id that root_span sets (gen_ai.conversation.id). If your app sets session.id or a vendor-specific session attribute instead, that value is dropped, and the traces don't group into a session.

Read the current session id

Call aio.current_conversation_id() inside a root_span block to get the active conversation id. Outside a block, it returns None.

import acceldata_aio_tracer as aio
aio.init(service="support-bot")
with aio.root_span("conv-1234", input_preview="Hello"):
    print(aio.current_conversation_id()) # conv-1234
print(aio.current_conversation_id()) # None

How root_span behaves when something goes wrong

  • If aio.init() hasn't run, root_span does nothing, and your code runs as usual.
  • If root_span itself fails, it doesn't raise. The block runs, and the value it yields is None.
  • If your own code raises an exception inside the block, the exception is raised again as usual.

Check the session in the UI

  1. In your project, go to the Sessions tab.

Sessions list showing sessions with their last activity, first message, turns, duration, tokens, and cost

  1. Select the session's First message link.

Session page showing the turns rail with one entry per trace and the selected turn's span waterfall

The session page lists each trace as a turn. Each turn shows the input_preview you passed as its message. Without an input preview, it shows the root span's name, and without that, the trace id.

For more about reading sessions, see Explore traces.

Troubleshooting

The Sessions list says "No sessions in this window"

  • Check that each unit of work runs inside aio.root_span() with a conversation_id. Spans without a conversation id don't appear in any session.
  • Check that aio.init() runs before root_span. Otherwise root_span does nothing.
  • Widen the time range, in case the conversation ran earlier.

Turns of one conversation show up as separate sessions

  • Check that you pass exactly the same conversation_id on every turn.

Next steps