Skip to content

[opentelemetry-instrumentation-genai-bedrock] Instrument invoke_inline_agent method - #736

Open
DylanRussell wants to merge 3 commits into
DylanRussell/more_bedrock_instrumentation_4from
DylanRussell/more_bedrock_instrumentation_5
Open

DylanRussell wants to merge 3 commits into
DylanRussell/more_bedrock_instrumentation_4from
DylanRussell/more_bedrock_instrumentation_5

Conversation

@DylanRussell

Copy link
Copy Markdown
Contributor

Description

Monkey patch invoke_inline_agent methods 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.

  • New feature (non-breaking change which adds functionality)

How has this been tested?

Unit tests

Checklist

  • Followed the style guidelines of this project
  • Changelog updated if the change requires an entry
  • Unit tests added
  • Documentation updated

Copilot AI lite review requested due to automatic review settings September 17, 2026 14:24
@DylanRussell
DylanRussell requested a review from a team as a code owner September 17, 2026 14:24
DylanRussell added a commit to DylanRussell/opentelemetry-python-genai that referenced this pull request Sep 17, 2026
@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Sep 17, 2026

Copy link
Copy Markdown

Pull request dashboard status

Waiting on reviewers · refreshed 2026-09-19 03:22 UTC

Review the latest changes.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

@DylanRussell
DylanRussell changed the base branch from main to DylanRussell/more_bedrock_instrumentation_4 September 17, 2026 14:26
@DylanRussell
DylanRussell added this pull request to stack #724 September 17, 2026 14:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 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. Since invoke_agent does 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[].parameters is a name-to-ParameterDetail map, whereas FunctionToolDefinition.parameters represents the JSON Schema object used by gen_ai.tool.definitions. Passing this map through emits an invalid shape such as { "city": { "type": "string" } } instead of an object schema with properties; 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

  • agentAliasId is an alias identifier, not the resolved agent version; the comment explicitly says the API does not return that version. Assigning it to agent_version emits a misleading gen_ai.agent.version attribute. Leave the version unset (or use a provider-specific alias attribute), and remove the duplicate assignment in extract_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 StreamingBody here 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 try block has ended, so the exception is re-raised without calling invocation.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.

lmolkova pushed a commit that referenced this pull request Sep 17, 2026
Assisted-by: Antigravity
@lmolkova
lmolkova force-pushed the DylanRussell/more_bedrock_instrumentation_5 branch from 60a5bc7 to 65c9b5c Compare September 17, 2026 20:42
- 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
@lmolkova
lmolkova force-pushed the DylanRussell/more_bedrock_instrumentation_5 branch from 65c9b5c to 1deba22 Compare September 19, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants