openai-sdk-helpers 0.2.0__py3-none-any.whl → 0.3.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.
- openai_sdk_helpers/__init__.py +4 -4
- openai_sdk_helpers/agent/__init__.py +6 -4
- openai_sdk_helpers/agent/base.py +211 -47
- openai_sdk_helpers/agent/config.py +354 -47
- openai_sdk_helpers/agent/coordination.py +7 -6
- openai_sdk_helpers/agent/runner.py +13 -4
- openai_sdk_helpers/agent/search/base.py +17 -17
- openai_sdk_helpers/agent/search/vector.py +13 -10
- openai_sdk_helpers/agent/search/web.py +13 -10
- openai_sdk_helpers/agent/summarizer.py +5 -4
- openai_sdk_helpers/agent/translator.py +5 -4
- openai_sdk_helpers/agent/validation.py +5 -4
- openai_sdk_helpers/response/base.py +70 -0
- openai_sdk_helpers/response/config.py +7 -149
- openai_sdk_helpers/utils/instructions.py +35 -0
- openai_sdk_helpers/utils/json_utils.py +10 -2
- openai_sdk_helpers/utils/registry.py +183 -0
- {openai_sdk_helpers-0.2.0.dist-info → openai_sdk_helpers-0.3.0.dist-info}/METADATA +1 -1
- {openai_sdk_helpers-0.2.0.dist-info → openai_sdk_helpers-0.3.0.dist-info}/RECORD +22 -20
- {openai_sdk_helpers-0.2.0.dist-info → openai_sdk_helpers-0.3.0.dist-info}/WHEEL +0 -0
- {openai_sdk_helpers-0.2.0.dist-info → openai_sdk_helpers-0.3.0.dist-info}/entry_points.txt +0 -0
- {openai_sdk_helpers-0.2.0.dist-info → openai_sdk_helpers-0.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,68 +1,375 @@
|
|
|
1
|
-
"""Configuration helpers for ``
|
|
1
|
+
"""Configuration helpers for ``BaseAgent``."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, Optional
|
|
6
8
|
|
|
9
|
+
from agents import Agent, Handoff, InputGuardrail, OutputGuardrail, Session
|
|
7
10
|
from agents.model_settings import ModelSettings
|
|
8
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
9
11
|
|
|
10
|
-
from ..
|
|
12
|
+
from ..utils import JSONSerializable
|
|
13
|
+
from ..utils.registry import BaseRegistry
|
|
14
|
+
from ..utils.instructions import resolve_instructions_from_path
|
|
11
15
|
|
|
12
16
|
|
|
13
|
-
class
|
|
14
|
-
"""
|
|
17
|
+
class AgentConfigurationRegistry(BaseRegistry["AgentConfiguration"]):
|
|
18
|
+
"""Registry for managing AgentConfiguration instances.
|
|
19
|
+
|
|
20
|
+
Inherits from BaseRegistry to provide centralized storage and retrieval
|
|
21
|
+
of agent configurations, enabling reusable agent specs across the application.
|
|
22
|
+
|
|
23
|
+
Examples
|
|
24
|
+
--------
|
|
25
|
+
>>> registry = AgentConfigurationRegistry()
|
|
26
|
+
>>> config = AgentConfiguration(
|
|
27
|
+
... name="test_agent",
|
|
28
|
+
... model="gpt-4o-mini",
|
|
29
|
+
... instructions="Test instructions"
|
|
30
|
+
... )
|
|
31
|
+
>>> registry.register(config)
|
|
32
|
+
>>> retrieved = registry.get("test_agent")
|
|
33
|
+
>>> retrieved.name
|
|
34
|
+
'test_agent'
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def load_from_directory(
|
|
38
|
+
self,
|
|
39
|
+
path: Path | str,
|
|
40
|
+
*,
|
|
41
|
+
config_class: type["AgentConfiguration"] | None = None,
|
|
42
|
+
) -> int:
|
|
43
|
+
"""Load all agent configurations from JSON files in a directory.
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
path : Path or str
|
|
48
|
+
Directory path containing JSON configuration files.
|
|
49
|
+
config_class : type[AgentConfiguration], optional
|
|
50
|
+
The configuration class to use for deserialization.
|
|
51
|
+
Defaults to AgentConfiguration.
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
int
|
|
56
|
+
Number of configurations successfully loaded and registered.
|
|
57
|
+
|
|
58
|
+
Raises
|
|
59
|
+
------
|
|
60
|
+
FileNotFoundError
|
|
61
|
+
If the directory does not exist.
|
|
62
|
+
NotADirectoryError
|
|
63
|
+
If the path is not a directory.
|
|
64
|
+
|
|
65
|
+
Examples
|
|
66
|
+
--------
|
|
67
|
+
>>> registry = AgentConfigurationRegistry()
|
|
68
|
+
>>> count = registry.load_from_directory("./agents")
|
|
69
|
+
>>> print(f"Loaded {count} configurations")
|
|
70
|
+
"""
|
|
71
|
+
if config_class is None:
|
|
72
|
+
config_class = AgentConfiguration
|
|
73
|
+
return super().load_from_directory(path, config_class=config_class)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Global default registry instance
|
|
77
|
+
_default_registry = AgentConfigurationRegistry()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_default_registry() -> AgentConfigurationRegistry:
|
|
81
|
+
"""Return the global default registry instance.
|
|
82
|
+
|
|
83
|
+
Returns
|
|
84
|
+
-------
|
|
85
|
+
AgentConfigurationRegistry
|
|
86
|
+
Singleton registry for application-wide configuration storage.
|
|
87
|
+
|
|
88
|
+
Examples
|
|
89
|
+
--------
|
|
90
|
+
>>> registry = get_default_registry()
|
|
91
|
+
>>> config = AgentConfiguration(
|
|
92
|
+
... name="test", model="gpt-4o-mini", instructions="Test instructions"
|
|
93
|
+
... )
|
|
94
|
+
>>> registry.register(config)
|
|
95
|
+
"""
|
|
96
|
+
return _default_registry
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(frozen=True, slots=True)
|
|
100
|
+
class AgentConfiguration(JSONSerializable):
|
|
101
|
+
"""Immutable configuration for building a BaseAgent.
|
|
102
|
+
|
|
103
|
+
Encapsulates all metadata required to define an agent including its
|
|
104
|
+
instructions, tools, model settings, handoffs, guardrails, and session
|
|
105
|
+
management. Inherits from JSONSerializable to support serialization.
|
|
106
|
+
|
|
107
|
+
This dataclass is frozen (immutable) to ensure thread-safety and
|
|
108
|
+
enable use as dictionary keys. All list-type fields use None as the
|
|
109
|
+
default value rather than mutable defaults like [] to avoid issues
|
|
110
|
+
with shared state across instances.
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
name : str
|
|
115
|
+
Unique identifier for the agent. Must be a non-empty string.
|
|
116
|
+
instructions : str or Path
|
|
117
|
+
Plain text instructions or a path to a Jinja template file whose
|
|
118
|
+
contents are loaded at runtime. Required field.
|
|
119
|
+
description : str, optional
|
|
120
|
+
Short description of the agent's purpose. Default is None.
|
|
121
|
+
model : str, optional
|
|
122
|
+
Model identifier to use (e.g., "gpt-4o-mini"). Default is None.
|
|
123
|
+
template_path : str or Path, optional
|
|
124
|
+
Path to the Jinja template (absolute or relative to prompt_dir).
|
|
125
|
+
This takes precedence over instructions if both are provided.
|
|
126
|
+
Default is None.
|
|
127
|
+
input_type : type, optional
|
|
128
|
+
Type describing the agent input, commonly a Pydantic model.
|
|
129
|
+
Default is None.
|
|
130
|
+
output_type : type, optional
|
|
131
|
+
Type describing the agent output, commonly a Pydantic model or
|
|
132
|
+
builtin like str. Default is None.
|
|
133
|
+
tools : list, optional
|
|
134
|
+
Tool definitions available to the agent. Default is None.
|
|
135
|
+
model_settings : ModelSettings, optional
|
|
136
|
+
Additional model configuration settings. Default is None.
|
|
137
|
+
handoffs : list[Agent or Handoff], optional
|
|
138
|
+
List of agents or handoff configurations that this agent can
|
|
139
|
+
delegate to for specific tasks. Default is None.
|
|
140
|
+
input_guardrails : list[InputGuardrail], optional
|
|
141
|
+
List of guardrails to validate agent inputs before processing.
|
|
142
|
+
Default is None.
|
|
143
|
+
output_guardrails : list[OutputGuardrail], optional
|
|
144
|
+
List of guardrails to validate agent outputs before returning.
|
|
145
|
+
Default is None.
|
|
146
|
+
session : Session, optional
|
|
147
|
+
Session configuration for automatically maintaining conversation
|
|
148
|
+
history across agent runs. Default is None.
|
|
15
149
|
|
|
16
150
|
Methods
|
|
17
151
|
-------
|
|
18
|
-
|
|
19
|
-
|
|
152
|
+
__post_init__()
|
|
153
|
+
Validate configuration invariants after initialization.
|
|
154
|
+
instructions_text
|
|
155
|
+
Return the resolved instruction content as a string.
|
|
156
|
+
create_agent(run_context_wrapper, prompt_dir, default_model)
|
|
157
|
+
Create a BaseAgent instance from this configuration.
|
|
158
|
+
replace(**changes)
|
|
159
|
+
Create a new AgentConfiguration with specified fields replaced.
|
|
160
|
+
to_json()
|
|
161
|
+
Return a JSON-compatible dict (inherited from JSONSerializable).
|
|
162
|
+
to_json_file(filepath)
|
|
163
|
+
Write serialized JSON data to a file (inherited from JSONSerializable).
|
|
164
|
+
from_json(data)
|
|
165
|
+
Create an instance from a JSON-compatible dict (inherited from JSONSerializable).
|
|
166
|
+
from_json_file(filepath)
|
|
167
|
+
Load an instance from a JSON file (inherited from JSONSerializable).
|
|
168
|
+
|
|
169
|
+
Examples
|
|
170
|
+
--------
|
|
171
|
+
>>> config = AgentConfiguration(
|
|
172
|
+
... name="summarizer",
|
|
173
|
+
... description="Summarizes text",
|
|
174
|
+
... model="gpt-4o-mini"
|
|
175
|
+
... )
|
|
176
|
+
>>> config.name
|
|
177
|
+
'summarizer'
|
|
20
178
|
"""
|
|
21
179
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
180
|
+
name: str
|
|
181
|
+
instructions: str | Path
|
|
182
|
+
description: Optional[str] = None
|
|
183
|
+
model: Optional[str] = None
|
|
184
|
+
template_path: Optional[str | Path] = None
|
|
185
|
+
input_type: Optional[type] = None
|
|
186
|
+
output_type: Optional[type] = None
|
|
187
|
+
tools: Optional[list] = None
|
|
188
|
+
model_settings: Optional[ModelSettings] = None
|
|
189
|
+
handoffs: Optional[list[Agent | Handoff]] = None
|
|
190
|
+
input_guardrails: Optional[list[InputGuardrail]] = None
|
|
191
|
+
output_guardrails: Optional[list[OutputGuardrail]] = None
|
|
192
|
+
session: Optional[Session] = None
|
|
193
|
+
|
|
194
|
+
def __post_init__(self) -> None:
|
|
195
|
+
"""Validate configuration invariants after initialization.
|
|
196
|
+
|
|
197
|
+
Ensures that the name is a non-empty string and that instructions
|
|
198
|
+
are properly formatted.
|
|
199
|
+
|
|
200
|
+
Raises
|
|
201
|
+
------
|
|
202
|
+
TypeError
|
|
203
|
+
If name is not a non-empty string.
|
|
204
|
+
If instructions is not a string or Path.
|
|
205
|
+
ValueError
|
|
206
|
+
If instructions is an empty string.
|
|
207
|
+
FileNotFoundError
|
|
208
|
+
If instructions is a Path that doesn't point to a readable file.
|
|
209
|
+
"""
|
|
210
|
+
if not self.name or not isinstance(self.name, str):
|
|
211
|
+
raise TypeError("AgentConfiguration.name must be a non-empty str")
|
|
212
|
+
|
|
213
|
+
# Validate instructions (required field, like in Response module)
|
|
214
|
+
instructions_value = self.instructions
|
|
215
|
+
if isinstance(instructions_value, str):
|
|
216
|
+
if not instructions_value.strip():
|
|
217
|
+
raise ValueError(
|
|
218
|
+
"AgentConfiguration.instructions must be a non-empty str"
|
|
219
|
+
)
|
|
220
|
+
elif isinstance(instructions_value, Path):
|
|
221
|
+
instruction_path = instructions_value.expanduser()
|
|
222
|
+
if not instruction_path.is_file():
|
|
223
|
+
raise FileNotFoundError(
|
|
224
|
+
f"Instruction template not found: {instruction_path}"
|
|
225
|
+
)
|
|
226
|
+
else:
|
|
227
|
+
raise TypeError("AgentConfiguration.instructions must be a str or Path")
|
|
228
|
+
|
|
229
|
+
if self.template_path is not None and isinstance(self.template_path, Path):
|
|
230
|
+
# Validate template_path if it's a Path object
|
|
231
|
+
template = self.template_path.expanduser()
|
|
232
|
+
if not template.exists():
|
|
233
|
+
# We don't raise here because template_path might be relative
|
|
234
|
+
# and resolved later with prompt_dir
|
|
235
|
+
pass
|
|
236
|
+
|
|
237
|
+
@property
|
|
238
|
+
def instructions_text(self) -> str:
|
|
239
|
+
"""Return the resolved instruction text.
|
|
57
240
|
|
|
58
241
|
Returns
|
|
59
242
|
-------
|
|
60
243
|
str
|
|
61
|
-
|
|
244
|
+
Plain-text instructions, loading template files when necessary.
|
|
245
|
+
"""
|
|
246
|
+
return self._resolve_instructions()
|
|
247
|
+
|
|
248
|
+
def _resolve_instructions(self) -> str:
|
|
249
|
+
"""Resolve instructions from string or file path."""
|
|
250
|
+
return resolve_instructions_from_path(self.instructions)
|
|
251
|
+
|
|
252
|
+
def create_agent(
|
|
253
|
+
self,
|
|
254
|
+
run_context_wrapper: Any = None,
|
|
255
|
+
prompt_dir: Path | None = None,
|
|
256
|
+
default_model: str | None = None,
|
|
257
|
+
) -> Any:
|
|
258
|
+
"""Create a BaseAgent instance from this configuration.
|
|
259
|
+
|
|
260
|
+
This is a convenience method that delegates to BaseAgent.from_configuration().
|
|
261
|
+
|
|
262
|
+
Parameters
|
|
263
|
+
----------
|
|
264
|
+
run_context_wrapper : RunContextWrapper or None, default=None
|
|
265
|
+
Optional wrapper providing runtime context for prompt rendering.
|
|
266
|
+
prompt_dir : Path or None, default=None
|
|
267
|
+
Optional directory holding prompt templates.
|
|
268
|
+
default_model : str or None, default=None
|
|
269
|
+
Optional fallback model identifier if config doesn't specify one.
|
|
270
|
+
|
|
271
|
+
Returns
|
|
272
|
+
-------
|
|
273
|
+
BaseAgent
|
|
274
|
+
Configured agent instance ready for execution.
|
|
275
|
+
|
|
276
|
+
Examples
|
|
277
|
+
--------
|
|
278
|
+
>>> config = AgentConfiguration(
|
|
279
|
+
... name="helper", model="gpt-4o-mini", instructions="Help the user"
|
|
280
|
+
... )
|
|
281
|
+
>>> agent = config.create_agent()
|
|
282
|
+
>>> result = agent.run_sync("Hello!")
|
|
283
|
+
"""
|
|
284
|
+
# Import here to avoid circular dependency
|
|
285
|
+
from .base import BaseAgent
|
|
286
|
+
|
|
287
|
+
return BaseAgent.from_configuration(
|
|
288
|
+
config=self,
|
|
289
|
+
run_context_wrapper=run_context_wrapper,
|
|
290
|
+
prompt_dir=prompt_dir,
|
|
291
|
+
default_model=default_model,
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
def replace(self, **changes: Any) -> AgentConfiguration:
|
|
295
|
+
"""Create a new AgentConfiguration with specified fields replaced.
|
|
296
|
+
|
|
297
|
+
Since AgentConfiguration is frozen (immutable), this method creates a new
|
|
298
|
+
instance with the specified changes applied. This is useful for
|
|
299
|
+
creating variations of a configuration.
|
|
300
|
+
|
|
301
|
+
Parameters
|
|
302
|
+
----------
|
|
303
|
+
**changes : Any
|
|
304
|
+
Keyword arguments specifying fields to change and their new values.
|
|
305
|
+
|
|
306
|
+
Returns
|
|
307
|
+
-------
|
|
308
|
+
AgentConfiguration
|
|
309
|
+
New configuration instance with changes applied.
|
|
310
|
+
|
|
311
|
+
Examples
|
|
312
|
+
--------
|
|
313
|
+
>>> config = AgentConfiguration(
|
|
314
|
+
... name="agent1", model="gpt-4o-mini", instructions="Agent instructions"
|
|
315
|
+
... )
|
|
316
|
+
>>> config2 = config.replace(name="agent2", description="Modified")
|
|
317
|
+
>>> config2.name
|
|
318
|
+
'agent2'
|
|
319
|
+
>>> config2.model
|
|
320
|
+
'gpt-4o-mini'
|
|
62
321
|
"""
|
|
63
|
-
|
|
322
|
+
from dataclasses import replace
|
|
323
|
+
|
|
324
|
+
return replace(self, **changes)
|
|
325
|
+
|
|
326
|
+
@classmethod
|
|
327
|
+
def from_json(cls, data: dict[str, Any]) -> AgentConfiguration:
|
|
328
|
+
"""Create an AgentConfiguration from JSON data.
|
|
329
|
+
|
|
330
|
+
Overrides the default JSONSerializable.from_json to properly handle
|
|
331
|
+
the instructions field, converting string paths that look like file
|
|
332
|
+
paths back to Path objects for proper file loading.
|
|
333
|
+
|
|
334
|
+
Parameters
|
|
335
|
+
----------
|
|
336
|
+
data : dict[str, Any]
|
|
337
|
+
Dictionary containing the configuration data.
|
|
338
|
+
|
|
339
|
+
Returns
|
|
340
|
+
-------
|
|
341
|
+
AgentConfiguration
|
|
342
|
+
New configuration instance.
|
|
343
|
+
|
|
344
|
+
Notes
|
|
345
|
+
-----
|
|
346
|
+
This method attempts to preserve the original type of the instructions
|
|
347
|
+
field. If instructions is a string that represents an existing file path,
|
|
348
|
+
it will be converted to a Path object to ensure proper file loading
|
|
349
|
+
behavior is maintained across JSON round-trips.
|
|
350
|
+
"""
|
|
351
|
+
# Make a copy to avoid modifying the input
|
|
352
|
+
data = data.copy()
|
|
353
|
+
|
|
354
|
+
# Handle instructions field: if it's a string path to an existing file,
|
|
355
|
+
# convert it back to Path for proper file loading
|
|
356
|
+
if "instructions" in data and data["instructions"] is not None:
|
|
357
|
+
instructions_value = data["instructions"]
|
|
358
|
+
if isinstance(instructions_value, str):
|
|
359
|
+
# Check if it looks like a file path and the file exists
|
|
360
|
+
# This preserves the intended behavior for file-based instructions
|
|
361
|
+
try:
|
|
362
|
+
potential_path = Path(instructions_value)
|
|
363
|
+
# Only convert to Path if it's an existing file
|
|
364
|
+
# This way, plain text instructions stay as strings
|
|
365
|
+
if potential_path.exists() and potential_path.is_file():
|
|
366
|
+
data["instructions"] = potential_path
|
|
367
|
+
except (OSError, ValueError):
|
|
368
|
+
# If path parsing fails, keep it as a string (likely plain text)
|
|
369
|
+
pass
|
|
64
370
|
|
|
371
|
+
# Use the parent class method for the rest
|
|
372
|
+
return super(AgentConfiguration, cls).from_json(data)
|
|
65
373
|
|
|
66
|
-
__all__ = ["AgentConfig"]
|
|
67
374
|
|
|
68
|
-
|
|
375
|
+
__all__ = ["AgentConfiguration", "AgentConfigurationRegistry", "get_default_registry"]
|
|
@@ -13,8 +13,8 @@ from typing import Any, Callable, Dict, List, Optional
|
|
|
13
13
|
|
|
14
14
|
from ..structure import TaskStructure, PlanStructure, PromptStructure
|
|
15
15
|
from ..utils import JSONSerializable, ensure_directory, log
|
|
16
|
-
from .base import
|
|
17
|
-
from .config import
|
|
16
|
+
from .base import BaseAgent
|
|
17
|
+
from .config import AgentConfiguration
|
|
18
18
|
from ..structure.plan.enum import AgentEnum
|
|
19
19
|
|
|
20
20
|
PromptFn = Callable[[str], PromptStructure]
|
|
@@ -23,7 +23,7 @@ ExecutePlanFn = Callable[[PlanStructure], List[str]]
|
|
|
23
23
|
SummarizeFn = Callable[[List[str]], str]
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
class CoordinatorAgent(
|
|
26
|
+
class CoordinatorAgent(BaseAgent, JSONSerializable):
|
|
27
27
|
"""Coordinate agent plans while persisting project state and outputs.
|
|
28
28
|
|
|
29
29
|
Methods
|
|
@@ -63,7 +63,7 @@ class CoordinatorAgent(AgentBase, JSONSerializable):
|
|
|
63
63
|
summarize_fn: SummarizeFn,
|
|
64
64
|
module_data_path: Path,
|
|
65
65
|
name: str,
|
|
66
|
-
config: Optional[
|
|
66
|
+
config: Optional[AgentConfiguration] = None,
|
|
67
67
|
prompt_dir: Optional[Path] = None,
|
|
68
68
|
default_model: Optional[str] = None,
|
|
69
69
|
) -> None:
|
|
@@ -83,7 +83,7 @@ class CoordinatorAgent(AgentBase, JSONSerializable):
|
|
|
83
83
|
Base path for persisting project artifacts.
|
|
84
84
|
name : str
|
|
85
85
|
Name of the parent module for data organization.
|
|
86
|
-
config :
|
|
86
|
+
config : AgentConfiguration or None, default=None
|
|
87
87
|
Optional agent configuration describing prompts and metadata.
|
|
88
88
|
prompt_dir : Path or None, default=None
|
|
89
89
|
Optional directory holding prompt templates.
|
|
@@ -91,8 +91,9 @@ class CoordinatorAgent(AgentBase, JSONSerializable):
|
|
|
91
91
|
Optional fallback model identifier.
|
|
92
92
|
"""
|
|
93
93
|
if config is None:
|
|
94
|
-
config =
|
|
94
|
+
config = AgentConfiguration(
|
|
95
95
|
name="coordinator_agent",
|
|
96
|
+
instructions="Coordinate agents for planning and summarization.",
|
|
96
97
|
description="Coordinates agents for planning and summarization.",
|
|
97
98
|
)
|
|
98
99
|
super().__init__(
|
|
@@ -9,7 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
|
|
10
10
|
from typing import Any, Dict, Optional
|
|
11
11
|
|
|
12
|
-
from agents import Agent, RunResult, RunResultStreaming, Runner
|
|
12
|
+
from agents import Agent, RunResult, RunResultStreaming, Runner, Session
|
|
13
13
|
|
|
14
14
|
from openai_sdk_helpers.utils.async_utils import run_coroutine_with_fallback
|
|
15
15
|
|
|
@@ -20,6 +20,7 @@ async def run_async(
|
|
|
20
20
|
*,
|
|
21
21
|
context: Optional[Dict[str, Any]] = None,
|
|
22
22
|
output_type: Optional[Any] = None,
|
|
23
|
+
session: Optional[Session] = None,
|
|
23
24
|
) -> Any:
|
|
24
25
|
"""Run an Agent asynchronously.
|
|
25
26
|
|
|
@@ -33,6 +34,8 @@ async def run_async(
|
|
|
33
34
|
Optional context dictionary passed to the agent.
|
|
34
35
|
output_type : type or None, default=None
|
|
35
36
|
Optional type used to cast the final output.
|
|
37
|
+
session : Session or None, default=None
|
|
38
|
+
Optional session for maintaining conversation history.
|
|
36
39
|
|
|
37
40
|
Returns
|
|
38
41
|
-------
|
|
@@ -49,7 +52,7 @@ async def run_async(
|
|
|
49
52
|
... return result
|
|
50
53
|
>>> asyncio.run(example()) # doctest: +SKIP
|
|
51
54
|
"""
|
|
52
|
-
result = await Runner.run(agent, input, context=context)
|
|
55
|
+
result = await Runner.run(agent, input, context=context, session=session)
|
|
53
56
|
if output_type is not None:
|
|
54
57
|
return result.final_output_as(output_type)
|
|
55
58
|
return result
|
|
@@ -61,6 +64,7 @@ def run_sync(
|
|
|
61
64
|
*,
|
|
62
65
|
context: Optional[Dict[str, Any]] = None,
|
|
63
66
|
output_type: Optional[Any] = None,
|
|
67
|
+
session: Optional[Session] = None,
|
|
64
68
|
) -> Any:
|
|
65
69
|
"""Run an Agent synchronously.
|
|
66
70
|
|
|
@@ -78,6 +82,8 @@ def run_sync(
|
|
|
78
82
|
Optional context dictionary passed to the agent.
|
|
79
83
|
output_type : type or None, default=None
|
|
80
84
|
Optional type used to cast the final output.
|
|
85
|
+
session : Session or None, default=None
|
|
86
|
+
Optional session for maintaining conversation history.
|
|
81
87
|
|
|
82
88
|
Returns
|
|
83
89
|
-------
|
|
@@ -95,7 +101,7 @@ def run_sync(
|
|
|
95
101
|
>>> agent = Agent(name="test", instructions="test", model="gpt-4o-mini")
|
|
96
102
|
>>> result = run_sync(agent, "What is 2+2?") # doctest: +SKIP
|
|
97
103
|
"""
|
|
98
|
-
coro = Runner.run(agent, input, context=context)
|
|
104
|
+
coro = Runner.run(agent, input, context=context, session=session)
|
|
99
105
|
result: RunResult = run_coroutine_with_fallback(coro)
|
|
100
106
|
if output_type is not None:
|
|
101
107
|
return result.final_output_as(output_type)
|
|
@@ -108,6 +114,7 @@ def run_streamed(
|
|
|
108
114
|
*,
|
|
109
115
|
context: Optional[Dict[str, Any]] = None,
|
|
110
116
|
output_type: Optional[Any] = None,
|
|
117
|
+
session: Optional[Session] = None,
|
|
111
118
|
) -> RunResultStreaming:
|
|
112
119
|
"""Stream agent execution results.
|
|
113
120
|
|
|
@@ -121,6 +128,8 @@ def run_streamed(
|
|
|
121
128
|
Optional context dictionary passed to the agent.
|
|
122
129
|
output_type : type or None, default=None
|
|
123
130
|
Optional type used to cast the final output.
|
|
131
|
+
session : Session or None, default=None
|
|
132
|
+
Optional session for maintaining conversation history.
|
|
124
133
|
|
|
125
134
|
Returns
|
|
126
135
|
-------
|
|
@@ -135,7 +144,7 @@ def run_streamed(
|
|
|
135
144
|
>>> for chunk in result.stream_text(): # doctest: +SKIP
|
|
136
145
|
... print(chunk, end="")
|
|
137
146
|
"""
|
|
138
|
-
result = Runner.run_streamed(agent, input, context=context)
|
|
147
|
+
result = Runner.run_streamed(agent, input, context=context, session=session)
|
|
139
148
|
if output_type is not None:
|
|
140
149
|
return result.final_output_as(output_type)
|
|
141
150
|
return result
|
|
@@ -12,8 +12,8 @@ from abc import ABC, abstractmethod
|
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Generic, List, Optional, TypeVar, Union
|
|
14
14
|
|
|
15
|
-
from ..base import
|
|
16
|
-
from ..config import
|
|
15
|
+
from ..base import BaseAgent
|
|
16
|
+
from ..config import AgentConfiguration
|
|
17
17
|
|
|
18
18
|
# Type variables for search workflow components
|
|
19
19
|
ItemType = TypeVar("ItemType") # Search item structure (e.g., WebSearchItemStructure)
|
|
@@ -23,7 +23,7 @@ ReportType = TypeVar("ReportType") # Final report structure
|
|
|
23
23
|
OutputType = TypeVar("OutputType") # Generic output type
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
class SearchPlanner(
|
|
26
|
+
class SearchPlanner(BaseAgent, Generic[PlanType]):
|
|
27
27
|
"""Generic planner agent for search workflows.
|
|
28
28
|
|
|
29
29
|
Subclasses implement specific planner logic by overriding the
|
|
@@ -34,7 +34,7 @@ class SearchPlanner(AgentBase, Generic[PlanType]):
|
|
|
34
34
|
run_agent(query)
|
|
35
35
|
Generate a search plan for the provided query.
|
|
36
36
|
_configure_agent()
|
|
37
|
-
Return
|
|
37
|
+
Return AgentConfiguration for this planner instance.
|
|
38
38
|
"""
|
|
39
39
|
|
|
40
40
|
def __init__(
|
|
@@ -59,17 +59,17 @@ class SearchPlanner(AgentBase, Generic[PlanType]):
|
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
@abstractmethod
|
|
62
|
-
def _configure_agent(self) ->
|
|
62
|
+
def _configure_agent(self) -> AgentConfiguration:
|
|
63
63
|
"""Return configuration for this planner.
|
|
64
64
|
|
|
65
65
|
Returns
|
|
66
66
|
-------
|
|
67
|
-
|
|
67
|
+
AgentConfiguration
|
|
68
68
|
Configuration with name, description, and output_type set.
|
|
69
69
|
|
|
70
70
|
Examples
|
|
71
71
|
--------
|
|
72
|
-
>>> config =
|
|
72
|
+
>>> config = AgentConfiguration(
|
|
73
73
|
... name="web_planner",
|
|
74
74
|
... description="Plan web searches",
|
|
75
75
|
... output_type=WebSearchPlanStructure,
|
|
@@ -98,7 +98,7 @@ class SearchPlanner(AgentBase, Generic[PlanType]):
|
|
|
98
98
|
return result
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
class SearchToolAgent(
|
|
101
|
+
class SearchToolAgent(BaseAgent, Generic[ItemType, ResultType, PlanType]):
|
|
102
102
|
"""Generic tool agent for executing search workflows.
|
|
103
103
|
|
|
104
104
|
Executes individual searches in a plan with concurrency control.
|
|
@@ -112,7 +112,7 @@ class SearchToolAgent(AgentBase, Generic[ItemType, ResultType, PlanType]):
|
|
|
112
112
|
run_search(item)
|
|
113
113
|
Execute a single search item.
|
|
114
114
|
_configure_agent()
|
|
115
|
-
Return
|
|
115
|
+
Return AgentConfiguration for this tool agent.
|
|
116
116
|
"""
|
|
117
117
|
|
|
118
118
|
def __init__(
|
|
@@ -142,17 +142,17 @@ class SearchToolAgent(AgentBase, Generic[ItemType, ResultType, PlanType]):
|
|
|
142
142
|
)
|
|
143
143
|
|
|
144
144
|
@abstractmethod
|
|
145
|
-
def _configure_agent(self) ->
|
|
145
|
+
def _configure_agent(self) -> AgentConfiguration:
|
|
146
146
|
"""Return configuration for this tool agent.
|
|
147
147
|
|
|
148
148
|
Returns
|
|
149
149
|
-------
|
|
150
|
-
|
|
150
|
+
AgentConfiguration
|
|
151
151
|
Configuration with name, description, input_type, and tools set.
|
|
152
152
|
|
|
153
153
|
Examples
|
|
154
154
|
--------
|
|
155
|
-
>>> config =
|
|
155
|
+
>>> config = AgentConfiguration(
|
|
156
156
|
... name="web_search",
|
|
157
157
|
... description="Perform web searches",
|
|
158
158
|
... input_type=WebSearchPlanStructure,
|
|
@@ -205,7 +205,7 @@ class SearchToolAgent(AgentBase, Generic[ItemType, ResultType, PlanType]):
|
|
|
205
205
|
return [result for result in results if result is not None]
|
|
206
206
|
|
|
207
207
|
|
|
208
|
-
class SearchWriter(
|
|
208
|
+
class SearchWriter(BaseAgent, Generic[ReportType]):
|
|
209
209
|
"""Generic writer agent for search workflow reports.
|
|
210
210
|
|
|
211
211
|
Synthesizes search results into a final report. Subclasses implement
|
|
@@ -216,7 +216,7 @@ class SearchWriter(AgentBase, Generic[ReportType]):
|
|
|
216
216
|
run_agent(query, search_results)
|
|
217
217
|
Generate a report from search results.
|
|
218
218
|
_configure_agent()
|
|
219
|
-
Return
|
|
219
|
+
Return AgentConfiguration for this writer instance.
|
|
220
220
|
"""
|
|
221
221
|
|
|
222
222
|
def __init__(
|
|
@@ -241,17 +241,17 @@ class SearchWriter(AgentBase, Generic[ReportType]):
|
|
|
241
241
|
)
|
|
242
242
|
|
|
243
243
|
@abstractmethod
|
|
244
|
-
def _configure_agent(self) ->
|
|
244
|
+
def _configure_agent(self) -> AgentConfiguration:
|
|
245
245
|
"""Return configuration for this writer.
|
|
246
246
|
|
|
247
247
|
Returns
|
|
248
248
|
-------
|
|
249
|
-
|
|
249
|
+
AgentConfiguration
|
|
250
250
|
Configuration with name, description, and output_type set.
|
|
251
251
|
|
|
252
252
|
Examples
|
|
253
253
|
--------
|
|
254
|
-
>>> config =
|
|
254
|
+
>>> config = AgentConfiguration(
|
|
255
255
|
... name="web_writer",
|
|
256
256
|
... description="Write web search report",
|
|
257
257
|
... output_type=WebSearchReportStructure,
|