openai-sdk-helpers 0.4.0__tar.gz → 0.4.2__tar.gz

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 (88) hide show
  1. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/PKG-INFO +1 -1
  2. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/pyproject.toml +1 -1
  3. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/__init__.py +6 -2
  4. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/__init__.py +4 -4
  5. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/base.py +168 -6
  6. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/config.py +47 -72
  7. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/search/__init__.py +4 -4
  8. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/search/vector.py +41 -29
  9. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/search/web.py +28 -24
  10. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/environment.py +22 -0
  11. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/response/config.py +22 -9
  12. openai_sdk_helpers-0.4.2/src/openai_sdk_helpers/response/planner.py +12 -0
  13. openai_sdk_helpers-0.4.2/src/openai_sdk_helpers/response/prompter.py +12 -0
  14. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/streamlit_app/__init__.py +4 -4
  15. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/streamlit_app/config.py +44 -33
  16. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/streamlit_app/streamlit_web_search.py +1 -1
  17. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/__init__.py +2 -2
  18. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/json/ref.py +3 -0
  19. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/registry.py +31 -4
  20. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/.gitignore +0 -0
  21. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/LICENSE +0 -0
  22. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/README.md +0 -0
  23. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/coordination.py +0 -0
  24. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/prompt_utils.py +0 -0
  25. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/runner.py +0 -0
  26. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/search/base.py +0 -0
  27. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/summarizer.py +0 -0
  28. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/translator.py +0 -0
  29. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/utils.py +0 -0
  30. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/agent/validation.py +0 -0
  31. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/cli.py +0 -0
  32. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/config.py +0 -0
  33. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/context_manager.py +0 -0
  34. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/deprecation.py +0 -0
  35. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/enums/__init__.py +0 -0
  36. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/enums/base.py +0 -0
  37. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/errors.py +0 -0
  38. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/files_api.py +0 -0
  39. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/logging_config.py +0 -0
  40. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/prompt/__init__.py +0 -0
  41. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/prompt/base.py +0 -0
  42. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/prompt/summarizer.jinja +0 -0
  43. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/prompt/translator.jinja +0 -0
  44. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/prompt/validator.jinja +0 -0
  45. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/py.typed +0 -0
  46. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/response/__init__.py +0 -0
  47. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/response/base.py +0 -0
  48. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/response/files.py +0 -0
  49. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/response/messages.py +0 -0
  50. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/response/runner.py +0 -0
  51. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/response/tool_call.py +0 -0
  52. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/response/vector_store.py +0 -0
  53. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/retry.py +0 -0
  54. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/streamlit_app/app.py +0 -0
  55. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/__init__.py +0 -0
  56. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/agent_blueprint.py +0 -0
  57. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/base.py +0 -0
  58. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/plan/__init__.py +0 -0
  59. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/plan/enum.py +0 -0
  60. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/plan/helpers.py +0 -0
  61. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/plan/plan.py +0 -0
  62. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/plan/task.py +0 -0
  63. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/plan/types.py +0 -0
  64. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/prompt.py +0 -0
  65. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/responses.py +0 -0
  66. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/summary.py +0 -0
  67. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/translation.py +0 -0
  68. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/validation.py +0 -0
  69. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/vector_search.py +0 -0
  70. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/structure/web_search.py +0 -0
  71. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/tools.py +0 -0
  72. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/types.py +0 -0
  73. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/async_utils.py +0 -0
  74. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/coercion.py +0 -0
  75. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/deprecation.py +0 -0
  76. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/encoding.py +0 -0
  77. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/instructions.py +0 -0
  78. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/json/__init__.py +0 -0
  79. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/json/base_model.py +0 -0
  80. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/json/data_class.py +0 -0
  81. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/json/utils.py +0 -0
  82. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/output_validation.py +0 -0
  83. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/path_utils.py +0 -0
  84. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/utils/validation.py +0 -0
  85. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/vector_storage/__init__.py +0 -0
  86. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/vector_storage/cleanup.py +0 -0
  87. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/vector_storage/storage.py +0 -0
  88. {openai_sdk_helpers-0.4.0 → openai_sdk_helpers-0.4.2}/src/openai_sdk_helpers/vector_storage/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openai-sdk-helpers
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Composable helpers for OpenAI SDK agents, prompts, and storage
5
5
  Author: openai-sdk-helpers maintainers
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "openai-sdk-helpers"
3
- version = "0.4.0"
3
+ version = "0.4.2"
4
4
  requires-python = ">=3.10"
5
5
  readme = "README.md"
6
6
  description = "Composable helpers for OpenAI SDK agents, prompts, and storage"
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from .environment import get_data_path, get_model
5
6
  from .utils.async_utils import run_coroutine_thread_safe, run_coroutine_with_fallback
6
7
  from .context_manager import (
7
8
  AsyncManagedResource,
@@ -61,7 +62,7 @@ from .agent import (
61
62
  SummarizerAgent,
62
63
  TranslatorAgent,
63
64
  ValidatorAgent,
64
- VectorSearch,
65
+ VectorAgentSearch,
65
66
  WebAgentSearch,
66
67
  )
67
68
  from .response import (
@@ -103,6 +104,9 @@ from .types import (
103
104
  )
104
105
 
105
106
  __all__ = [
107
+ # Environment utilities
108
+ "get_data_path",
109
+ "get_model",
106
110
  # Async utilities
107
111
  "run_coroutine_thread_safe",
108
112
  "run_coroutine_with_fallback",
@@ -156,7 +160,7 @@ __all__ = [
156
160
  "SummarizerAgent",
157
161
  "TranslatorAgent",
158
162
  "ValidatorAgent",
159
- "VectorSearch",
163
+ "VectorAgentSearch",
160
164
  "WebAgentSearch",
161
165
  "ExtendedSummaryStructure",
162
166
  "WebSearchStructure",
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from .base import AgentBase
6
- from .config import AgentConfiguration, AgentConfigurationRegistry, get_default_registry
6
+ from .config import AgentConfiguration, AgentRegistry, get_default_registry
7
7
  from ..structure.plan.enum import AgentEnum
8
8
  from .coordination import CoordinatorAgent
9
9
  from .runner import run_sync, run_async, run_streamed
@@ -12,13 +12,13 @@ from .summarizer import SummarizerAgent
12
12
  from .translator import TranslatorAgent
13
13
  from .validation import ValidatorAgent
14
14
  from .utils import run_coroutine_agent_sync
15
- from .search.vector import VectorSearch
15
+ from .search.vector import VectorAgentSearch
16
16
  from .search.web import WebAgentSearch
17
17
 
18
18
  __all__ = [
19
19
  "AgentBase",
20
20
  "AgentConfiguration",
21
- "AgentConfigurationRegistry",
21
+ "AgentRegistry",
22
22
  "get_default_registry",
23
23
  "AgentEnum",
24
24
  "CoordinatorAgent",
@@ -32,6 +32,6 @@ __all__ = [
32
32
  "SummarizerAgent",
33
33
  "TranslatorAgent",
34
34
  "ValidatorAgent",
35
- "VectorSearch",
35
+ "VectorAgentSearch",
36
36
  "WebAgentSearch",
37
37
  ]
@@ -2,8 +2,9 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import json
5
6
  from pathlib import Path
6
- from typing import Any, Dict, Optional, Protocol, cast
7
+ from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Protocol, cast
7
8
  import uuid
8
9
 
9
10
  from agents import (
@@ -21,16 +22,23 @@ from jinja2 import Template
21
22
 
22
23
  from ..utils.json.data_class import DataclassJSONSerializable
23
24
  from ..structure.base import StructureBase
25
+ from ..structure.prompt import PromptStructure
24
26
 
25
27
  from ..utils import (
26
28
  check_filepath,
27
29
  log,
28
30
  )
29
31
 
32
+ from ..tools import tool_handler_factory
33
+
30
34
  from .runner import run_async, run_streamed, run_sync
31
35
 
36
+ if TYPE_CHECKING:
37
+ from ..config import OpenAISettings
38
+ from ..response.base import ResponseBase, ToolHandler
39
+
32
40
 
33
- class AgentConfigurationLike(Protocol):
41
+ class AgentConfigurationProtocol(Protocol):
34
42
  """Protocol describing the configuration attributes for AgentBase."""
35
43
 
36
44
  @property
@@ -181,6 +189,10 @@ class AgentBase(DataclassJSONSerializable):
181
189
  Return a streaming result for the agent execution.
182
190
  as_tool()
183
191
  Return the agent as a callable tool.
192
+ as_response_tool()
193
+ Return response tool handler and definition for Responses API use.
194
+ build_response(openai_settings, data_path=None, tool_handlers=None, system_vector_store=None)
195
+ Build a ResponseBase instance based on this agent.
184
196
  close()
185
197
  Clean up agent resources (can be overridden by subclasses).
186
198
  """
@@ -188,7 +200,7 @@ class AgentBase(DataclassJSONSerializable):
188
200
  def __init__(
189
201
  self,
190
202
  *,
191
- config: AgentConfigurationLike,
203
+ config: AgentConfigurationProtocol,
192
204
  run_context_wrapper: Optional[RunContextWrapper[Dict[str, Any]]] = None,
193
205
  data_path: Path | str | None = None,
194
206
  prompt_dir: Optional[Path] = None,
@@ -198,7 +210,7 @@ class AgentBase(DataclassJSONSerializable):
198
210
 
199
211
  Parameters
200
212
  ----------
201
- config : AgentConfigurationLike
213
+ config : AgentConfigurationProtocol
202
214
  Configuration describing this agent.
203
215
  run_context_wrapper : RunContextWrapper or None, default=None
204
216
  Optional wrapper providing runtime context for prompt rendering.
@@ -428,7 +440,7 @@ class AgentBase(DataclassJSONSerializable):
428
440
  "model": self.model,
429
441
  }
430
442
  if self._output_structure:
431
- agent_config["output_structure"] = self._output_structure
443
+ agent_config["output_type"] = self._output_structure
432
444
  if self._tools:
433
445
  agent_config["tools"] = self._tools
434
446
  if self._model_settings:
@@ -575,6 +587,156 @@ class AgentBase(DataclassJSONSerializable):
575
587
  )
576
588
  return tool_obj
577
589
 
590
+ def as_response_tool(
591
+ self,
592
+ *,
593
+ tool_name: str | None = None,
594
+ tool_description: str | None = None,
595
+ ) -> tuple[dict[str, Callable[..., Any]], dict[str, Any]]:
596
+ """Return response tool handler and definition for Responses API use.
597
+
598
+ The returned handler serializes tool output as JSON using
599
+ ``tool_handler_factory`` so downstream response flows can rely on a
600
+ consistent payload format.
601
+
602
+ Parameters
603
+ ----------
604
+ tool_name : str or None, default=None
605
+ Optional override for the tool name. When None, uses the agent name.
606
+ tool_description : str or None, default=None
607
+ Optional override for the tool description. When None, uses the
608
+ agent description.
609
+
610
+ Returns
611
+ -------
612
+ tuple[dict[str, Callable[..., Any]], dict[str, Any]]
613
+ Tool handler mapping and tool definition for Responses API usage.
614
+
615
+ Examples
616
+ --------
617
+ >>> tool_handler, tool_definition = agent.as_response_tool()
618
+ >>> response = ResponseBase(
619
+ ... name="agent_tool",
620
+ ... instructions="Use the agent tool when needed.",
621
+ ... tools=[tool_definition],
622
+ ... output_structure=None,
623
+ ... tool_handlers=tool_handler,
624
+ ... openai_settings=settings,
625
+ ... )
626
+ >>> response.run_sync("Invoke the agent tool") # doctest: +SKIP
627
+ """
628
+
629
+ def _run_agent(**kwargs: Any) -> Any:
630
+ prompt = kwargs.get("prompt")
631
+ if prompt is None:
632
+ if len(kwargs) == 1:
633
+ prompt = next(iter(kwargs.values()))
634
+ else:
635
+ prompt = json.dumps(kwargs)
636
+ return self.run_sync(str(prompt))
637
+
638
+ name = tool_name or self.name
639
+ description = tool_description or self.description
640
+ input_model = self._input_structure or PromptStructure
641
+ tool_handler = {name: tool_handler_factory(_run_agent, input_model=input_model)}
642
+ tool_definition = {
643
+ "type": "function",
644
+ "name": name,
645
+ "description": description,
646
+ "strict": True,
647
+ "additionalProperties": False,
648
+ "parameters": self._build_response_parameters(),
649
+ }
650
+ return tool_handler, tool_definition
651
+
652
+ def build_response(
653
+ self,
654
+ *,
655
+ openai_settings: OpenAISettings,
656
+ data_path: Path | str | None = None,
657
+ tool_handlers: dict[str, ToolHandler] | None = None,
658
+ system_vector_store: list[str] | None = None,
659
+ ) -> ResponseBase[StructureBase]:
660
+ """Build a ResponseBase instance from this agent configuration.
661
+
662
+ Parameters
663
+ ----------
664
+ openai_settings : OpenAISettings
665
+ Authentication and model settings applied to the generated response.
666
+ data_path : Path, str, or None, default None
667
+ Optional path for storing response artifacts. When None, the
668
+ response uses the default data directory.
669
+ tool_handlers : dict[str, ToolHandler] or None, default None
670
+ Optional mapping of tool names to handler callables.
671
+ system_vector_store : list[str] or None, default None
672
+ Optional list of vector store names to attach as system context.
673
+
674
+ Returns
675
+ -------
676
+ ResponseBase[StructureBase]
677
+ ResponseBase instance configured with this agent's settings.
678
+
679
+ Examples
680
+ --------
681
+ >>> from openai_sdk_helpers import OpenAISettings
682
+ >>> response = agent.build_response(openai_settings=OpenAISettings.from_env())
683
+ """
684
+ from ..response.base import ResponseBase, ToolHandler
685
+ from ..config import OpenAISettings
686
+
687
+ if not isinstance(openai_settings, OpenAISettings):
688
+ raise TypeError("openai_settings must be an OpenAISettings instance")
689
+
690
+ tools = self._normalize_response_tools(self.tools)
691
+
692
+ return ResponseBase(
693
+ name=self.name,
694
+ instructions=self.instructions_text,
695
+ tools=tools,
696
+ output_structure=self.output_structure,
697
+ system_vector_store=system_vector_store,
698
+ data_path=data_path,
699
+ tool_handlers=tool_handlers,
700
+ openai_settings=openai_settings,
701
+ )
702
+
703
+ def _build_response_parameters(self) -> dict[str, Any]:
704
+ """Build the Responses API parameter schema for this agent tool.
705
+
706
+ Returns
707
+ -------
708
+ dict[str, Any]
709
+ JSON schema describing tool input parameters.
710
+ """
711
+ if self._input_structure is not None:
712
+ return self._input_structure.get_schema()
713
+ return {
714
+ "type": "object",
715
+ "properties": {
716
+ "prompt": {"type": "string", "description": "Prompt text to run."}
717
+ },
718
+ "required": ["prompt"],
719
+ "additionalProperties": False,
720
+ }
721
+
722
+ @staticmethod
723
+ def _normalize_response_tools(tools: Optional[list]) -> Optional[list]:
724
+ """Normalize tool definitions for the Responses API."""
725
+ if not tools:
726
+ return tools
727
+
728
+ normalized: list[Any] = []
729
+ for tool in tools:
730
+ if hasattr(tool, "to_dict") and callable(tool.to_dict):
731
+ normalized.append(tool.to_dict())
732
+ elif hasattr(tool, "to_openai_tool") and callable(tool.to_openai_tool):
733
+ normalized.append(tool.to_openai_tool())
734
+ elif hasattr(tool, "schema"):
735
+ normalized.append(tool.schema)
736
+ else:
737
+ normalized.append(tool)
738
+ return normalized
739
+
578
740
  def __enter__(self) -> AgentBase:
579
741
  """Enter the context manager for resource management.
580
742
 
@@ -651,4 +813,4 @@ class AgentBase(DataclassJSONSerializable):
651
813
  log(f"Saved messages to {target}")
652
814
 
653
815
 
654
- __all__ = ["AgentConfigurationLike", "AgentBase"]
816
+ __all__ = ["AgentConfigurationProtocol", "AgentBase"]
@@ -10,20 +10,20 @@ from agents import Agent, Handoff, InputGuardrail, OutputGuardrail, Session
10
10
  from agents.model_settings import ModelSettings
11
11
 
12
12
  from ..utils.json.data_class import DataclassJSONSerializable
13
- from ..utils.registry import BaseRegistry
13
+ from ..utils.registry import RegistryBase
14
14
  from ..utils.instructions import resolve_instructions_from_path
15
15
  from ..structure.base import StructureBase
16
16
 
17
17
 
18
- class AgentConfigurationRegistry(BaseRegistry["AgentConfiguration"]):
18
+ class AgentRegistry(RegistryBase["AgentConfiguration"]):
19
19
  """Registry for managing AgentConfiguration instances.
20
20
 
21
- Inherits from BaseRegistry to provide centralized storage and retrieval
21
+ Inherits from RegistryBase to provide centralized storage and retrieval
22
22
  of agent configurations, enabling reusable agent specs across the application.
23
23
 
24
24
  Examples
25
25
  --------
26
- >>> registry = AgentConfigurationRegistry()
26
+ >>> registry = AgentRegistry()
27
27
  >>> config = AgentConfiguration(
28
28
  ... name="test_agent",
29
29
  ... model="gpt-4o-mini",
@@ -65,7 +65,7 @@ class AgentConfigurationRegistry(BaseRegistry["AgentConfiguration"]):
65
65
 
66
66
  Examples
67
67
  --------
68
- >>> registry = AgentConfigurationRegistry()
68
+ >>> registry = AgentRegistry()
69
69
  >>> count = registry.load_from_directory("./agents")
70
70
  >>> print(f"Loaded {count} configurations")
71
71
  """
@@ -74,12 +74,12 @@ class AgentConfigurationRegistry(BaseRegistry["AgentConfiguration"]):
74
74
  return super().load_from_directory(path, config_class=config_class)
75
75
 
76
76
 
77
- def get_default_registry() -> AgentConfigurationRegistry:
77
+ def get_default_registry() -> AgentRegistry:
78
78
  """Return the global default registry instance.
79
79
 
80
80
  Returns
81
81
  -------
82
- AgentConfigurationRegistry
82
+ AgentRegistry
83
83
  Singleton registry for application-wide configuration storage.
84
84
 
85
85
  Examples
@@ -187,9 +187,8 @@ class AgentConfiguration(DataclassJSONSerializable):
187
187
  input_guardrails: Optional[list[InputGuardrail]] = None
188
188
  output_guardrails: Optional[list[OutputGuardrail]] = None
189
189
  session: Optional[Session] = None
190
- _instructions_cache: Optional[str] = field(
191
- default=None, init=False, repr=False, compare=False
192
- )
190
+ add_output_instructions: bool = False
191
+ add_web_search_tool: bool = False
193
192
 
194
193
  def __post_init__(self) -> None:
195
194
  """Validate configuration invariants after initialization.
@@ -258,11 +257,16 @@ class AgentConfiguration(DataclassJSONSerializable):
258
257
  str
259
258
  Plain-text instructions, loading template files when necessary.
260
259
  """
261
- cached = self._instructions_cache
262
- if cached is None:
263
- cached = self._resolve_instructions()
264
- object.__setattr__(self, "_instructions_cache", cached)
265
- return cached
260
+ resolved_instructions: str = resolve_instructions_from_path(self.instructions)
261
+ output_instructions = ""
262
+ if self.output_structure is not None and self.add_output_instructions:
263
+ output_instructions = self.output_structure.get_prompt(
264
+ add_enum_values=False
265
+ )
266
+ if output_instructions:
267
+ return f"{resolved_instructions}\n{output_instructions}"
268
+
269
+ return resolved_instructions
266
270
 
267
271
  def _resolve_instructions(self) -> str:
268
272
  """Resolve instructions from string or file path."""
@@ -361,69 +365,40 @@ class AgentConfiguration(DataclassJSONSerializable):
361
365
 
362
366
  return replace(self, **changes)
363
367
 
364
- def to_json(self) -> dict[str, Any]:
365
- """Return a JSON-compatible dict representation.
366
-
367
- Returns
368
- -------
369
- dict[str, Any]
370
- Serialized configuration data without cached fields.
371
- """
372
- data = DataclassJSONSerializable.to_json(self)
373
- data.pop("_instructions_cache", None)
374
- return data
375
-
376
- @classmethod
377
- def from_json(cls, data: dict[str, Any]) -> AgentConfiguration:
378
- """Create an AgentConfiguration from JSON data.
368
+ def to_response_config(self) -> Any:
369
+ """Convert this AgentConfiguration to a ResponseConfiguration.
379
370
 
380
- Overrides the default JSONSerializable.from_json to properly handle
381
- the instructions field, converting string paths that look like file
382
- paths back to Path objects for proper file loading.
383
-
384
- Parameters
385
- ----------
386
- data : dict[str, Any]
387
- Dictionary containing the configuration data.
371
+ This is a convenience method for creating a ResponseConfiguration
372
+ instance using the relevant fields from this agent configuration.
388
373
 
389
374
  Returns
390
375
  -------
391
- AgentConfiguration
392
- New configuration instance.
393
-
394
- Notes
395
- -----
396
- This method attempts to preserve the original type of the instructions
397
- field. If instructions is a string that represents an existing file path,
398
- it will be converted to a Path object to ensure proper file loading
399
- behavior is maintained across JSON round-trips.
376
+ ResponseConfiguration
377
+ New response configuration instance.
378
+
379
+ Examples
380
+ --------
381
+ >>> agent_config = AgentConfiguration(
382
+ ... name="responder",
383
+ ... model="gpt-4o-mini",
384
+ ... instructions="Respond to user queries"
385
+ ... )
386
+ >>> response_config = agent_config.to_response_config()
387
+ >>> response_config.name
388
+ 'responder'
400
389
  """
401
- # Make a copy to avoid modifying the input
402
- data = data.copy()
403
- data.pop("_instructions_cache", None)
404
-
405
- # Handle instructions field: if it's a string path to an existing file,
406
- # convert it back to Path for proper file loading
407
- if "instructions" in data and data["instructions"] is not None:
408
- instructions_value = data["instructions"]
409
- if isinstance(instructions_value, str):
410
- # Check if it looks like a file path and the file exists
411
- # This preserves the intended behavior for file-based instructions
412
- try:
413
- potential_path = Path(instructions_value)
414
- # Only convert to Path if it's an existing file
415
- # This way, plain text instructions stay as strings
416
- if potential_path.exists() and potential_path.is_file():
417
- data["instructions"] = potential_path
418
- except (OSError, ValueError):
419
- # If path parsing fails, keep it as a string (likely plain text)
420
- pass
421
-
422
- # Use the parent class method for the rest
423
- return super(AgentConfiguration, cls).from_json(data)
390
+ from ..response.config import ResponseConfiguration
391
+
392
+ return ResponseConfiguration(
393
+ name=self.name,
394
+ instructions=self.instructions,
395
+ input_structure=self.input_structure,
396
+ output_structure=self.output_structure,
397
+ tools=self.tools,
398
+ )
424
399
 
425
400
 
426
401
  # Global default registry instance
427
- _default_registry = AgentConfigurationRegistry()
402
+ _default_registry = AgentRegistry()
428
403
 
429
- __all__ = ["AgentConfiguration", "AgentConfigurationRegistry", "get_default_registry"]
404
+ __all__ = ["AgentConfiguration", "AgentRegistry", "get_default_registry"]
@@ -10,10 +10,10 @@ from .web import (
10
10
  )
11
11
  from .vector import (
12
12
  MAX_CONCURRENT_SEARCHES as VECTOR_MAX_CONCURRENT_SEARCHES,
13
- VectorSearchPlanner,
13
+ VectorAgentPlanner,
14
14
  VectorSearchTool,
15
15
  VectorSearchWriter,
16
- VectorSearch,
16
+ VectorAgentSearch,
17
17
  )
18
18
 
19
19
  __all__ = [
@@ -26,8 +26,8 @@ __all__ = [
26
26
  "WebAgentWriter",
27
27
  "WebAgentSearch",
28
28
  "VECTOR_MAX_CONCURRENT_SEARCHES",
29
- "VectorSearchPlanner",
29
+ "VectorAgentPlanner",
30
30
  "VectorSearchTool",
31
31
  "VectorSearchWriter",
32
- "VectorSearch",
32
+ "VectorAgentSearch",
33
33
  ]
@@ -7,6 +7,7 @@ from typing import Any, Callable, Dict, List, Optional
7
7
 
8
8
  from agents import custom_span, gen_trace_id, trace
9
9
 
10
+ from ...structure.prompt import PromptStructure
10
11
  from ...structure.vector_search import (
11
12
  VectorSearchItemStructure,
12
13
  VectorSearchItemResultStructure,
@@ -15,6 +16,7 @@ from ...structure.vector_search import (
15
16
  VectorSearchPlanStructure,
16
17
  VectorSearchReportStructure,
17
18
  )
19
+ from ...tools import tool_handler_factory
18
20
  from ...vector_storage import VectorStorage
19
21
  from ..config import AgentConfiguration
20
22
  from ..utils import run_coroutine_agent_sync
@@ -23,7 +25,7 @@ from .base import SearchPlanner, SearchToolAgent, SearchWriter
23
25
  MAX_CONCURRENT_SEARCHES = 10
24
26
 
25
27
 
26
- class VectorSearchPlanner(SearchPlanner[VectorSearchPlanStructure]):
28
+ class VectorAgentPlanner(SearchPlanner[VectorSearchPlanStructure]):
27
29
  """Plan vector searches to satisfy a user query.
28
30
 
29
31
  Parameters
@@ -241,7 +243,7 @@ class VectorSearchWriter(SearchWriter[VectorSearchReportStructure]):
241
243
  )
242
244
 
243
245
 
244
- class VectorSearch:
246
+ class VectorAgentSearch:
245
247
  """Manage the complete vector search workflow.
246
248
 
247
249
  This high-level agent orchestrates a multi-step research process that plans
@@ -292,6 +294,8 @@ class VectorSearch:
292
294
  Execute the research workflow asynchronously.
293
295
  run_agent_sync(search_query)
294
296
  Execute the research workflow synchronously.
297
+ as_response_tool(vector_store_name, tool_name, tool_description)
298
+ Build a Responses API tool definition and handler.
295
299
  run_vector_agent(search_query)
296
300
  Convenience asynchronous entry point for the workflow.
297
301
  run_vector_agent_sync(search_query)
@@ -306,9 +310,9 @@ class VectorSearch:
306
310
  def __init__(
307
311
  self,
308
312
  *,
313
+ vector_store_name: str,
309
314
  prompt_dir: Optional[Path] = None,
310
315
  default_model: Optional[str] = None,
311
- vector_store_name: Optional[str] = None,
312
316
  max_concurrent_searches: int = MAX_CONCURRENT_SEARCHES,
313
317
  vector_storage: Optional[VectorStorage] = None,
314
318
  vector_storage_factory: Optional[Callable[[str], VectorStorage]] = None,
@@ -336,7 +340,7 @@ class VectorSearch:
336
340
  """
337
341
  trace_id = gen_trace_id()
338
342
  with trace("VectorSearch trace", trace_id=trace_id):
339
- planner = VectorSearchPlanner(
343
+ planner = VectorAgentPlanner(
340
344
  prompt_dir=self._prompt_dir, default_model=self._default_model
341
345
  )
342
346
  tool = VectorSearchTool(
@@ -383,45 +387,53 @@ class VectorSearch:
383
387
  """
384
388
  return run_coroutine_agent_sync(self.run_agent(search_query))
385
389
 
386
- @staticmethod
387
- async def run_vector_agent(search_query: str) -> VectorSearchStructure:
388
- """Return a research report for the given query using ``VectorSearch``.
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.
389
397
 
390
398
  Parameters
391
399
  ----------
392
- search_query : str
393
- User's research query.
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.
394
406
 
395
407
  Returns
396
408
  -------
397
- VectorSearchStructure
398
- Completed research output.
409
+ tuple[dict[str, Callable[..., Any]], dict[str, Any]]
410
+ Tool handler mapping and tool definition for Responses API usage.
399
411
  """
400
- return await VectorSearch().run_agent(search_query=search_query)
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
+ )
401
420
 
402
- @staticmethod
403
- def run_vector_agent_sync(search_query: str) -> VectorSearchStructure:
404
- """Run :meth:`run_vector_agent` synchronously for ``search_query``.
421
+ def _run_search(prompt: str) -> VectorSearchStructure:
422
+ return run_coroutine_agent_sync(search.run_agent(search_query=prompt))
405
423
 
406
- Parameters
407
- ----------
408
- search_query : str
409
- User's research query.
410
-
411
- Returns
412
- -------
413
- VectorSearchStructure
414
- Completed research output.
415
- """
416
- return run_coroutine_agent_sync(
417
- VectorSearch.run_vector_agent(search_query=search_query)
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
418
429
  )
430
+ return tool_handler, tool_definition
419
431
 
420
432
 
421
433
  __all__ = [
422
434
  "MAX_CONCURRENT_SEARCHES",
423
- "VectorSearchPlanner",
435
+ "VectorAgentPlanner",
424
436
  "VectorSearchTool",
425
437
  "VectorSearchWriter",
426
- "VectorSearch",
438
+ "VectorAgentSearch",
427
439
  ]