diff --git a/litellm/proxy/db/db_spend_update_writer.py b/litellm/proxy/db/db_spend_update_writer.py index dc928921425..f233c7cfea0 100644 --- a/litellm/proxy/db/db_spend_update_writer.py +++ b/litellm/proxy/db/db_spend_update_writer.py @@ -1737,22 +1737,9 @@ async def add_spend_log_transaction_to_daily_agent_transaction( "agent_id is None for request. Skipping incrementing agent spend." ) return - payload_with_agent_id = cast( - SpendLogsPayload, - { - **payload, - "agent_id": payload["agent_id"], - }, - ) - base_daily_transaction = ( - await self._common_add_spend_log_transaction_to_daily_transaction( - payload_with_agent_id, prisma_client, "agent" - ) - ) - if base_daily_transaction is None: - return + endpoint_str = base_daily_transaction.get("endpoint") or "" - daily_transaction_key = f"{payload['agent_id']}_{base_daily_transaction['date']}_{payload_with_agent_id['api_key']}_{payload_with_agent_id['model']}_{payload_with_agent_id['custom_llm_provider']}_{endpoint_str}" + daily_transaction_key = f"{payload['agent_id']}_{base_daily_transaction['date']}_{payload['api_key']}_{payload['model']}_{payload['custom_llm_provider']}_{endpoint_str}" daily_transaction = DailyAgentSpendTransaction( agent_id=payload['agent_id'], **base_daily_transaction ) diff --git a/tests/test_litellm/proxy/db/test_db_spend_update_writer.py b/tests/test_litellm/proxy/db/test_db_spend_update_writer.py index 6ccecf59eed..42350d1e28e 100644 --- a/tests/test_litellm/proxy/db/test_db_spend_update_writer.py +++ b/tests/test_litellm/proxy/db/test_db_spend_update_writer.py @@ -790,6 +790,53 @@ async def test_add_spend_log_transaction_to_daily_agent_transaction_skips_when_a writer.daily_agent_spend_update_queue.add_update.assert_not_called() +@pytest.mark.asyncio +async def test_daily_agent_transaction_calls_common_helper_once(): + """ + Regression test for #21181: _common_add_spend_log_transaction_to_daily_transaction + should be called exactly once per request in the agent spend path, not twice. + """ + writer = DBSpendUpdateWriter() + mock_prisma = MagicMock() + mock_prisma.get_request_status = MagicMock(return_value="success") + + payload = { + "request_id": "req-dedup", + "agent_id": "agent-dedup", + "user": "test-user", + "startTime": "2024-01-01T12:00:00", + "api_key": "test-key", + "model": "gpt-4", + "custom_llm_provider": "openai", + "model_group": "gpt-4-group", + "prompt_tokens": 20, + "completion_tokens": 10, + "spend": 0.3, + "metadata": '{"usage_object": {}}', + } + + writer.daily_agent_spend_update_queue.add_update = AsyncMock() + + with patch.object( + writer, + "_common_add_spend_log_transaction_to_daily_transaction", + wraps=writer._common_add_spend_log_transaction_to_daily_transaction, + ) as mock_common: + await writer.add_spend_log_transaction_to_daily_agent_transaction( + payload=payload, + prisma_client=mock_prisma, + ) + + # The common helper should be called exactly once, not twice + assert mock_common.call_count == 1, ( + f"Expected _common_add_spend_log_transaction_to_daily_transaction to be " + f"called once, but it was called {mock_common.call_count} times" + ) + + # Verify the transaction was still queued correctly + writer.daily_agent_spend_update_queue.add_update.assert_called_once() + + @pytest.mark.asyncio async def test_endpoint_field_is_correctly_mapped_from_call_type(): """