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/context.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""Context implementation for AGNT5 SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import contextvars
|
|
6
|
+
import logging
|
|
7
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional, TypeVar, Union
|
|
8
|
+
|
|
9
|
+
T = TypeVar("T")
|
|
10
|
+
|
|
11
|
+
# Task-local context variable for automatic context propagation
|
|
12
|
+
# This is NOT a global variable - contextvars provide task-isolated storage
|
|
13
|
+
# Each asyncio task gets its own independent copy, preventing cross-contamination
|
|
14
|
+
_current_context: contextvars.ContextVar[Optional["Context"]] = contextvars.ContextVar(
|
|
15
|
+
"_current_context", default=None
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class _CorrelationFilter(logging.Filter):
|
|
20
|
+
"""Inject correlation IDs (run_id, trace_id, span_id) into every log record."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, runtime_context: Any) -> None:
|
|
23
|
+
super().__init__()
|
|
24
|
+
self.runtime_context = runtime_context
|
|
25
|
+
|
|
26
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
27
|
+
"""Add correlation IDs as extra fields to the log record."""
|
|
28
|
+
record.run_id = self.runtime_context.run_id
|
|
29
|
+
if self.runtime_context.trace_id:
|
|
30
|
+
record.trace_id = self.runtime_context.trace_id
|
|
31
|
+
if self.runtime_context.span_id:
|
|
32
|
+
record.span_id = self.runtime_context.span_id
|
|
33
|
+
return True
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Context:
|
|
37
|
+
"""
|
|
38
|
+
Base context providing common functionality.
|
|
39
|
+
|
|
40
|
+
Provides:
|
|
41
|
+
- Logging with correlation IDs
|
|
42
|
+
- Execution metadata (run_id, attempt)
|
|
43
|
+
- Runtime context for tracing
|
|
44
|
+
|
|
45
|
+
Extended by:
|
|
46
|
+
- FunctionContext: Minimal context for stateless functions
|
|
47
|
+
- WorkflowContext: Context for durable workflows
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
run_id: str,
|
|
53
|
+
attempt: int = 0,
|
|
54
|
+
runtime_context: Optional[Any] = None,
|
|
55
|
+
) -> None:
|
|
56
|
+
"""
|
|
57
|
+
Initialize base context.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
run_id: Unique execution identifier
|
|
61
|
+
attempt: Retry attempt number (0-indexed)
|
|
62
|
+
runtime_context: RuntimeContext for trace correlation
|
|
63
|
+
"""
|
|
64
|
+
self._run_id = run_id
|
|
65
|
+
self._attempt = attempt
|
|
66
|
+
self._runtime_context = runtime_context
|
|
67
|
+
|
|
68
|
+
# Create logger with correlation
|
|
69
|
+
self._logger = logging.getLogger(f"agnt5.{run_id}")
|
|
70
|
+
from ._telemetry import setup_context_logger
|
|
71
|
+
setup_context_logger(self._logger)
|
|
72
|
+
|
|
73
|
+
if runtime_context:
|
|
74
|
+
self._logger.addFilter(_CorrelationFilter(runtime_context))
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def run_id(self) -> str:
|
|
78
|
+
"""Unique execution identifier."""
|
|
79
|
+
return self._run_id
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def attempt(self) -> int:
|
|
83
|
+
"""Current retry attempt (0-indexed)."""
|
|
84
|
+
return self._attempt
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def logger(self) -> logging.Logger:
|
|
88
|
+
"""Full logger for .debug(), .warning(), .error(), etc."""
|
|
89
|
+
return self._logger
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def get_current_context() -> Optional[Context]:
|
|
93
|
+
"""
|
|
94
|
+
Get the current execution context from task-local storage.
|
|
95
|
+
|
|
96
|
+
This function retrieves the context that was set by the nearest enclosing
|
|
97
|
+
decorator (@function, @workflow) or Agent.run() call in the current asyncio task.
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
Current Context if available (WorkflowContext, FunctionContext, AgentContext),
|
|
101
|
+
None if no context is set (e.g., running outside AGNT5 execution)
|
|
102
|
+
|
|
103
|
+
Example:
|
|
104
|
+
>>> ctx = get_current_context()
|
|
105
|
+
>>> if ctx:
|
|
106
|
+
... ctx.logger.info("Logging from anywhere in the call stack!")
|
|
107
|
+
... runtime = ctx._runtime_context # Access tracing context
|
|
108
|
+
|
|
109
|
+
Note:
|
|
110
|
+
This uses Python's contextvars which provide task-local (NOT global) storage.
|
|
111
|
+
Each asyncio task has its own isolated context, preventing cross-contamination
|
|
112
|
+
between concurrent executions.
|
|
113
|
+
"""
|
|
114
|
+
return _current_context.get()
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def set_current_context(ctx: Context) -> contextvars.Token:
|
|
118
|
+
"""
|
|
119
|
+
Set the current execution context in task-local storage.
|
|
120
|
+
|
|
121
|
+
This is typically called by decorators and framework code, not by user code.
|
|
122
|
+
Returns a token that can be used to reset the context to its previous value.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
ctx: Context to set as current
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Token for resetting the context later (use with contextvars.Token.reset())
|
|
129
|
+
|
|
130
|
+
Example:
|
|
131
|
+
>>> token = set_current_context(my_context)
|
|
132
|
+
>>> try:
|
|
133
|
+
... # Context is available via get_current_context()
|
|
134
|
+
... do_work()
|
|
135
|
+
>>> finally:
|
|
136
|
+
... _current_context.reset(token) # Restore previous context
|
|
137
|
+
|
|
138
|
+
Note:
|
|
139
|
+
Always use try/finally to ensure context is properly reset, even if
|
|
140
|
+
an exception occurs. This prevents context leakage between executions.
|
|
141
|
+
"""
|
|
142
|
+
return _current_context.set(ctx)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def get_workflow_context() -> Optional["WorkflowContext"]:
|
|
146
|
+
"""
|
|
147
|
+
Get the WorkflowContext from the current context or its parent chain.
|
|
148
|
+
|
|
149
|
+
This function traverses the context hierarchy to find a WorkflowContext,
|
|
150
|
+
which is needed for emitting workflow checkpoints from nested contexts
|
|
151
|
+
like AgentContext or FunctionContext.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
WorkflowContext if found in the context chain, None otherwise
|
|
155
|
+
|
|
156
|
+
Example:
|
|
157
|
+
>>> # Inside an agent called from a workflow
|
|
158
|
+
>>> workflow_ctx = get_workflow_context()
|
|
159
|
+
>>> if workflow_ctx:
|
|
160
|
+
... workflow_ctx._send_checkpoint("workflow.lm.started", {...})
|
|
161
|
+
"""
|
|
162
|
+
from .workflow import WorkflowContext
|
|
163
|
+
|
|
164
|
+
ctx = get_current_context()
|
|
165
|
+
|
|
166
|
+
# Traverse up the context chain looking for WorkflowContext
|
|
167
|
+
while ctx is not None:
|
|
168
|
+
if isinstance(ctx, WorkflowContext):
|
|
169
|
+
return ctx
|
|
170
|
+
# Check if this context has a parent_context attribute
|
|
171
|
+
if hasattr(ctx, 'parent_context'):
|
|
172
|
+
ctx = ctx.parent_context
|
|
173
|
+
else:
|
|
174
|
+
break
|
|
175
|
+
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
|