This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
devopscritical PriorityID: opentelemetry-w3c-span-link-async-choreography-standard

OpenTelemetry W3C Span Link Asynchronous Choreography Standard

Enforces non-causal OpenTelemetry Span Links instead of parent-child trace contexts across message-driven broker boundaries such as Kafka and AWS SQS. Using direct parent-child contexts across asynchronous broker queues artificially inflates producer latency metrics, creates unbounded distributed trace graphs, and misrepresents independent consumer execution as downstream blocking calls. Consumers must initiate a detached root trace and record the extracted producer context via links with explicit link attributes.

Prohibited Anti-Pattern: Direct Parent Context Propagation in Asynchronous Queue Consumers Corrupting Trace Durations

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenTelemetry W3C Span Link Asynchronous Choreography Standard - Enforces non-causal OpenTelemetry Span Links instead of parent-child trace contexts across message-driven broker boundaries such as Kafka and AWS SQS. Using direct parent-child contexts across asynchronous broker queues artificially inflates producer latency metrics, creates unbounded distributed trace graphs, and misrepresents independent consumer execution as downstream blocking calls. Consumers must initiate a detached root trace and record the extracted producer context via links with explicit link attributes.
globs: src/**/*.ts, src/**/*.js, src/**/*.py, src/**/*.go
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/opentelemetry-w3c-span-link-async-choreography-standard"
---

# OpenTelemetry W3C Span Link Asynchronous Choreography Standard

> **Severity**: CRITICAL | **Category**: devops
> **Anti-Pattern Warning**: Direct Parent Context Propagation in Asynchronous Queue Consumers Corrupting Trace Durations

## System Constraints
You are a Principal Observability and Systems Architect enforcing the OpenTelemetry W3C Span Link Asynchronous Choreography Standard. You must ensure that asynchronous message consumers (Kafka, RabbitMQ, SQS, Google Pub/Sub) do not set the extracted publisher context as the active parent span of the consumer processing span. You must mandate that consumers extract incoming W3C traceparent headers and attach them strictly as OpenTelemetry Span Links (`links: [{ context: extractedSpanContext }]`) on a newly created, unparented root span. This prevents distorted critical-path SLAs, broken flame graphs, and unbounded trace topologies across long-lived async workflows.

## Strict Guidelines
- Engineers MUST extract W3C `traceparent` and `tracestate` headers using the standard OpenTelemetry propagator (`propagation.extract(ROOT_CONTEXT, message.headers)`).
- Engineers MUST NOT pass the extracted message context as the active parent context when invoking `tracer.startActiveSpan()` or `tracer.startSpan()` for asynchronous message consumption.
- Engineers MUST start consumer spans in an isolated root context (`ROOT_CONTEXT`) with the extracted context included exclusively inside the `links` option array.
- Engineers MUST add messaging semantic conventions to the span link attributes, including `messaging.system`, `messaging.destination.name`, and `messaging.operation` set to 'process'.
- Engineers MUST explicitly set the span kind to `SpanKind.CONSUMER` or `SpanKind.SERVER` depending on the choreographic boundary, ensuring broker polling operations remain separate from message processing spans.
- Pipelines processing batch messages MUST generate one span per batch or individual message, attaching links for each distinct message context in the batch rather than establishing multiple inheritance.

## Bad vs Good Implementations
### Kafka Message Consumer Trace Propagation via Span Links

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Passing extractedContext directly to startActiveSpan causes the consumer span to become a direct child of the producer span. This ties asynchronous broker processing time, consumer queue lag, and backoff retries to the original producer's synchronous HTTP/RPC lifecycle, breaking critical-path latency metrics and creating massive, unbounded trace topologies.
```typescript
import { trace, propagation, SpanKind } from '@opentelemetry/api';
import { EachMessagePayload } from 'kafkajs';

const tracer = trace.getTracer('payment-processor');

export async function handleKafkaMessage({ message, topic, partition }: EachMessagePayload) {
  // ANTI-PATTERN: Extracting context and directly setting it as active parent
  const extractedContext = propagation.extract(trace.setSpan(ROOT_CONTEXT, undefined as any), message.headers);

  // Corrupts trace critical-path: consumer lag and retry duration incorrectly
  // inflate the producer's original span duration and creates a massive trace tree.
  await trace.getTracer('payment-processor').startActiveSpan(
    `kafka.process ${topic}`,
    { kind: SpanKind.CONSUMER },
    extractedContext,
    async (span) => {
      try {
        await processPayment(message.value?.toString());
      } finally {
        span.end();
      }
    }
  );
}
```

