Trailsense Documentation

Quickstart with OpenLLMetry

Send your first agent traces to Trailsense with a small OpenLLMetry-style setup and a root span that includes `trailsense.input` and `trailsense.output`.

This quickstart uses Python and OpenLLMetry to send a minimal conversation trace to Trailsense. If you already emit OpenTelemetry from another stack, you can keep your existing instrumentation and point it to the Trailsense endpoint.

Try the Full Example First

We recommend spinning up this GitHub Codespace which contains a complete working example.

Install Dependencies

Install the packages used by the example:

terminal
pip install openai opentelemetry-api traceloop-sdk

Paste the Minimal Example

quickstart-openllmetry.py
import os
from openai import OpenAI
from opentelemetry import trace
from traceloop.sdk import Traceloop
from traceloop.sdk.decorators import conversation

# Change these settings:
OPENAI_API_KEY = "YOUR_OPENAI_API_KEY"
OTLP_ENDPOINT = "http://ingest.trailsense.ai/v1/traces"
TRAILSENSE_API_TOKEN = "GENERATE_TOKEN_FROM_SETTINGS_API_KEYS"


Traceloop.init(
    disable_batch=True,
    api_endpoint=OTLP_ENDPOINT,
    headers={"Authorization": f"Bearer {TRAILSENSE_API_TOKEN}"},
)
client = OpenAI(api_key=OPENAI_API_KEY)
tracer = trace.get_tracer(__name__)


@conversation(conversation_id="conversation_id")
def run_turn(messages):
    with tracer.start_as_current_span("conversation_turn") as span:
        completion = client.chat.completions.create(
            model="gpt-4o-mini", messages=messages
        )
        answer = completion.choices[0].message.content or ""
        span.set_attribute("trailsense.input", messages[-1]["content"])
        span.set_attribute("trailsense.output", answer)
        return answer


messages = [{"role": "system", "content": "You are a helpful assistant."}]
print("Chat started. Type 'exit' to quit.\n")
while True:
    user_text = input("You: ").strip()
    if not user_text or user_text.lower() == "exit":
        break
    messages.append({"role": "user", "content": user_text})
    answer = run_turn(messages)
    messages.append({"role": "assistant", "content": answer})
    print(f"Agent: {answer}\n")

Root Span Rule

Keep trailsense.input and trailsense.output on the root span for the user-visible turn. Child model and tool spans can still carry detailed trace data, but Trailsense builds the conversation view from the root span.

Conversation ID Rule

The example uses one fixed conversation ID so all demo turns land in the same session. In production, use the real chat, thread, or session ID from your app. Do not reuse one hardcoded value for every user.

Run the Script and Check Trailsense

Start the script from your terminal:

terminal
python quickstart-openllmetry.py

Then send a message in the terminal. A session might look like this:

terminal
Chat started. Type 'exit' to quit.

You: Hello
Agent: Hello. How can I help you today?

You: Explain what a root span is
Agent: A root span is the top-level span for one traced operation.

Navigate to Trailsense.ai and this session shall appear.

Breakdown of example

Each part of the example has a distinct job:

  • Traceloop.init(...) exports OTEL data to the Trailsense ingest endpoint and authenticates with a bearer token.
  • @conversation(...) keeps all turns grouped under a stable conversation ID.
  • conversation_turn represents one user-visible turn and acts as the root span for that turn.
  • trailsense.input and trailsense.output tell Trailsense which text to show in the conversation view.

Any model spans, framework spans, or tool spans can still appear as child spans under that root span. The transcript stays clean because Trailsense reads the human-facing input and output from the root span, not from the nested execution details.

Common Mistakes

ProblemResult
No stable conversation IDTurns may be split across separate sessions.
One hardcoded conversation ID is reused across every user or chatUnrelated conversations may be merged into the same session.
trailsense.input and trailsense.output are set on child spans instead of the root spanThe conversation view may be incomplete, misleading, or empty.
Wrong OTLP endpoint or missing auth headerTraces will not reach Trailsense.
The root span does not represent a real user-visible turnThe conversation view becomes harder to read and reason about.

Next Step

Once the quickstart is working, read the OTEL Additions for Trailsense guide to keep the conversation view clean and consistent as your instrumentation grows.

On this page