[opentelemetry-instrumentation-genai-bedrock] Instrument invoke_inline_agent method - #736
Conversation
Assisted-by: Antigravity
Pull request dashboard statusWaiting on reviewers · refreshed 2026-09-19 03:22 UTC Review the latest changes. Status above doesn't look right?
|
There was a problem hiding this comment.
🔵 Needs a closer look
Unresolved correctness, stream-lifecycle, compatibility, and scope or disclosure findings remain.
Pull request overview
This PR expands Bedrock GenAI instrumentation to async clients, embeddings, agents, retrieval/RAG APIs, and stream lifecycle handling.
Changes:
- Adds sync/async patching, extractors, and stream wrappers.
- Adds unit, conformance, cassette, and integration coverage.
- Updates dependencies, documentation, shared utilities, and changelogs.
File summaries
| File | Reviewed change |
|---|---|
util/opentelemetry-util-genai/tests/test_stream.py |
Tests abandoned-stream finalization. |
util/opentelemetry-util-genai/src/opentelemetry/util/genai/stream.py |
Adds abandoned-stream finalization; the finalizer must also swallow BaseException cancellation errors. |
util/opentelemetry-util-genai/.changelog/723.fixed |
Documents the stream finalization fix. |
instrumentation/opentelemetry-instrumentation-genai-llama-index/tests/requirements.oldest.txt |
Adds a workflow test dependency; unrelated scope concern remains. |
instrumentation/opentelemetry-instrumentation-genai-llama-index/tests/requirements.latest.txt |
Adds a workflow test dependency; unrelated scope concern remains. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_invoke_model.py |
Tests embedding instrumentation. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_conformance.py |
Registers new conformance scenarios. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_async.py |
Tests async operations; compatibility concerns remain for the oldest supported environment. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_agent.py |
Tests agent and retrieval APIs. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/requirements.oldest.txt |
Adds the oldest async test dependency. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/requirements.latest.txt |
Adds the latest async test dependency. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/retrieve.py |
Adds retrieval conformance coverage. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/retrieve_and_generate.py |
Adds RAG conformance coverage. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/retrieve_and_generate_streaming.py |
Adds streaming RAG conformance coverage. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/invoke_agent.py |
Adds agent conformance coverage. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/conformance/embedding.py |
Adds embedding conformance coverage. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_retrieve_conformance.yaml |
Adds a retrieval cassette; its synthetic origin requires disclosure, tracking, or re-recording. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_retrieve_and_generate_stream_conformance.yaml |
Adds a streaming RAG cassette. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_retrieve_and_generate_conformance.yaml |
Adds a RAG cassette. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_invoke_model_titan_embedding_conformance.yaml |
Adds an embedding cassette. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/cassettes/test_invoke_agent_conformance.yaml |
Adds an agent cassette. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/stream.py |
Adds Bedrock stream wrappers; unresolved lifecycle, buffering, close-error, abandonment, and UTF-8 handling findings remain. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/patch.py |
Patches sync/async APIs; unresolved embedding-body, error-telemetry, alias/version, and scope findings remain. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/extractors.py |
Adds telemetry extraction; alias/version mapping, retrieval typing, and function-schema normalization require correction. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/README.rst |
Documents expanded support; the documented scope does not match the PR description. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/pyproject.toml |
Updates dependency configuration. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/.changelog/736.added |
Documents inline-agent support. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/.changelog/733.added |
Documents RAG support. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/.changelog/723.added |
Documents agent and retrieval support. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/.changelog/722.added |
Documents embedding support. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/.changelog/721.added |
Documents async support. |
Review details
Suppressed comments (8)
instrumentation/opentelemetry-instrumentation-genai-bedrock/README.rst:19
- The PR description is limited to instrumenting
invoke_inline_agent, but these documented changes also add embeddings,invoke_agent, retrieval/RAG operations, async client support, abandoned-stream behavior, and unrelated llama-index requirements. Please split the unrelated work or update the PR scope/description before merging.
* Synchronous and asynchronous embeddings via the InvokeModel API (``client.invoke_model`` with embedding models such as Amazon Titan and Cohere)
* Synchronous and asynchronous remote agent invocation via the Bedrock Agent Runtime API (``client.invoke_agent``)
* Synchronous and asynchronous remote inline agent invocation via the Bedrock Agent Runtime API (``client.invoke_inline_agent``)
* Synchronous and asynchronous Knowledge Base retrieval via the Bedrock Agent Runtime API (``client.retrieve``)
* Synchronous and asynchronous Knowledge Base RetrieveAndGenerate via the Bedrock Agent Runtime API (``client.retrieve_and_generate``)
* Synchronous and asynchronous streaming Knowledge Base RetrieveAndGenerateStream via the Bedrock Agent Runtime API (``client.retrieve_and_generate_stream``)
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/extractors.py:951
- This repeats the incorrect mapping of Bedrock's alias ID to
gen_ai.agent.version. Sinceinvoke_agentdoes not expose the version selected by the alias, recording the alias here mislabels the semantic attribute; omit it unless the actual resolved version is available.
# version the alias resolved to. The alias is the closest available identifier of
# which agent revision served the request.
agent_alias_id = api_params.get("agentAliasId")
if agent_alias_id:
invocation.agent_version = str(agent_alias_id)
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/extractors.py:1243
- The retrieval extractor constructs the structured retrieval-document attribute as
list[dict[str, Any]]and stores it directly on the invocation. Structured GenAI attributes must use a util-genai model; add the shared retrieval-document type in util-genai first and populate that type here so the schema cannot drift.
docs: list[dict[str, Any]] = []
for item in results:
if not _is_dict(item):
continue
doc: dict[str, Any] = {}
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/extractors.py:1012
- Bedrock's
functionSchema.functions[].parametersis a name-to-ParameterDetailmap, whereasFunctionToolDefinition.parametersrepresents the JSON Schema object used bygen_ai.tool.definitions. Passing this map through emits an invalid shape such as{ "city": { "type": "string" } }instead of an object schema withproperties; normalize the map, including descriptions and required fields, before storing it.
tool_defs.append(
FunctionToolDefinition(
name=name,
description=desc,
parameters=params if _is_dict(params) else {},
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/patch.py:406
agentAliasIdis an alias identifier, not the resolved agent version; the comment explicitly says the API does not return that version. Assigning it toagent_versionemits a misleadinggen_ai.agent.versionattribute. Leave the version unset (or use a provider-specific alias attribute), and remove the duplicate assignment inextract_invoke_agent_request.
# InvokeAgent addresses an agent by alias rather than by version, and an alias
# resolves to a version server-side.
raw_alias_id = api_params.get("agentAliasId")
if raw_alias_id:
invocation.agent_version = str(raw_alias_id)
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/patch.py:207
- Reading the
StreamingBodyhere eagerly consumes the embedding response before the caller receives it. That adds I/O and latency and changes when body-read failures occur, violating the SDK's lazy return contract; use a lazy body wrapper and finalize when the caller consumes or closes it instead.
if hasattr(body_stream, "read"):
raw_bytes = body_stream.read()
response["body"] = StreamingBody(
io.BytesIO(raw_bytes), len(raw_bytes)
)
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/patch.py:731
- The PR title and description scope the change to
invoke_inline_agent, but this branch also adds embeddings, async clients,invoke_agent, retrieval, retrieve-and-generate, and a global stream finalizer. These are separate user-visible features with separate changelog fragments; split the work or update the PR scope and review description before merging.
if service_name not in (BEDROCK_RUNTIME, BEDROCK_AGENT_RUNTIME):
return wrapped(*args, **kwargs)
operation_name = args[0] if args else kwargs.get("operation_name")
raw_params = args[1] if len(args) > 1 else kwargs.get("api_params")
instrumentation/opentelemetry-instrumentation-genai-bedrock/src/opentelemetry/instrumentation/genai/bedrock/patch.py:215
- A failure while reading the synchronous embedding response body occurs after the only
tryblock has ended, so the exception is re-raised without callinginvocation.fail; the embedding span can remain unfinished and no error telemetry is recorded. Include body reading and extraction in the telemetry error boundary and re-raise the original exception.
raw_bytes = b""
body_stream = response.get("body")
if hasattr(body_stream, "read"):
raw_bytes = body_stream.read()
response["body"] = StreamingBody(
io.BytesIO(raw_bytes), len(raw_bytes)
)
extract_embedding_response(
response,
raw_bytes,
invocation,
)
invocation.stop()
return response
- Files reviewed: 5/5 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
60a5bc7 to
65c9b5c
Compare
- Instrument synchronous and asynchronous invoke_inline_agent operations - Extract model, instruction, input/output messages, agent name, session ID, guardrail ID, knowledge base ID, and tool definitions - Add comprehensive unit tests covering sync, async, content capture, and error cases - Update Bedrock README supported operations and add changelog fragment Assisted-by: Antigravity
Assisted-by: Antigravity
Assisted-by: Antigravity
65c9b5c to
1deba22
Compare
Description
Monkey patch
invoke_inline_agentmethods so they generate an invoke remote agent span (RemoteAgentInvocation).This API lets you create an agent on the fly which exists / retains conversation history for a specified number of seconds.
Type of change
Please delete options that are not relevant.
How has this been tested?
Unit tests
Checklist