openai-agents 0.3.2__py3-none-any.whl → 0.3.3__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.

Potentially problematic release.


This version of openai-agents might be problematic. Click here for more details.

@@ -0,0 +1,279 @@
1
+ from __future__ import annotations
2
+
3
+ import inspect
4
+ from collections.abc import Awaitable
5
+ from dataclasses import dataclass, field
6
+ from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, overload
7
+
8
+ from typing_extensions import TypedDict, TypeVar
9
+
10
+ from .exceptions import UserError
11
+ from .tool_context import ToolContext
12
+ from .util._types import MaybeAwaitable
13
+
14
+ if TYPE_CHECKING:
15
+ from .agent import Agent
16
+
17
+
18
+ @dataclass
19
+ class ToolInputGuardrailResult:
20
+ """The result of a tool input guardrail run."""
21
+
22
+ guardrail: ToolInputGuardrail[Any]
23
+ """The guardrail that was run."""
24
+
25
+ output: ToolGuardrailFunctionOutput
26
+ """The output of the guardrail function."""
27
+
28
+
29
+ @dataclass
30
+ class ToolOutputGuardrailResult:
31
+ """The result of a tool output guardrail run."""
32
+
33
+ guardrail: ToolOutputGuardrail[Any]
34
+ """The guardrail that was run."""
35
+
36
+ output: ToolGuardrailFunctionOutput
37
+ """The output of the guardrail function."""
38
+
39
+
40
+ class RejectContentBehavior(TypedDict):
41
+ """Rejects the tool call/output but continues execution with a message to the model."""
42
+
43
+ type: Literal["reject_content"]
44
+ message: str
45
+
46
+
47
+ class RaiseExceptionBehavior(TypedDict):
48
+ """Raises an exception to halt execution."""
49
+
50
+ type: Literal["raise_exception"]
51
+
52
+
53
+ class AllowBehavior(TypedDict):
54
+ """Allows normal tool execution to continue."""
55
+
56
+ type: Literal["allow"]
57
+
58
+
59
+ @dataclass
60
+ class ToolGuardrailFunctionOutput:
61
+ """The output of a tool guardrail function."""
62
+
63
+ output_info: Any
64
+ """
65
+ Optional data about checks performed. For example, the guardrail could include
66
+ information about the checks it performed and granular results.
67
+ """
68
+
69
+ behavior: RejectContentBehavior | RaiseExceptionBehavior | AllowBehavior = field(
70
+ default_factory=lambda: AllowBehavior(type="allow")
71
+ )
72
+ """
73
+ Defines how the system should respond when this guardrail result is processed.
74
+ - allow: Allow normal tool execution to continue without interference (default)
75
+ - reject_content: Reject the tool call/output but continue execution with a message to the model
76
+ - raise_exception: Halt execution by raising a ToolGuardrailTripwireTriggered exception
77
+ """
78
+
79
+ @classmethod
80
+ def allow(cls, output_info: Any = None) -> ToolGuardrailFunctionOutput:
81
+ """Create a guardrail output that allows the tool execution to continue normally.
82
+
83
+ Args:
84
+ output_info: Optional data about checks performed.
85
+
86
+ Returns:
87
+ ToolGuardrailFunctionOutput configured to allow normal execution.
88
+ """
89
+ return cls(output_info=output_info, behavior=AllowBehavior(type="allow"))
90
+
91
+ @classmethod
92
+ def reject_content(cls, message: str, output_info: Any = None) -> ToolGuardrailFunctionOutput:
93
+ """Create a guardrail output that rejects the tool call/output but continues execution.
94
+
95
+ Args:
96
+ message: Message to send to the model instead of the tool result.
97
+ output_info: Optional data about checks performed.
98
+
99
+ Returns:
100
+ ToolGuardrailFunctionOutput configured to reject the content.
101
+ """
102
+ return cls(
103
+ output_info=output_info,
104
+ behavior=RejectContentBehavior(type="reject_content", message=message),
105
+ )
106
+
107
+ @classmethod
108
+ def raise_exception(cls, output_info: Any = None) -> ToolGuardrailFunctionOutput:
109
+ """Create a guardrail output that raises an exception to halt execution.
110
+
111
+ Args:
112
+ output_info: Optional data about checks performed.
113
+
114
+ Returns:
115
+ ToolGuardrailFunctionOutput configured to raise an exception.
116
+ """
117
+ return cls(output_info=output_info, behavior=RaiseExceptionBehavior(type="raise_exception"))
118
+
119
+
120
+ @dataclass
121
+ class ToolInputGuardrailData:
122
+ """Input data passed to a tool input guardrail function."""
123
+
124
+ context: ToolContext[Any]
125
+ """
126
+ The tool context containing information about the current tool execution.
127
+ """
128
+
129
+ agent: Agent[Any]
130
+ """
131
+ The agent that is executing the tool.
132
+ """
133
+
134
+
135
+ @dataclass
136
+ class ToolOutputGuardrailData(ToolInputGuardrailData):
137
+ """Input data passed to a tool output guardrail function.
138
+
139
+ Extends input data with the tool's output.
140
+ """
141
+
142
+ output: Any
143
+ """
144
+ The output produced by the tool function.
145
+ """
146
+
147
+
148
+ TContext_co = TypeVar("TContext_co", bound=Any, covariant=True)
149
+
150
+
151
+ @dataclass
152
+ class ToolInputGuardrail(Generic[TContext_co]):
153
+ """A guardrail that runs before a function tool is invoked."""
154
+
155
+ guardrail_function: Callable[
156
+ [ToolInputGuardrailData], MaybeAwaitable[ToolGuardrailFunctionOutput]
157
+ ]
158
+ """
159
+ The function that implements the guardrail logic.
160
+ """
161
+
162
+ name: str | None = None
163
+ """
164
+ Optional name for the guardrail. If not provided, uses the function name.
165
+ """
166
+
167
+ def get_name(self) -> str:
168
+ return self.name or self.guardrail_function.__name__
169
+
170
+ async def run(self, data: ToolInputGuardrailData) -> ToolGuardrailFunctionOutput:
171
+ if not callable(self.guardrail_function):
172
+ raise UserError(f"Guardrail function must be callable, got {self.guardrail_function}")
173
+
174
+ result = self.guardrail_function(data)
175
+ if inspect.isawaitable(result):
176
+ return await result
177
+ return result
178
+
179
+
180
+ @dataclass
181
+ class ToolOutputGuardrail(Generic[TContext_co]):
182
+ """A guardrail that runs after a function tool is invoked."""
183
+
184
+ guardrail_function: Callable[
185
+ [ToolOutputGuardrailData], MaybeAwaitable[ToolGuardrailFunctionOutput]
186
+ ]
187
+ """
188
+ The function that implements the guardrail logic.
189
+ """
190
+
191
+ name: str | None = None
192
+ """
193
+ Optional name for the guardrail. If not provided, uses the function name.
194
+ """
195
+
196
+ def get_name(self) -> str:
197
+ return self.name or self.guardrail_function.__name__
198
+
199
+ async def run(self, data: ToolOutputGuardrailData) -> ToolGuardrailFunctionOutput:
200
+ if not callable(self.guardrail_function):
201
+ raise UserError(f"Guardrail function must be callable, got {self.guardrail_function}")
202
+
203
+ result = self.guardrail_function(data)
204
+ if inspect.isawaitable(result):
205
+ return await result
206
+ return result
207
+
208
+
209
+ # Decorators
210
+ _ToolInputFuncSync = Callable[[ToolInputGuardrailData], ToolGuardrailFunctionOutput]
211
+ _ToolInputFuncAsync = Callable[[ToolInputGuardrailData], Awaitable[ToolGuardrailFunctionOutput]]
212
+
213
+
214
+ @overload
215
+ def tool_input_guardrail(func: _ToolInputFuncSync): ...
216
+
217
+
218
+ @overload
219
+ def tool_input_guardrail(func: _ToolInputFuncAsync): ...
220
+
221
+
222
+ @overload
223
+ def tool_input_guardrail(
224
+ *, name: str | None = None
225
+ ) -> Callable[[_ToolInputFuncSync | _ToolInputFuncAsync], ToolInputGuardrail[Any]]: ...
226
+
227
+
228
+ def tool_input_guardrail(
229
+ func: _ToolInputFuncSync | _ToolInputFuncAsync | None = None,
230
+ *,
231
+ name: str | None = None,
232
+ ) -> (
233
+ ToolInputGuardrail[Any]
234
+ | Callable[[_ToolInputFuncSync | _ToolInputFuncAsync], ToolInputGuardrail[Any]]
235
+ ):
236
+ """Decorator to create a ToolInputGuardrail from a function."""
237
+
238
+ def decorator(f: _ToolInputFuncSync | _ToolInputFuncAsync) -> ToolInputGuardrail[Any]:
239
+ return ToolInputGuardrail(guardrail_function=f, name=name or f.__name__)
240
+
241
+ if func is not None:
242
+ return decorator(func)
243
+ return decorator
244
+
245
+
246
+ _ToolOutputFuncSync = Callable[[ToolOutputGuardrailData], ToolGuardrailFunctionOutput]
247
+ _ToolOutputFuncAsync = Callable[[ToolOutputGuardrailData], Awaitable[ToolGuardrailFunctionOutput]]
248
+
249
+
250
+ @overload
251
+ def tool_output_guardrail(func: _ToolOutputFuncSync): ...
252
+
253
+
254
+ @overload
255
+ def tool_output_guardrail(func: _ToolOutputFuncAsync): ...
256
+
257
+
258
+ @overload
259
+ def tool_output_guardrail(
260
+ *, name: str | None = None
261
+ ) -> Callable[[_ToolOutputFuncSync | _ToolOutputFuncAsync], ToolOutputGuardrail[Any]]: ...
262
+
263
+
264
+ def tool_output_guardrail(
265
+ func: _ToolOutputFuncSync | _ToolOutputFuncAsync | None = None,
266
+ *,
267
+ name: str | None = None,
268
+ ) -> (
269
+ ToolOutputGuardrail[Any]
270
+ | Callable[[_ToolOutputFuncSync | _ToolOutputFuncAsync], ToolOutputGuardrail[Any]]
271
+ ):
272
+ """Decorator to create a ToolOutputGuardrail from a function."""
273
+
274
+ def decorator(f: _ToolOutputFuncSync | _ToolOutputFuncAsync) -> ToolOutputGuardrail[Any]:
275
+ return ToolOutputGuardrail(guardrail_function=f, name=name or f.__name__)
276
+
277
+ if func is not None:
278
+ return decorator(func)
279
+ return decorator
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openai-agents
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: OpenAI Agents SDK
5
5
  Project-URL: Homepage, https://openai.github.io/openai-agents-python/