#### Production Standard (Correct)
> **Standard**: Starting the span using ROOT_CONTEXT decouples consumer processing latency from the original producer trace. The extracted context is recorded strictly as a Span Link with metadata attributes, accurately reflecting the asynchronous, decoupled nature of choreographic message passing.
```typescript
import { trace, propagation, SpanKind, ROOT_CONTEXT } from '@opentelemetry/api';
import { EachMessagePayload } from 'kafkajs';

const tracer = trace.getTracer('payment-processor');

export async function handleKafkaMessage({ message, topic, partition }: EachMessagePayload) {
  // Extract W3C carrier from message headers
  const extractedContext = propagation.extract(ROOT_CONTEXT, message.headers);
  const linkedSpanContext = trace.getSpanContext(extractedContext);

  // Establish non-causal Span Link if valid context exists
  const links = linkedSpanContext && linkedSpanContext.isValid
    ? [{
        context: linkedSpanContext,
        attributes: {
          'messaging.system': 'kafka',
          'messaging.destination.name': topic,
          'messaging.kafka.partition': partition,
        },
      }]
    : [];

  // Start clean root span detached from producer's synchronous execution lifecycle
  await tracer.startActiveSpan(
    `process ${topic}`,
    {
      kind: SpanKind.CONSUMER,
      links,
      attributes: {
        'messaging.system': 'kafka',
        'messaging.destination.name': topic,
        'messaging.operation': 'process',
      },
    },
    ROOT_CONTEXT,
    async (span) => {
      try {
        await processPayment(message.value?.toString());
      } catch (error) {
        span.recordException(error as Error);
        throw error;
      } finally {
        span.end();
      }
    }
  );
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: OpenTelemetry W3C Span Link Asynchronous Choreography Standard

OpenTelemetry W3C Span Link Asynchronous Choreography Standard defines an industrial-grade behavioral standard for devops engineering. Enforces non-causal OpenTelemetry Span Links instead of parent-child trace contexts across message-driven broker boundaries such as Kafka and AWS SQS. Using direct parent-child contexts across asynchronous broker queues artificially inflates producer latency metrics, creates unbounded distributed trace graphs, and misrepresents independent consumer execution as downstream blocking calls. Consumers must initiate a detached root trace and record the extracted producer context via links with explicit link attributes. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Direct Parent Context Propagation in Asynchronous Queue Consumers Corrupting Trace Durations Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftDirect Parent Context Propagation in Asynchronous Queue Consumers Corrupting Trace DurationsCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST extract W3C `traceparent` and `tracestate` headers using the standard OpenTelemetry propagator (`propagation.extract(ROOT_CONTEXT, message.headers)`).

Engineers MUST extract W3C `traceparent` and `tracestate` headers using the standard OpenTelemetry propagator (`propagation.extract(ROOT_CONTEXT, message.headers)`).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT pass the extracted message context as the active parent context when invoking `tracer.startActiveSpan()` or `tracer.startSpan()` for asynchronous message consumption.

Engineers MUST NOT pass the extracted message context as the active parent context when invoking `tracer.startActiveSpan()` or `tracer.startSpan()` for asynchronous message consumption.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST start consumer spans in an isolated root context (`ROOT_CONTEXT`) with the extracted context included exclusively inside the `links` option array.

Engineers MUST start consumer spans in an isolated root context (`ROOT_CONTEXT`) with the extracted context included exclusively inside the `links` option array.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Engineers MUST add messaging semantic conventions to the span link attributes, including `messaging.system`, `messaging.destination.name`, and `messaging.operation` set to 'process'.

Engineers MUST add messaging semantic conventions to the span link attributes, including `messaging.system`, `messaging.destination.name`, and `messaging.operation` set to 'process'.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Engineers MUST explicitly set the span kind to `SpanKind.CONSUMER` or `SpanKind.SERVER` depending on the choreographic boundary, ensuring broker polling operations remain separate from message processing spans.

Engineers MUST explicitly set the span kind to `SpanKind.CONSUMER` or `SpanKind.SERVER` depending on the choreographic boundary, ensuring broker polling operations remain separate from message processing spans.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
6

Pipelines processing batch messages MUST generate one span per batch or individual message, attaching links for each distinct message context in the batch rather than establishing multiple inheritance.

Pipelines processing batch messages MUST generate one span per batch or individual message, attaching links for each distinct message context in the batch rather than establishing multiple inheritance.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is OpenTelemetry W3C Span Link Asynchronous Choreography Standard critical for AI coding assistants?

Enforces non-causal OpenTelemetry Span Links instead of parent-child trace contexts across message-driven broker boundaries such as Kafka and AWS SQS. Using direct parent-child contexts across asynchronous broker queues artificially inflates producer latency metrics, creates unbounded distributed trace graphs, and misrepresents independent consumer execution as downstream blocking calls. Consumers must initiate a detached root trace and record the extracted producer context via links with explicit link attributes. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Direct Parent Context Propagation in Asynchronous Queue Consumers Corrupting Trace Durations) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

OpenTelemetry