agnt5 0.2.8a10__cp310-abi3-manylinux_2_34_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of agnt5 might be problematic. Click here for more details.
- agnt5/__init__.py +91 -0
- agnt5/_compat.py +16 -0
- agnt5/_core.abi3.so +0 -0
- agnt5/_retry_utils.py +169 -0
- agnt5/_schema_utils.py +312 -0
- agnt5/_telemetry.py +182 -0
- agnt5/agent.py +1685 -0
- agnt5/client.py +741 -0
- agnt5/context.py +178 -0
- agnt5/entity.py +795 -0
- agnt5/exceptions.py +102 -0
- agnt5/function.py +321 -0
- agnt5/lm.py +813 -0
- agnt5/tool.py +648 -0
- agnt5/tracing.py +196 -0
- agnt5/types.py +110 -0
- agnt5/version.py +19 -0
- agnt5/worker.py +1619 -0
- agnt5/workflow.py +1048 -0
- agnt5-0.2.8a10.dist-info/METADATA +25 -0
- agnt5-0.2.8a10.dist-info/RECORD +22 -0
- agnt5-0.2.8a10.dist-info/WHEEL +4 -0
agnt5/tracing.py
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""
|
|
2
|
+
User-facing tracing API for AGNT5 SDK.
|
|
3
|
+
|
|
4
|
+
Provides decorators and context managers for instrumenting Python code with
|
|
5
|
+
OpenTelemetry spans. All spans are created via Rust FFI and exported through
|
|
6
|
+
the centralized Rust OpenTelemetry system.
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
```python
|
|
10
|
+
from agnt5.tracing import span
|
|
11
|
+
|
|
12
|
+
@span("my_operation")
|
|
13
|
+
async def my_function(ctx, data):
|
|
14
|
+
# Your code here
|
|
15
|
+
return result
|
|
16
|
+
|
|
17
|
+
# Or use context manager
|
|
18
|
+
from agnt5.tracing import span_context
|
|
19
|
+
|
|
20
|
+
async def process():
|
|
21
|
+
with span_context("processing", user_id="123") as s:
|
|
22
|
+
data = await fetch_data()
|
|
23
|
+
s.set_attribute("records", str(len(data)))
|
|
24
|
+
return data
|
|
25
|
+
```
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
import functools
|
|
29
|
+
import inspect
|
|
30
|
+
from contextlib import contextmanager
|
|
31
|
+
from typing import Any, Callable, Dict, Optional
|
|
32
|
+
|
|
33
|
+
from ._core import create_span as _create_span
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def span(
|
|
37
|
+
name: Optional[str] = None,
|
|
38
|
+
component_type: str = "function",
|
|
39
|
+
runtime_context: Optional[Any] = None,
|
|
40
|
+
**attributes: str
|
|
41
|
+
):
|
|
42
|
+
"""
|
|
43
|
+
Decorator to automatically create spans for functions.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
name: Span name (defaults to function name)
|
|
47
|
+
component_type: Component type (default: "function")
|
|
48
|
+
runtime_context: Optional RuntimeContext for trace linking
|
|
49
|
+
**attributes: Additional span attributes
|
|
50
|
+
|
|
51
|
+
Example:
|
|
52
|
+
```python
|
|
53
|
+
@span("fetch_user_data", user_type="premium")
|
|
54
|
+
async def fetch_user(user_id: str):
|
|
55
|
+
return await db.get_user(user_id)
|
|
56
|
+
```
|
|
57
|
+
"""
|
|
58
|
+
def decorator(func: Callable) -> Callable:
|
|
59
|
+
span_name = name or func.__name__
|
|
60
|
+
|
|
61
|
+
if inspect.iscoroutinefunction(func):
|
|
62
|
+
@functools.wraps(func)
|
|
63
|
+
async def async_wrapper(*args, **kwargs):
|
|
64
|
+
# Try to extract runtime_context from first arg if it's a Context
|
|
65
|
+
ctx = runtime_context
|
|
66
|
+
if ctx is None and args:
|
|
67
|
+
from .context import Context
|
|
68
|
+
if isinstance(args[0], Context):
|
|
69
|
+
ctx = args[0]._runtime_context
|
|
70
|
+
|
|
71
|
+
with _create_span(span_name, component_type, ctx, attributes) as s:
|
|
72
|
+
try:
|
|
73
|
+
result = await func(*args, **kwargs)
|
|
74
|
+
# Span automatically marked as OK on success
|
|
75
|
+
return result
|
|
76
|
+
except Exception as e:
|
|
77
|
+
# Exception automatically recorded by PySpan.__exit__
|
|
78
|
+
raise
|
|
79
|
+
return async_wrapper
|
|
80
|
+
else:
|
|
81
|
+
@functools.wraps(func)
|
|
82
|
+
def sync_wrapper(*args, **kwargs):
|
|
83
|
+
# Try to extract runtime_context from first arg if it's a Context
|
|
84
|
+
ctx = runtime_context
|
|
85
|
+
if ctx is None and args:
|
|
86
|
+
from .context import Context
|
|
87
|
+
if isinstance(args[0], Context):
|
|
88
|
+
ctx = args[0]._runtime_context
|
|
89
|
+
|
|
90
|
+
with _create_span(span_name, component_type, ctx, attributes) as s:
|
|
91
|
+
try:
|
|
92
|
+
result = func(*args, **kwargs)
|
|
93
|
+
return result
|
|
94
|
+
except Exception as e:
|
|
95
|
+
raise
|
|
96
|
+
return sync_wrapper
|
|
97
|
+
|
|
98
|
+
return decorator
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@contextmanager
|
|
102
|
+
def span_context(
|
|
103
|
+
name: str,
|
|
104
|
+
component_type: str = "operation",
|
|
105
|
+
runtime_context: Optional[Any] = None,
|
|
106
|
+
**attributes: str
|
|
107
|
+
):
|
|
108
|
+
"""
|
|
109
|
+
Context manager for creating spans around code blocks.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
name: Span name
|
|
113
|
+
component_type: Component type (default: "operation")
|
|
114
|
+
runtime_context: Optional RuntimeContext for trace linking
|
|
115
|
+
**attributes: Span attributes
|
|
116
|
+
|
|
117
|
+
Yields:
|
|
118
|
+
PySpan object with set_attribute() and record_exception() methods
|
|
119
|
+
|
|
120
|
+
Example:
|
|
121
|
+
```python
|
|
122
|
+
with span_context("db_query", runtime_context=ctx._runtime_context, table="users") as s:
|
|
123
|
+
results = query_database()
|
|
124
|
+
s.set_attribute("result_count", str(len(results)))
|
|
125
|
+
```
|
|
126
|
+
"""
|
|
127
|
+
s = _create_span(name, component_type, runtime_context, attributes)
|
|
128
|
+
try:
|
|
129
|
+
yield s
|
|
130
|
+
# Context manager automatically calls s.__exit__ which sets status
|
|
131
|
+
except Exception as e:
|
|
132
|
+
# Exception will be recorded by __exit__
|
|
133
|
+
raise
|
|
134
|
+
finally:
|
|
135
|
+
# PySpan's __exit__ is called automatically when context ends
|
|
136
|
+
pass
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def create_task_span(name: str, runtime_context: Optional[Any] = None, **attributes: str):
|
|
140
|
+
"""
|
|
141
|
+
Create a span for task execution.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
name: Task name
|
|
145
|
+
runtime_context: Optional RuntimeContext for trace linking
|
|
146
|
+
**attributes: Task attributes
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
PySpan object to use as context manager
|
|
150
|
+
|
|
151
|
+
Example:
|
|
152
|
+
```python
|
|
153
|
+
with create_task_span("process_data", runtime_context=ctx._runtime_context, batch_size="100") as s:
|
|
154
|
+
result = await process()
|
|
155
|
+
```
|
|
156
|
+
"""
|
|
157
|
+
return _create_span(name, "task", runtime_context, attributes)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def create_workflow_span(name: str, runtime_context: Optional[Any] = None, **attributes: str):
|
|
161
|
+
"""
|
|
162
|
+
Create a span for workflow execution.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
name: Workflow name
|
|
166
|
+
runtime_context: Optional RuntimeContext for trace linking
|
|
167
|
+
**attributes: Workflow attributes
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
PySpan object to use as context manager
|
|
171
|
+
"""
|
|
172
|
+
return _create_span(name, "workflow", runtime_context, attributes)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def create_agent_span(name: str, runtime_context: Optional[Any] = None, **attributes: str):
|
|
176
|
+
"""
|
|
177
|
+
Create a span for agent execution.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
name: Agent name
|
|
181
|
+
runtime_context: Optional RuntimeContext for trace linking
|
|
182
|
+
**attributes: Agent attributes
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
PySpan object to use as context manager
|
|
186
|
+
"""
|
|
187
|
+
return _create_span(name, "agent", runtime_context, attributes)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
__all__ = [
|
|
191
|
+
"span",
|
|
192
|
+
"span_context",
|
|
193
|
+
"create_task_span",
|
|
194
|
+
"create_workflow_span",
|
|
195
|
+
"create_agent_span",
|
|
196
|
+
]
|
agnt5/types.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Type definitions and protocols for AGNT5 SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional, Protocol, TypeVar, Union
|
|
8
|
+
|
|
9
|
+
# Type aliases
|
|
10
|
+
JSON = Union[Dict[str, Any], List[Any], str, int, float, bool, None]
|
|
11
|
+
HandlerFunc = Callable[..., Awaitable[Any]]
|
|
12
|
+
|
|
13
|
+
T = TypeVar("T")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BackoffType(str, Enum):
|
|
17
|
+
"""Backoff strategy for retry policies."""
|
|
18
|
+
|
|
19
|
+
CONSTANT = "constant"
|
|
20
|
+
LINEAR = "linear"
|
|
21
|
+
EXPONENTIAL = "exponential"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class RetryPolicy:
|
|
26
|
+
"""Configuration for function retry behavior."""
|
|
27
|
+
|
|
28
|
+
max_attempts: int = 3
|
|
29
|
+
initial_interval_ms: int = 1000
|
|
30
|
+
max_interval_ms: int = 60000
|
|
31
|
+
|
|
32
|
+
def __post_init__(self) -> None:
|
|
33
|
+
if self.max_attempts < 1:
|
|
34
|
+
raise ValueError("max_attempts must be at least 1")
|
|
35
|
+
if self.initial_interval_ms < 0:
|
|
36
|
+
raise ValueError("initial_interval_ms must be non-negative")
|
|
37
|
+
if self.max_interval_ms < self.initial_interval_ms:
|
|
38
|
+
raise ValueError("max_interval_ms must be >= initial_interval_ms")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class BackoffPolicy:
|
|
43
|
+
"""Configuration for retry backoff strategy."""
|
|
44
|
+
|
|
45
|
+
type: BackoffType = BackoffType.EXPONENTIAL
|
|
46
|
+
multiplier: float = 2.0
|
|
47
|
+
|
|
48
|
+
def __post_init__(self) -> None:
|
|
49
|
+
if self.multiplier <= 0:
|
|
50
|
+
raise ValueError("multiplier must be positive")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class FunctionConfig:
|
|
55
|
+
"""Configuration for a function handler."""
|
|
56
|
+
|
|
57
|
+
name: str
|
|
58
|
+
handler: HandlerFunc
|
|
59
|
+
retries: Optional[RetryPolicy] = None
|
|
60
|
+
backoff: Optional[BackoffPolicy] = None
|
|
61
|
+
input_schema: Optional[Dict[str, Any]] = None
|
|
62
|
+
output_schema: Optional[Dict[str, Any]] = None
|
|
63
|
+
metadata: Optional[Dict[str, str]] = None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass
|
|
67
|
+
class WorkflowConfig:
|
|
68
|
+
"""Configuration for a workflow handler."""
|
|
69
|
+
|
|
70
|
+
name: str
|
|
71
|
+
handler: HandlerFunc
|
|
72
|
+
input_schema: Optional[Dict[str, Any]] = None
|
|
73
|
+
output_schema: Optional[Dict[str, Any]] = None
|
|
74
|
+
metadata: Optional[Dict[str, str]] = None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class ContextProtocol(Protocol):
|
|
78
|
+
"""Protocol defining the Context interface."""
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def run_id(self) -> str:
|
|
82
|
+
"""Workflow/run identifier."""
|
|
83
|
+
...
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def step_id(self) -> Optional[str]:
|
|
87
|
+
"""Current step identifier."""
|
|
88
|
+
...
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def attempt(self) -> int:
|
|
92
|
+
"""Retry attempt number."""
|
|
93
|
+
...
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def component_type(self) -> str:
|
|
97
|
+
"""Component type: 'function', 'entity', 'workflow'."""
|
|
98
|
+
...
|
|
99
|
+
|
|
100
|
+
async def get(self, key: str, default: Any = None) -> Any:
|
|
101
|
+
"""Get value from state."""
|
|
102
|
+
...
|
|
103
|
+
|
|
104
|
+
def set(self, key: str, value: Any) -> None:
|
|
105
|
+
"""Set value in state."""
|
|
106
|
+
...
|
|
107
|
+
|
|
108
|
+
def delete(self, key: str) -> None:
|
|
109
|
+
"""Delete key from state."""
|
|
110
|
+
...
|
agnt5/version.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Version information for agnt5 SDK."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _get_version() -> str:
|
|
5
|
+
"""Get package version from installed metadata.
|
|
6
|
+
|
|
7
|
+
This uses importlib.metadata (Python 3.8+) to read the version from
|
|
8
|
+
the installed package metadata, maintaining pyproject.toml as the
|
|
9
|
+
single source of truth.
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
Package version string, or "0.0.0+dev" for development installs.
|
|
13
|
+
"""
|
|
14
|
+
try:
|
|
15
|
+
from importlib.metadata import version
|
|
16
|
+
return version("agnt5")
|
|
17
|
+
except Exception:
|
|
18
|
+
# Development/editable install fallback
|
|
19
|
+
return "0.0.0+dev"
|