t0-agents 2.14.0__py3-none-any.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.
- t0_agents/__init__.py +182 -0
- t0_agents/core/__init__.py +43 -0
- t0_agents/core/_runtime.py +137 -0
- t0_agents/core/agent.py +908 -0
- t0_agents/core/config.py +460 -0
- t0_agents/core/conversation.py +248 -0
- t0_agents/core/elicitation_forwarder.py +344 -0
- t0_agents/core/exceptions.py +112 -0
- t0_agents/core/middleware/__init__.py +63 -0
- t0_agents/core/middleware/base.py +323 -0
- t0_agents/core/middleware/builtins.py +841 -0
- t0_agents/core/output.py +271 -0
- t0_agents/core/outputs/__init__.py +33 -0
- t0_agents/core/outputs/chat.py +113 -0
- t0_agents/core/outputs/json.py +221 -0
- t0_agents/core/outputs/streaming.py +71 -0
- t0_agents/core/outputs/structured.py +298 -0
- t0_agents/core/outputs/tool_call.py +110 -0
- t0_agents/core/run.py +865 -0
- t0_agents/core/structured.py +433 -0
- t0_agents/core/turn_engine.py +534 -0
- t0_agents/core/types.py +524 -0
- t0_agents/delegation/__init__.py +27 -0
- t0_agents/delegation/orchestrator.py +83 -0
- t0_agents/delegation/provider.py +223 -0
- t0_agents/delegation/routing.py +36 -0
- t0_agents/glow/__init__.py +69 -0
- t0_agents/glow/_spec.py +87 -0
- t0_agents/glow/_typing.py +104 -0
- t0_agents/glow/agent_handle.py +87 -0
- t0_agents/glow/app.py +1192 -0
- t0_agents/glow/conversation.py +562 -0
- t0_agents/glow/decorators.py +617 -0
- t0_agents/glow/di.py +162 -0
- t0_agents/glow/guardrails_typing.py +77 -0
- t0_agents/glow/handle.py +639 -0
- t0_agents/glow/mcp_typing.py +336 -0
- t0_agents/glow/output_inference.py +88 -0
- t0_agents/glow/py.typed +0 -0
- t0_agents/glow/selectors.py +163 -0
- t0_agents/guardrails/__init__.py +43 -0
- t0_agents/guardrails/approval.py +144 -0
- t0_agents/guardrails/base.py +52 -0
- t0_agents/guardrails/limits.py +126 -0
- t0_agents/guardrails/regex.py +142 -0
- t0_agents/guardrails/runtime.py +198 -0
- t0_agents/guardrails/structured.py +86 -0
- t0_agents/guardrails/validators.py +59 -0
- t0_agents/mcp/__init__.py +20 -0
- t0_agents/mcp/adapter.py +151 -0
- t0_agents/mcp/elicitation.py +40 -0
- t0_agents/mcp/loop.py +674 -0
- t0_agents/mcp/runtime.py +1368 -0
- t0_agents/memory/__init__.py +20 -0
- t0_agents/memory/base.py +48 -0
- t0_agents/memory/in_memory.py +44 -0
- t0_agents/memory/sqlite.py +126 -0
- t0_agents/memory/tensorzero.py +823 -0
- t0_agents/py.typed +0 -0
- t0_agents/serve/__init__.py +60 -0
- t0_agents/serve/app.py +270 -0
- t0_agents/serve/lifespan.py +43 -0
- t0_agents/serve/protocol.py +233 -0
- t0_agents/serve/routes.py +142 -0
- t0_agents/serve/session.py +330 -0
- t0_agents/serve/streaming_routes.py +408 -0
- t0_agents/serve/ws_protocol.py +90 -0
- t0_agents/stream/__init__.py +68 -0
- t0_agents/stream/assembler.py +325 -0
- t0_agents/stream/codec.py +176 -0
- t0_agents/stream/events.py +236 -0
- t0_agents/stream/runner.py +553 -0
- t0_agents/stream/status.py +100 -0
- t0_agents/testing/__init__.py +118 -0
- t0_agents/testing/assertions.py +272 -0
- t0_agents/testing/builders.py +81 -0
- t0_agents/testing/embedded.py +112 -0
- t0_agents/testing/fixtures.py +144 -0
- t0_agents/testing/mcp.py +104 -0
- t0_agents/testing/mocks.py +649 -0
- t0_agents/testing/scenarios.py +86 -0
- t0_agents/testing/scripted.py +172 -0
- t0_agents/testing/streaming_mocks.py +157 -0
- t0_agents/tooling/__init__.py +5 -0
- t0_agents/tooling/filtered.py +71 -0
- t0_agents/usage/__init__.py +23 -0
- t0_agents/usage/in_memory.py +24 -0
- t0_agents/usage/ledger.py +24 -0
- t0_agents/usage/middleware.py +214 -0
- t0_agents/usage/records.py +80 -0
- t0_agents/usage/sqlite.py +189 -0
- t0_agents/wire/__init__.py +86 -0
- t0_agents/wire/frames.py +382 -0
- t0_agents/wire/stages.py +556 -0
- t0_agents-2.14.0.dist-info/METADATA +298 -0
- t0_agents-2.14.0.dist-info/RECORD +98 -0
- t0_agents-2.14.0.dist-info/WHEEL +4 -0
- t0_agents-2.14.0.dist-info/licenses/LICENSE +21 -0
t0_agents/__init__.py
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"""t0-agents: The Pythonic agentic framework for TensorZero."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from tensorzero import ToolChoice
|
|
6
|
+
|
|
7
|
+
__version__ = "2.14.0"
|
|
8
|
+
|
|
9
|
+
from t0_agents.core.agent import AGENT_TAG, Agent
|
|
10
|
+
from t0_agents.core.config import AgentConfig
|
|
11
|
+
from t0_agents.core.conversation import ConversationUsage
|
|
12
|
+
from t0_agents.core.elicitation_forwarder import (
|
|
13
|
+
ElicitationForwarder,
|
|
14
|
+
ElicitationRequest,
|
|
15
|
+
)
|
|
16
|
+
from t0_agents.core.exceptions import (
|
|
17
|
+
ConfigurationError,
|
|
18
|
+
GuardrailBlockedError,
|
|
19
|
+
MaxTurnsExceededError,
|
|
20
|
+
MemoryHistoryUnavailableError,
|
|
21
|
+
RunCancelledError,
|
|
22
|
+
RunFailedError,
|
|
23
|
+
SubAgentError,
|
|
24
|
+
T0AgentsError,
|
|
25
|
+
T0AgentsFatalError,
|
|
26
|
+
)
|
|
27
|
+
from t0_agents.core.middleware import (
|
|
28
|
+
CostTrackingMiddleware,
|
|
29
|
+
GuardrailsMiddleware,
|
|
30
|
+
JsonRetryMiddleware,
|
|
31
|
+
MemoryMiddleware,
|
|
32
|
+
Middleware,
|
|
33
|
+
ObservabilityMiddleware,
|
|
34
|
+
RunContext,
|
|
35
|
+
SubAgentMiddleware,
|
|
36
|
+
)
|
|
37
|
+
from t0_agents.core.output import (
|
|
38
|
+
Attempt,
|
|
39
|
+
InferenceRequest,
|
|
40
|
+
OutputDiagnostics,
|
|
41
|
+
OutputMode,
|
|
42
|
+
ParseFailure,
|
|
43
|
+
Recovery,
|
|
44
|
+
)
|
|
45
|
+
from t0_agents.core.outputs import (
|
|
46
|
+
ChatOutput,
|
|
47
|
+
JsonOutput,
|
|
48
|
+
StreamingOutput,
|
|
49
|
+
StructuredOutput,
|
|
50
|
+
ToolCallOutput,
|
|
51
|
+
)
|
|
52
|
+
from t0_agents.core.run import Run, RunInput, RunState
|
|
53
|
+
from t0_agents.core.structured import StructuredInferenceResult, permissive_parse
|
|
54
|
+
from t0_agents.core.types import (
|
|
55
|
+
AgentResult,
|
|
56
|
+
ExtraBodyPatch,
|
|
57
|
+
Guardrail,
|
|
58
|
+
GuardrailLogEntry,
|
|
59
|
+
MemoryProvider,
|
|
60
|
+
RunUsage,
|
|
61
|
+
ToolCallUsage,
|
|
62
|
+
ToolProvider,
|
|
63
|
+
)
|
|
64
|
+
from t0_agents.delegation import SubAgentToolProvider
|
|
65
|
+
from t0_agents.mcp import run_agent
|
|
66
|
+
from t0_agents.stream import (
|
|
67
|
+
CODEC_VERSION,
|
|
68
|
+
AgentEvent,
|
|
69
|
+
DoneEvent,
|
|
70
|
+
ElicitationRequestedEvent,
|
|
71
|
+
ElicitationResolvedEvent,
|
|
72
|
+
ErrorEvent,
|
|
73
|
+
RunErrorEvent,
|
|
74
|
+
Status,
|
|
75
|
+
StreamingAgentLoop,
|
|
76
|
+
TextDeltaEvent,
|
|
77
|
+
TextEndEvent,
|
|
78
|
+
ThoughtDeltaEvent,
|
|
79
|
+
ThoughtEvent,
|
|
80
|
+
ToolCallDeltaEvent,
|
|
81
|
+
ToolCallEvent,
|
|
82
|
+
ToolProgressEvent,
|
|
83
|
+
ToolResultEvent,
|
|
84
|
+
TurnEndEvent,
|
|
85
|
+
TurnStreamAssembler,
|
|
86
|
+
event_from_dict,
|
|
87
|
+
event_to_dict,
|
|
88
|
+
split_tool_identity,
|
|
89
|
+
synthesize_statuses,
|
|
90
|
+
)
|
|
91
|
+
from t0_agents.tooling import FilteredToolProvider
|
|
92
|
+
from t0_agents.usage import (
|
|
93
|
+
InferenceUsage,
|
|
94
|
+
RunUsageRecord,
|
|
95
|
+
UsageLedger,
|
|
96
|
+
UsageLedgerMiddleware,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
__all__ = [
|
|
100
|
+
"AGENT_TAG",
|
|
101
|
+
"CODEC_VERSION",
|
|
102
|
+
"Agent",
|
|
103
|
+
"AgentConfig",
|
|
104
|
+
"AgentEvent",
|
|
105
|
+
"AgentResult",
|
|
106
|
+
"Attempt",
|
|
107
|
+
"ChatOutput",
|
|
108
|
+
"ConfigurationError",
|
|
109
|
+
"ConversationUsage",
|
|
110
|
+
"CostTrackingMiddleware",
|
|
111
|
+
"DoneEvent",
|
|
112
|
+
"ElicitationForwarder",
|
|
113
|
+
"ElicitationRequest",
|
|
114
|
+
"ElicitationRequestedEvent",
|
|
115
|
+
"ElicitationResolvedEvent",
|
|
116
|
+
"ErrorEvent",
|
|
117
|
+
"ExtraBodyPatch",
|
|
118
|
+
"FilteredToolProvider",
|
|
119
|
+
"Guardrail",
|
|
120
|
+
"GuardrailBlockedError",
|
|
121
|
+
"GuardrailLogEntry",
|
|
122
|
+
"GuardrailsMiddleware",
|
|
123
|
+
"InferenceRequest",
|
|
124
|
+
"InferenceUsage",
|
|
125
|
+
"JsonOutput",
|
|
126
|
+
"JsonRetryMiddleware",
|
|
127
|
+
"MaxTurnsExceededError",
|
|
128
|
+
"MemoryHistoryUnavailableError",
|
|
129
|
+
"MemoryMiddleware",
|
|
130
|
+
"MemoryProvider",
|
|
131
|
+
"Middleware",
|
|
132
|
+
"ObservabilityMiddleware",
|
|
133
|
+
"OutputDiagnostics",
|
|
134
|
+
"OutputMode",
|
|
135
|
+
"ParseFailure",
|
|
136
|
+
"Recovery",
|
|
137
|
+
"Run",
|
|
138
|
+
"RunCancelledError",
|
|
139
|
+
"RunContext",
|
|
140
|
+
"RunErrorEvent",
|
|
141
|
+
"RunFailedError",
|
|
142
|
+
"RunInput",
|
|
143
|
+
"RunState",
|
|
144
|
+
"RunUsage",
|
|
145
|
+
"RunUsageRecord",
|
|
146
|
+
"Status",
|
|
147
|
+
"StreamingAgentLoop",
|
|
148
|
+
"StreamingOutput",
|
|
149
|
+
"StructuredInferenceResult",
|
|
150
|
+
"StructuredOutput",
|
|
151
|
+
"SubAgentError",
|
|
152
|
+
"SubAgentMiddleware",
|
|
153
|
+
"SubAgentToolProvider",
|
|
154
|
+
"T0AgentsError",
|
|
155
|
+
"T0AgentsFatalError",
|
|
156
|
+
"TextDeltaEvent",
|
|
157
|
+
"TextEndEvent",
|
|
158
|
+
"ThoughtDeltaEvent",
|
|
159
|
+
"ThoughtEvent",
|
|
160
|
+
"ToolCallDeltaEvent",
|
|
161
|
+
"ToolCallEvent",
|
|
162
|
+
"ToolCallOutput",
|
|
163
|
+
"ToolCallUsage",
|
|
164
|
+
"ToolChoice",
|
|
165
|
+
"ToolProgressEvent",
|
|
166
|
+
"ToolProvider",
|
|
167
|
+
"ToolResultEvent",
|
|
168
|
+
"TurnEndEvent",
|
|
169
|
+
"TurnStreamAssembler",
|
|
170
|
+
"UsageLedger",
|
|
171
|
+
"UsageLedgerMiddleware",
|
|
172
|
+
"__version__",
|
|
173
|
+
"event_from_dict",
|
|
174
|
+
"event_to_dict",
|
|
175
|
+
"permissive_parse",
|
|
176
|
+
"run_agent",
|
|
177
|
+
"split_tool_identity",
|
|
178
|
+
"synthesize_statuses",
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
# Library best practice: prevent "No handler found" warnings.
|
|
182
|
+
logging.getLogger("t0_agents").addHandler(logging.NullHandler())
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Core types, configuration, and exceptions for t0-agents."""
|
|
2
|
+
|
|
3
|
+
from t0_agents.core.agent import Agent
|
|
4
|
+
from t0_agents.core.config import AgentConfig
|
|
5
|
+
from t0_agents.core.elicitation_forwarder import (
|
|
6
|
+
ElicitationForwarder,
|
|
7
|
+
ElicitationRequest,
|
|
8
|
+
)
|
|
9
|
+
from t0_agents.core.exceptions import (
|
|
10
|
+
ConfigurationError,
|
|
11
|
+
GuardrailBlockedError,
|
|
12
|
+
MaxTurnsExceededError,
|
|
13
|
+
MemoryHistoryUnavailableError,
|
|
14
|
+
SubAgentError,
|
|
15
|
+
T0AgentsError,
|
|
16
|
+
T0AgentsFatalError,
|
|
17
|
+
)
|
|
18
|
+
from t0_agents.core.types import (
|
|
19
|
+
AgentResult,
|
|
20
|
+
Guardrail,
|
|
21
|
+
GuardrailLogEntry,
|
|
22
|
+
MemoryProvider,
|
|
23
|
+
ToolProvider,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"Agent",
|
|
28
|
+
"AgentConfig",
|
|
29
|
+
"AgentResult",
|
|
30
|
+
"ConfigurationError",
|
|
31
|
+
"ElicitationForwarder",
|
|
32
|
+
"ElicitationRequest",
|
|
33
|
+
"Guardrail",
|
|
34
|
+
"GuardrailBlockedError",
|
|
35
|
+
"GuardrailLogEntry",
|
|
36
|
+
"MaxTurnsExceededError",
|
|
37
|
+
"MemoryHistoryUnavailableError",
|
|
38
|
+
"MemoryProvider",
|
|
39
|
+
"SubAgentError",
|
|
40
|
+
"T0AgentsError",
|
|
41
|
+
"T0AgentsFatalError",
|
|
42
|
+
"ToolProvider",
|
|
43
|
+
]
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Internal runtime primitives for :class:`t0_agents.core.run.Run`.
|
|
2
|
+
|
|
3
|
+
Houses the :class:`EventBuffer` that backs ``Run.events()`` and
|
|
4
|
+
``Run.stream_text()``. Lives in a private module (leading underscore)
|
|
5
|
+
because the buffer's surface is an implementation detail of ``Run``;
|
|
6
|
+
public consumers go through ``Run`` rather than allocating buffers
|
|
7
|
+
directly.
|
|
8
|
+
|
|
9
|
+
The buffer is bounded (default :data:`EventBuffer.MAX_EVENTS` = 10 000)
|
|
10
|
+
to keep long-running agents from leaking memory. When the cap is
|
|
11
|
+
reached the oldest event is dropped, :attr:`EventBuffer.truncated`
|
|
12
|
+
latches ``True``, and a single WARN log fires per buffer instance so
|
|
13
|
+
operators see the overflow without log spam. Each consumer iterator
|
|
14
|
+
tracks its own logical cursor, so concurrent consumers do not affect
|
|
15
|
+
each other — and ``replay=True`` consumers see every event that is
|
|
16
|
+
still in the buffer (which is the full history when no truncation
|
|
17
|
+
has occurred).
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import asyncio
|
|
23
|
+
import logging
|
|
24
|
+
from collections.abc import AsyncIterator
|
|
25
|
+
|
|
26
|
+
from t0_agents.stream.events import AgentEvent
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class EventBuffer:
|
|
32
|
+
"""Bounded, replayable event buffer for one :class:`Run`.
|
|
33
|
+
|
|
34
|
+
Producers call :meth:`put` once per event and :meth:`close` once at
|
|
35
|
+
end-of-stream. Consumers call :meth:`iter_from` to read events
|
|
36
|
+
starting at a logical cursor (``self.total_pushed`` for "live",
|
|
37
|
+
``0`` for "replay"). The buffer wakes every waiting consumer via
|
|
38
|
+
an :class:`asyncio.Condition` whenever a new event arrives or the
|
|
39
|
+
buffer is closed.
|
|
40
|
+
|
|
41
|
+
Concurrent consumers each maintain their own cursor; the buffer
|
|
42
|
+
holds the underlying storage and the synchronisation primitive.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
MAX_EVENTS: int = 10_000
|
|
46
|
+
|
|
47
|
+
def __init__(self) -> None:
|
|
48
|
+
self._events: list[AgentEvent] = []
|
|
49
|
+
self._drop_count: int = 0
|
|
50
|
+
self._total_pushed: int = 0
|
|
51
|
+
self._truncated: bool = False
|
|
52
|
+
self._warned_truncation: bool = False
|
|
53
|
+
self._closed = asyncio.Event()
|
|
54
|
+
self._cond = asyncio.Condition()
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def total_pushed(self) -> int:
|
|
58
|
+
"""Logical index that the next ``put`` will assign."""
|
|
59
|
+
return self._total_pushed
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def truncated(self) -> bool:
|
|
63
|
+
"""``True`` if any oldest events were dropped to honour the cap."""
|
|
64
|
+
return self._truncated
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def closed(self) -> bool:
|
|
68
|
+
"""``True`` after :meth:`close` has been called."""
|
|
69
|
+
return self._closed.is_set()
|
|
70
|
+
|
|
71
|
+
async def put(self, event: AgentEvent) -> None:
|
|
72
|
+
"""Append ``event`` and wake every waiting consumer.
|
|
73
|
+
|
|
74
|
+
Drops the oldest event when the buffer is already at
|
|
75
|
+
:attr:`MAX_EVENTS`. Sets :attr:`truncated` on the first drop
|
|
76
|
+
and emits a single WARN log so operators see the overflow.
|
|
77
|
+
"""
|
|
78
|
+
async with self._cond:
|
|
79
|
+
if self._closed.is_set():
|
|
80
|
+
raise RuntimeError(
|
|
81
|
+
"EventBuffer.put() called after close() — programmer error"
|
|
82
|
+
)
|
|
83
|
+
self._events.append(event)
|
|
84
|
+
self._total_pushed += 1
|
|
85
|
+
if len(self._events) > self.MAX_EVENTS:
|
|
86
|
+
self._events.pop(0)
|
|
87
|
+
self._drop_count += 1
|
|
88
|
+
if not self._truncated:
|
|
89
|
+
self._truncated = True
|
|
90
|
+
if not self._warned_truncation:
|
|
91
|
+
logger.warning(
|
|
92
|
+
"EventBuffer overflow: more than %d events buffered; "
|
|
93
|
+
"oldest events are being dropped. Run.replay() / "
|
|
94
|
+
"events(replay=True) will surface only the most "
|
|
95
|
+
"recent %d events.",
|
|
96
|
+
self.MAX_EVENTS,
|
|
97
|
+
self.MAX_EVENTS,
|
|
98
|
+
)
|
|
99
|
+
self._warned_truncation = True
|
|
100
|
+
self._cond.notify_all()
|
|
101
|
+
|
|
102
|
+
async def close(self) -> None:
|
|
103
|
+
"""Mark the buffer closed and wake every waiting consumer."""
|
|
104
|
+
async with self._cond:
|
|
105
|
+
self._closed.set()
|
|
106
|
+
self._cond.notify_all()
|
|
107
|
+
|
|
108
|
+
async def iter_from(self, *, start_cursor: int) -> AsyncIterator[AgentEvent]:
|
|
109
|
+
"""Yield events starting at the given logical cursor.
|
|
110
|
+
|
|
111
|
+
The cursor is a logical index into the stream of pushed events
|
|
112
|
+
(not a physical index into the underlying list). When the
|
|
113
|
+
cursor is below the earliest still-buffered event because of
|
|
114
|
+
truncation, the iterator skips forward to the first available
|
|
115
|
+
event. When the cursor reaches the current head, the iterator
|
|
116
|
+
waits on the :class:`asyncio.Condition` until either a new
|
|
117
|
+
event arrives or the buffer is closed.
|
|
118
|
+
"""
|
|
119
|
+
cursor = max(0, start_cursor)
|
|
120
|
+
while True:
|
|
121
|
+
await self._cond.acquire()
|
|
122
|
+
try:
|
|
123
|
+
while cursor >= self._total_pushed and not self._closed.is_set():
|
|
124
|
+
await self._cond.wait()
|
|
125
|
+
if cursor >= self._total_pushed and self._closed.is_set():
|
|
126
|
+
return
|
|
127
|
+
if cursor < self._drop_count:
|
|
128
|
+
cursor = self._drop_count
|
|
129
|
+
if cursor >= self._total_pushed:
|
|
130
|
+
# The buffer was closed between catch-up and read;
|
|
131
|
+
# loop back to the closed-check at the top.
|
|
132
|
+
continue
|
|
133
|
+
event = self._events[cursor - self._drop_count]
|
|
134
|
+
cursor += 1
|
|
135
|
+
finally:
|
|
136
|
+
self._cond.release()
|
|
137
|
+
yield event
|