Skip to content

Commit a516260

Browse files
notgitikajariy17
andauthored
Revert "feat: Emit OTEL attributes for AgentCore Evaluation support (#368)" (#380)
This reverts commit 8bae410. Co-authored-by: Trirmadura J Ariyawansa <tjariy@amazon.com>
1 parent 14b236e commit a516260

2 files changed

Lines changed: 4 additions & 386 deletions

File tree

src/bedrock_agentcore/runtime/app.py

Lines changed: 4 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,6 @@ def __init__(
120120
self.handlers: Dict[str, Callable] = {}
121121
self._ping_handler: Optional[Callable] = None
122122
self._websocket_handler: Optional[Callable] = None
123-
self._prompt_key: Optional[str] = None
124-
self._response_key: Optional[str] = None
125123
self._active_tasks: Dict[int, Dict[str, Any]] = {}
126124
self._task_counter_lock: threading.Lock = threading.Lock()
127125
self._forced_ping_status: Optional[PingStatus] = None
@@ -146,44 +144,18 @@ def __init__(
146144
self.logger.addHandler(handler)
147145
self.logger.setLevel(logging.DEBUG if self.debug else logging.INFO)
148146

149-
def entrypoint(
150-
self, func: Callable = None, *, prompt_key: Optional[str] = None, response_key: Optional[str] = None
151-
) -> Callable:
147+
def entrypoint(self, func: Callable) -> Callable:
152148
"""Decorator to register a function as the main entrypoint.
153149
154150
Args:
155151
func: The function to register as entrypoint
156-
prompt_key: Optional key to extract user prompt from the payload dict.
157-
If not specified, tries common keys in order (prompt, input, query,
158-
message, question, user_input) then falls back to JSON serialization.
159-
response_key: Optional key to extract agent response from the result dict.
160-
If not specified, the full result is used.
161152
162153
Returns:
163154
The decorated function with added serve method
164-
165-
Examples:
166-
@app.entrypoint
167-
def handler(payload):
168-
...
169-
170-
@app.entrypoint(prompt_key="user_input")
171-
def handler(payload):
172-
...
173155
"""
174-
175-
def decorator(f: Callable) -> Callable:
176-
self.handlers["main"] = f
177-
self._prompt_key = prompt_key
178-
self._response_key = response_key
179-
f.run = lambda port=8080, host=None: self.run(port, host)
180-
return f
181-
182-
if func is not None:
183-
# Called as @app.entrypoint without arguments
184-
return decorator(func)
185-
# Called as @app.entrypoint(...) with arguments
186-
return decorator
156+
self.handlers["main"] = func
157+
func.run = lambda port=8080, host=None: self.run(port, host)
158+
return func
187159

188160
def ping(self, func: Callable) -> Callable:
189161
"""Decorator to register a custom ping status handler.
@@ -412,78 +384,6 @@ def _takes_context(self, handler: Callable) -> bool:
412384
except Exception:
413385
return False
414386

415-
def _emit_invocation_otel_attributes(self, payload: Any, result: Any) -> None:
416-
"""Emit OTEL span attributes with the invocation input and output.
417-
418-
These attributes provide a canonical, framework-agnostic source of the
419-
user's prompt and the agent's response for AgentCore Evaluation. They
420-
enable evaluation of agents that use custom state schemas (e.g. workflow
421-
agents with TypedDict states) where the default MessagesState-based
422-
extraction in the evaluation mapper would fail.
423-
424-
The attributes are set on the current active span (typically the root
425-
POST /invocations span created by ADOT auto-instrumentation).
426-
427-
When prompt_key or response_key is configured via @app.entrypoint(),
428-
those specific keys are used to extract from dict payloads/results.
429-
Otherwise, a heuristic tries common keys in priority order.
430-
"""
431-
try:
432-
from opentelemetry import trace as otel_trace
433-
434-
span = otel_trace.get_current_span()
435-
if not span or not span.is_recording():
436-
return
437-
438-
# Extract user prompt from payload
439-
user_prompt = None
440-
if isinstance(payload, dict):
441-
if self._prompt_key is not None:
442-
value = payload.get(self._prompt_key)
443-
if isinstance(value, str):
444-
user_prompt = value
445-
else:
446-
for key in ("prompt", "input", "query", "message", "question", "user_input"):
447-
if key in payload and isinstance(payload[key], str):
448-
user_prompt = payload[key]
449-
break
450-
if user_prompt is None:
451-
user_prompt = json.dumps(payload, ensure_ascii=False, default=str)
452-
elif isinstance(payload, str):
453-
user_prompt = payload
454-
else:
455-
user_prompt = str(payload)
456-
457-
# Extract agent response from result
458-
agent_response = None
459-
if isinstance(result, str):
460-
agent_response = result
461-
elif isinstance(result, Response):
462-
pass # Skip for streaming/custom responses — cannot capture full output
463-
elif isinstance(result, dict) and self._response_key is not None:
464-
value = result.get(self._response_key)
465-
if isinstance(value, str):
466-
agent_response = value
467-
elif value is not None:
468-
try:
469-
agent_response = json.dumps(value, ensure_ascii=False, default=str)
470-
except Exception:
471-
agent_response = str(value)
472-
elif result is not None:
473-
try:
474-
agent_response = json.dumps(result, ensure_ascii=False, default=str)
475-
except Exception:
476-
agent_response = str(result)
477-
478-
if user_prompt:
479-
span.set_attribute("agentcore.invocation.user_prompt", user_prompt[:16384])
480-
if agent_response:
481-
span.set_attribute("agentcore.invocation.agent_response", agent_response[:16384])
482-
except ImportError:
483-
pass # OpenTelemetry not installed — silently skip
484-
except Exception:
485-
self.logger.debug("Failed to emit invocation OTEL attributes", exc_info=True)
486-
487387
async def _handle_invocation(self, request):
488388
request_context = self._build_request_context(request)
489389

@@ -511,8 +411,6 @@ async def _handle_invocation(self, request):
511411
self.logger.debug("Invoking handler: %s", handler_name)
512412
result = await self._invoke_handler(handler, request_context, takes_context, payload)
513413

514-
self._emit_invocation_otel_attributes(payload, result)
515-
516414
duration = time.time() - start_time
517415
if inspect.isgenerator(result):
518416
self.logger.info("Returning streaming response (generator) (%.3fs)", duration)

0 commit comments

Comments
 (0)