Send OpenInference spans to Future AGI
Export traces from the Python OpenInference OpenAI instrumentor to Future AGI over OTLP/HTTP.
Send Python OpenAI traces from OpenInference to Observe using a standard OTLP/HTTP exporter. Future AGI reads OpenInference’s span kinds, model names, token counts and input/output attributes; no Future AGI instrumentation package is needed.
This guide covers OpenAI text calls. It does not configure sessions, users, embeddings, images, cost reporting or evaluations. Other OpenInference instrumentors may emit different attributes.
The old Django OTLP route (/api/public/otel/...) is retired. A response from that path is not evidence that spans are ingested. Use the collector endpoint below.
Install
Use Python 3.10 or later, below 3.16, as required by the OpenInference OpenAI package. The instruments extra installs the OpenAI SDK dependency.
pip install 'openinference-instrumentation-openai[instruments]==0.1.68' \
opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
Configure
Set the collector base URL and credentials before starting Python. FI_BASE_URL includes /tracer for Future AGI Cloud; the Python example appends /v1/traces.
export FI_BASE_URL="https://api.futureagi.com/tracer"
export FI_API_KEY="your-futureagi-api-key"
export FI_SECRET_KEY="your-futureagi-secret-key"
export OPENAI_API_KEY="your-openai-api-key"
export OPENAI_MODEL="your-available-openai-model"
For self-hosted Future AGI, replace FI_BASE_URL with your collector base URL. OpenInference captures request and response content by default; configure the switches under Privacy before starting the application if you need to hide it.
Point a standard OTLP/HTTP exporter at Future AGI. Three things matter:
- The path is
/v1/traces(or/tracer/v1/traces) on your Future AGI collector. Traces only; there are no log or metric routes. - Send the
X-Api-KeyandX-Secret-Keyheaders. An uncompressed body works on every release; Future AGI cloud and self-hosted v1.56.0 and later also accept gzip. - Set the resource attribute
project_name. A request without it is answered400. A project that does not exist yet is created.
import os
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter, Compression
from openinference.instrumentation.openai import OpenAIInstrumentor
provider = TracerProvider(resource=Resource.create({
"service.name": "my-app",
"project_name": "my-openinference-project",
"project_type": "observe",
}))
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(
endpoint=os.environ["FI_BASE_URL"].rstrip("/") + "/v1/traces",
headers={"X-Api-Key": os.environ["FI_API_KEY"], "X-Secret-Key": os.environ["FI_SECRET_KEY"]},
compression=Compression.NoCompression,
)))
OpenAIInstrumentor().instrument(tracer_provider=provider)
Run a request
Continue the same Python script with a text request. Choose an OpenAI model available to your account using OPENAI_MODEL.
from openai import OpenAI
try:
response = OpenAI().chat.completions.create(
model=os.environ["OPENAI_MODEL"],
messages=[{"role": "user", "content": "Suggest a name for a community garden."}],
)
print(response.choices[0].message.content)
finally:
provider.shutdown()
shutdown() sends pending spans before this short-lived process exits. Open Observe in Future AGI and select my-openinference-project to inspect the trace.
What is captured
Future AGI maps OpenInference span attributes as follows:
| OpenInference span | Stored as | Notes |
|---|---|---|
openinference.span.kind=AGENT | agent | Parent of the others; shown in the trace tree and Agent Graph |
RETRIEVER | retriever | input.value is the query. retrieval.documents.* attributes are kept in the span’s extra attributes, not in the output column |
LLM (OpenAI instrumentor) | llm | llm.model_name becomes the model; llm.token_count.prompt / completion become prompt and completion tokens; total is their sum |
TOOL (tracer.tool decorator) | tool | Inputs and outputs from input.value / output.value |
| Exception in a span | status ERROR | Message appears in the status message |
An unrecognised openinference.span.kind value never makes the export fail; the span is stored with type unknown. PROMPT and DECISION are two such values in current OpenInference semantic conventions.
Privacy
OpenInference captures content by default (prompts, completions, tool arguments and results, retrieval text). Turn it off with the OpenInference settings, not Future AGI’s FI_HIDE_*:
export OPENINFERENCE_HIDE_INPUTS=true
export OPENINFERENCE_HIDE_OUTPUTS=true
export OPENINFERENCE_HIDE_INPUT_MESSAGES=true
export OPENINFERENCE_HIDE_OUTPUT_MESSAGES=true
export OPENINFERENCE_HIDE_INPUT_TEXT=true
export OPENINFERENCE_HIDE_OUTPUT_TEXT=true
These settings replace input.value and output.value with __REDACTED__ and omit input and output message attributes. Exception messages are still exported in the span status, including provider error bodies. Keep secrets and personal data out of exception messages, or strip the status message in an OpenTelemetry Collector before export.
Troubleshooting
- HTTP 400. The resource has no
project_name: set the attribute. For a gzip body, releases before v1.56.0 answered HTTP 400; current releases accept gzip.Compression.NoCompressionworks on both. - 401. Missing or wrong
X-Api-Key/X-Secret-Key. - Spans never appear but the export returned 200. The project could not be resolved for your key; the collector drops those spans and still answers 200. Check the project name and key workspace.
- Model or token columns empty on a failed call. An LLM call that errors before a response has no usage data; that is expected.
- Content still visible after hiding. Check which variable your instrumentor reads, and see the exception-message note under Privacy.
Limitations
- Display of types follows Future AGI’s own mapping of
openinference.span.kind; there is no OpenInference-specific UI. - Retriever documents are not shown in the output column.
- This recipe supports the Python OpenAI instrumentor only. Other OpenInference instrumentors are outside its supported scope, even when they use the same attribute keys.
Questions & Discussion