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.
Files changed (98) hide show
  1. t0_agents/__init__.py +182 -0
  2. t0_agents/core/__init__.py +43 -0
  3. t0_agents/core/_runtime.py +137 -0
  4. t0_agents/core/agent.py +908 -0
  5. t0_agents/core/config.py +460 -0
  6. t0_agents/core/conversation.py +248 -0
  7. t0_agents/core/elicitation_forwarder.py +344 -0
  8. t0_agents/core/exceptions.py +112 -0
  9. t0_agents/core/middleware/__init__.py +63 -0
  10. t0_agents/core/middleware/base.py +323 -0
  11. t0_agents/core/middleware/builtins.py +841 -0
  12. t0_agents/core/output.py +271 -0
  13. t0_agents/core/outputs/__init__.py +33 -0
  14. t0_agents/core/outputs/chat.py +113 -0
  15. t0_agents/core/outputs/json.py +221 -0
  16. t0_agents/core/outputs/streaming.py +71 -0
  17. t0_agents/core/outputs/structured.py +298 -0
  18. t0_agents/core/outputs/tool_call.py +110 -0
  19. t0_agents/core/run.py +865 -0
  20. t0_agents/core/structured.py +433 -0
  21. t0_agents/core/turn_engine.py +534 -0
  22. t0_agents/core/types.py +524 -0
  23. t0_agents/delegation/__init__.py +27 -0
  24. t0_agents/delegation/orchestrator.py +83 -0
  25. t0_agents/delegation/provider.py +223 -0
  26. t0_agents/delegation/routing.py +36 -0
  27. t0_agents/glow/__init__.py +69 -0
  28. t0_agents/glow/_spec.py +87 -0
  29. t0_agents/glow/_typing.py +104 -0
  30. t0_agents/glow/agent_handle.py +87 -0
  31. t0_agents/glow/app.py +1192 -0
  32. t0_agents/glow/conversation.py +562 -0
  33. t0_agents/glow/decorators.py +617 -0
  34. t0_agents/glow/di.py +162 -0
  35. t0_agents/glow/guardrails_typing.py +77 -0
  36. t0_agents/glow/handle.py +639 -0
  37. t0_agents/glow/mcp_typing.py +336 -0
  38. t0_agents/glow/output_inference.py +88 -0
  39. t0_agents/glow/py.typed +0 -0
  40. t0_agents/glow/selectors.py +163 -0
  41. t0_agents/guardrails/__init__.py +43 -0
  42. t0_agents/guardrails/approval.py +144 -0
  43. t0_agents/guardrails/base.py +52 -0
  44. t0_agents/guardrails/limits.py +126 -0
  45. t0_agents/guardrails/regex.py +142 -0
  46. t0_agents/guardrails/runtime.py +198 -0
  47. t0_agents/guardrails/structured.py +86 -0
  48. t0_agents/guardrails/validators.py +59 -0
  49. t0_agents/mcp/__init__.py +20 -0
  50. t0_agents/mcp/adapter.py +151 -0
  51. t0_agents/mcp/elicitation.py +40 -0
  52. t0_agents/mcp/loop.py +674 -0
  53. t0_agents/mcp/runtime.py +1368 -0
  54. t0_agents/memory/__init__.py +20 -0
  55. t0_agents/memory/base.py +48 -0
  56. t0_agents/memory/in_memory.py +44 -0
  57. t0_agents/memory/sqlite.py +126 -0
  58. t0_agents/memory/tensorzero.py +823 -0
  59. t0_agents/py.typed +0 -0
  60. t0_agents/serve/__init__.py +60 -0
  61. t0_agents/serve/app.py +270 -0
  62. t0_agents/serve/lifespan.py +43 -0
  63. t0_agents/serve/protocol.py +233 -0
  64. t0_agents/serve/routes.py +142 -0
  65. t0_agents/serve/session.py +330 -0
  66. t0_agents/serve/streaming_routes.py +408 -0
  67. t0_agents/serve/ws_protocol.py +90 -0
  68. t0_agents/stream/__init__.py +68 -0
  69. t0_agents/stream/assembler.py +325 -0
  70. t0_agents/stream/codec.py +176 -0
  71. t0_agents/stream/events.py +236 -0
  72. t0_agents/stream/runner.py +553 -0
  73. t0_agents/stream/status.py +100 -0
  74. t0_agents/testing/__init__.py +118 -0
  75. t0_agents/testing/assertions.py +272 -0
  76. t0_agents/testing/builders.py +81 -0
  77. t0_agents/testing/embedded.py +112 -0
  78. t0_agents/testing/fixtures.py +144 -0
  79. t0_agents/testing/mcp.py +104 -0
  80. t0_agents/testing/mocks.py +649 -0
  81. t0_agents/testing/scenarios.py +86 -0
  82. t0_agents/testing/scripted.py +172 -0
  83. t0_agents/testing/streaming_mocks.py +157 -0
  84. t0_agents/tooling/__init__.py +5 -0
  85. t0_agents/tooling/filtered.py +71 -0
  86. t0_agents/usage/__init__.py +23 -0
  87. t0_agents/usage/in_memory.py +24 -0
  88. t0_agents/usage/ledger.py +24 -0
  89. t0_agents/usage/middleware.py +214 -0
  90. t0_agents/usage/records.py +80 -0
  91. t0_agents/usage/sqlite.py +189 -0
  92. t0_agents/wire/__init__.py +86 -0
  93. t0_agents/wire/frames.py +382 -0
  94. t0_agents/wire/stages.py +556 -0
  95. t0_agents-2.14.0.dist-info/METADATA +298 -0
  96. t0_agents-2.14.0.dist-info/RECORD +98 -0
  97. t0_agents-2.14.0.dist-info/WHEEL +4 -0
  98. 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