On this page

For AI agents: a documentation index is available at /docs/llms.txt. Append .md to any page URL for markdown, or send Accept: text/markdown.

Send AWS Strands traces to Agent Analytics

The Python Strands Agents SDK emits OpenTelemetry GenAI spans. Point that exporter at Amplitude. You don't need the Amplitude AI SDK in the agent process.

This page covers Strands Agents 1.60.0. Amplitude stores the spans you export. Scrub personal data before it leaves your infrastructure. Refer to Agent Analytics privacy modes.

Paste this prompt into your AI coding agent, such as Cursor, Claude Code, Windsurf, GitHub Copilot, or Codex.

text
Connect this Python Strands agent to Amplitude Agent Analytics with native OpenTelemetry.

Fetch https://raw.githubusercontent.com/amplitude/Amplitude-AI-Node/main/docs/integrations/strands.md
and follow "Part 2: Coding agent procedure".
If @amplitude/ai is installed, the same file is under node_modules/@amplitude/ai/docs/integrations/.
Also follow https://raw.githubusercontent.com/amplitude/Amplitude-AI-Node/main/docs/integrations/privacy.md
and scrub content before export.
Follow links in the guide. If your source isn't listed, start at https://raw.githubusercontent.com/amplitude/Amplitude-AI-Node/main/docs/integrations/README.md

Review the changes, then verify with the steps in Get started.

What this means for you

  • You run: The Strands process, with its OpenTelemetry exporter pointed at Amplitude. A Collector is optional. Use one when you already collect gRPC spans or when you scrub attributes there.
  • You need: strands-agents[otel]==1.60.0, your Amplitude project API key, and a stable conversation ID and product-analytics user ID on every turn.
  • Protocol: OTLP over HTTP. Amplitude accepts protobuf and JSON. Amplitude doesn't accept gRPC. Bridge gRPC through a Collector that exports OTLP/HTTP.
  • Privacy: Amplitude doesn't scrub content after receipt. Mask or drop the content attributes before export.

Export

Set these variables in the agent process. In Python, encode the space in the header value as %20. Leave Authorization= as written.

bash
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://api.amplitude.com/otlp/v1/traces
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20<project API key>"
OTEL_SERVICE_NAME=order-support
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental,gen_ai_tool_definitions,gen_ai_span_attributes_only

EU data residency uses https://api.eu.amplitude.com/otlp/v1/traces.

gen_ai_span_attributes_only puts prompts, completions, and system instructions on span attributes. Amplitude doesn't read span events. Without that flag, identity, model, and token counts can still arrive, and the message text doesn't.

Call StrandsTelemetry().setup_otlp_exporter() before you construct Agent(). If a tracer provider is already installed, pass it in:

python
from opentelemetry import trace
from strands.telemetry import StrandsTelemetry

StrandsTelemetry(tracer_provider=trace.get_tracer_provider()).setup_otlp_exporter()

Identity

Pass one trace_attributes dictionary when you construct the agent. Strands copies it onto the model span and each tool span.

Strands writes gen_ai.provider.name=strands-agents unless trace_attributes sets it afterward. Set the real provider. Amplitude records cost only when the span includes gen_ai.usage.cost.

What carries over

A later turn repeats the earlier user text inside gen_ai.input.messages. Amplitude doesn't emit that earlier user message again. Tool output is [Agent] Tool Output. System instructions, when present, are [Agent] System Prompt on the AI Response.

Session close

[Agent] Session End is optional and recommended. A native Strands export doesn't send it. Amplitude closes the session after 30 minutes without a qualifying agent event by default, and 24 hours from the session start when no per-session override is set. The first close is the one that counts. Enrichment, including the Session Record and content-based signals, runs once after that close. The record typically arrives 15 to 20 minutes after the ingestion batch processes the close, and can take longer during a backlog. Amplitude stores events that arrive after the close, and those events don't recompute that record.

When you know the unit of work is finished, send one [Agent] Session End over the HTTP API with the same session.id as [Agent] Session ID. A pure Strands export uses the server defaults. The OpenTelemetry translator doesn't read an idle-timeout attribute from a span. To change the idle window, send the HTTP [Agent] Context key idle_timeout_minutes, or set [Agent] Session Idle Timeout Minutes on that Session End event. Refer to How sessions close.

When the app already runs the SDK

If the agent process already uses the Amplitude AI SDK, AmplitudeAgentExporter or enableOtel() can map spans in that process. Native OTLP above is the path when the SDK isn't loaded. SDK redactPii applies only on the in-process path.

Get started

Follow the Strands integration guide. Send two turns with the same session.id, then confirm in Live Events:

  1. Session ID is session.id, not a trace ID.
  2. User ID is the product-analytics user, not unknown.
  3. Agent ID is gen_ai.agent.id.
  4. The turn shows User Message text, the tool call, and AI Response text, with the model name and both token counts.
  5. A canary of ada@example.com and 555-123-4567 is stored as [email] and [phone]. The raw values are absent.
  6. The second turn doesn't duplicate the first user message.

A parenthesized US number keeps the opening parenthesis: Call (555) 123-4567 becomes Call ([phone].

Guide last verified on October 14, 2026, against strands-agents 1.60.0. Strands is a trademark of its owner. Amplitude isn't affiliated with or endorsed by that owner.

Was this helpful?