Skip to content

Commit 3ca64a2

Browse files
author
Michal Stanek
committed
Add standalone invoke_agent instrumentation demo
1 parent e4f33d6 commit 3ca64a2

File tree

1 file changed

+146
-0
lines changed
  • instrumentation/opentelemetry-instrumentation-botocore/examples/bedrock-runtime/zero-code

1 file changed

+146
-0
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#!/usr/bin/env python3
2+
3+
import boto3
4+
import json
5+
import uuid
6+
import logging
7+
from botocore.exceptions import ClientError
8+
9+
# Configure logging
10+
logging.basicConfig(level=logging.INFO)
11+
logger = logging.getLogger(__name__)
12+
13+
class WeatherAgentDemo:
14+
def __init__(self):
15+
# Initialize Bedrock Agents Runtime client
16+
self.client = boto3.client('bedrock-agent-runtime')
17+
18+
# Replace these with your actual agent IDs
19+
self.agent_id = "TFMZVIWXR7"
20+
self.agent_alias_id = "ZT7YYHO8TO"
21+
22+
# Generate a unique session ID for this conversation
23+
self.session_id = str(uuid.uuid4())
24+
25+
def invoke_agent(self, input_text, session_state=None, end_session=False):
26+
"""Invoke the Bedrock agent with various features enabled."""
27+
try:
28+
# Prepare the request parameters
29+
request_params = {
30+
"agentId": self.agent_id,
31+
"agentAliasId": self.agent_alias_id,
32+
"sessionId": self.session_id,
33+
"inputText": input_text,
34+
"enableTrace": True, # Enable tracing for debugging
35+
"endSession": end_session,
36+
}
37+
38+
# Add session state if provided (for returning control results)
39+
if session_state:
40+
request_params["sessionState"] = session_state
41+
42+
# Invoke the agent
43+
response = self.client.invoke_agent(**request_params)
44+
45+
# Process the streaming response
46+
completion = ""
47+
trace_data = []
48+
49+
for event in response.get("completion"):
50+
if "chunk" in event:
51+
chunk = event["chunk"]
52+
completion += chunk["bytes"].decode()
53+
elif "trace" in event:
54+
trace_data.append(event["trace"])
55+
elif "returnControl" in event:
56+
# Handle the case where the agent returns control
57+
return {"type": "return_control", "data": event["returnControl"]}
58+
59+
return {
60+
"type": "completion",
61+
"completion": completion,
62+
"trace": trace_data
63+
}
64+
65+
except ClientError as e:
66+
logger.error(f"Error invoking agent: {e}")
67+
raise
68+
69+
def handle_return_control(self, return_control_data):
70+
"""Simulate handling returned control by providing weather data."""
71+
invocation_id = return_control_data["invocationId"]
72+
invocation_inputs = return_control_data["invocationInputs"][0]
73+
74+
# Simulate weather API response (using function result format)
75+
weather_response = {
76+
"actionGroup": invocation_inputs["functionInvocationInput"]["actionGroup"],
77+
"function": invocation_inputs["functionInvocationInput"]["function"],
78+
"responseBody": {
79+
"TEXT": {
80+
"body": "It's 55F in Seattle today, rainy."
81+
}
82+
}
83+
}
84+
85+
# Prepare session state with the returned control results
86+
session_state = {
87+
"invocationId": invocation_id,
88+
"returnControlInvocationResults": [
89+
{"functionResult": weather_response}
90+
]
91+
}
92+
93+
return session_state
94+
95+
def run_demo(self):
96+
"""Run the demo showcasing multiple InvokeAgent features."""
97+
print("Starting Weather Agent Demo...")
98+
99+
# Step 1: Initial request for weather
100+
print("Step 1: Asking for Seattle weather")
101+
initial_prompt = "What's the weather like in Seattle today?"
102+
response = self.invoke_agent(initial_prompt)
103+
104+
if response["type"] == "return_control":
105+
print("Agent requested weather data via return control.")
106+
107+
# Step 2: Handle return control and provide weather data
108+
session_state = self.handle_return_control(response["data"])
109+
print("Step 2: Providing weather data back to agent.")
110+
final_response = self.invoke_agent(
111+
"Process the weather data",
112+
session_state=session_state,
113+
end_session=False # Keeping session open for potential follow-up
114+
)
115+
116+
if final_response["type"] == "completion":
117+
print("\nFinal Response:")
118+
print(final_response["completion"])
119+
if final_response["trace"]:
120+
print("\nTrace Information:")
121+
for trace in final_response["trace"]:
122+
print(json.dumps(trace, indent=2))
123+
else:
124+
# Should not happen if session_state is provided correctly
125+
logger.warning(f"Unexpected response type after providing session state: {final_response.get('type')}")
126+
print("Received unexpected response after providing data.")
127+
128+
elif response["type"] == "completion":
129+
# Agent answered directly without needing function call/return control
130+
print("\nAgent responded directly:")
131+
print(response["completion"])
132+
if response["trace"]:
133+
print("\nTrace Information:")
134+
for trace in response["trace"]:
135+
print(json.dumps(trace, indent=2))
136+
else:
137+
# Handle other unexpected response types
138+
logger.error(f"Unexpected initial response type: {response.get('type')}")
139+
print(f"Received unexpected response type: {response.get('type')}")
140+
141+
if __name__ == "__main__":
142+
try:
143+
demo = WeatherAgentDemo()
144+
demo.run_demo()
145+
except Exception as e:
146+
logger.error(f"Demo failed unexpectedly: {e}", exc_info=True) # Add traceback info

0 commit comments

Comments
 (0)