Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ pip install agentops
```


#### Session replays in 2 lines of code
#### Trace replays in 2 lines of code

Initialize the AgentOps client and automatically get analytics on all your LLM calls.

Expand All @@ -97,10 +97,10 @@ agentops.init( < INSERT YOUR API KEY HERE >)
...

# End of program
agentops.end_session('Success')
agentops.end_trace('Success')
```

All your sessions can be viewed on the [AgentOps dashboard](https://app.agentops.ai?ref=gh)
All your traces can be viewed on the [AgentOps dashboard](https://app.agentops.ai?ref=gh)
<br/>

<details>
Expand All @@ -117,9 +117,9 @@ All your sessions can be viewed on the [AgentOps dashboard](https://app.agentops
</details>

<details>
<summary>Session Replays</summary>
<summary>Trace Replays</summary>
<a href="https://app.agentops.ai?ref=gh">
<img src="docs/images/external/app_screenshots/session-replay.png" style="width: 90%;" alt="Session Replays"/>
<img src="docs/images/external/app_screenshots/session-replay.png" style="width: 90%;" alt="Trace Replays"/>
</a>
</details>

Expand All @@ -140,12 +140,12 @@ Add powerful observability to your agents, tools, and functions with as little c
Refer to our [documentation](http://docs.agentops.ai)

```python
# Create a session span (root for all other spans)
from agentops.sdk.decorators import session
# Create a trace span (root for all other spans)
from agentops.sdk.decorators import trace

@session
@trace
def my_workflow():
# Your session code here
# Your trace code here
return result
```

Expand Down Expand Up @@ -183,7 +183,7 @@ def my_workflow(data):

```python
# Nest decorators for proper span hierarchy
from agentops.sdk.decorators import session, agent, operation
from agentops.sdk.decorators import trace, agent, operation

@agent
class MyAgent:
Expand All @@ -196,8 +196,8 @@ class MyAgent:
result = self.nested_operation("test message")
return result

@session
def my_session():
@trace
def my_trace():
agent = MyAgent()
return agent.main_operation()
```
Expand Down
15 changes: 8 additions & 7 deletions agentops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,22 @@
# Client global instance; one per process runtime
_client = Client()


def record(event):
"""
Legacy function to record an event. This is kept for backward compatibility.

In the current version, this simply sets the end_timestamp on the event.

Args:
event: The event to record
"""
from agentops.helpers.time import get_ISO_time

# TODO: Manual timestamp assignment is a temporary fix; should use proper event lifecycle
if event and hasattr(event, 'end_timestamp'):
if event and hasattr(event, "end_timestamp"):
event.end_timestamp = get_ISO_time()

return event


Expand Down Expand Up @@ -141,6 +142,7 @@ def configure(**kwargs):

_client.configure(**kwargs)


# For backwards compatibility and testing


Expand All @@ -149,8 +151,7 @@ def get_client() -> Client:
return _client



from agentops.legacy import * # type: ignore
from agentops.legacy import * # type: ignore

__all__ = [
"init",
Expand Down
3 changes: 1 addition & 2 deletions agentops/client/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
class TokenFetcher(Protocol):
"""Protocol for token fetching functions"""

def __call__(self, api_key: str) -> str:
...
def __call__(self, api_key: str) -> str: ...


class BaseApiClient:
Expand Down
18 changes: 9 additions & 9 deletions agentops/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from agentops.client.api import ApiClient
from agentops.config import Config
from agentops.exceptions import AgentOpsClientNotInitializedException, NoApiKeyException, NoSessionException
from agentops.exceptions import AgentOpsClientNotInitializedException, NoApiKeyException, NoTraceException
from agentops.instrumentation import instrument_all
from agentops.logging import logger
from agentops.logging.config import configure_logging, intercept_opentelemetry_logging
Expand Down Expand Up @@ -58,18 +58,18 @@ def init(self, **kwargs):

self.initialized = True

# Start a session if auto_start_session is True
session = None
if self.config.auto_start_session:
from agentops.legacy import start_session
# Start a trace if auto_start_trace is True
trace = None
if self.config.auto_start_trace:
from agentops.legacy import start_trace

# Pass default_tags if they exist
if self.config.default_tags:
session = start_session(tags=list(self.config.default_tags))
trace = start_trace(tags=list(self.config.default_tags))
else:
session = start_session()
return session
trace = start_trace()

return trace

def configure(self, **kwargs):
"""Update client configuration"""
Expand Down
36 changes: 18 additions & 18 deletions agentops/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ class ConfigDict(TypedDict):
max_queue_size: Optional[int]
default_tags: Optional[List[str]]
instrument_llm_calls: Optional[bool]
auto_start_session: Optional[bool]
auto_start_trace: Optional[bool]
auto_init: Optional[bool]
skip_auto_end_session: Optional[bool]
skip_auto_end_trace: Optional[bool]
env_data_opt_out: Optional[bool]
log_level: Optional[Union[str, int]]
fail_safe: Optional[bool]
Expand All @@ -49,7 +49,7 @@ class Config:
default_factory=lambda: get_env_int("AGENTOPS_MAX_WAIT_TIME", 5000),
metadata={"description": "Maximum time in milliseconds to wait for API responses"},
)

export_flush_interval: int = field(
default_factory=lambda: get_env_int("AGENTOPS_EXPORT_FLUSH_INTERVAL", 1000),
metadata={"description": "Time interval in milliseconds between automatic exports of telemetry data"},
Expand All @@ -70,19 +70,19 @@ class Config:
metadata={"description": "Whether to automatically instrument and track LLM API calls"},
)

auto_start_session: bool = field(
default_factory=lambda: get_env_bool("AGENTOPS_AUTO_START_SESSION", True),
metadata={"description": "Whether to automatically start a session when initializing"},
auto_start_trace: bool = field(
default_factory=lambda: get_env_bool("AGENTOPS_AUTO_START_TRACE", True),
metadata={"description": "Whether to automatically start a trace when initializing"},
)

auto_init: bool = field(
default_factory=lambda: get_env_bool("AGENTOPS_AUTO_INIT", True),
metadata={"description": "Whether to automatically initialize the client on import"},
)

skip_auto_end_session: bool = field(
default_factory=lambda: get_env_bool("AGENTOPS_SKIP_AUTO_END_SESSION", False),
metadata={"description": "Whether to skip automatically ending sessions on program exit"},
skip_auto_end_trace: bool = field(
default_factory=lambda: get_env_bool("AGENTOPS_SKIP_AUTO_END_TRACE", False),
metadata={"description": "Whether to skip automatically ending traces on program exit"},
)

env_data_opt_out: bool = field(
Expand Down Expand Up @@ -129,9 +129,9 @@ def configure(
max_queue_size: Optional[int] = None,
default_tags: Optional[List[str]] = None,
instrument_llm_calls: Optional[bool] = None,
auto_start_session: Optional[bool] = None,
auto_start_trace: Optional[bool] = None,
auto_init: Optional[bool] = None,
skip_auto_end_session: Optional[bool] = None,
skip_auto_end_trace: Optional[bool] = None,
env_data_opt_out: Optional[bool] = None,
log_level: Optional[Union[str, int]] = None,
fail_safe: Optional[bool] = None,
Expand All @@ -154,7 +154,7 @@ def configure(

if max_wait_time is not None:
self.max_wait_time = max_wait_time

if export_flush_interval is not None:
self.export_flush_interval = export_flush_interval

Expand All @@ -167,14 +167,14 @@ def configure(
if instrument_llm_calls is not None:
self.instrument_llm_calls = instrument_llm_calls

if auto_start_session is not None:
self.auto_start_session = auto_start_session
if auto_start_trace is not None:
self.auto_start_trace = auto_start_trace

if auto_init is not None:
self.auto_init = auto_init

if skip_auto_end_session is not None:
self.skip_auto_end_session = skip_auto_end_session
if skip_auto_end_trace is not None:
self.skip_auto_end_trace = skip_auto_end_trace

if env_data_opt_out is not None:
self.env_data_opt_out = env_data_opt_out
Expand Down Expand Up @@ -216,9 +216,9 @@ def dict(self):
"max_queue_size": self.max_queue_size,
"default_tags": self.default_tags,
"instrument_llm_calls": self.instrument_llm_calls,
"auto_start_session": self.auto_start_session,
"auto_start_trace": self.auto_start_trace,
"auto_init": self.auto_init,
"skip_auto_end_session": self.skip_auto_end_session,
"skip_auto_end_trace": self.skip_auto_end_trace,
"env_data_opt_out": self.env_data_opt_out,
"log_level": self.log_level,
"fail_safe": self.fail_safe,
Expand Down
14 changes: 14 additions & 0 deletions agentops/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
from agentops.logging import logger


class MultiTraceException(Exception):
def __init__(self, message):
super().__init__(message)


class NoTraceException(Exception):
def __init__(self, message="No trace found"):
super().__init__(message)


class MultiSessionException(Exception):
"""@deprecated Use MultiTraceException instead."""

def __init__(self, message):
super().__init__(message)


class NoSessionException(Exception):
"""@deprecated Use NoTraceException instead."""

def __init__(self, message="No session found"):
super().__init__(message)

Expand Down
1 change: 1 addition & 0 deletions agentops/helpers/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
def is_coroutine_or_generator(fn: Any) -> bool:
"""Check if a function is asynchronous (coroutine or async generator)"""
import inspect

return inspect.iscoroutinefunction(fn) or inspect.isasyncgenfunction(fn)
Loading
Loading