-
Notifications
You must be signed in to change notification settings - Fork 449
Description
Checks
- I have updated to the lastest minor and patch version of Strands
- I have checked the documentation and this is not expected behavior
- I have searched ./issues and there are no duplicates of my issue
Strands Version
1.12.0
Python Version
3.12.2
Operating System
macOS
Installation Method
pip
Steps to Reproduce
- Basic strands agent deployed on Bedrock AgentCore runtime with ADOT Python dependency:
import uvicorn
import time
import boto3
import json
from datetime import datetime
from strands import Agent, tool
from strands.models import BedrockModel
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from bedrock_agentcore_starter_toolkit.operations.memory.manager import MemoryManager
from bedrock_agentcore.memory.session import MemorySessionManager
from bedrock_agentcore.memory.constants import ConversationalMessage, MessageRole
from bedrock_agentcore_starter_toolkit.operations.memory.models.strategies import SemanticStrategy
@tool
def get_clinic_hours():
"""Get pet clinic operating hours"""
return "Monday-Friday: 8AM-6PM, Saturday: 9AM-4PM, Sunday: Closed."
agent_app = BedrockAgentCoreApp()
# Initialize memory
memory_manager = MemoryManager(region_name="us-east-1")
memory = memory_manager.get_or_create_memory(
name="PetClinicMemory",
description="Pet clinic conversation memory",
strategies=[SemanticStrategy(name="clinicMemory", description="Pet clinic semantic memory", namespaces=["/clinic/{actorId}"])]
)
# Wait for memory to be active
while True:
memory_status = memory_manager.get_memory(memory.get("id"))
if memory_status.get("status") == "ACTIVE":
break
time.sleep(1)
session_manager = MemorySessionManager(memory_id=memory.get("id"), region_name="us-east-1")
def create_clinic_agent():
model = BedrockModel(model_id="us.anthropic.claude-3-5-haiku-20241022-v1:0")
return Agent(model=model, tools=[get_clinic_hours], system_prompt="You are a pet clinic assistant.")
@agent_app.entrypoint
async def invoke(payload, context):
agent = create_clinic_agent()
msg = payload.get('prompt', '')
response_data = []
async for event in agent.stream_async(msg):
if 'data' in event:
response_data.append(event['data'])
response = ''.join(response_data)
# Store in memory using direct boto3 CreateEvent call
client = boto3.client('bedrock-agentcore', region_name='us-east-1')
# Create user message event
client.create_event(
memoryId="PetClinicMemory-VC8Jp09Rb1",
actorId="user",
sessionId="clinic_session",
eventTimestamp=int(datetime.utcnow().timestamp()),
payload=[
{
"conversational": {
"content": {
"text": msg
},
"role": "USER"
}
}
]
)
# Create assistant message event
client.create_event(
memoryId="PetClinicMemory-VC8Jp09Rb1",
actorId="user",
sessionId="clinic_session",
eventTimestamp=int(datetime.utcnow().timestamp()),
payload=[
{
"conversational": {
"content": {
"text": response
},
"role": "ASSISTANT"
}
}
]
)
return response
if __name__ == "__main__":
uvicorn.run(agent_app, host='0.0.0.0', port=8080)
- requirements.txt:
strands-agents
strands-agents-tools
uv
boto3
bedrock-agentcore
bedrock-agentcore-starter-toolkit
aws-opentelemetry-distro>=0.12.1
- Dockerfile:
FROM public.ecr.aws/docker/library/python:3.12-slim
WORKDIR /app
COPY requirements.txt requirements.txt
# Install from requirements file
RUN pip install -r requirements.txt
RUN pip install aws-opentelemetry-distro>=0.10.1
# Set AWS region environment variable
ENV AWS_REGION=us-east-1
ENV AWS_DEFAULT_REGION=us-east-1
# Signal that this is running in Docker for host binding logic
ENV DOCKER_CONTAINER=1
# Create non-root user
RUN useradd -m -u 1000 bedrock_agentcore
USER bedrock_agentcore
EXPOSE 8080
EXPOSE 8000
# Copy entire project (respecting .dockerignore)
COPY . .
# Use the full module path
CMD ["opentelemetry-instrument", "python", "-m", "app"]
Expected Behavior
We see a broken Trace view for Strands Agent on CloudWatch/GenAI Obs Console below. There’s an unexpected node named strands-agents that always appears in traces for agents built with Strands SDK. This happens because Strands SDK manually creates an OTel Client Span when starting the agentic workflow for incoming prompts. In OTel spec, Client Spans represent for outbound HTTP calls, but in this case, it should be an Internal Span to capture the event loop activity.
Actual Behavior
Span kind SHOULD be CLIENTand MAY be set to INTERNAL on spans representing call to models running in the same process. It’s RECOMMENDED to use CLIENT kind when the GenAI system being instrumented usually runs in a different process than its client or when the GenAI call happens over instrumented protocol such as HTTP.
In this case, the agent span represents internal activity. Labeling it as a CLIENT span would not align with OTel’s intended use of that span kind.
Additional Context
Possible Solution
No response
Related Issues
No response