openai-sdk-helpers 0.4.2__py3-none-any.whl → 0.5.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 (68) hide show
  1. openai_sdk_helpers/__init__.py +45 -41
  2. openai_sdk_helpers/agent/__init__.py +4 -6
  3. openai_sdk_helpers/agent/base.py +110 -191
  4. openai_sdk_helpers/agent/{config.py → configuration.py} +24 -32
  5. openai_sdk_helpers/agent/{coordination.py → coordinator.py} +22 -23
  6. openai_sdk_helpers/agent/runner.py +3 -45
  7. openai_sdk_helpers/agent/search/base.py +54 -76
  8. openai_sdk_helpers/agent/search/vector.py +92 -108
  9. openai_sdk_helpers/agent/search/web.py +104 -82
  10. openai_sdk_helpers/agent/summarizer.py +22 -28
  11. openai_sdk_helpers/agent/translator.py +22 -24
  12. openai_sdk_helpers/agent/{validation.py → validator.py} +19 -23
  13. openai_sdk_helpers/cli.py +8 -22
  14. openai_sdk_helpers/environment.py +8 -13
  15. openai_sdk_helpers/errors.py +9 -0
  16. openai_sdk_helpers/extract/__init__.py +23 -0
  17. openai_sdk_helpers/extract/extractor.py +157 -0
  18. openai_sdk_helpers/extract/generator.py +476 -0
  19. openai_sdk_helpers/prompt/extractor_config_agent_instructions.jinja +6 -0
  20. openai_sdk_helpers/prompt/extractor_config_generator.jinja +37 -0
  21. openai_sdk_helpers/prompt/extractor_config_generator_instructions.jinja +9 -0
  22. openai_sdk_helpers/prompt/extractor_prompt_optimizer_agent_instructions.jinja +4 -0
  23. openai_sdk_helpers/prompt/extractor_prompt_optimizer_request.jinja +11 -0
  24. openai_sdk_helpers/prompt/vector_planner.jinja +7 -0
  25. openai_sdk_helpers/prompt/vector_search.jinja +6 -0
  26. openai_sdk_helpers/prompt/vector_writer.jinja +7 -0
  27. openai_sdk_helpers/response/__init__.py +3 -7
  28. openai_sdk_helpers/response/base.py +89 -98
  29. openai_sdk_helpers/response/{config.py → configuration.py} +45 -20
  30. openai_sdk_helpers/response/files.py +2 -0
  31. openai_sdk_helpers/response/planner.py +1 -1
  32. openai_sdk_helpers/response/prompter.py +1 -1
  33. openai_sdk_helpers/response/runner.py +1 -48
  34. openai_sdk_helpers/response/tool_call.py +0 -141
  35. openai_sdk_helpers/response/vector_store.py +8 -5
  36. openai_sdk_helpers/streamlit_app/__init__.py +1 -1
  37. openai_sdk_helpers/streamlit_app/app.py +17 -18
  38. openai_sdk_helpers/streamlit_app/{config.py → configuration.py} +13 -13
  39. openai_sdk_helpers/structure/__init__.py +16 -0
  40. openai_sdk_helpers/structure/base.py +239 -278
  41. openai_sdk_helpers/structure/extraction.py +1228 -0
  42. openai_sdk_helpers/structure/plan/plan.py +0 -20
  43. openai_sdk_helpers/structure/plan/task.py +0 -33
  44. openai_sdk_helpers/structure/prompt.py +16 -0
  45. openai_sdk_helpers/structure/responses.py +2 -2
  46. openai_sdk_helpers/structure/web_search.py +0 -10
  47. openai_sdk_helpers/tools.py +346 -99
  48. openai_sdk_helpers/types.py +3 -3
  49. openai_sdk_helpers/utils/__init__.py +9 -6
  50. openai_sdk_helpers/utils/json/base_model.py +316 -33
  51. openai_sdk_helpers/utils/json/data_class.py +1 -1
  52. openai_sdk_helpers/utils/langextract.py +194 -0
  53. openai_sdk_helpers/utils/registry.py +19 -15
  54. openai_sdk_helpers/vector_storage/storage.py +1 -1
  55. {openai_sdk_helpers-0.4.2.dist-info → openai_sdk_helpers-0.5.0.dist-info}/METADATA +25 -11
  56. openai_sdk_helpers-0.5.0.dist-info/RECORD +95 -0
  57. openai_sdk_helpers/agent/prompt_utils.py +0 -15
  58. openai_sdk_helpers/context_manager.py +0 -241
  59. openai_sdk_helpers/deprecation.py +0 -167
  60. openai_sdk_helpers/retry.py +0 -175
  61. openai_sdk_helpers/streamlit_app/streamlit_web_search.py +0 -75
  62. openai_sdk_helpers/utils/deprecation.py +0 -167
  63. openai_sdk_helpers-0.4.2.dist-info/RECORD +0 -88
  64. /openai_sdk_helpers/{logging_config.py → logging.py} +0 -0
  65. /openai_sdk_helpers/{config.py → settings.py} +0 -0
  66. {openai_sdk_helpers-0.4.2.dist-info → openai_sdk_helpers-0.5.0.dist-info}/WHEEL +0 -0
  67. {openai_sdk_helpers-0.4.2.dist-info → openai_sdk_helpers-0.5.0.dist-info}/entry_points.txt +0 -0
  68. {openai_sdk_helpers-0.4.2.dist-info → openai_sdk_helpers-0.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -3,11 +3,12 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from pathlib import Path
6
- from typing import Any, Callable, Dict, List, Optional
6
+ from typing import Any, Callable, List, Optional
7
7
 
8
8
  from agents import custom_span, gen_trace_id, trace
9
+ from agents.model_settings import ModelSettings
9
10
 
10
- from ...structure.prompt import PromptStructure
11
+ from ...environment import DEFAULT_PROMPT_DIR
11
12
  from ...structure.vector_search import (
12
13
  VectorSearchItemStructure,
13
14
  VectorSearchItemResultStructure,
@@ -16,11 +17,11 @@ from ...structure.vector_search import (
16
17
  VectorSearchPlanStructure,
17
18
  VectorSearchReportStructure,
18
19
  )
19
- from ...tools import tool_handler_factory
20
20
  from ...vector_storage import VectorStorage
21
- from ..config import AgentConfiguration
21
+ from ..configuration import AgentConfiguration
22
22
  from ..utils import run_coroutine_agent_sync
23
23
  from .base import SearchPlanner, SearchToolAgent, SearchWriter
24
+ from ..base import AgentBase
24
25
 
25
26
  MAX_CONCURRENT_SEARCHES = 10
26
27
 
@@ -30,10 +31,10 @@ class VectorAgentPlanner(SearchPlanner[VectorSearchPlanStructure]):
30
31
 
31
32
  Parameters
32
33
  ----------
33
- prompt_dir : Path or None, default=None
34
- Directory containing prompt templates.
35
- default_model : str or None, default=None
36
- Default model identifier to use when not defined in config.
34
+ template_path : Path | str | None, optional
35
+ Template file path for prompt rendering.
36
+ model : str | None, optional
37
+ Model identifier to use when not defined in configuration.
37
38
 
38
39
  Methods
39
40
  -------
@@ -43,20 +44,19 @@ class VectorAgentPlanner(SearchPlanner[VectorSearchPlanStructure]):
43
44
  Raises
44
45
  ------
45
46
  ValueError
46
- If the default model is not provided.
47
+ If the configuration omits a model identifier.
47
48
 
48
49
  Examples
49
50
  --------
50
- >>> planner = VectorSearchPlanner(default_model="gpt-4o-mini")
51
+ >>> planner = VectorSearchPlanner(model="gpt-4o-mini")
51
52
  """
52
53
 
53
- def __init__(
54
- self, prompt_dir: Optional[Path] = None, default_model: Optional[str] = None
55
- ) -> None:
56
- """Initialize the planner agent."""
57
- super().__init__(prompt_dir=prompt_dir, default_model=default_model)
58
-
59
- def _configure_agent(self) -> AgentConfiguration:
54
+ def _configure_agent(
55
+ self,
56
+ template_path: Path | str | None = None,
57
+ model: str | None = None,
58
+ **kwargs: Any,
59
+ ) -> AgentConfiguration:
60
60
  """Return configuration for the vector planner agent.
61
61
 
62
62
  Returns
@@ -69,6 +69,9 @@ class VectorAgentPlanner(SearchPlanner[VectorSearchPlanStructure]):
69
69
  instructions="Agent instructions",
70
70
  description="Plan vector searches based on a user query.",
71
71
  output_structure=VectorSearchPlanStructure,
72
+ model_settings=ModelSettings(tool_choice="none"),
73
+ template_path=template_path,
74
+ model=model,
72
75
  )
73
76
 
74
77
 
@@ -83,11 +86,11 @@ class VectorSearchTool(
83
86
 
84
87
  Parameters
85
88
  ----------
86
- prompt_dir : Path or None, default=None
87
- Directory containing prompt templates.
88
- default_model : str or None, default=None
89
- Default model identifier to use when not defined in config.
90
- store_name : str or None, default=None
89
+ template_path : Path | str | None, optional
90
+ Template file path for prompt rendering.
91
+ model : str | None, optional
92
+ Model identifier to use when not defined in configuration.
93
+ store_name : str
91
94
  Name of the vector store to query.
92
95
  max_concurrent_searches : int, default=MAX_CONCURRENT_SEARCHES
93
96
  Maximum number of concurrent vector search tasks to run.
@@ -107,36 +110,20 @@ class VectorSearchTool(
107
110
  Raises
108
111
  ------
109
112
  ValueError
110
- If the default model is not provided.
113
+ If the configuration omits a model identifier.
111
114
 
112
115
  Examples
113
116
  --------
114
- >>> tool = VectorSearchTool(default_model="gpt-4o-mini", store_name="my_store")
117
+ >>> tool = VectorSearchTool(model="gpt-4o-mini", store_name="my_store")
115
118
  """
116
119
 
117
- def __init__(
120
+ def _configure_agent(
118
121
  self,
119
122
  *,
120
- prompt_dir: Optional[Path] = None,
121
- default_model: Optional[str] = None,
122
- store_name: Optional[str] = None,
123
- max_concurrent_searches: int = MAX_CONCURRENT_SEARCHES,
124
- vector_storage: Optional[VectorStorage] = None,
125
- vector_storage_factory: Optional[Callable[[str], VectorStorage]] = None,
126
- ) -> None:
127
- """Initialize the search tool agent."""
128
- self._vector_storage: Optional[VectorStorage] = None
129
- self._store_name = store_name or "editorial"
130
- self._vector_storage_factory = vector_storage_factory
131
- if vector_storage is not None:
132
- self._vector_storage = vector_storage
133
- super().__init__(
134
- prompt_dir=prompt_dir,
135
- default_model=default_model,
136
- max_concurrent_searches=max_concurrent_searches,
137
- )
138
-
139
- def _configure_agent(self) -> AgentConfiguration:
123
+ template_path: Path | str | None = None,
124
+ model: str | None = None,
125
+ **kwargs: Any,
126
+ ) -> AgentConfiguration:
140
127
  """Return configuration for the vector search tool agent.
141
128
 
142
129
  Returns
@@ -144,12 +131,37 @@ class VectorSearchTool(
144
131
  AgentConfiguration
145
132
  Configuration with name, description, and input type.
146
133
  """
134
+ if self._store_name is None:
135
+ raise ValueError("store_name must be provided to configure the agent.")
147
136
  return AgentConfiguration(
148
137
  name="vector_search",
149
138
  instructions="Agent instructions",
150
139
  description="Perform vector searches based on a search plan.",
151
140
  input_structure=VectorSearchPlanStructure,
152
141
  output_structure=VectorSearchItemResultsStructure,
142
+ model_settings=ModelSettings(tool_choice="none"),
143
+ template_path=template_path,
144
+ model=model,
145
+ )
146
+
147
+ def __init__(
148
+ self,
149
+ *,
150
+ store_name: str,
151
+ template_path: Path | str | None = None,
152
+ model: str | None = None,
153
+ max_concurrent_searches: int = MAX_CONCURRENT_SEARCHES,
154
+ vector_storage: Optional[VectorStorage] = None,
155
+ vector_storage_factory: Optional[Callable[[str], VectorStorage]] = None,
156
+ ) -> None:
157
+ """Initialize the vector search tool agent."""
158
+ self._vector_storage = vector_storage
159
+ self._vector_storage_factory = vector_storage_factory
160
+ self._store_name = store_name
161
+ super().__init__(
162
+ template_path=template_path,
163
+ model=model,
164
+ max_concurrent_searches=max_concurrent_searches,
153
165
  )
154
166
 
155
167
  def _get_vector_storage(self) -> VectorStorage:
@@ -201,10 +213,10 @@ class VectorSearchWriter(SearchWriter[VectorSearchReportStructure]):
201
213
 
202
214
  Parameters
203
215
  ----------
204
- prompt_dir : Path or None, default=None
205
- Directory containing prompt templates.
206
- default_model : str or None, default=None
207
- Default model identifier to use when not defined in config.
216
+ template_path : Path | str | None, optional
217
+ Template file path for prompt rendering.
218
+ model : str | None, optional
219
+ Model identifier to use when not defined in configuration.
208
220
 
209
221
  Methods
210
222
  -------
@@ -214,20 +226,32 @@ class VectorSearchWriter(SearchWriter[VectorSearchReportStructure]):
214
226
  Raises
215
227
  ------
216
228
  ValueError
217
- If the default model is not provided.
229
+ If the configuration omits a model identifier.
218
230
 
219
231
  Examples
220
232
  --------
221
- >>> writer = VectorSearchWriter(default_model="gpt-4o-mini")
233
+ >>> writer = VectorSearchWriter(model="gpt-4o-mini")
222
234
  """
223
235
 
224
236
  def __init__(
225
- self, prompt_dir: Optional[Path] = None, default_model: Optional[str] = None
237
+ self,
238
+ template_path: Path | str | None = None,
239
+ model: str | None = None,
240
+ **kwargs: Any,
226
241
  ) -> None:
227
242
  """Initialize the writer agent."""
228
- super().__init__(prompt_dir=prompt_dir, default_model=default_model)
243
+ configuration = self._configure_agent(
244
+ template_path=template_path, model=model, **kwargs
245
+ )
246
+ super().__init__(configuration=configuration)
229
247
 
230
- def _configure_agent(self) -> AgentConfiguration:
248
+ def _configure_agent(
249
+ self,
250
+ *,
251
+ template_path: Path | str | None = None,
252
+ model: str | None = None,
253
+ **kwargs: Any,
254
+ ) -> AgentConfiguration:
231
255
  """Return configuration for the vector writer agent.
232
256
 
233
257
  Returns
@@ -240,10 +264,13 @@ class VectorSearchWriter(SearchWriter[VectorSearchReportStructure]):
240
264
  instructions="Agent instructions",
241
265
  description="Write a report based on search results.",
242
266
  output_structure=VectorSearchReportStructure,
267
+ model_settings=ModelSettings(tool_choice="none"),
268
+ template_path=template_path,
269
+ model=model,
243
270
  )
244
271
 
245
272
 
246
- class VectorAgentSearch:
273
+ class VectorAgentSearch(AgentBase):
247
274
  """Manage the complete vector search workflow.
248
275
 
249
276
  This high-level agent orchestrates a multi-step research process that plans
@@ -254,9 +281,10 @@ class VectorAgentSearch:
254
281
  Parameters
255
282
  ----------
256
283
  prompt_dir : Path or None, default=None
257
- Directory containing prompt templates.
284
+ Directory containing prompt templates. Defaults to the packaged
285
+ ``prompt`` directory when not provided.
258
286
  default_model : str or None, default=None
259
- Default model identifier to use when not defined in config.
287
+ Default model identifier to use when not defined in configuration.
260
288
  vector_store_name : str or None, default=None
261
289
  Name of the vector store to query.
262
290
  max_concurrent_searches : int, default=MAX_CONCURRENT_SEARCHES
@@ -304,7 +332,7 @@ class VectorAgentSearch:
304
332
  Raises
305
333
  ------
306
334
  ValueError
307
- If the default model is not provided.
335
+ If the model identifier is not provided.
308
336
  """
309
337
 
310
338
  def __init__(
@@ -318,7 +346,7 @@ class VectorAgentSearch:
318
346
  vector_storage_factory: Optional[Callable[[str], VectorStorage]] = None,
319
347
  ) -> None:
320
348
  """Create the main VectorSearch agent."""
321
- self._prompt_dir = prompt_dir
349
+ self._prompt_dir = prompt_dir or DEFAULT_PROMPT_DIR
322
350
  self._default_model = default_model
323
351
  self._vector_store_name = vector_store_name
324
352
  self._max_concurrent_searches = max_concurrent_searches
@@ -341,18 +369,16 @@ class VectorAgentSearch:
341
369
  trace_id = gen_trace_id()
342
370
  with trace("VectorSearch trace", trace_id=trace_id):
343
371
  planner = VectorAgentPlanner(
344
- prompt_dir=self._prompt_dir, default_model=self._default_model
372
+ template_path=self._prompt_dir, model=self._default_model
345
373
  )
346
374
  tool = VectorSearchTool(
347
- prompt_dir=self._prompt_dir,
348
- default_model=self._default_model,
349
- store_name=self._vector_store_name,
375
+ template_path=self._prompt_dir,
376
+ model=self._default_model,
350
377
  max_concurrent_searches=self._max_concurrent_searches,
351
- vector_storage=self._vector_storage,
352
- vector_storage_factory=self._vector_storage_factory,
378
+ store_name=self._vector_store_name,
353
379
  )
354
380
  writer = VectorSearchWriter(
355
- prompt_dir=self._prompt_dir, default_model=self._default_model
381
+ template_path=self._prompt_dir, model=self._default_model
356
382
  )
357
383
  with custom_span("vector_search.plan"):
358
384
  search_plan = await planner.run_agent(query=search_query)
@@ -387,48 +413,6 @@ class VectorAgentSearch:
387
413
  """
388
414
  return run_coroutine_agent_sync(self.run_agent(search_query))
389
415
 
390
- def as_response_tool(
391
- self,
392
- *,
393
- tool_name: str = "vector_search",
394
- tool_description: str = "Run the vector search workflow.",
395
- ) -> tuple[dict[str, Callable[..., Any]], dict[str, Any]]:
396
- """Return a Responses API tool handler and definition.
397
-
398
- Parameters
399
- ----------
400
- vector_store_name : str
401
- Name of the vector store to use for the response tool.
402
- tool_name : str, default="vector_search"
403
- Name to use for the response tool.
404
- tool_description : str, default="Run the vector search workflow."
405
- Description for the response tool.
406
-
407
- Returns
408
- -------
409
- tuple[dict[str, Callable[..., Any]], dict[str, Any]]
410
- Tool handler mapping and tool definition for Responses API usage.
411
- """
412
- search = VectorAgentSearch(
413
- prompt_dir=self._prompt_dir,
414
- default_model=self._default_model,
415
- vector_store_name=self._vector_store_name,
416
- max_concurrent_searches=self._max_concurrent_searches,
417
- vector_storage=self._vector_storage,
418
- vector_storage_factory=self._vector_storage_factory,
419
- )
420
-
421
- def _run_search(prompt: str) -> VectorSearchStructure:
422
- return run_coroutine_agent_sync(search.run_agent(search_query=prompt))
423
-
424
- tool_handler = {
425
- tool_name: tool_handler_factory(_run_search, input_model=PromptStructure)
426
- }
427
- tool_definition = PromptStructure.response_tool_definition(
428
- tool_name, tool_description=tool_description
429
- )
430
- return tool_handler, tool_definition
431
-
432
416
 
433
417
  __all__ = [
434
418
  "MAX_CONCURRENT_SEARCHES",
@@ -3,13 +3,14 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from pathlib import Path
6
- from typing import Any, Callable, Dict, List, Optional, Union
6
+ from typing import Any, Dict, Optional, Union
7
7
 
8
8
  from agents import custom_span, gen_trace_id, trace
9
9
  from agents.model_settings import ModelSettings
10
10
  from agents.tool import WebSearchTool
11
11
 
12
12
  from ...structure.prompt import PromptStructure
13
+ from ..base import AgentBase
13
14
  from ...structure.web_search import (
14
15
  WebSearchItemStructure,
15
16
  WebSearchItemResultStructure,
@@ -17,10 +18,10 @@ from ...structure.web_search import (
17
18
  WebSearchPlanStructure,
18
19
  WebSearchReportStructure,
19
20
  )
20
- from ...tools import tool_handler_factory
21
- from ..config import AgentConfiguration
21
+ from ..configuration import AgentConfiguration
22
22
  from ..utils import run_coroutine_agent_sync
23
23
  from .base import SearchPlanner, SearchToolAgent, SearchWriter
24
+ from ...tools import ToolSpec, ToolHandlerRegistration
24
25
 
25
26
  MAX_CONCURRENT_SEARCHES = 10
26
27
 
@@ -30,10 +31,10 @@ class WebAgentPlanner(SearchPlanner[WebSearchPlanStructure]):
30
31
 
31
32
  Parameters
32
33
  ----------
33
- prompt_dir : Path or None, default=None
34
- Directory containing prompt templates.
35
- default_model : str or None, default=None
36
- Default model identifier to use when not defined in config.
34
+ template_path : Path | str | None, default=None
35
+ Template file path for prompt rendering.
36
+ model : str | None, default=None
37
+ Model identifier to use when not defined in configuration.
37
38
 
38
39
  Methods
39
40
  -------
@@ -43,20 +44,19 @@ class WebAgentPlanner(SearchPlanner[WebSearchPlanStructure]):
43
44
  Raises
44
45
  ------
45
46
  ValueError
46
- If the default model is not provided.
47
+ If the configuration omits a model identifier.
47
48
 
48
49
  Examples
49
50
  --------
50
- >>> planner = WebAgentPlanner(default_model="gpt-4o-mini")
51
+ >>> planner = WebAgentPlanner(model="gpt-4o-mini")
51
52
  """
52
53
 
53
- def __init__(
54
- self, prompt_dir: Optional[Path] = None, default_model: Optional[str] = None
55
- ) -> None:
56
- """Initialize the planner agent."""
57
- super().__init__(prompt_dir=prompt_dir, default_model=default_model)
58
-
59
- def _configure_agent(self) -> AgentConfiguration:
54
+ def _configure_agent(
55
+ self,
56
+ template_path: Path | str | None = None,
57
+ model: str | None = None,
58
+ **kwargs: Any,
59
+ ) -> AgentConfiguration:
60
60
  """Return configuration for the web planner agent.
61
61
 
62
62
  Returns
@@ -68,6 +68,8 @@ class WebAgentPlanner(SearchPlanner[WebSearchPlanStructure]):
68
68
  name="web_planner",
69
69
  instructions="Agent instructions",
70
70
  description="Agent that plans web searches based on a user query.",
71
+ template_path=template_path,
72
+ model=model,
71
73
  output_structure=WebSearchPlanStructure,
72
74
  )
73
75
 
@@ -81,10 +83,10 @@ class WebSearchToolAgent(
81
83
 
82
84
  Parameters
83
85
  ----------
84
- prompt_dir : Path or None, default=None
85
- Directory containing prompt templates.
86
- default_model : str or None, default=None
87
- Default model identifier to use when not defined in config.
86
+ template_path : Path | str | None, default=None
87
+ Template file path for prompt rendering.
88
+ model : str or None, default=None
89
+ Model identifier to use when not defined in configuration.
88
90
 
89
91
  Methods
90
92
  -------
@@ -96,24 +98,20 @@ class WebSearchToolAgent(
96
98
  Raises
97
99
  ------
98
100
  ValueError
99
- If the default model is not provided.
101
+ If the model is not provided.
100
102
 
101
103
  Examples
102
104
  --------
103
- >>> tool = WebSearchToolAgent(default_model="gpt-4o-mini")
105
+ >>> tool = WebSearchToolAgent(model="gpt-4o-mini")
104
106
  """
105
107
 
106
- def __init__(
107
- self, prompt_dir: Optional[Path] = None, default_model: Optional[str] = None
108
- ) -> None:
109
- """Initialize the search tool agent."""
110
- super().__init__(
111
- prompt_dir=prompt_dir,
112
- default_model=default_model,
113
- max_concurrent_searches=MAX_CONCURRENT_SEARCHES,
114
- )
115
-
116
- def _configure_agent(self) -> AgentConfiguration:
108
+ def _configure_agent(
109
+ self,
110
+ *,
111
+ template_path: Path | str | None = None,
112
+ model: str | None = None,
113
+ **kwargs: Any,
114
+ ) -> AgentConfiguration:
117
115
  """Return configuration for the web search tool agent.
118
116
 
119
117
  Returns
@@ -125,6 +123,8 @@ class WebSearchToolAgent(
125
123
  name="web_search",
126
124
  instructions="Agent instructions",
127
125
  description="Agent that performs web searches and summarizes results.",
126
+ template_path=template_path,
127
+ model=model,
128
128
  input_structure=WebSearchPlanStructure,
129
129
  tools=[WebSearchTool()],
130
130
  model_settings=ModelSettings(tool_choice="required"),
@@ -186,10 +186,10 @@ class WebAgentWriter(SearchWriter[WebSearchReportStructure]):
186
186
 
187
187
  Parameters
188
188
  ----------
189
- prompt_dir : Path or None, default=None
190
- Directory containing prompt templates.
191
- default_model : str or None, default=None
192
- Default model identifier to use when not defined in config.
189
+ template_path : Path | str | None, default=None
190
+ Template file path for prompt rendering.
191
+ model : str | None, default=None
192
+ Model identifier to use when not defined in configuration.
193
193
 
194
194
  Methods
195
195
  -------
@@ -199,20 +199,31 @@ class WebAgentWriter(SearchWriter[WebSearchReportStructure]):
199
199
  Raises
200
200
  ------
201
201
  ValueError
202
- If the default model is not provided.
202
+ If the configuration omits a model identifier.
203
203
 
204
204
  Examples
205
205
  --------
206
- >>> writer = WebAgentWriter(default_model="gpt-4o-mini")
206
+ >>> writer = WebAgentWriter(model="gpt-4o-mini")
207
207
  """
208
208
 
209
209
  def __init__(
210
- self, prompt_dir: Optional[Path] = None, default_model: Optional[str] = None
210
+ self,
211
+ template_path: Path | str | None = None,
212
+ model: str | None = None,
213
+ **kwargs: Any,
211
214
  ) -> None:
212
215
  """Initialize the writer agent."""
213
- super().__init__(prompt_dir=prompt_dir, default_model=default_model)
216
+ configuration = self._configure_agent(
217
+ template_path=template_path, model=model, **kwargs
218
+ )
219
+ super().__init__(configuration=configuration)
214
220
 
215
- def _configure_agent(self) -> AgentConfiguration:
221
+ def _configure_agent(
222
+ self,
223
+ template_path: Path | str | None = None,
224
+ model: str | None = None,
225
+ **kwargs: Any,
226
+ ) -> AgentConfiguration:
216
227
  """Return configuration for the web writer agent.
217
228
 
218
229
  Returns
@@ -224,19 +235,21 @@ class WebAgentWriter(SearchWriter[WebSearchReportStructure]):
224
235
  name="web_writer",
225
236
  instructions="Agent instructions",
226
237
  description="Agent that writes a report based on web search results.",
238
+ template_path=template_path,
239
+ model=model,
227
240
  output_structure=WebSearchReportStructure,
228
241
  )
229
242
 
230
243
 
231
- class WebAgentSearch:
244
+ class WebAgentSearch(AgentBase):
232
245
  """Manage the complete web search workflow.
233
246
 
234
247
  Parameters
235
248
  ----------
236
- prompt_dir : Path or None, default=None
237
- Directory containing prompt templates.
238
- default_model : str or None, default=None
239
- Default model identifier to use when not defined in config.
249
+ template_path : Path | str | None, default=None
250
+ Template file path for prompt rendering.
251
+ model : str | None, default=None
252
+ Model identifier to use when not defined in configuration.
240
253
 
241
254
  Methods
242
255
  -------
@@ -254,21 +267,36 @@ class WebAgentSearch:
254
267
  Raises
255
268
  ------
256
269
  ValueError
257
- If the default model is not provided.
270
+ If the model identifier is not provided.
258
271
 
259
272
  Examples
260
273
  --------
261
- >>> search = WebAgentSearch(default_model="gpt-4o-mini")
274
+ >>> search = WebAgentSearch(model="gpt-4o-mini")
262
275
  """
263
276
 
264
277
  def __init__(
265
278
  self,
266
- prompt_dir: Optional[Path] = None,
267
- default_model: Optional[str] = None,
279
+ *,
280
+ template_path: Path | str | None = None,
281
+ model: str | None = None,
268
282
  ) -> None:
269
- """Create the main web search agent."""
270
- self._prompt_dir = prompt_dir
271
- self._default_model = default_model
283
+ """Initialize the web search orchestration agent.
284
+
285
+ Parameters
286
+ ----------
287
+ template_path : Path | str | None, default=None
288
+ Optional template file path for prompt rendering.
289
+ model : str | None, default=None
290
+ Model identifier to use when not defined in configuration.
291
+ """
292
+ configuration = AgentConfiguration(
293
+ name="web_agent_search",
294
+ instructions="Agent instructions",
295
+ description="Run a multi-step web search workflow.",
296
+ template_path=template_path,
297
+ model=model,
298
+ )
299
+ super().__init__(configuration=configuration)
272
300
 
273
301
  async def run_agent_async(self, search_query: str) -> WebSearchStructure:
274
302
  """Execute the entire research workflow for ``search_query``.
@@ -286,14 +314,12 @@ class WebAgentSearch:
286
314
  trace_id = gen_trace_id()
287
315
  with trace("WebAgentSearch trace", trace_id=trace_id):
288
316
  planner = WebAgentPlanner(
289
- prompt_dir=self._prompt_dir, default_model=self._default_model
317
+ template_path=self._template_path, model=self.model
290
318
  )
291
319
  tool = WebSearchToolAgent(
292
- prompt_dir=self._prompt_dir, default_model=self._default_model
293
- )
294
- writer = WebAgentWriter(
295
- prompt_dir=self._prompt_dir, default_model=self._default_model
320
+ template_path=self._template_path, model=self.model
296
321
  )
322
+ writer = WebAgentWriter(template_path=self._template_path, model=self.model)
297
323
  search_plan = await planner.run_agent(query=search_query)
298
324
  search_results = await tool.run_agent(search_plan=search_plan)
299
325
  search_report = await writer.run_agent(search_query, search_results)
@@ -320,37 +346,33 @@ class WebAgentSearch:
320
346
  """
321
347
  return run_coroutine_agent_sync(self.run_agent_async(search_query))
322
348
 
323
- def as_response_tool(
324
- self,
325
- *,
326
- tool_name: str = "web_search",
327
- tool_description: str = "Run the web search workflow.",
328
- ) -> tuple[dict[str, Callable[..., Any]], dict[str, Any]]:
329
- """Return a Responses API tool handler and definition.
349
+ def as_tool_registration(
350
+ self, tool_name: str, tool_description: str
351
+ ) -> ToolHandlerRegistration:
352
+ """Build a Responses API tool definition and handler for the web search agent.
330
353
 
331
354
  Parameters
332
355
  ----------
333
- tool_name : str, default="web_search"
334
- Name to use for the response tool.
335
- tool_description : str, default="Run the web search workflow."
336
- Description for the response tool.
356
+ tool_name : str
357
+ Name of the tool.
358
+ tool_description : str
359
+ Description of the tool.
337
360
 
338
361
  Returns
339
362
  -------
340
- tuple[dict[str, Callable[..., Any]], dict[str, Any]]
341
- Tool handler mapping and tool definition for Responses API usage.
363
+ ToolHandlerRegistration
364
+ Tool definition and handler for the Responses API.
342
365
  """
343
-
344
- def _run_search(prompt: str) -> WebSearchStructure:
345
- return run_coroutine_agent_sync(self.run_agent_async(search_query=prompt))
346
-
347
- tool_handler = {
348
- tool_name: tool_handler_factory(_run_search, input_model=PromptStructure)
349
- }
350
- tool_definition = PromptStructure.response_tool_definition(
351
- tool_name, tool_description=tool_description
366
+ tool_spec = ToolSpec(
367
+ input_structure=PromptStructure,
368
+ tool_name=tool_name,
369
+ tool_description=tool_description,
370
+ output_structure=WebSearchStructure,
371
+ )
372
+ return ToolHandlerRegistration(
373
+ handler=self.run_agent_sync,
374
+ tool_spec=tool_spec,
352
375
  )
353
- return tool_handler, tool_definition
354
376
 
355
377
 
356
378
  __all__ = [