From 873015b2a94826ba609a78aad4d5ed10d612d0ee Mon Sep 17 00:00:00 2001 From: habema Date: Mon, 27 Oct 2025 15:02:50 +0300 Subject: [PATCH 1/6] add individual request usage tracking --- src/agents/usage.py | 66 +++++++++++++ tests/test_usage.py | 219 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 284 insertions(+), 1 deletion(-) diff --git a/src/agents/usage.py b/src/agents/usage.py index 3639cf944..ec959f26c 100644 --- a/src/agents/usage.py +++ b/src/agents/usage.py @@ -4,6 +4,30 @@ from pydantic.dataclasses import dataclass +@dataclass +class IndividualRequestUsage: + """Usage details for a single API request. + + This is useful for cost calculation when different pricing rates apply based on + per-request token counts (e.g., Anthropic's 200K token threshold pricing). + """ + + input_tokens: int + """Input tokens for this individual request.""" + + output_tokens: int + """Output tokens for this individual request.""" + + total_tokens: int + """Total tokens (input + output) for this individual request.""" + + input_tokens_details: InputTokensDetails + """Details about the input tokens for this individual request.""" + + output_tokens_details: OutputTokensDetails + """Details about the output tokens for this individual request.""" + + @dataclass class Usage: requests: int = 0 @@ -27,7 +51,34 @@ class Usage: total_tokens: int = 0 """Total tokens sent and received, across all requests.""" + individual_requests: list[IndividualRequestUsage] = field(default_factory=list) + """List of individual request usage details for accurate per-request cost calculation. + + This field preserves the token counts for each individual API request made during a run. + This is particularly useful for providers like Anthropic that have different pricing + tiers based on per-request token counts (e.g., different rates for requests with more + or fewer than 200K tokens). + + Each call to `add()` automatically creates an entry in this list if the added usage + represents a new request (i.e., has non-zero tokens). + + Example: + For a run that makes 3 API calls with 100K, 150K, and 80K input tokens each, + the aggregated `input_tokens` would be 330K, but `individual_requests` would + preserve the [100K, 150K, 80K] breakdown needed for accurate cost calculation. + """ + def add(self, other: "Usage") -> None: + """Add another Usage object to this one, aggregating all fields. + + This method automatically preserves individual request details for accurate + cost calculation. When adding a Usage object that represents a single request + (requests=1), it creates an IndividualRequestUsage entry to preserve the + per-request token breakdown. + + Args: + other: The Usage object to add to this one. + """ self.requests += other.requests if other.requests else 0 self.input_tokens += other.input_tokens if other.input_tokens else 0 self.output_tokens += other.output_tokens if other.output_tokens else 0 @@ -41,3 +92,18 @@ def add(self, other: "Usage") -> None: reasoning_tokens=self.output_tokens_details.reasoning_tokens + other.output_tokens_details.reasoning_tokens ) + + # Automatically preserve individual request details for accurate cost calculation. + # If the other Usage represents a single request with tokens, record it. + if other.requests == 1 and other.total_tokens > 0: + individual_usage = IndividualRequestUsage( + input_tokens=other.input_tokens, + output_tokens=other.output_tokens, + total_tokens=other.total_tokens, + input_tokens_details=other.input_tokens_details, + output_tokens_details=other.output_tokens_details, + ) + self.individual_requests.append(individual_usage) + elif other.individual_requests: + # If the other Usage already has individual request breakdowns, merge them. + self.individual_requests.extend(other.individual_requests) diff --git a/tests/test_usage.py b/tests/test_usage.py index 405f99ddf..213c55c3f 100644 --- a/tests/test_usage.py +++ b/tests/test_usage.py @@ -1,6 +1,6 @@ from openai.types.responses.response_usage import InputTokensDetails, OutputTokensDetails -from agents.usage import Usage +from agents.usage import IndividualRequestUsage, Usage def test_usage_add_aggregates_all_fields(): @@ -50,3 +50,220 @@ def test_usage_add_aggregates_with_none_values(): assert u1.total_tokens == 15 assert u1.input_tokens_details.cached_tokens == 4 assert u1.output_tokens_details.reasoning_tokens == 6 + + +def test_individual_request_usage_creation(): + """Test that IndividualRequestUsage is created correctly.""" + individual = IndividualRequestUsage( + input_tokens=100, + output_tokens=200, + total_tokens=300, + input_tokens_details=InputTokensDetails(cached_tokens=10), + output_tokens_details=OutputTokensDetails(reasoning_tokens=20), + ) + + assert individual.input_tokens == 100 + assert individual.output_tokens == 200 + assert individual.total_tokens == 300 + assert individual.input_tokens_details.cached_tokens == 10 + assert individual.output_tokens_details.reasoning_tokens == 20 + + +def test_usage_add_preserves_single_request(): + """Test that adding a single request Usage creates an IndividualRequestUsage entry.""" + u1 = Usage() + u2 = Usage( + requests=1, + input_tokens=100, + input_tokens_details=InputTokensDetails(cached_tokens=10), + output_tokens=200, + output_tokens_details=OutputTokensDetails(reasoning_tokens=20), + total_tokens=300, + ) + + u1.add(u2) + + # Should preserve the individual request details + assert len(u1.individual_requests) == 1 + individual = u1.individual_requests[0] + assert individual.input_tokens == 100 + assert individual.output_tokens == 200 + assert individual.total_tokens == 300 + assert individual.input_tokens_details.cached_tokens == 10 + assert individual.output_tokens_details.reasoning_tokens == 20 + + +def test_usage_add_ignores_zero_token_requests(): + """Test that zero-token requests don't create IndividualRequestUsage entries.""" + u1 = Usage() + u2 = Usage( + requests=1, + input_tokens=0, + input_tokens_details=InputTokensDetails(cached_tokens=0), + output_tokens=0, + output_tokens_details=OutputTokensDetails(reasoning_tokens=0), + total_tokens=0, + ) + + u1.add(u2) + + # Should not create an individual request entry for zero tokens + assert len(u1.individual_requests) == 0 + + +def test_usage_add_ignores_multi_request_usage(): + """Test that multi-request Usage objects don't create IndividualRequestUsage entries.""" + u1 = Usage() + u2 = Usage( + requests=3, # Multiple requests + input_tokens=100, + input_tokens_details=InputTokensDetails(cached_tokens=10), + output_tokens=200, + output_tokens_details=OutputTokensDetails(reasoning_tokens=20), + total_tokens=300, + ) + + u1.add(u2) + + # Should not create an individual request entry for multi-request usage + assert len(u1.individual_requests) == 0 + + +def test_usage_add_merges_existing_individual_requests(): + """Test that existing individual_requests are merged when adding Usage objects.""" + # Create first usage with individual requests + u1 = Usage() + u2 = Usage( + requests=1, + input_tokens=100, + input_tokens_details=InputTokensDetails(cached_tokens=10), + output_tokens=200, + output_tokens_details=OutputTokensDetails(reasoning_tokens=20), + total_tokens=300, + ) + u1.add(u2) + + # Create second usage with individual requests + u3 = Usage( + requests=1, + input_tokens=50, + input_tokens_details=InputTokensDetails(cached_tokens=5), + output_tokens=75, + output_tokens_details=OutputTokensDetails(reasoning_tokens=10), + total_tokens=125, + ) + + u1.add(u3) + + # Should have both individual requests + assert len(u1.individual_requests) == 2 + + # First request + first = u1.individual_requests[0] + assert first.input_tokens == 100 + assert first.output_tokens == 200 + assert first.total_tokens == 300 + + # Second request + second = u1.individual_requests[1] + assert second.input_tokens == 50 + assert second.output_tokens == 75 + assert second.total_tokens == 125 + + +def test_usage_add_with_pre_existing_individual_requests(): + """Test adding Usage objects that already have individual_requests.""" + u1 = Usage() + + # Create a usage with individual requests + u2 = Usage( + requests=1, + input_tokens=100, + input_tokens_details=InputTokensDetails(cached_tokens=10), + output_tokens=200, + output_tokens_details=OutputTokensDetails(reasoning_tokens=20), + total_tokens=300, + ) + u1.add(u2) + + # Create another usage with individual requests + u3 = Usage( + requests=1, + input_tokens=50, + input_tokens_details=InputTokensDetails(cached_tokens=5), + output_tokens=75, + output_tokens_details=OutputTokensDetails(reasoning_tokens=10), + total_tokens=125, + ) + + # Add u3 to u1 + u1.add(u3) + + # Should have both individual requests + assert len(u1.individual_requests) == 2 + assert u1.individual_requests[0].input_tokens == 100 + assert u1.individual_requests[1].input_tokens == 50 + + +def test_usage_individual_requests_default_empty(): + """Test that individual_requests defaults to an empty list.""" + u = Usage() + assert u.individual_requests == [] + + +def test_anthropic_cost_calculation_scenario(): + """Test a realistic scenario for Anthropic cost calculation with 200K token thresholds.""" + # Simulate 3 API calls: 100K, 150K, and 80K input tokens each + # None exceed 200K, so they should all use the lower pricing tier + + usage = Usage() + + # First request: 100K input tokens + req1 = Usage( + requests=1, + input_tokens=100_000, + input_tokens_details=InputTokensDetails(cached_tokens=0), + output_tokens=50_000, + output_tokens_details=OutputTokensDetails(reasoning_tokens=0), + total_tokens=150_000, + ) + usage.add(req1) + + # Second request: 150K input tokens + req2 = Usage( + requests=1, + input_tokens=150_000, + input_tokens_details=InputTokensDetails(cached_tokens=0), + output_tokens=75_000, + output_tokens_details=OutputTokensDetails(reasoning_tokens=0), + total_tokens=225_000, + ) + usage.add(req2) + + # Third request: 80K input tokens + req3 = Usage( + requests=1, + input_tokens=80_000, + input_tokens_details=InputTokensDetails(cached_tokens=0), + output_tokens=40_000, + output_tokens_details=OutputTokensDetails(reasoning_tokens=0), + total_tokens=120_000, + ) + usage.add(req3) + + # Verify aggregated totals + assert usage.requests == 3 + assert usage.input_tokens == 330_000 # 100K + 150K + 80K + assert usage.output_tokens == 165_000 # 50K + 75K + 40K + assert usage.total_tokens == 495_000 # 150K + 225K + 120K + + # Verify individual request preservation + assert len(usage.individual_requests) == 3 + assert usage.individual_requests[0].input_tokens == 100_000 + assert usage.individual_requests[1].input_tokens == 150_000 + assert usage.individual_requests[2].input_tokens == 80_000 + + # All individual requests are under 200K threshold + for req in usage.individual_requests: + assert req.input_tokens < 200_000 + assert req.output_tokens < 200_000 From 8618c602acbde0974d161060b75e3bf2a4e5dc59 Mon Sep 17 00:00:00 2001 From: habema Date: Mon, 27 Oct 2025 15:29:30 +0300 Subject: [PATCH 2/6] code review : rename IndividualRequestUsage to RequestUsage --- src/agents/usage.py | 16 +++---- tests/test_usage.py | 100 ++++++++++++++++++++++---------------------- 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/agents/usage.py b/src/agents/usage.py index ec959f26c..0d336abd2 100644 --- a/src/agents/usage.py +++ b/src/agents/usage.py @@ -5,7 +5,7 @@ @dataclass -class IndividualRequestUsage: +class RequestUsage: """Usage details for a single API request. This is useful for cost calculation when different pricing rates apply based on @@ -51,7 +51,7 @@ class Usage: total_tokens: int = 0 """Total tokens sent and received, across all requests.""" - individual_requests: list[IndividualRequestUsage] = field(default_factory=list) + request_usage_entries: list[RequestUsage] = field(default_factory=list) """List of individual request usage details for accurate per-request cost calculation. This field preserves the token counts for each individual API request made during a run. @@ -64,7 +64,7 @@ class Usage: Example: For a run that makes 3 API calls with 100K, 150K, and 80K input tokens each, - the aggregated `input_tokens` would be 330K, but `individual_requests` would + the aggregated `input_tokens` would be 330K, but `request_usage_entries` would preserve the [100K, 150K, 80K] breakdown needed for accurate cost calculation. """ @@ -73,7 +73,7 @@ def add(self, other: "Usage") -> None: This method automatically preserves individual request details for accurate cost calculation. When adding a Usage object that represents a single request - (requests=1), it creates an IndividualRequestUsage entry to preserve the + (requests=1), it creates an RequestUsage entry to preserve the per-request token breakdown. Args: @@ -96,14 +96,14 @@ def add(self, other: "Usage") -> None: # Automatically preserve individual request details for accurate cost calculation. # If the other Usage represents a single request with tokens, record it. if other.requests == 1 and other.total_tokens > 0: - individual_usage = IndividualRequestUsage( + individual_usage = RequestUsage( input_tokens=other.input_tokens, output_tokens=other.output_tokens, total_tokens=other.total_tokens, input_tokens_details=other.input_tokens_details, output_tokens_details=other.output_tokens_details, ) - self.individual_requests.append(individual_usage) - elif other.individual_requests: + self.request_usage_entries.append(individual_usage) + elif other.request_usage_entries: # If the other Usage already has individual request breakdowns, merge them. - self.individual_requests.extend(other.individual_requests) + self.request_usage_entries.extend(other.request_usage_entries) diff --git a/tests/test_usage.py b/tests/test_usage.py index 213c55c3f..e61cfeb49 100644 --- a/tests/test_usage.py +++ b/tests/test_usage.py @@ -1,6 +1,6 @@ from openai.types.responses.response_usage import InputTokensDetails, OutputTokensDetails -from agents.usage import IndividualRequestUsage, Usage +from agents.usage import RequestUsage, Usage def test_usage_add_aggregates_all_fields(): @@ -52,9 +52,9 @@ def test_usage_add_aggregates_with_none_values(): assert u1.output_tokens_details.reasoning_tokens == 6 -def test_individual_request_usage_creation(): - """Test that IndividualRequestUsage is created correctly.""" - individual = IndividualRequestUsage( +def test_request_usage_creation(): + """Test that RequestUsage is created correctly.""" + request_usage = RequestUsage( input_tokens=100, output_tokens=200, total_tokens=300, @@ -62,15 +62,15 @@ def test_individual_request_usage_creation(): output_tokens_details=OutputTokensDetails(reasoning_tokens=20), ) - assert individual.input_tokens == 100 - assert individual.output_tokens == 200 - assert individual.total_tokens == 300 - assert individual.input_tokens_details.cached_tokens == 10 - assert individual.output_tokens_details.reasoning_tokens == 20 + assert request_usage.input_tokens == 100 + assert request_usage.output_tokens == 200 + assert request_usage.total_tokens == 300 + assert request_usage.input_tokens_details.cached_tokens == 10 + assert request_usage.output_tokens_details.reasoning_tokens == 20 def test_usage_add_preserves_single_request(): - """Test that adding a single request Usage creates an IndividualRequestUsage entry.""" + """Test that adding a single request Usage creates an RequestUsage entry.""" u1 = Usage() u2 = Usage( requests=1, @@ -83,18 +83,18 @@ def test_usage_add_preserves_single_request(): u1.add(u2) - # Should preserve the individual request details - assert len(u1.individual_requests) == 1 - individual = u1.individual_requests[0] - assert individual.input_tokens == 100 - assert individual.output_tokens == 200 - assert individual.total_tokens == 300 - assert individual.input_tokens_details.cached_tokens == 10 - assert individual.output_tokens_details.reasoning_tokens == 20 + # Should preserve the request usage details + assert len(u1.request_usage_entries) == 1 + request_usage = u1.request_usage_entries[0] + assert request_usage.input_tokens == 100 + assert request_usage.output_tokens == 200 + assert request_usage.total_tokens == 300 + assert request_usage.input_tokens_details.cached_tokens == 10 + assert request_usage.output_tokens_details.reasoning_tokens == 20 def test_usage_add_ignores_zero_token_requests(): - """Test that zero-token requests don't create IndividualRequestUsage entries.""" + """Test that zero-token requests don't create request_usage_entries.""" u1 = Usage() u2 = Usage( requests=1, @@ -107,12 +107,12 @@ def test_usage_add_ignores_zero_token_requests(): u1.add(u2) - # Should not create an individual request entry for zero tokens - assert len(u1.individual_requests) == 0 + # Should not create a request_usage_entry for zero tokens + assert len(u1.request_usage_entries) == 0 def test_usage_add_ignores_multi_request_usage(): - """Test that multi-request Usage objects don't create IndividualRequestUsage entries.""" + """Test that multi-request Usage objects don't create request_usage_entries.""" u1 = Usage() u2 = Usage( requests=3, # Multiple requests @@ -125,13 +125,13 @@ def test_usage_add_ignores_multi_request_usage(): u1.add(u2) - # Should not create an individual request entry for multi-request usage - assert len(u1.individual_requests) == 0 + # Should not create a request usage entry for multi-request usage + assert len(u1.request_usage_entries) == 0 -def test_usage_add_merges_existing_individual_requests(): - """Test that existing individual_requests are merged when adding Usage objects.""" - # Create first usage with individual requests +def test_usage_add_merges_existing_request_usage_entries(): + """Test that existing request_usage_entries are merged when adding Usage objects.""" + # Create first usage with request_usage_entries u1 = Usage() u2 = Usage( requests=1, @@ -143,7 +143,7 @@ def test_usage_add_merges_existing_individual_requests(): ) u1.add(u2) - # Create second usage with individual requests + # Create second usage with request_usage_entries u3 = Usage( requests=1, input_tokens=50, @@ -155,27 +155,27 @@ def test_usage_add_merges_existing_individual_requests(): u1.add(u3) - # Should have both individual requests - assert len(u1.individual_requests) == 2 + # Should have both request_usage_entries + assert len(u1.request_usage_entries) == 2 # First request - first = u1.individual_requests[0] + first = u1.request_usage_entries[0] assert first.input_tokens == 100 assert first.output_tokens == 200 assert first.total_tokens == 300 # Second request - second = u1.individual_requests[1] + second = u1.request_usage_entries[1] assert second.input_tokens == 50 assert second.output_tokens == 75 assert second.total_tokens == 125 -def test_usage_add_with_pre_existing_individual_requests(): - """Test adding Usage objects that already have individual_requests.""" +def test_usage_add_with_pre_existing_request_usage_entries(): + """Test adding Usage objects that already have request_usage_entries.""" u1 = Usage() - # Create a usage with individual requests + # Create a usage with request_usage_entries u2 = Usage( requests=1, input_tokens=100, @@ -186,7 +186,7 @@ def test_usage_add_with_pre_existing_individual_requests(): ) u1.add(u2) - # Create another usage with individual requests + # Create another usage with request_usage_entries u3 = Usage( requests=1, input_tokens=50, @@ -199,16 +199,16 @@ def test_usage_add_with_pre_existing_individual_requests(): # Add u3 to u1 u1.add(u3) - # Should have both individual requests - assert len(u1.individual_requests) == 2 - assert u1.individual_requests[0].input_tokens == 100 - assert u1.individual_requests[1].input_tokens == 50 + # Should have both request_usage_entries + assert len(u1.request_usage_entries) == 2 + assert u1.request_usage_entries[0].input_tokens == 100 + assert u1.request_usage_entries[1].input_tokens == 50 -def test_usage_individual_requests_default_empty(): - """Test that individual_requests defaults to an empty list.""" +def test_usage_request_usage_entries_default_empty(): + """Test that request_usage_entries defaults to an empty list.""" u = Usage() - assert u.individual_requests == [] + assert u.request_usage_entries == [] def test_anthropic_cost_calculation_scenario(): @@ -257,13 +257,13 @@ def test_anthropic_cost_calculation_scenario(): assert usage.output_tokens == 165_000 # 50K + 75K + 40K assert usage.total_tokens == 495_000 # 150K + 225K + 120K - # Verify individual request preservation - assert len(usage.individual_requests) == 3 - assert usage.individual_requests[0].input_tokens == 100_000 - assert usage.individual_requests[1].input_tokens == 150_000 - assert usage.individual_requests[2].input_tokens == 80_000 + # Verify request_usage_entries preservation + assert len(usage.request_usage_entries) == 3 + assert usage.request_usage_entries[0].input_tokens == 100_000 + assert usage.request_usage_entries[1].input_tokens == 150_000 + assert usage.request_usage_entries[2].input_tokens == 80_000 - # All individual requests are under 200K threshold - for req in usage.individual_requests: + # All request_usage_entries are under 200K threshold + for req in usage.request_usage_entries: assert req.input_tokens < 200_000 assert req.output_tokens < 200_000 From 7e43c4b7b4215268838c04b409de3c97962300fd Mon Sep 17 00:00:00 2001 From: habema Date: Mon, 27 Oct 2025 15:31:25 +0300 Subject: [PATCH 3/6] format-check --- tests/test_usage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_usage.py b/tests/test_usage.py index e61cfeb49..2d53aa531 100644 --- a/tests/test_usage.py +++ b/tests/test_usage.py @@ -263,7 +263,7 @@ def test_anthropic_cost_calculation_scenario(): assert usage.request_usage_entries[1].input_tokens == 150_000 assert usage.request_usage_entries[2].input_tokens == 80_000 - # All request_usage_entries are under 200K threshold + # All request_usage_entries are under 200K threshold for req in usage.request_usage_entries: assert req.input_tokens < 200_000 assert req.output_tokens < 200_000 From d29875448b8773fdfe0cfda9a9ae962d81395556 Mon Sep 17 00:00:00 2001 From: habema Date: Tue, 28 Oct 2025 11:57:09 +0300 Subject: [PATCH 4/6] docstring cleanup --- src/agents/usage.py | 23 ++++++----------------- tests/test_usage.py | 2 +- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/agents/usage.py b/src/agents/usage.py index 0d336abd2..565255327 100644 --- a/src/agents/usage.py +++ b/src/agents/usage.py @@ -6,11 +6,7 @@ @dataclass class RequestUsage: - """Usage details for a single API request. - - This is useful for cost calculation when different pricing rates apply based on - per-request token counts (e.g., Anthropic's 200K token threshold pricing). - """ + """Usage details for a single API request.""" input_tokens: int """Input tokens for this individual request.""" @@ -52,12 +48,7 @@ class Usage: """Total tokens sent and received, across all requests.""" request_usage_entries: list[RequestUsage] = field(default_factory=list) - """List of individual request usage details for accurate per-request cost calculation. - - This field preserves the token counts for each individual API request made during a run. - This is particularly useful for providers like Anthropic that have different pricing - tiers based on per-request token counts (e.g., different rates for requests with more - or fewer than 200K tokens). + """List of RequestUsage entries for accurate per-request cost calculation. Each call to `add()` automatically creates an entry in this list if the added usage represents a new request (i.e., has non-zero tokens). @@ -65,16 +56,14 @@ class Usage: Example: For a run that makes 3 API calls with 100K, 150K, and 80K input tokens each, the aggregated `input_tokens` would be 330K, but `request_usage_entries` would - preserve the [100K, 150K, 80K] breakdown needed for accurate cost calculation. + preserve the [100K, 150K, 80K] breakdown, which could be helpful for detailed + cost calculation or context window management. """ def add(self, other: "Usage") -> None: """Add another Usage object to this one, aggregating all fields. - This method automatically preserves individual request details for accurate - cost calculation. When adding a Usage object that represents a single request - (requests=1), it creates an RequestUsage entry to preserve the - per-request token breakdown. + This method automatically preserves request_usage_entries. Args: other: The Usage object to add to this one. @@ -93,7 +82,7 @@ def add(self, other: "Usage") -> None: + other.output_tokens_details.reasoning_tokens ) - # Automatically preserve individual request details for accurate cost calculation. + # Automatically preserve request_usage_entries. # If the other Usage represents a single request with tokens, record it. if other.requests == 1 and other.total_tokens > 0: individual_usage = RequestUsage( diff --git a/tests/test_usage.py b/tests/test_usage.py index 2d53aa531..d0e674111 100644 --- a/tests/test_usage.py +++ b/tests/test_usage.py @@ -212,7 +212,7 @@ def test_usage_request_usage_entries_default_empty(): def test_anthropic_cost_calculation_scenario(): - """Test a realistic scenario for Anthropic cost calculation with 200K token thresholds.""" + """Test a realistic scenario for Sonnet 4.5 cost calculation with 200K token thresholds.""" # Simulate 3 API calls: 100K, 150K, and 80K input tokens each # None exceed 200K, so they should all use the lower pricing tier From 19d5fa095fd0addc20face83645d0454acfdd007 Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Fri, 31 Oct 2025 12:19:16 +0900 Subject: [PATCH 5/6] Apply suggestion from @seratch --- src/agents/usage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agents/usage.py b/src/agents/usage.py index 565255327..87c411893 100644 --- a/src/agents/usage.py +++ b/src/agents/usage.py @@ -85,7 +85,7 @@ def add(self, other: "Usage") -> None: # Automatically preserve request_usage_entries. # If the other Usage represents a single request with tokens, record it. if other.requests == 1 and other.total_tokens > 0: - individual_usage = RequestUsage( + request_usage = RequestUsage( input_tokens=other.input_tokens, output_tokens=other.output_tokens, total_tokens=other.total_tokens, From 0da2e5ea8951c7a42af92decbebb02620ae8fc8a Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Fri, 31 Oct 2025 12:19:22 +0900 Subject: [PATCH 6/6] Apply suggestion from @seratch --- src/agents/usage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agents/usage.py b/src/agents/usage.py index 87c411893..a2b41529e 100644 --- a/src/agents/usage.py +++ b/src/agents/usage.py @@ -92,7 +92,7 @@ def add(self, other: "Usage") -> None: input_tokens_details=other.input_tokens_details, output_tokens_details=other.output_tokens_details, ) - self.request_usage_entries.append(individual_usage) + self.request_usage_entries.append(request_usage) elif other.request_usage_entries: # If the other Usage already has individual request breakdowns, merge them. self.request_usage_entries.extend(other.request_usage_entries)