6
6
  Project-URL: Repository, https://github.com/openai/openai-agents-python
@@ -32,6 +32,8 @@ Provides-Extra: litellm
32
32
  Requires-Dist: litellm<2,>=1.67.4.post1; extra == 'litellm'
33
33
  Provides-Extra: realtime
34
34
  Requires-Dist: websockets<16,>=15.0; extra == 'realtime'
35
+ Provides-Extra: redis
36
+ Requires-Dist: redis>=6.4.0; extra == 'redis'
35
37
  Provides-Extra: sqlalchemy
36
38
  Requires-Dist: asyncpg>=0.29.0; extra == 'sqlalchemy'
37
39
  Requires-Dist: sqlalchemy>=2.0; extra == 'sqlalchemy'
@@ -75,6 +77,8 @@ pip install openai-agents
75
77
 
76
78
  For voice support, install with the optional `voice` group: `pip install 'openai-agents[voice]'`.
77
79
 
80
+ For Redis session support, install with the optional `redis` group: `pip install 'openai-agents[redis]'`.
81
+
78
82
  ### uv
79
83
 
80
84
  If you're familiar with [uv](https://docs.astral.sh/uv/), using the tool would be even similar:
@@ -86,6 +90,8 @@ uv add openai-agents
86
90
 
87
91
  For voice support, install with the optional `voice` group: `uv add 'openai-agents[voice]'`.
