Skip to main content
Version: v6.0.0 [Falcon]

bat.telemetry.attributes

OpenTelemetry attribute names and values set on the ADK's own spans.

GEN_AI_OPERATION_NAME​

GEN_AI_OPERATION_NAME = "gen_ai.operation.name"

The operation a span performs, e.g. OP_INVOKE_AGENT.

GEN_AI_AGENT_NAME​

GEN_AI_AGENT_NAME = "gen_ai.agent.name"

The name of the agent the span belongs to.

GEN_AI_CONVERSATION_ID​

GEN_AI_CONVERSATION_ID = "gen_ai.conversation.id"

The conversation (A2A context) id.

OP_INVOKE_AGENT​

OP_INVOKE_AGENT = "invoke_agent"

GEN_AI_OPERATION_NAME value of a span invoking an agent.

BAT_TASK_ID​

BAT_TASK_ID = "bat.a2a.task_id"

The A2A task id: with the conversation id, it selects one turn's spans.

BAT_A2A_TASK_STATE​

BAT_A2A_TASK_STATE = "bat.a2a.task_state"

Final A2A TaskState of a call to another agent, on CallAgentNode's span.

SESSION_ID​

SESSION_ID = "session.id"

Groups a conversation's traces into one Phoenix session (the context id).

OPENINFERENCE_PROJECT_NAME​

OPENINFERENCE_PROJECT_NAME = "openinference.project.name"

Resource attribute selecting the Phoenix project. Agents that share a distributed trace must share a project, or the trace fragments.

INPUT_VALUE​

INPUT_VALUE = "input.value"

Span input, shown by Phoenix as a span's Input.

OUTPUT_VALUE​

OUTPUT_VALUE = "output.value"

Span output, shown by Phoenix as a span's Output.

bat.telemetry.setup

setup_telemetry​

def setup_telemetry(config: Optional[TelemetryConfig] = None) -> bool

Install the global tracer provider, exporters and LangChain instrumentation. Idempotent.

Returns:

  • bool - False when telemetry is disabled or the telemetry extra is missing (logged; the agent keeps running without it).

shutdown_telemetry​

def shutdown_telemetry() -> None

Flush buffered spans and close the exporters. Idempotent; registered with atexit by :func:setup_telemetry.

mark_span_error​

def mark_span_error(span: Any, description: str) -> None

Set span's status to ERROR, saying why.

Trace readers (the eval engine, Phoenix) key off the status, not the recorded exception. A no-op without the telemetry extra.

get_tracer​

def get_tracer(name: str) -> Any

Return a tracer for name; a no-op one without the telemetry extra.

OTel's tracer is a proxy that starts recording once :func:setup_telemetry installs the provider, so a module-level tracer = get_tracer(__name__) captured at import time still works.

inject_context​

def inject_context(carrier: Dict[str, str],
span: Optional[Any] = None) -> Dict[str, str]

Inject the current trace context, or span's, into carrier.

Pass span from async generators that yield across tasks, where attaching it to the ambient context would break the contextvars detach.

extract_context​

def extract_context(carrier: Dict[str, str]) -> Optional[Any]

Extract a trace context from carrier; None when unavailable.

is_enabled​

def is_enabled() -> bool

Whether telemetry has been successfully initialized.

bat.telemetry.privacy

Telemetry privacy levels: one ordered dial instead of several booleans.

Each level is a superset of the one below it, so the setting reads as "how much of the agent's internals may leave the process" rather than as a set of independent switches that can be combined into states nobody designed.

Being ordered is also what makes the privacy floor simple: an agent sets a minimum level in its own source and the effective level is max(floor, configured) -- see :func:resolve_privacy. With booleans this was an OR per flag; with a ladder it is one comparison that cannot express a contradiction.

Levels​

none (0) No redaction. Spans carry prompts, completions, tool definitions and node names in full. The default.

content (1) Redact what the agent says and knows: prompts, messages, completions, invocation parameters, and every tool's description, parameter schema and call arguments. Tool names and node names still export, so traces stay fully navigable and the eval engine's tool-call metrics keep working.

names (2) Also redact span names, so LangGraph node names stop leaking. Span kinds (LLM/CHAIN/TOOL) replace them, so the trace keeps its shape. The eval engine is still unaffected.

full (3) Also redact tool names. Only token counts, span kinds, hierarchy and timing survive. NOTE: the eval engine reconstructs per-episode tool calls from span attributes and keys its metrics off the tool name, so at this level those metrics go empty. Use it when the tool inventory itself is considered proprietary.

TelemetryPrivacyLevel​

TelemetryPrivacyLevel = Literal["none", "content", "names", "full"]

TelemetryPrivacyLevel is a type alias for the names of the TelemetryPrivacy levels, as written in config.yaml.

TelemetryPrivacy Objects​

class TelemetryPrivacy(IntEnum)

How much of the agent's internals may leave the process.

Ordered and cumulative: each level redacts everything the level below it does. See the module docstring for what each one covers.

hides_content​

@property
def hides_content() -> bool

Prompts, completions and tool descriptions/schemas/arguments.

hides_span_names​

@property
def hides_span_names() -> bool

Span (LangGraph node) names.

hides_tool_names​

@property
def hides_tool_names() -> bool

Tool names (costs the eval engine its tool-call metrics).

parse_privacy​

def parse_privacy(value: object) -> TelemetryPrivacy

Coerce a config.yaml value into a :class:TelemetryPrivacy.

Accepts the level name (case-insensitive) or its ordinal; None means "not configured" and maps to :attr:TelemetryPrivacy.NONE.

Raises:

  • ValueError - For anything else. A typo'd level must fail loudly, not fall back to none and export in the clear.

resolve_privacy​

def resolve_privacy(configured: object,
floor: object = TelemetryPrivacy.NONE) -> TelemetryPrivacy

Combine what config.yaml asked for with the agent's own floor, choosing the more private of the two.

Arguments:

  • configured object - The level config.yaml asked for, as a level name, an ordinal, or a :class:TelemetryPrivacy.
  • floor object - The minimum the agent allows. Defaults to :attr:TelemetryPrivacy.NONE, which leaves configured to decide alone.

Raises:

  • ValueError - If configured is not a known level.

bat.telemetry.config

ExporterSpec Objects​

@dataclass
class ExporterSpec()

One span destination.

Attributes:

  • kind str - "file", "otlp" or "console".
  • file_path Optional[str] - JSONL file, for file.
  • traces_endpoint Optional[str] - OTLP/HTTP traces URL, for otlp.

TelemetryConfig Objects​

@dataclass
class TelemetryConfig()

Resolved telemetry settings.

Attributes:

  • enabled bool - Master switch.
  • service_name str - The service.name resource attribute.
  • project_name Optional[str] - Phoenix project (the openinference.project.name resource attribute); None leaves Phoenix's default project.
  • privacy TelemetryPrivacy - See :mod:bat.telemetry.privacy.
  • exporters List[ExporterSpec] - Every span goes to all of them.

from_settings​

@classmethod
def from_settings(
cls,
*,
enabled: bool = False,
service_name: Optional[str] = None,
project_name: Optional[str] = None,
privacy: object = None,
outputs: Optional[List[Dict[str, Any]]] = None,
default_service_name: Optional[str] = None) -> "TelemetryConfig"

Build a :class:TelemetryConfig from the config.yaml telemetry section.

service_name falls back to default_service_name (the agent card name), then DEFAULT_SERVICE_NAME. Each outputs entry is a dict with type (local/remote/console) and file_path or endpoint; unknown types are skipped.