OpenLLMetry (Traceloop SDK) Integration with Future AGI Tracing

Send OpenLLMetry traces to Future AGI by pointing the Traceloop SDK at the collector with environment variables. No traceAI package needed.

📝
TL;DR

OpenLLMetry (the Traceloop SDK) already exports OTLP over HTTP, so there is no traceAI package for it. Point TRACELOOP_BASE_URL at the Future AGI collector, pass your keys in TRACELOOP_HEADERS, set a project_name resource attribute, and turn content capture off if you do not want prompts stored.

1. Installation

pip install traceloop-sdk==0.62.4 openai httpx requests

traceloop-sdk 0.62.4 imports httpx and requests without declaring them, so install both.


2. Set environment variables

export FI_API_KEY="your-futureagi-api-key"
export FI_SECRET_KEY="your-futureagi-secret-key"
export OPENAI_API_KEY="your-openai-api-key"  # model-provider key, separate from Future AGI keys

# Future AGI Cloud. The SDK appends /v1/traces.
# Self-hosted: use your collector origin, without /v1/traces.
export TRACELOOP_BASE_URL="https://api.futureagi.com/tracer"

# Percent-encode the values: the SDK splits this variable on every comma.
export TRACELOOP_HEADERS="$(python -c 'import os; from urllib.parse import quote; print("x-api-key={0},x-secret-key={1}".format(quote(os.environ["FI_API_KEY"], safe=""), quote(os.environ["FI_SECRET_KEY"], safe="")))')"

# Does not suppress exception/status text or the OpenAI base URL; see Privacy.
export TRACELOOP_TRACE_CONTENT=false     # the SDK default is true
export TRACELOOP_METRICS_ENABLED=false   # the collector serves no /v1/metrics
unset TRACELOOP_API_KEY                  # that key is for Traceloop's own host

3. Initialize the SDK

Set the Future AGI project as resource attributes. The collector rejects a batch whose resource has no project_name (HTTP 400) and creates the project on first use.

from traceloop.sdk import Traceloop

Traceloop.init(
    app_name="my-app",  # exported as service.name
    resource_attributes={
        "project_name": "openllmetry_project",
        "project_type": "observe",
    },
    telemetry_enabled=False,
)

4. Run your app

In the same Python script, after the initialization above, use the Traceloop decorators and your model client. The OpenAI() client reads OPENAI_API_KEY from step 2; Future AGI keys authenticate trace export only and cannot authorize model calls.

from openai import OpenAI
from traceloop.sdk.decorators import agent, tool, workflow

@tool(name="lookup_policy")
def lookup_policy(question: str) -> str:
    return "Refunds are accepted within 30 days of purchase."

@agent(name="support_agent")
def support_agent(question: str) -> str:
    facts = lookup_policy(question)
    response = OpenAI().chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "Answer using only these facts: " + facts},
            {"role": "user", "content": question},
        ],
    )
    return response.choices[0].message.content or ""

@workflow(name="support_request")
def support_request(question: str) -> str:
    return support_agent(question)

print(support_request("What is the refund window?"))

A short script exports on normal exit (the SDK registers an atexit flush). See the complete example.


What is captured

Open Observe in Future AGI and select openllmetry_project to inspect the trace. Each decorated function and model call becomes a span, with parent links matching your code.

SpanStored typeModel and tokens
@workflow, @task, @agent, @toolunknownnone
OpenAI chat callllmmodel, prompt tokens, completion tokens
  • The model call is typed llm from gen_ai.operation.name=chat. Its model and token counts come from the gen_ai.* keys that 0.62.4 emits.
  • The collector does not read traceloop.span.kind, so the decorator spans show as unknown. Every traceloop.* key is kept as a span attribute, so you can still filter on traceloop.span.kind.
  • A failed model call or a decorated function that raises is stored with status ERROR on the whole path up to the workflow span.
  • With content on, the text stays in the span attributes (gen_ai.input.messages, gen_ai.output.messages, traceloop.entity.input, traceloop.entity.output). The Input and Output columns of the trace view stay empty.

Privacy

The Traceloop SDK captures content unless TRACELOOP_TRACE_CONTENT is false. This page sets it to false.

  • Content off: prompts, answers, tool arguments and tool results are not exported by this setup.
  • Content on (unset or true): content appears in attributes on decorated spans and model calls.
  • Not covered by the switch: when a call fails, the SDK sets the exception message as the span status message, so the provider’s error text is stored. The collector stores the exception event with its name and timestamp only. The OpenAI base URL is stored as gen_ai.openai.api_base on the model-call span.
  • With content on, a base64 image in a prompt makes the OpenAI instrumentor upload it to <TRACELOOP_BASE_URL>/v2/traces/.... The collector has no such route. Keep content off, or keep base64 images out of prompts.

Troubleshooting

  • Unexpected collector path: omit /v1/traces from TRACELOOP_BASE_URL; use https://api.futureagi.com/tracer for Future AGI Cloud.
  • HTTP 400 from the collector: the resource has no project_name. Add it to resource_attributes.
  • HTTP 401: check TRACELOOP_HEADERS. An unencoded comma in a key cuts the value short, and a value with a space, quote, semicolon or backslash is dropped with a warning that prints the whole pair.
  • ModuleNotFoundError: httpx: install httpx and requests next to the SDK.
  • A /v1/metrics request fails: set TRACELOOP_METRICS_ENABLED=false.
  • No spans in a short script: the SDK flushes on exit. Make sure the process exits normally, or call Traceloop.init(disable_batch=True) while debugging.
  • The SDK switches to gRPC: a base URL without http:// or https:// selects gRPC. Use an HTTP or HTTPS collector origin for this setup.

Limitations

  • Decorator spans are stored as unknown; traceloop.span.kind remains available as a filterable attribute.
  • Input and Output columns are empty even with content on, because the collector fills them only from input.value and output.value.
  • gRPC, Traceloop’s hosted dashboard, datasets and prompt registry are not part of this integration.
  • This example covers OpenAI Chat Completions; it does not establish support for every OpenLLMetry instrumentor.

How this differs from traceAI instrumentors

traceAI packages (for example traceAI-openai) wrap the client library and set Future AGI span kinds themselves. OpenLLMetry is a separate instrumentation that exports its own attributes. This recipe sends them as they are, with no mapping of its own, so span kinds follow what the collector reads. If you want Future AGI kinds on every span, use the traceAI instrumentor for your library instead.

Was this page helpful?

Questions & Discussion