Operate

SDKs & clients

Point any chat client at the control plane on :4000. Pass tenant, agent, and intent metadata so LensAI and RouteIQ can attribute and route. Export OTel spans so TraceForge joins with your existing traces.

Environment

VariablePurpose
INFERIX_BASE_URLhttp://localhost:4000/v1
INFERIX_API_KEYMaster key (Bearer)
INFERIX_TENANT_IDDefault tenant_id label
INFERIX_AGENT_IDDefault agent_id
OTEL_EXPORTER_OTLP_ENDPOINTCollector TraceForge also scrapes / joins

Python

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["INFERIX_API_KEY"],
    base_url=os.environ.get("INFERIX_BASE_URL", "http://localhost:4000/v1"),
)

resp = client.chat.completions.create(
    model="owned/general-llm",
    messages=[{"role": "user", "content": "ping"}],
    extra_headers={
        "X-Inferix-Tenant": os.environ["INFERIX_TENANT_ID"],
        "X-Inferix-Agent": "support",
        "X-Inferix-Intent": "order_status",
    },
)
print(resp.model, resp.choices[0].message.content)

JavaScript / TypeScript

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.INFERIX_API_KEY,
  baseURL: process.env.INFERIX_BASE_URL ?? "http://localhost:4000/v1",
});

const resp = await client.chat.completions.create(
  {
    model: "owned/slm-support",
    messages: [{ role: "user", content: "Refund order 4421" }],
  },
  {
    headers: {
      "X-Inferix-Tenant": process.env.INFERIX_TENANT_ID!,
      "X-Inferix-Agent": "support",
      "X-Inferix-Intent": "refund_request",
    },
  },
);

Go

req, _ := http.NewRequest(
  "POST",
  os.Getenv("INFERIX_BASE_URL")+"/chat/completions",
  body,
)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFERIX_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Inferix-Tenant", os.Getenv("INFERIX_TENANT_ID"))
req.Header.Set("X-Inferix-Agent", "incident")
req.Header.Set("X-Inferix-Intent", "kafka_lag")

resp, err := http.DefaultClient.Do(req)

OpenTelemetry for TraceForge

Emit gen_ai.* spans from your agent runtime. Inferix creates a root inferix.call span and links child tool spans when you propagate traceparent / baggage with tenant_id, agent_id, and task_id.

# Python sketch
from opentelemetry import trace
tracer = trace.get_tracer("support-agent")

with tracer.start_as_current_span("agent.tool.shop.get_order") as span:
    span.set_attribute("tool_name", "shop.get_order")
    span.set_attribute("gen_ai.operation.name", "tool")
    span.set_attribute("tenant_id", tenant)
    # execute tool...
    span.set_attribute("business.success", True)
  • Always keep the root span (sampling must not drop it)
  • Hash prompts; do not put raw PII in span attributes
  • Dual-write cost_usd on tool/model spans when available
  • Tag HITL waits so long exclusive time is not mistaken for hangs

More: TraceForge, Observability.

Identity dimensions

Required for clean dashboards: tenant_id, agent_id, task_id, trace_id, model_id, prompt_version, tool_schema_version, env. Missing tenant_id breaks cost attribution — LensAI rejects unlabeled events at ingest when configured.

Latency, cost, tokens, ingest path, and operator failure modes.

LensAI →