88
92
 
93
+ For Redis session support, install with the optional `redis` group: `uv add 'openai-agents[redis]'`.
94
+
89
95
  ## Hello world example
90
96
 
91
97
  ```python
@@ -255,8 +261,13 @@ print(result.final_output) # "Approximately 39 million"
255
261
  ```python
256
262
  from agents import Agent, Runner, SQLiteSession
257
263
 
258
- # Custom SQLite database file
264
+ # SQLite - file-based or in-memory database
259
265
  session = SQLiteSession("user_123", "conversations.db")
266
+
267
+ # Redis - for scalable, distributed deployments
268
+ # from agents.extensions.memory import RedisSession
269
+ # session = RedisSession.from_url("user_123", url="redis://localhost:6379/0")
270
+
260
271
  agent = Agent(name="Assistant")
261
272
 
262
273
  # Different session IDs maintain separate conversation histories
@@ -1,11 +1,11 @@
1
- agents/__init__.py,sha256=Kr6-8HItTfnz5HFS9x7PVD99v_Lu9VxlE27UjX3BH8M,8000
1
+ agents/__init__.py,sha256=ckLaHgy95UvhXWWfqYUW0uBO1PKMNcf3GUqnRBDifIs,8728
2
2
  agents/_config.py,sha256=ANrM7GP2VSQehDkMc9qocxkUlPwqU-i5sieMJyEwxpM,796
