From ffae6863efeecd885a97388fa93ab44766b30b0a Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 1 Jul 2026 00:54:41 +0530 Subject: [PATCH 01/24] feat(langchain): add ChatAnthropic support to langchain instrumentation Adds ChatAnthropic to the list of supported chat models in the LangChain callback handler. Previously only ChatOpenAI and ChatBedrock were instrumented; Anthropic users received no spans. Changes: - Add ChatAnthropic to the allowlist in on_chat_model_start - Add 'model' param key for model name extraction (Anthropic uses 'model', not 'model_name' or 'model_id') - Add 'stop_sequences' fallback for stop param (Anthropic's param name) - Add 'max_tokens' fallback for max tokens param - Add langchain-anthropic to test requirements - Add ChatAnthropic fixture and VCR cassette test Fixes #139 --- .../genai/langchain/callback_handler.py | 5 +- ...chat_anthropic_claude_sonnet_llm_call.yaml | 46 +++++++++++++++++++ .../tests/conftest.py | 13 ++++++ .../tests/requirements.latest.txt | 7 ++- .../tests/test_llm_call.py | 20 ++++++++ 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_llm_call.yaml diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py index 1ef79105..5f26fe22 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py @@ -193,6 +193,7 @@ def on_chat_model_start( metadata: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> None: + if "invocation_params" in kwargs: params = ( kwargs["invocation_params"].get("params") @@ -206,6 +207,7 @@ def on_chat_model_start( for model_tag in ( "model_name", # ChatOpenAI / ChatAnthropic "model_id", # ChatBedrock + "model", # ChatGoogleGenerativeAI / ChatVertexAI / ChatGroq / ChatMistralAI / ChatCohere / ChatOllama / ChatDeepSeek / ChatXAI ): if (model := (params or {}).get(model_tag)) is not None: @@ -235,9 +237,10 @@ def on_chat_model_start( top_p = params.get("top_p") frequency_penalty = params.get("frequency_penalty") presence_penalty = params.get("presence_penalty") - stop_sequences = params.get("stop") + stop_sequences = params.get("stop") or params.get("stop_sequences") seed = params.get("seed") temperature = params.get("temperature") + # ``max_completion_tokens`` is OpenAI-specific; fall back to the # generic ``max_tokens`` used by Anthropic, Mistral, Cohere, etc. max_tokens = params.get("max_completion_tokens") or params.get( diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_llm_call.yaml b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_llm_call.yaml new file mode 100644 index 00000000..68f62393 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_llm_call.yaml @@ -0,0 +1,46 @@ +interactions: +- request: + body: |- + {"model": "claude-sonnet-4-5", "max_tokens": 1024, "temperature": 0.1, "system": "You are a helpful assistant!", "messages": [{"role": "user", "content": "What is the capital of France?"}]} + headers: + Content-Type: + - application/json + User-Agent: + - !!binary | + QW50aHJvcGljL1B5dGhvbiAxLjAuMA== + x-api-key: + - test_key + anthropic-version: + - '2023-06-01' + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: |- + { + "id": "msg_01XFDUDYJgAACzvnptvVoYEL", + "type": "message", + "role": "assistant", + "model": "claude-sonnet-4-5", + "content": [ + { + "type": "text", + "text": "The capital of France is Paris." + } + ], + "stop_reason": "end_turn", + "stop_sequence": null, + "usage": { + "input_tokens": 13, + "output_tokens": 10 + } + } + headers: + Content-Type: + - application/json + Date: + - Thu, 04 Sep 2025 20:00:58 GMT + status: + code: 200 + message: OK +version: 1 \ No newline at end of file diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/conftest.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/conftest.py index 93bf04a4..d2c4ce04 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/conftest.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/conftest.py @@ -7,6 +7,7 @@ import boto3 import pytest +from langchain_anthropic import ChatAnthropic from langchain_aws import ChatBedrock from langchain_google_genai import ChatGoogleGenerativeAI from langchain_openai import ChatOpenAI @@ -65,6 +66,18 @@ def fixture_us_amazon_nova_lite_v1_0(): yield llm +@pytest.fixture(scope="function", name="chat_anthropic_claude_sonnet") +def fixture_chat_anthropic_claude_sonnet(): + llm_model_value = "claude-sonnet-4-5" + llm = ChatAnthropic( + model=llm_model_value, + api_key="test_key", + temperature=0.1, + max_tokens=1024, + ) + yield llm + + @pytest.fixture(scope="function", name="gemini") def fixture_gemini(): llm_model_value = "gemini-2.5-pro" diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt index a23c0e71..a7527eff 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt @@ -18,7 +18,12 @@ langchain==1.3.14 langchain-openai==1.3.5 langchain-aws==1.6.2 langchain-google-genai==4.2.7 +<<<<<<< HEAD boto3==1.43.52 +======= +langchain-anthropic==1.4.8 +boto3==1.43.49 +>>>>>>> fe63f9b (feat(langchain): add ChatAnthropic support to langchain instrumentation) -e util/opentelemetry-util-genai --e instrumentation/opentelemetry-instrumentation-genai-langchain[instruments] +-e instrumentation/opentelemetry-instrumentation-genai-langchain[instruments] \ No newline at end of file diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index ebd585dc..6b161d8f 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -214,6 +214,26 @@ def test_us_amazon_nova_lite_v1_0_bedrock_llm_call( assert_bedrock_completion_attributes(spans[0], result) +@pytest.mark.vcr() +def test_chat_anthropic_claude_sonnet_llm_call( + span_exporter, start_instrumentation, chat_anthropic_claude_sonnet +): + messages = [ + SystemMessage(content="You are a helpful assistant!"), + HumanMessage(content="What is the capital of France?"), + ] + + result = chat_anthropic_claude_sonnet.invoke(messages) + + assert result.content.find("The capital of France is Paris") != -1 + + # verify spans + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + span = spans[0] + assert span.attributes.get("gen_ai.request.model") == "claude-sonnet-4-5" + + # span_exporter, start_instrumentation, gemini are coming from fixtures defined in conftest.py def test_gemini(span_exporter, start_instrumentation, gemini, vcr): messages = [ From ef5276347e6a1bed08b576e1920373d4d796d188 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 1 Jul 2026 00:59:58 +0530 Subject: [PATCH 02/24] changelog: add entry for ChatAnthropic langchain support --- .../.changelog/+139.added | 1 + 1 file changed, 1 insertion(+) create mode 100644 instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/+139.added diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/+139.added b/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/+139.added new file mode 100644 index 00000000..85b964f7 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/+139.added @@ -0,0 +1 @@ +Add ChatAnthropic support to LangChain instrumentation callback handler. \ No newline at end of file From b6ef07dc169d95ac567fce083eafbd56f215f7fb Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 1 Jul 2026 01:04:57 +0530 Subject: [PATCH 03/24] fix: address Copilot review comments --- .../genai/langchain/callback_handler.py | 11 +++++------ .../tests/test_llm_call.py | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py index 5f26fe22..de02667a 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py @@ -237,14 +237,13 @@ def on_chat_model_start( top_p = params.get("top_p") frequency_penalty = params.get("frequency_penalty") presence_penalty = params.get("presence_penalty") - stop_sequences = params.get("stop") or params.get("stop_sequences") + stop_sequences = params.get("stop") if params.get("stop") is not None else params.get("stop_sequences") seed = params.get("seed") temperature = params.get("temperature") - - # ``max_completion_tokens`` is OpenAI-specific; fall back to the - # generic ``max_tokens`` used by Anthropic, Mistral, Cohere, etc. - max_tokens = params.get("max_completion_tokens") or params.get( - "max_tokens" + max_tokens = ( + params.get("max_completion_tokens") + if params.get("max_completion_tokens") is not None + else params.get("max_tokens") ) provider = normalize_provider(metadata) or "unknown" diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index 6b161d8f..126eb9a6 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -231,7 +231,7 @@ def test_chat_anthropic_claude_sonnet_llm_call( spans = span_exporter.get_finished_spans() assert len(spans) == 1 span = spans[0] - assert span.attributes.get("gen_ai.request.model") == "claude-sonnet-4-5" + assert span.attributes.get(gen_ai_attributes.GEN_AI_REQUEST_MODEL) == "claude-sonnet-4-5" # span_exporter, start_instrumentation, gemini are coming from fixtures defined in conftest.py From d832e66593f596ecef26739768879a4e5554f06e Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 1 Jul 2026 01:06:50 +0530 Subject: [PATCH 04/24] fix: rename changelog fragment to match PR number --- .../.changelog/{+139.added => 188.added} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/{+139.added => 188.added} (100%) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/+139.added b/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/188.added similarity index 100% rename from instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/+139.added rename to instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/188.added From acd78dc0eb0c303b12a15388096b9264f29224ef Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 1 Jul 2026 01:12:41 +0530 Subject: [PATCH 05/24] fix: apply ruff formatting --- .../instrumentation/genai/langchain/callback_handler.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py index de02667a..61ec286c 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py @@ -194,6 +194,7 @@ def on_chat_model_start( **kwargs: Any, ) -> None: + if "invocation_params" in kwargs: params = ( kwargs["invocation_params"].get("params") @@ -237,7 +238,11 @@ def on_chat_model_start( top_p = params.get("top_p") frequency_penalty = params.get("frequency_penalty") presence_penalty = params.get("presence_penalty") - stop_sequences = params.get("stop") if params.get("stop") is not None else params.get("stop_sequences") + stop_sequences = ( + params.get("stop") + if params.get("stop") is not None + else params.get("stop_sequences") + ) seed = params.get("seed") temperature = params.get("temperature") max_tokens = ( From 173109000d46af47536b6273d48cee21e6a7aa88 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 1 Jul 2026 01:17:14 +0530 Subject: [PATCH 06/24] fix: apply ruff formatting to test_llm_call.py --- .../tests/test_llm_call.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index 126eb9a6..ffb16d6a 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -231,7 +231,10 @@ def test_chat_anthropic_claude_sonnet_llm_call( spans = span_exporter.get_finished_spans() assert len(spans) == 1 span = spans[0] - assert span.attributes.get(gen_ai_attributes.GEN_AI_REQUEST_MODEL) == "claude-sonnet-4-5" + assert ( + span.attributes.get(gen_ai_attributes.GEN_AI_REQUEST_MODEL) + == "claude-sonnet-4-5" + ) # span_exporter, start_instrumentation, gemini are coming from fixtures defined in conftest.py From b31a02f8db011c7b5184b6b6982a494ac1b8d3f4 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Mon, 6 Jul 2026 12:35:55 +0530 Subject: [PATCH 07/24] test(langchain): add VCR tool-calling test for ChatAnthropic --- ...hat_anthropic_claude_sonnet_tool_call.yaml | 73 +++++++++++++++++++ .../tests/test_llm_call.py | 34 +++++++++ 2 files changed, 107 insertions(+) create mode 100644 instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml new file mode 100644 index 00000000..3e0b916f --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml @@ -0,0 +1,73 @@ +interactions: +- request: + body: |- + { + "model": "claude-sonnet-4-5", + "max_tokens": 1024, + "temperature": 0.1, + "tools": [ + { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "input_schema": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. Boston, MA" + } + }, + "required": ["location"] + } + } + ], + "messages": [ + { + "role": "user", + "content": "What's the weather in Seattle?" + } + ] + } + headers: + Content-Type: + - application/json + x-api-key: + - test_key + anthropic-version: + - '2023-06-01' + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: |- + { + "id": "msg_anthropic_tool_call_001", + "type": "message", + "role": "assistant", + "model": "claude-sonnet-4-5", + "content": [ + { + "type": "tool_use", + "id": "toolu_01", + "name": "get_current_weather", + "input": { + "location": "Seattle, WA" + } + } + ], + "stop_reason": "tool_use", + "stop_sequence": null, + "usage": { + "input_tokens": 20, + "output_tokens": 15 + } + } + headers: + Content-Type: + - application/json + Date: + - Thu, 04 Sep 2025 20:00:58 GMT + status: + code: 200 + message: OK +version: 1 \ No newline at end of file diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index ffb16d6a..3694a45b 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -237,6 +237,40 @@ def test_chat_anthropic_claude_sonnet_llm_call( ) +@pytest.mark.vcr() +def test_chat_anthropic_claude_sonnet_tool_call( + span_exporter, start_instrumentation, chat_anthropic_claude_sonnet +): + from langchain_core.tools import tool + + @tool + def get_current_weather(location: str) -> str: + """Get the current weather in a given location.""" + return f"The weather in {location} is sunny." + + llm_with_tools = chat_anthropic_claude_sonnet.bind_tools( + [get_current_weather] + ) + + messages = [ + HumanMessage(content="What's the weather in Seattle?"), + ] + + llm_with_tools.invoke(messages) + + # verify spans + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + span = spans[0] + assert ( + span.attributes.get(gen_ai_attributes.GEN_AI_REQUEST_MODEL) + == "claude-sonnet-4-5" + ) + assert span.attributes.get( + gen_ai_attributes.GEN_AI_RESPONSE_FINISH_REASONS + ) == ("tool_calls",) + + # span_exporter, start_instrumentation, gemini are coming from fixtures defined in conftest.py def test_gemini(span_exporter, start_instrumentation, gemini, vcr): messages = [ From 324cc721ff49d78b6e8e1f2f5d278039feb2a308 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Mon, 6 Jul 2026 12:41:54 +0530 Subject: [PATCH 08/24] fix: move tool import to top-level --- .../tests/test_llm_call.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index 3694a45b..5df55cb4 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -10,6 +10,7 @@ HumanMessage, SystemMessage, ) +from langchain_core.tools import tool from openai import AuthenticationError from opentelemetry.instrumentation.genai.langchain.utils import ( @@ -241,7 +242,6 @@ def test_chat_anthropic_claude_sonnet_llm_call( def test_chat_anthropic_claude_sonnet_tool_call( span_exporter, start_instrumentation, chat_anthropic_claude_sonnet ): - from langchain_core.tools import tool @tool def get_current_weather(location: str) -> str: From b0ea4d1411b954777a2e2b51eedcc87a83b43919 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Tue, 7 Jul 2026 12:18:51 +0530 Subject: [PATCH 09/24] fix(langchain): correct stop_reason key lookup for Anthropic finish reason --- .../instrumentation/genai/langchain/callback_handler.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py index 61ec286c..5db166be 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py @@ -333,8 +333,9 @@ def on_llm_end( and chat_generation.message.response_metadata ): finish_reason = ( - chat_generation.message.response_metadata.get( - "stopReason", "unknown" + chat_generation.message.response_metadata.get("stopReason") + or chat_generation.message.response_metadata.get( + "stop_reason", "unknown" ) ) From f02c380f3555d2b95ab8a88b08b0db90c916b0d6 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Tue, 7 Jul 2026 12:24:03 +0530 Subject: [PATCH 10/24] fix(langchain): apply ruff formatting, align finish_reason assertion with tool_use convention --- .../instrumentation/genai/langchain/callback_handler.py | 4 +++- .../tests/test_llm_call.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py index 5db166be..cf2bbf72 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py @@ -333,7 +333,9 @@ def on_llm_end( and chat_generation.message.response_metadata ): finish_reason = ( - chat_generation.message.response_metadata.get("stopReason") + chat_generation.message.response_metadata.get( + "stopReason" + ) or chat_generation.message.response_metadata.get( "stop_reason", "unknown" ) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index 5df55cb4..0d2acc22 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -268,7 +268,7 @@ def get_current_weather(location: str) -> str: ) assert span.attributes.get( gen_ai_attributes.GEN_AI_RESPONSE_FINISH_REASONS - ) == ("tool_calls",) + ) == ("tool_use",) # span_exporter, start_instrumentation, gemini are coming from fixtures defined in conftest.py From ce861db1f9342d45f642342ba1669d1577220bc4 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Tue, 7 Jul 2026 12:30:17 +0530 Subject: [PATCH 11/24] style(langchain): remove blank line per ruff 0.14.1 formatting --- .../tests/test_llm_call.py | 1 - 1 file changed, 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index 0d2acc22..b6642218 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -242,7 +242,6 @@ def test_chat_anthropic_claude_sonnet_llm_call( def test_chat_anthropic_claude_sonnet_tool_call( span_exporter, start_instrumentation, chat_anthropic_claude_sonnet ): - @tool def get_current_weather(location: str) -> str: """Get the current weather in a given location.""" From 3083253fce90d28efe35cbc18c1b661c02eb7ac1 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Thu, 9 Jul 2026 15:24:09 +0530 Subject: [PATCH 12/24] style: remove leftover blank lines from conflict resolution --- .../instrumentation/genai/langchain/callback_handler.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py index cf2bbf72..55318abd 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py @@ -193,8 +193,6 @@ def on_chat_model_start( metadata: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> None: - - if "invocation_params" in kwargs: params = ( kwargs["invocation_params"].get("params") @@ -208,7 +206,6 @@ def on_chat_model_start( for model_tag in ( "model_name", # ChatOpenAI / ChatAnthropic "model_id", # ChatBedrock - "model", # ChatGoogleGenerativeAI / ChatVertexAI / ChatGroq / ChatMistralAI / ChatCohere / ChatOllama / ChatDeepSeek / ChatXAI ): if (model := (params or {}).get(model_tag)) is not None: From d3bf7e2f16866824151366ca3085e71912292ffc Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Sat, 11 Jul 2026 20:41:10 +0530 Subject: [PATCH 13/24] docs: clarify changelog entry per rads-1996's review --- .../.changelog/188.added | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/188.added b/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/188.added index 85b964f7..5e455cb3 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/188.added +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/188.added @@ -1 +1,2 @@ -Add ChatAnthropic support to LangChain instrumentation callback handler. \ No newline at end of file +Add ChatAnthropic tool-calling test coverage and fix finish_reason extraction for +Anthropic responses in LangChain instrumentation. \ No newline at end of file From 66e7bea8de1d90f2d303b37fed06ad6870c4efd6 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 15 Jul 2026 00:57:01 +0530 Subject: [PATCH 14/24] test(langchain): add coverage for stop_sequences fallback per review Adds a VCR-backed test exercising the else branch in the stop/stop_sequences fallback (params.get('stop') is None, params.get('stop_sequences') set), which was previously untested. Cassette is AI-synthesized pending re-record against the live API. Assisted-by: Claude Sonnet 5 --- ...claude_sonnet_stop_sequences_fallback.yaml | 55 +++++++++++++++++++ .../tests/test_llm_call.py | 18 ++++++ 2 files changed, 73 insertions(+) create mode 100644 instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_fallback.yaml diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_fallback.yaml b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_fallback.yaml new file mode 100644 index 00000000..62cf46c6 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_fallback.yaml @@ -0,0 +1,55 @@ +# TODO: this is generated by AI, re-record +interactions: +- request: + body: |- + { + "model": "claude-sonnet-4-5", + "max_tokens": 1024, + "temperature": 0.1, + "stop_sequences": ["STOP"], + "messages": [ + { + "role": "user", + "content": "Say hi" + } + ] + } + headers: + Content-Type: + - application/json + x-api-key: + - test_key + anthropic-version: + - '2023-06-01' + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: |- + { + "id": "msg_anthropic_stop_sequences_001", + "type": "message", + "role": "assistant", + "model": "claude-sonnet-4-5", + "content": [ + { + "type": "text", + "text": "Hi there!" + } + ], + "stop_reason": "stop_sequence", + "stop_sequence": "STOP", + "usage": { + "input_tokens": 10, + "output_tokens": 5 + } + } + headers: + Content-Type: + - application/json + Date: + - Thu, 04 Sep 2025 20:00:58 GMT + status: + code: 200 + message: OK +version: 1 \ No newline at end of file diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index b6642218..9994a0bd 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -761,3 +761,21 @@ def assert_log_parent(log_record, span): assert log_record.trace_id == span.get_span_context().trace_id assert log_record.span_id == span.get_span_context().span_id assert log_record.trace_flags == span.get_span_context().trace_flags + + +@pytest.mark.vcr() +def test_chat_anthropic_claude_sonnet_stop_sequences_fallback( + span_exporter, start_instrumentation, chat_anthropic_claude_sonnet +): + from langchain_core.messages import HumanMessage + + llm = chat_anthropic_claude_sonnet.bind(stop_sequences=["STOP"]) + llm.invoke([HumanMessage(content="Say hi")]) + + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + span = spans[0] + stop_sequences = span.attributes.get( + gen_ai_attributes.GEN_AI_REQUEST_STOP_SEQUENCES + ) + assert stop_sequences == ("STOP",) From 71dbde85f99197cd023b386038dca1d2cfa10e60 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 15 Jul 2026 01:18:26 +0530 Subject: [PATCH 15/24] docs(langchain): add AI-generated header to tool_call cassette per AGENTS.md The test_chat_anthropic_claude_sonnet_tool_call.yaml cassette was missing the required disclosure header for synthetic cassettes. --- .../cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml index 3e0b916f..a879897f 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml @@ -1,3 +1,4 @@ +# TODO: this is generated by AI, re-record interactions: - request: body: |- From 5603c51f2c844040732a2bcf65d2a8608bd871bf Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 15 Jul 2026 01:29:18 +0530 Subject: [PATCH 16/24] fix(langchain): add langchain-anthropic to conformance env deps The langchain-conformance tox env was missing langchain-anthropic, causing a ModuleNotFoundError once conftest.py imports ChatAnthropic unconditionally (surfaced after rebasing onto upstream/main). --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index ac839f6e..53ce2c77 100644 --- a/tox.ini +++ b/tox.ini @@ -146,6 +146,7 @@ deps = langchain-conformance: -e {toxinidir}/util/opentelemetry-util-genai langchain-conformance: -e {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-langchain[instruments] langchain-conformance: langchain-openai + langchain-conformance: langchain-anthropic langchain-conformance: langchain-aws langchain-conformance: langchain-google-genai langchain-conformance: boto3 From 13b625ad003ea5144b316125bce811f999c3368a Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 15 Jul 2026 13:49:32 +0530 Subject: [PATCH 17/24] fix(langchain): rebuild tool_call cassette to match real request body Upstream's rebase added body to the VCR match_on config, and the existing tool_call cassette was a hand-approximated recording that no longer matched the actual payload langchain-anthropic produces (max_tokens, temperature, and tool schema field order had drifted). Rebuilt the cassette body from the real payload captured via ChatAnthropic._get_request_payload() using the exact fixture params. Also removes a redundant inline import in the stop_sequences test flagged by ruff's PLC0415 (import already exists at module level). --- ...hat_anthropic_claude_sonnet_tool_call.yaml | 28 +------------------ .../tests/test_llm_call.py | 2 -- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml index a879897f..bffbe782 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_tool_call.yaml @@ -2,33 +2,7 @@ interactions: - request: body: |- - { - "model": "claude-sonnet-4-5", - "max_tokens": 1024, - "temperature": 0.1, - "tools": [ - { - "name": "get_current_weather", - "description": "Get the current weather in a given location", - "input_schema": { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "The city and state, e.g. Boston, MA" - } - }, - "required": ["location"] - } - } - ], - "messages": [ - { - "role": "user", - "content": "What's the weather in Seattle?" - } - ] - } + {"model":"claude-sonnet-4-5","max_tokens":1024,"messages":[{"role":"user","content":"What's the weather in Seattle?"}],"temperature":0.1,"tools":[{"name":"get_current_weather","input_schema":{"properties":{"location":{"type":"string"}},"required":["location"],"type":"object"},"description":"Get the current weather in a given location."}]} headers: Content-Type: - application/json diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index 9994a0bd..b92cd793 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -767,8 +767,6 @@ def assert_log_parent(log_record, span): def test_chat_anthropic_claude_sonnet_stop_sequences_fallback( span_exporter, start_instrumentation, chat_anthropic_claude_sonnet ): - from langchain_core.messages import HumanMessage - llm = chat_anthropic_claude_sonnet.bind(stop_sequences=["STOP"]) llm.invoke([HumanMessage(content="Say hi")]) From 46c311a518d4e07deb172352b70570cb7421563f Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 15 Jul 2026 14:17:06 +0530 Subject: [PATCH 18/24] fix(langchain): pin langchain-anthropic in oldest test requirements The oldest tox env was missing langchain-anthropic entirely, causing the same ModuleNotFoundError seen earlier in the conformance env. Pinned to 0.3.0, matching the era of the other oldest-supported provider pins (langchain-openai==0.2.0, langchain-google-genai==2.0.0) and requiring langchain-core>=0.3.0, compatible with this package's own langchain>=0.3.21 floor. --- .../tests/requirements.oldest.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.oldest.txt b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.oldest.txt index 7b1e5347..5fcdee5b 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.oldest.txt +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.oldest.txt @@ -23,4 +23,5 @@ langchain-openai==0.2.0 langchain-aws==0.2.2 langchain-google-genai==2.0.0 -boto3==1.37.0 +langchain-anthropic==0.3.0 +boto3==1.37.0 \ No newline at end of file From 1e7c6cf94607ae69ab457e43c8c856cc2d88bf51 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Thu, 16 Jul 2026 00:47:18 +0530 Subject: [PATCH 19/24] fix(langchain): add serialized.kwargs fallback for constructor-level stop_sequences Per eternalcuriouslearner's suggestion: when stop_sequences is passed at ChatAnthropic construction time rather than via bind() or invoke(), it only appears in serialized['kwargs'], never in invocation_params. Confirmed via debug prints (removed before commit) that the current two-level fallback (params.get('stop') / params.get('stop_sequences')) silently misses this case. Added a third fallback checking serialized.get('kwargs', {}).get('stop_sequences'), with a new VCR test covering the constructor-time path specifically. --- .../genai/langchain/callback_handler.py | 12 ++--- ...t_stop_sequences_constructor_fallback.yaml | 44 +++++++++++++++++++ .../tests/test_llm_call.py | 21 +++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_constructor_fallback.yaml diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py index 55318abd..9cf664d4 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py @@ -235,11 +235,13 @@ def on_chat_model_start( top_p = params.get("top_p") frequency_penalty = params.get("frequency_penalty") presence_penalty = params.get("presence_penalty") - stop_sequences = ( - params.get("stop") - if params.get("stop") is not None - else params.get("stop_sequences") - ) + stop_sequences = params.get("stop") + if stop_sequences is None: + stop_sequences = params.get("stop_sequences") + if stop_sequences is None: + stop_sequences = (serialized.get("kwargs") or {}).get( + "stop_sequences" + ) seed = params.get("seed") temperature = params.get("temperature") max_tokens = ( diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_constructor_fallback.yaml b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_constructor_fallback.yaml new file mode 100644 index 00000000..5792bc91 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_constructor_fallback.yaml @@ -0,0 +1,44 @@ +# TODO: this is generated by AI, re-record +interactions: +- request: + body: |- + {"max_tokens":64000,"messages":[{"role":"user","content":"Say hi"}],"model":"claude-sonnet-4-5","stop_sequences":["STOP"]} + headers: + Content-Type: + - application/json + x-api-key: + - test_key + anthropic-version: + - '2023-06-01' + method: POST + uri: https://api.anthropic.com/v1/messages + response: + body: + string: |- + { + "id": "msg_anthropic_constructor_stop_sequences_001", + "type": "message", + "role": "assistant", + "model": "claude-sonnet-4-5", + "content": [ + { + "type": "text", + "text": "Hi there!" + } + ], + "stop_reason": "stop_sequence", + "stop_sequence": "STOP", + "usage": { + "input_tokens": 10, + "output_tokens": 5 + } + } + headers: + Content-Type: + - application/json + Date: + - Thu, 04 Sep 2025 20:00:58 GMT + status: + code: 200 + message: OK +version: 1 \ No newline at end of file diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index b92cd793..415e6ae1 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -5,6 +5,7 @@ from typing import Optional import pytest +from langchain_anthropic import ChatAnthropic from langchain_core.messages import ( FunctionMessage, HumanMessage, @@ -777,3 +778,23 @@ def test_chat_anthropic_claude_sonnet_stop_sequences_fallback( gen_ai_attributes.GEN_AI_REQUEST_STOP_SEQUENCES ) assert stop_sequences == ("STOP",) + + +@pytest.mark.vcr() +def test_chat_anthropic_claude_sonnet_stop_sequences_constructor_fallback( + span_exporter, start_instrumentation +): + model = ChatAnthropic( + model="claude-sonnet-4-5", + api_key="test_key", + stop_sequences=["STOP"], + ) + model.invoke([HumanMessage(content="Say hi")]) + + spans = span_exporter.get_finished_spans() + assert len(spans) == 1 + span = spans[0] + stop_sequences = span.attributes.get( + gen_ai_attributes.GEN_AI_REQUEST_STOP_SEQUENCES + ) + assert stop_sequences == ("STOP",) From 216acf7f93aa5c08bfd06ca733205faae7da7034 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Thu, 16 Jul 2026 01:07:58 +0530 Subject: [PATCH 20/24] fix(langchain): pin max_tokens for cross-version cassette compatibility, fix typecheck Explicitly pins max_tokens=1024 in the constructor-fallback test so the request body is identical across langchain-anthropic versions (the library's own default changed between the oldest-pinned 0.3.0 and latest, causing a VCR body-match failure on the oldest env). Also fixes a pyright reportUnknownVariableType/reportUnknownMemberType error by giving serialized_kwargs an explicit dict[str, Any] annotation. --- .../instrumentation/genai/langchain/callback_handler.py | 5 +++-- ...ic_claude_sonnet_stop_sequences_constructor_fallback.yaml | 2 +- .../tests/test_llm_call.py | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py index 9cf664d4..646b6faa 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py @@ -239,9 +239,10 @@ def on_chat_model_start( if stop_sequences is None: stop_sequences = params.get("stop_sequences") if stop_sequences is None: - stop_sequences = (serialized.get("kwargs") or {}).get( - "stop_sequences" + serialized_kwargs: dict[str, Any] = ( + serialized.get("kwargs") or {} ) + stop_sequences = serialized_kwargs.get("stop_sequences") seed = params.get("seed") temperature = params.get("temperature") max_tokens = ( diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_constructor_fallback.yaml b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_constructor_fallback.yaml index 5792bc91..97cfe6b8 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_constructor_fallback.yaml +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/cassettes/test_chat_anthropic_claude_sonnet_stop_sequences_constructor_fallback.yaml @@ -2,7 +2,7 @@ interactions: - request: body: |- - {"max_tokens":64000,"messages":[{"role":"user","content":"Say hi"}],"model":"claude-sonnet-4-5","stop_sequences":["STOP"]} + {"max_tokens":1024,"messages":[{"role":"user","content":"Say hi"}],"model":"claude-sonnet-4-5","stop_sequences":["STOP"]} headers: Content-Type: - application/json diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index 415e6ae1..4a09b8fb 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -787,6 +787,7 @@ def test_chat_anthropic_claude_sonnet_stop_sequences_constructor_fallback( model = ChatAnthropic( model="claude-sonnet-4-5", api_key="test_key", + max_tokens=1024, stop_sequences=["STOP"], ) model.invoke([HumanMessage(content="Say hi")]) From 8ddf5144161b33138c5e5ead381a3b0cfa3afd53 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 22 Jul 2026 01:05:46 +0530 Subject: [PATCH 21/24] fix: remove leftover merge conflict markers in requirements.latest.txt --- .../tests/requirements.latest.txt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt index a7527eff..a0da1a27 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt @@ -18,12 +18,6 @@ langchain==1.3.14 langchain-openai==1.3.5 langchain-aws==1.6.2 langchain-google-genai==4.2.7 -<<<<<<< HEAD -boto3==1.43.52 - -======= langchain-anthropic==1.4.8 -boto3==1.43.49 ->>>>>>> fe63f9b (feat(langchain): add ChatAnthropic support to langchain instrumentation) --e util/opentelemetry-util-genai +boto3==1.43.52 -e instrumentation/opentelemetry-instrumentation-genai-langchain[instruments] \ No newline at end of file From 17232807b69cdf0e9873b297b207fb828168c0a0 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 22 Jul 2026 10:08:37 +0530 Subject: [PATCH 22/24] fix: resolve conflict markers in requirements.latest.txt, sync boto3/util-genai with main --- .../tests/requirements.latest.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt index a0da1a27..7a3eb751 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/requirements.latest.txt @@ -19,5 +19,6 @@ langchain-openai==1.3.5 langchain-aws==1.6.2 langchain-google-genai==4.2.7 langchain-anthropic==1.4.8 -boto3==1.43.52 +boto3==1.43.53 +-e util/opentelemetry-util-genai -e instrumentation/opentelemetry-instrumentation-genai-langchain[instruments] \ No newline at end of file From e364186a469bce22fb94f2d5d3f4505537fa1b03 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 21 Jul 2026 23:01:18 -0700 Subject: [PATCH 23/24] Apply suggestions from code review Co-authored-by: Liudmila Molkova --- .../tests/test_llm_call.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index 4a09b8fb..5f4836d7 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -238,6 +238,11 @@ def test_chat_anthropic_claude_sonnet_llm_call( == "claude-sonnet-4-5" ) + assert ( + span.attributes.get(gen_ai_attributes.GEN_AI_REQUEST_MAX_TOKENS) + == 1024 + ) + @pytest.mark.vcr() def test_chat_anthropic_claude_sonnet_tool_call( From febe547b2853be3018a64a669297e8998bae2514 Mon Sep 17 00:00:00 2001 From: bhumikadangayach Date: Wed, 22 Jul 2026 11:39:22 +0530 Subject: [PATCH 24/24] fix: remove trailing whitespace from test_llm_call.py --- .../tests/test_llm_call.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py index 5f4836d7..1519aec8 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py +++ b/instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py @@ -241,7 +241,7 @@ def test_chat_anthropic_claude_sonnet_llm_call( assert ( span.attributes.get(gen_ai_attributes.GEN_AI_REQUEST_MAX_TOKENS) == 1024 - ) + ) @pytest.mark.vcr()