diff --git a/src/agents/tracing/processors.py b/src/agents/tracing/processors.py index 1b39deda..29eb0f58 100644 --- a/src/agents/tracing/processors.py +++ b/src/agents/tracing/processors.py @@ -5,6 +5,7 @@ import random import threading import time +from functools import cached_property from typing import Any import httpx @@ -50,9 +51,9 @@ def __init__( base_delay: Base delay (in seconds) for the first backoff. max_delay: Maximum delay (in seconds) for backoff growth. """ - self.api_key = api_key or os.environ.get("OPENAI_API_KEY") - self.organization = organization or os.environ.get("OPENAI_ORG_ID") - self.project = project or os.environ.get("OPENAI_PROJECT_ID") + self._api_key = api_key + self._organization = organization + self._project = project self.endpoint = endpoint self.max_retries = max_retries self.base_delay = base_delay @@ -68,8 +69,22 @@ def set_api_key(self, api_key: str): api_key: The OpenAI API key to use. This is the same key used by the OpenAI Python client. """ + # We're specifically setting the underlying cached property as well + self._api_key = api_key self.api_key = api_key + @cached_property + def api_key(self): + return self._api_key or os.environ.get("OPENAI_API_KEY") + + @cached_property + def organization(self): + return self._organization or os.environ.get("OPENAI_ORG_ID") + + @cached_property + def project(self): + return self._project or os.environ.get("OPENAI_PROJECT_ID") + def export(self, items: list[Trace | Span[Any]]) -> None: if not items: return diff --git a/tests/tracing/test_processor_api_key.py b/tests/tracing/test_processor_api_key.py new file mode 100644 index 00000000..b0a0218a --- /dev/null +++ b/tests/tracing/test_processor_api_key.py @@ -0,0 +1,27 @@ +import pytest + +from agents.tracing.processors import BackendSpanExporter + + +@pytest.mark.asyncio +async def test_processor_api_key(monkeypatch): + # If the API key is not set, it should be None + monkeypatch.delenv("OPENAI_API_KEY", None) + processor = BackendSpanExporter() + assert processor.api_key is None + + # If we set it afterwards, it should be the new value + processor.set_api_key("test_api_key") + assert processor.api_key == "test_api_key" + + +@pytest.mark.asyncio +async def test_processor_api_key_from_env(monkeypatch): + # If the API key is not set at creation time but set before access time, it should be the new + # value + monkeypatch.delenv("OPENAI_API_KEY", None) + processor = BackendSpanExporter() + + # If we set it afterwards, it should be the new value + monkeypatch.setenv("OPENAI_API_KEY", "foo_bar_123") + assert processor.api_key == "foo_bar_123"