3
3
  agents/_debug.py,sha256=dRe2dUlA9bCLp6f8bAdiX7JfGyJuHyS_DRdW0kZshl0,856
4
- agents/_run_impl.py,sha256=9mW1kh9_WC9GvTgo4GyroMhthzaH-qKpTKIZxE15kEE,46352
4
+ agents/_run_impl.py,sha256=hGkagVDsrh4XU-eOtoopHDXDZRisGPHE3ddmKiwswF0,54690
5
5
  agents/agent.py,sha256=P5AzwKz3FiQJjzfautF0R9JzxkTXEeItcEkJgn8z5mM,19832
6
6
  agents/agent_output.py,sha256=teTFK8unUN3esXhmEBO0bQGYQm1Axd5rYleDt9TFDgw,7153
7
7
  agents/computer.py,sha256=XD44UgiUWSfniv-xKwwDP6wFKVwBiZkpaL1hO-0-7ZA,2516
8
- agents/exceptions.py,sha256=NHMdHE0cZ6AdA6UgUylTzVHAX05Ol1CkO814a0FdZcs,2862
8
+ agents/exceptions.py,sha256=roJsYttB5i7FQlzRQNg8QSVdALZFz5u7kUeVvJdaitE,4156
9
9
  agents/function_schema.py,sha256=njtbLt44DOkIU0a0U8TeDNEx-iQZU8oohwy3k7-k4A8,14855
10
10
  agents/guardrail.py,sha256=7P-kd9rKPhgB8rtI31MCV5ho4ZrEaNCQxHvE8IK3EOk,9582
11
11
  agents/handoffs.py,sha256=kDTM3nj3E_0khiJPMJAIN00gektMTRNbaYSbc5ZCnBM,11411
@@ -16,24 +16,27 @@ agents/model_settings.py,sha256=7Ul-Xg-aNVXIbK6V4Rm2t5EEfNR0tsy_A9ac_wFqLLk,6828
16
16
  agents/prompts.py,sha256=Ss5y_7s2HFcRAOAKu4WTxQszs5ybI8TfbxgEYdnj9sg,2231
