# Multi-Agent Operations: GovOps, Distributed Tracing, and Enterprise Resilience

Building a multi-agent system is only half the engineering challenge. Once autonomous agents start interacting, dynamically routing tasks, calling APIs, and updating state stores in production, non-deterministic behaviors emerge. A single infinite loop between agents can burn thousands of dollars in token costs within minutes, while an untraced failure can silently degrade downstream business applications.

To run multi-agent systems reliably at scale, enterprise engineering teams must establish robust **operations and observability (GovOps)**. This article provides the complete operational blueprint: translating telemetry concepts for non-AI engineers, mapping telemetry emission across system components, standardizing on OpenTelemetry GenAI semantic conventions, and connecting specialized AI tools with enterprise APM platforms.

## 1\. Non-Technical Primer: The 3 Pillars of Observability for AI Systems

For software engineers, SREs, and IT managers entering the AI space, managing multi-agent systems requires translating traditional observability pillars into AI-native equivalents:

![](https://cdn.hashnode.com/uploads/covers/6a157ef2da253d50d4a02fc4/f4946a0a-43e0-40f0-b608-a675fcec4602.png align="center")

*   **Metrics (Numeric Health Counters):** Time-series numerical aggregations used for dashboards and alerts. In traditional systems, you monitor CPU and RAM; in multi-agent systems, you monitor token velocity, cost allocation per agent, and TTFT (time-to-first-token).
    
*   **Logs (Immutable Event Snapshots):** Immutable records captured at specific execution points. In AI systems, logs capture prompt templates, raw model output text, and JSON arguments passed into tools.
    
*   **Traces (Multi-Hop Causal Graphs):** The causal chain showing how a single user request flows across multiple agents. Each operation is a **Span** containing timing, model parameters, and status codes.
    

## 2\. Multi-Agent System Components & Telemetry Emission Map

Every component in an enterprise multi-agent architecture must be instrumented to emit standardized metrics, logs, and traces.

![](https://cdn.hashnode.com/uploads/covers/6a157ef2da253d50d4a02fc4/b5432fb3-7470-4639-969b-7bb00b890fa5.png align="center")

### **A. API Gateway / Ingress Router**

**Role:** Entry point receiving client requests, handling TLS termination/authentication, enforcing edge rate limits, and initiating/propagating the root execution trace.

*   **Metrics:**
    
    *   Request volume & latency (`http.server.request.duration`, `http.server.active_requests`)
        
    *   HTTP status codes (`http.response.status_code` e.g., 2xx, 4xx, 5xx)
        
    *   Ingress rate-limit throttles & drops (`ingress.rate_limit.throttled_count`)
        
*   **Traces:**
    
    *   Creates the root trace span ([`operation.name`](http://operation.name) `= "ingress_request"`).
        
    *   Extracts/Injects W3C context headers (`traceparent`, `tracestate`) for downstream propagation.
        
    *   Attaches standard user & session baggage ([`enduser.id`](http://enduser.id), [`session.id`](http://session.id), `gen_`[`ai.conversation.id`](http://ai.conversation.id)).
        
*   **Log Events:**
    
    *   Authentication/Authorization audit logs (`auth.status = "success|deny"`)
        
    *   Payload schema validation exceptions (`http.request.body.validation_error`)
        
*   **Enterprise Storage Target:** Datadog / Dynatrace / API Gateway Access Logs (Splunk/Elastic)
    

### **B. Supervisor / Orchestrator Node**

*   **Role:** Evaluates high-level user intent, manages dynamic task decomposition, orchestrates inter-agent routing loops, maintains context across iterations, and enforces policy routing.
    
*   **Telemetry Emitted:**
    
    *   **Traces:** Parent span capturing the routing and control loop (`gen_ai.operation.name = "route_task"`).
        
    *   *Core Attributes:* `gen_ai.agent.name`, `gen_ai.conversation.id`, `gen_ai.provider.name`, `supervisor.selected_worker`, `safr.disposition.verdict` (`ALLOW` | `DENY` | `ESCALATE`).
        
*   **Metrics:**
    
    *   `gen_ai.agent.loop_count` (Counter): Total orchestration iterations before reaching task completion or termination.
        
    *   `gen_ai.orchestration.routing.count` (Counter): Total routing decisions partitioned by `source_agent`, `target_agent`, and `status`.
        
    *   `gen_ai.agent.recursion.depth` (Gauge): Current depth of nested agent invocations to catch runaway agent loops.
        
*   **Logs:** Structured events capturing goal-decomposition summaries, state-transition decisions, fallback route triggers, and policy interception results.
    

### **C. Specialized Worker Agents (Domain LLMs)**

*   **Role:** Domain-bound reasoning nodes (e.g., code analysis, SQL generation, document parsing) that execute specific sub-tasks, interface with models, and dispatch lower-level tool calls.
    
*   **Telemetry Emitted:**
    
    *   **Traces:** Child span capturing the agent's execution context (`gen_ai.operation.name = "chat"` or `"generate"`).
        
    *   *Core Attributes:* `gen_ai.agent.name`, `gen_ai.provider.name`, `gen_ai.request.model`, `gen_ai.request.temperature`, `gen_ai.request.top_p`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens`, `gen_ai.usage.cache_read.input_tokens`, `gen_ai.client.cost`.
        
*   **Metrics:**
    
    *   `gen_ai.client.token.usage` (Counter): Input, output, and cached token consumption tagged by `gen_ai.agent.name` and `gen_ai.request.model`.
        
    *   `gen_ai.client.operation.duration` (Histogram): End-to-end model inference and reasoning latency.
        
    *   `gen_ai.client.cost` (Counter): Cumulative financial cost ($ USD) computed per agent execution.
        
*   **Logs:** OTel Span Events or linked log records containing system prompt snapshots, user inputs, and output completions (sanitized for PII/PHI).
    

#### Joint FinOps & Resilience Controls: Guarding Against Recursive Delegation Spikes

In a multi-agent system, execution loops and recursive agent delegation represent both an operational resilience risk and a severe financial exposure. An undetected inter-agent loop (e.g., Worker A requesting clarification from Worker B indefinitely) doesn't just hit a timeout—it exponentially consumes tokens, driving runaway cost spikes within minutes.

Enterprise GovOps treats **iteration caps** and **token budget caps** as a unified FinOps + Resilience safeguard:

*   **Hard Iteration Caps:** Restrict any single workflow thread to a maximum of $N$ inter-agent hops (e.g., max 5 loops) before forcing a graceful state pause or human-in-the-loop (HITL) escalation.
    
*   **Token Budget Hard Stop:** Enforce per-request token caps directly within the state machine. If an agent thread consumes over 50,000 cumulative tokens, execution terminates with an `EXCEEDED_TOKEN_BUDGET` error status.
    
*   **Cost-Aware Dynamic Routing:** Automatically downgrade non-critical worker sub-tasks from frontier models (e.g., GPT-4o / Claude 3.5 Sonnet) to lightweight specialized models (e.g., 7B/70B domain models) when sub-task complexity is below a predetermined threshold.
    

### D. Specialized Worker Ingestion Engines (ScrapeGraphAI, Gortex, TurboOCR)

*   **Role:** Fetches unstructured data, executes Tree-sitter AST queries, or parses local PDFs.
    
*   **Telemetry Emitted:**
    
    *   **Metrics:** Document/file parsing latency, tool error rates, memory usage.
        
    *   **Logs:** Input arguments (URLs, file paths, AST selectors) and structured JSON returns.
        
    *   **Traces:** Deepest child span attached to the parent worker execution span.
        

## 3\. Deep Dive: Metrics, Logs, and Traces Matrix

To operate multi-agent systems reliably at enterprise scale, observability must bridge classic infrastructure telemetry with specialized AI agent mechanics. Relying solely on token counts or basic HTTP latencies obscures trajectory loops, tool integration failures, and governance violations.

#### Pillar 1: Token Economics & FinOps Metrics

<table style="min-width: 100px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><td colspan="1" rowspan="1"><p><strong>Telemetry Signal</strong></p></td><td colspan="1" rowspan="1"><p><strong>What It Measures</strong></p></td><td colspan="1" rowspan="1"><p><strong>OpenTelemetry Attribute / Instrument Name</strong></p></td><td colspan="1" rowspan="1"><p><strong>Enterprise Storage Target</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Token Utilization</strong> (Prompt vs. Completion split)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.client.token.usage</code> (<code>gen_ai.usage.input_tokens</code>, <code>gen_ai.usage.output_tokens</code>)</p></td><td colspan="1" rowspan="1"><p>Prometheus / Dynatrace / Datadog</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Prompt Cache Hit Ratio</strong> (Percentage of context tokens served via model prompt cache)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.usage.cache_read_input_tokens</code> / <code>gen_ai.usage.input_tokens</code></p></td><td colspan="1" rowspan="1"><p>Datadog / Grafana / FinOps Portal</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Financial Cost ($)</strong> (Real-time token-to-dollar conversion)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.client.cost</code></p></td><td colspan="1" rowspan="1"><p>FinOps Dashboard / CloudWatch / Datadog</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Reasoning-to-Output Token Ratio</strong> (Internal Chain-of-Thought scratchpad size vs. final answer)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.usage.reasoning_tokens</code> / <code>gen_ai.usage.output_tokens</code></p></td><td colspan="1" rowspan="1"><p>Prometheus / Langfuse</p></td></tr></tbody></table>

#### Pillar 2: Multi-Agent Trajectory & Task Execution

<table style="min-width: 100px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><td colspan="1" rowspan="1"><p><strong>Telemetry Signal</strong></p></td><td colspan="1" rowspan="1"><p><strong>What It Measures</strong></p></td><td colspan="1" rowspan="1"><p><strong>OpenTelemetry Attribute / Instrument Name</strong></p></td><td colspan="1" rowspan="1"><p><strong>Enterprise Storage Target</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Agent Loops / Retries</strong> (Recursion count per orchestration workflow)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.agent.loop_count</code></p></td><td colspan="1" rowspan="1"><p>Prometheus / Grafana</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Step Efficiency / Trajectory Length</strong> (Total sub-agent handoffs or reasoning steps per task)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.agent.trajectory_step_count</code></p></td><td colspan="1" rowspan="1"><p>Prometheus / Dynatrace</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Task Completion Rate</strong> (Percentage of user sessions successfully resolved without failure)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.workflow.completion_status</code> = <code>"success"</code></p></td><td colspan="1" rowspan="1"><p>Grafana / Datadog</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Inter-Agent Handoff Failure Rate</strong> (Failed context or task delegation between agents)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.agent.handoff_error_count</code></p></td><td colspan="1" rowspan="1"><p>Prometheus / Splunk</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Plan Adherence / Drift Rate</strong> (Percentage of actions deviating from original plan)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.agent.plan_drift_score</code></p></td><td colspan="1" rowspan="1"><p>Arize Phoenix / Langsmith</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Trace Span</strong></p></td><td colspan="1" rowspan="1"><p><strong>Inter-Agent Routing</strong> (Handoff orchestration spans across worker agents)</p></td><td colspan="1" rowspan="1"><p><code>gen_</code><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="http://ai.operation.name" style="pointer-events: none;"><code>ai.operation.name</code></a><code> = "invoke_agent"</code> (<code>gen_</code><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="http://ai.agent.name" style="pointer-events: none;"><code>ai.agent.name</code></a>)</p></td><td colspan="1" rowspan="1"><p>Dynatrace / Jaeger / Zipkin</p></td></tr></tbody></table>

#### Pillar 3: GovOps, Safety & Quality Assurance

<table style="min-width: 100px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><td colspan="1" rowspan="1"><p><strong>Telemetry Signal</strong></p></td><td colspan="1" rowspan="1"><p><strong>What It Measures</strong></p></td><td colspan="1" rowspan="1"><p><strong>OpenTelemetry Attribute / Instrument Name</strong></p></td><td colspan="1" rowspan="1"><p><strong>Enterprise Storage Target</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>PDP / Guardrail Interception Rate</strong> (Actions blocked by Policy Decision Point proxies)</p></td><td colspan="1" rowspan="1"><p><code>safr.disposition.verdict</code> = <code>"DENY"</code></p></td><td colspan="1" rowspan="1"><p>Splunk / Datadog / GovOps Portal</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Human Escalation Rate</strong> (Percentage of requests routed to HITL escrow queues)</p></td><td colspan="1" rowspan="1"><p><code>safr.disposition.verdict</code> = <code>"ESCALATE"</code></p></td><td colspan="1" rowspan="1"><p>Datadog / PagerDuty / Grafana</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>RAG Hallucination &amp; Faithfulness Rate</strong> (Factual alignment of generated context)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.evaluation.faithfulness_score</code></p></td><td colspan="1" rowspan="1"><p>Arize Phoenix / Langfuse</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Safety &amp; Tone Violation Rate</strong> (PII leakages, prompt injections, or toxicity hits)</p></td><td colspan="1" rowspan="1"><p><code>gen_</code><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="http://ai.evaluation.safety" style="pointer-events: none;"><code>ai.evaluation.safety</code></a><code>_violation</code></p></td><td colspan="1" rowspan="1"><p>Elastic / Splunk / Guardrails Dashboard</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Fallback / No-Match Rate</strong> (Frequency of fallback branch triggers or empty tool outputs)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.workflow.fallback_triggered</code></p></td><td colspan="1" rowspan="1"><p>Prometheus / Grafana</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Log Event</strong></p></td><td colspan="1" rowspan="1"><p><strong>Raw Prompt &amp; Completion</strong> (Captures user/agent text payloads safely as events)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.content.prompt</code>, <code>gen_ai.content.completion</code></p></td><td colspan="1" rowspan="1"><p>Langfuse / Arize Phoenix / CloudWatch</p></td></tr></tbody></table>

#### Pillar 4: System Performance & Tool Execution Mechanics

<table style="min-width: 100px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><td colspan="1" rowspan="1"><p><strong>Telemetry Signal</strong></p></td><td colspan="1" rowspan="1"><p><strong>What It Measures</strong></p></td><td colspan="1" rowspan="1"><p><strong>OpenTelemetry Attribute / Instrument Name</strong></p></td><td colspan="1" rowspan="1"><p><strong>Enterprise Storage Target</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Model &amp; Operation Latency</strong> (p50/p95/p99 duration of LLM inference calls)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.client.operation.duration</code></p></td><td colspan="1" rowspan="1"><p>Prometheus / Dynatrace</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Instant Recognition Rate</strong> (Time-to-First-Token [TTFT] in streaming workflows)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.server.time_to_first_token</code></p></td><td colspan="1" rowspan="1"><p>Prometheus / Grafana</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Tool Execution Failure Rate</strong> (API 5xx, timeouts, or network errors vs. LLM faults)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.tool.execution_status</code> = <code>"error"</code></p></td><td colspan="1" rowspan="1"><p>Prometheus / Datadog</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Argument Schema Correctness Rate</strong> (Accuracy of agent-generated JSON tool payloads)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.tool.schema_validation_passed</code></p></td><td colspan="1" rowspan="1"><p>Splunk / Langfuse</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Metric</strong></p></td><td colspan="1" rowspan="1"><p><strong>Error / System Fault Rate</strong> (Uncaught application exceptions across multi-agent processes)</p></td><td colspan="1" rowspan="1"><p><code>exception.type</code>, <code>error.type</code></p></td><td colspan="1" rowspan="1"><p>Dynatrace / Datadog / Sentry</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Trace Span</strong></p></td><td colspan="1" rowspan="1"><p><strong>Tool Execution Span</strong> (Distributed tracing across underlying API/database calls)</p></td><td colspan="1" rowspan="1"><p><code>gen_ai.operation.name = "execute_tool"</code> (<code>gen_ai.tool.name</code>)</p></td><td colspan="1" rowspan="1"><p>Dynatrace / Jaeger / Arize Phoenix</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Log Event</strong></p></td><td colspan="1" rowspan="1"><p><strong>Tool Payload &amp; Exceptions</strong> (Full JSON arguments and stack traces)</p></td><td colspan="1" rowspan="1"><p>Tool JSON arguments, <code>exception.stacktrace</code></p></td><td colspan="1" rowspan="1"><p>Elastic / Splunk / Langfuse</p></td></tr></tbody></table>

## 4\. Standardization: OpenTelemetry GenAI Semantic Conventions

Without standardized instrumentation, every vendor uses different attribute names (e.g., `prompt_tokens` vs `input_tokens`). **OpenTelemetry (OTel) GenAI Semantic Conventions** standardize attribute names across all LLMs and agent frameworks:

```yaml
# Core Standardized Span Attributes
gen_ai.operation.name: "chat" | "execute_tool" | "route_task"
gen_ai.provider.name: "openai" | "anthropic" | "google"
gen_ai.request.model: "gpt-4o" | "claude-3-5-sonnet" | "gemini-1.5-pro"
gen_ai.usage.input_tokens: 1280
gen_ai.usage.output_tokens: 340
gen_ai.usage.cost: 0.0042
gen_ai.response.finish_reasons: ["stop"]
```

### Dynamic Application-Layer Permissioning in Tracing Spans

While OpenTelemetry distributed tracing visually maps what happens across agents, enterprise security enforcement dictates what is *permitted* to happen.

To bridge observability and security compliance, dynamic gateways (like ContextForge MCP proxies) must log explicit **Policy Evaluation Results** directly into OpenTelemetry trace spans. This creates an immutable, audit-ready log that proves RBAC and tool access policies were actively enforced before any external tool executed.

"Logging explicit policy evaluation results inside OTel spans directly aligns with runtime compliance standards like the MAS SAFR (Safeguards for Agentic Finance at Runtime) framework."

## 5\. Architectural Tooling Ecosystem: Where to Use What

Enterprise AI observability requires a dual-tier tooling strategy:

![](https://cdn.hashnode.com/uploads/covers/6a157ef2da253d50d4a02fc4/63287d63-181a-4543-807a-cc5787d21ee9.png align="center")

### Tier 1: AI-Native Observability Tools (Langfuse / Arize Phoenix)

*   **Role:** Deep prompt debugging, LLM evaluation, hallucination detection, and prompt versioning.
    
*   **When to Use:**
    
    *   Debugging multi-step agent reasoning during development and testing.
        
    *   Running LLM-as-a-Judge evaluations on live production outputs.
        
    *   Inspecting full conversational threads and human feedback (thumbs up/down).
        

### Tier 2: Enterprise APM & Infrastructure Platforms (Dynatrace / Datadog)

*   **Role:** Full-stack IT health, unified microservice tracing, infrastructure correlation, and SRE alerting.
    
*   **When to Use:**
    
    *   Correlating agent performance with backend infrastructure (Redis state locks, Kafka consumer lag, PostgreSQL latency).
        
    *   Setting up automated enterprise alerts when LLM costs exceed budget thresholds or response SLAs breach 5 seconds.
        
    *   Single-pane-of-glass operational visibility for enterprise operations teams.
        

## 6\. Production Implementation: OpenTelemetry OTLP Exporter

The following production Python script instruments a Multi-Agent Supervisor workflow using the OpenTelemetry SDK. It formats telemetry according to GenAI Semantic Conventions and exports OTLP streams directly to enterprise collectors (such as Dynatrace or OpenTelemetry Collector).

```python
# observability/otel_agent_tracer.py
import json
import os
import time
from typing import Any, Dict
from opentelemetry import trace
from opentelemetry.baggage import set_baggage
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.trace import SpanKind, StatusCode

# 1. Configure OpenTelemetry OTLP Exporter (Dynatrace / OTLP Collector)
OTLP_ENDPOINT = os.getenv(
    "OTEL_EXPORTER_OTLP_ENDPOINT",
    "https://your-environment.live.dynatrace.com/api/v2/otlp/v1/traces",
)
OTLP_TOKEN = os.getenv(
    "OTEL_EXPORTER_OTLP_HEADERS", "Api-Token dt0c01.sample_token"
)

provider = TracerProvider()
otlp_exporter = OTLPSpanExporter(
    endpoint=OTLP_ENDPOINT, headers={"Authorization": OTLP_TOKEN}
)
provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
trace.set_tracer_provider(provider)

tracer = trace.get_tracer("multi_agent_ecosystem", "1.0.0")


# 2. Instrumented Multi-Agent Workflow
def execute_multi_agent_workflow(
    user_query: str, session_id: str, user_id: str = "usr_4910"
):
    # Context Propagation: Set W3C Baggage attributes
    set_baggage("enduser.id", user_id)
    set_baggage("gen_ai.conversation.id", session_id)

    # Root Span: Captures total user request workflow
    with tracer.start_as_current_span(
        "multi_agent_workflow", kind=SpanKind.SERVER
    ) as root_span:
        root_span.set_attribute("gen_ai.operation.name", "route_task")
        root_span.set_attribute("gen_ai.conversation.id", session_id)
        root_span.set_attribute("enduser.id", user_id)
        root_span.set_attribute("gen_ai.content.prompt", user_query)

        # Step 1: Supervisor Node Routing Span
        with tracer.start_as_current_span(
            "supervisor_routing", kind=SpanKind.INTERNAL
        ) as supervisor_span:
            supervisor_span.set_attribute("gen_ai.operation.name", "route_task")
            supervisor_span.set_attribute("gen_ai.agent.name", "primary_supervisor")
            supervisor_span.set_attribute("gen_ai.provider.name", "openai")
            supervisor_span.set_attribute("gen_ai.request.model", "gpt-4o")

            # SAFR GovOps Check
            supervisor_span.set_attribute("safr.disposition.verdict", "ALLOW")

            selected_worker = "code_analysis_worker"
            supervisor_span.set_attribute(
                "supervisor.selected_worker", selected_worker
            )

        # Step 2: Worker Execution Span
        with tracer.start_as_current_span(
            "worker_execution", kind=SpanKind.CLIENT
        ) as worker_span:
            worker_span.set_attribute("gen_ai.operation.name", "chat")
            worker_span.set_attribute("gen_ai.agent.name", selected_worker)
            worker_span.set_attribute("gen_ai.provider.name", "anthropic")
            worker_span.set_attribute("gen_ai.request.model", "claude-3-5-sonnet")

            # Execute child tool call
            tool_result = run_gortex_code_parser(query=user_query)

            # Record Token & Cost Metrics (OTel GenAI Semantic Conventions)
            worker_span.set_attribute("gen_ai.usage.input_tokens", 850)
            worker_span.set_attribute("gen_ai.usage.output_tokens", 210)
            worker_span.set_attribute("gen_ai.client.cost", 0.0056)
            worker_span.set_attribute("worker.status", "SUCCESS")


def run_gortex_code_parser(query: str) -> Dict[str, Any]:
    """Child span capturing specialized worker tool call execution."""
    with tracer.start_as_current_span(
        "tool_gortex_parser", kind=SpanKind.INTERNAL
    ) as tool_span:
        tool_span.set_attribute("gen_ai.operation.name", "execute_tool")
        tool_span.set_attribute("gen_ai.tool.name", "gortex_tree_sitter")
        tool_span.set_attribute(
            "gen_ai.tool.call.arguments", json.dumps({"query": query})
        )

        try:
            time.sleep(0.15)  # Simulate parsing latency
            tool_span.set_attribute("gen_ai.tool.execution_status", "success")
            tool_span.set_status(StatusCode.OK)
            return {"status": "parsed", "nodes_found": 12}

        except Exception as exc:
            tool_span.record_exception(exc)
            tool_span.set_status(StatusCode.ERROR, str(exc))
            tool_span.set_attribute("gen_ai.tool.execution_status", "error")
            raise exc


if __name__ == "__main__":
    execute_multi_agent_workflow(
        user_query="Find security vulnerability in authentication class",
        session_id="sess_88910a2",
        user_id="usr_4910",
    )
    print("Telemetry successfully emitted via OpenTelemetry OTLP.")
```

## Summary

Building production-grade multi-agent ecosystems requires balancing autonomous capabilities with disciplined operational governance. By standardizing telemetry around OpenTelemetry GenAI semantic conventions, routing signals through specialized AI observability tools like Langfuse alongside enterprise platforms like Dynatrace, and enforcing rate limits and token budget controls, enterprise organizations can operate agentic AI with total reliability, complete auditability, and predictable cost management.