17
17
  agents/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
18
18
  agents/repl.py,sha256=NX0BE5YDnmGQ2rdQsmLm3CKkQZ5m4GC95xXmUsAXJVs,2539
19
- agents/result.py,sha256=Ykf5V-DyufMgLEi2YhKFecMr_G8XDEiL-aIBBRcL5Zg,12050
20
- agents/run.py,sha256=RyaFenUly9XXzdB70FAW2p_qpxSbavv9B5B_KdSdSk0,65257
19
+ agents/result.py,sha256=i3AtgXMRDiqPOnaflZrusVT9pS98kC8atlrRFKEgk20,12428
20
+ agents/run.py,sha256=Pu1OBFz-h8MKt03cytKsgsXoHX4pfT7nZnIwxxaf178,66030
21
21
  agents/run_context.py,sha256=vuSUQM8O4CLensQY27-22fOqECnw7yvwL9U3WO8b_bk,851
22
22
  agents/stream_events.py,sha256=VFyTu-DT3ZMnHLtMbg-X_lxec0doQxNfx-hVxLB0BpI,1700
23
23
  agents/strict_schema.py,sha256=_KuEJkglmq-Fj3HSeYP4WqTvqrxbSKu6gezfz5Brhh0,5775
24
- agents/tool.py,sha256=mk4mKWy-K2eHIygLTNZf447oyIRqLz8Ex1R-wEQ9vS8,17023
24
+ agents/tool.py,sha256=RqEMkX47-LyHDBINyL3iHP7cOsf4DwlNT70S-X4mE9I,17425
25
25
  agents/tool_context.py,sha256=g53mgaeX7kCwPaIReiwuUejD8qC7QejMS-F3Wnkuhhg,1866
26
+ agents/tool_guardrails.py,sha256=2uXEr_R5AWy9NHtBjd7G7upc3uZSuoP86Hfsc-qTadM,8344
26
27
  agents/usage.py,sha256=Tb5udGd3DPgD0JBdRD8fDctTE4M-zKML5uRn8ZG1yBc,1675
27
28
  agents/version.py,sha256=_1knUwzSK-HUeZTpRUkk6Z-CIcurqXuEplbV5TLJ08E,230
28
29
  agents/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
30
  agents/extensions/handoff_filters.py,sha256=CS-k7TGCtT8TW3GeXb04OoFBXKdjg8-85QXswWAYBmI,2095
30
31
  agents/extensions/handoff_prompt.py,sha256=oGWN0uNh3Z1L7E-Ev2up8W084fFrDNOsLDy7P6bcmic,1006
31
32
  agents/extensions/visualization.py,sha256=sf9D_C-HMwkbWdZccTZvvMPRy_NSiwbm48tRJlESQBI,5144
32
- agents/extensions/memory/__init__.py,sha256=m2LezCvjjo1PgbdA-grEMCQBnzVKuTpaxfQgioJbnZg,1459
33
+ agents/extensions/memory/__init__.py,sha256=CJqBzkU6knvDKHhM7H4VrFw9DygLuZikgKJqcLKji2Y,2233
34
+ agents/extensions/memory/advanced_sqlite_session.py,sha256=rCrXM878foAuBN-rN2fibP2GHs-1hTtRx-TQcDKIfGI,52883
33
35
  agents/extensions/memory/encrypt_session.py,sha256=PVnZIEj50bjUq16OLnMKrbZiinLkrVpamPPEw8RnUCA,6485
36
+ agents/extensions/memory/redis_session.py,sha256=JwXY6zUTMgq9bRezlyFZ4Tze7DO7T0hioTc23qjSHjU,9838
34
37
  agents/extensions/memory/sqlalchemy_session.py,sha256=H0aykdB4lUikmzKgwWQqI1PSYZBvHA4TDnaj9rP4HDI,11583
35
38
  agents/extensions/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- agents/extensions/models/litellm_model.py,sha256=N4EVgii2d1oVvYQKptJ0QdjelfgujRm9kfPW_T5sBXg,18031
39
+ agents/extensions/models/litellm_model.py,sha256=FM4wIouSWIqXHoksZodoWsMLYTF4CT3j0IeFSWf-8oo,23642
37
40
  agents/extensions/models/litellm_provider.py,sha256=ZHgh1nMoEvA7NpawkzLh3JDuDFtwXUV94Rs7UrwWqAk,1083
38
41
  agents/mcp/__init__.py,sha256=yHmmYlrmEHzUas1inRLKL2iPqbb_-107G3gKe_tyg4I,750
39
42
  agents/mcp/server.py,sha256=4T58xiWCLiCm6JoUy_3jYWz5A8ZNsHiV1hIxjahoedU,26624
@@ -45,7 +48,7 @@ agents/memory/sqlite_session.py,sha256=6HGzSL70mQgutITIPZUC2x2Qtj6U4hXiZTceu3Da7
45
48
  agents/memory/util.py,sha256=ZAHOrNVA36xICFzuNgHgEA1_s_oEMO6Wsu6-EecY8JU,586
46
49
  agents/models/__init__.py,sha256=E0XVqWayVAsFqxucDLBW30siaqfNQsVrAnfidG_C3ok,287
47
50
  agents/models/_openai_shared.py,sha256=4Ngwo2Fv2RXY61Pqck1cYPkSln2tDnb8Ai-ao4QG-iE,836
48
- agents/models/chatcmpl_converter.py,sha256=anhAfw_5fRO3JtGGSPFbX_A6TKW0t-dK6orIffvaUpU,24514
51
+ agents/models/chatcmpl_converter.py,sha256=yPf8AbCm43hpkB37zd3gdPtD-wHdcCDQS9vSeAmBPk4,24748
49
52
  agents/models/chatcmpl_helpers.py,sha256=YC2krp_-uBgRCrCEImLjNvONTWRWfwLlPKHI4kBmNXE,1483
50
53
  agents/models/chatcmpl_stream_handler.py,sha256=r8nc-4hJg1plw87y24MD48O23xnfC_2gHKowtOYgO3M,28896
51
54
  agents/models/default_models.py,sha256=mlvBePn8H4UkHo7lN-wh7A3k2ciLgBUFKpROQxzdTfs,2098
@@ -105,7 +108,7 @@ agents/voice/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
105
108
  agents/voice/models/openai_model_provider.py,sha256=Khn0uT-VhsEbe7_OhBMGFQzXNwL80gcWZyTHl3CaBII,3587
106
109
  agents/voice/models/openai_stt.py,sha256=eZ0dmX_uDywpR1H3Q2N5jrV7NK3bR9l2a1InWM3yegk,17151
107
110
  agents/voice/models/openai_tts.py,sha256=4KoLQuFDHKu5a1VTJlu9Nj3MHwMlrn9wfT_liJDJ2dw,1477
108
- openai_agents-0.3.2.dist-info/METADATA,sha256=LSs6G1M2jEDrXEGTP_S__4F5cmifoRvEMOJ7AZH4hMU,12462
109
- openai_agents-0.3.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
110
- openai_agents-0.3.2.dist-info/licenses/LICENSE,sha256=E994EspT7Krhy0qGiES7WYNzBHrh1YDk3r--8d1baRU,1063
111
- openai_agents-0.3.2.dist-info/RECORD,,
111
+ openai_agents-0.3.3.dist-info/METADATA,sha256=hFUaemXENkZOPW-c06PatiRUDp19Mx0yj8LQ74eyHOk,12933
112
+ openai_agents-0.3.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
113
+ openai_agents-0.3.3.dist-info/licenses/LICENSE,sha256=E994EspT7Krhy0qGiES7WYNzBHrh1YDk3r--8d1baRU,1063
114
+ openai_agents-0.3.3.dist-info/RECORD,,