openai-sdk-helpers 0.3.0__py3-none-any.whl → 0.4.1__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 +6 -6
- openai_sdk_helpers/agent/__init__.py +4 -4
- openai_sdk_helpers/agent/base.py +254 -113
- openai_sdk_helpers/agent/config.py +91 -37
- openai_sdk_helpers/agent/coordination.py +64 -28
- openai_sdk_helpers/agent/runner.py +16 -15
- openai_sdk_helpers/agent/search/base.py +94 -45
- openai_sdk_helpers/agent/search/vector.py +86 -58
- openai_sdk_helpers/agent/search/web.py +71 -40
- openai_sdk_helpers/agent/summarizer.py +32 -7
- openai_sdk_helpers/agent/translator.py +57 -24
- openai_sdk_helpers/agent/validation.py +34 -4
- openai_sdk_helpers/cli.py +42 -0
- openai_sdk_helpers/config.py +0 -1
- openai_sdk_helpers/environment.py +3 -2
- openai_sdk_helpers/files_api.py +35 -3
- openai_sdk_helpers/prompt/base.py +6 -0
- openai_sdk_helpers/response/__init__.py +3 -3
- openai_sdk_helpers/response/base.py +142 -73
- openai_sdk_helpers/response/config.py +63 -58
- openai_sdk_helpers/response/files.py +5 -5
- openai_sdk_helpers/response/messages.py +3 -3
- openai_sdk_helpers/response/runner.py +7 -7
- openai_sdk_helpers/response/tool_call.py +94 -4
- openai_sdk_helpers/response/vector_store.py +3 -3
- openai_sdk_helpers/streamlit_app/__init__.py +4 -4
- openai_sdk_helpers/streamlit_app/app.py +16 -16
- openai_sdk_helpers/streamlit_app/config.py +82 -70
- openai_sdk_helpers/streamlit_app/streamlit_web_search.py +2 -2
- openai_sdk_helpers/structure/__init__.py +6 -2
- openai_sdk_helpers/structure/agent_blueprint.py +2 -2
- openai_sdk_helpers/structure/base.py +8 -99
- openai_sdk_helpers/structure/plan/plan.py +2 -2
- openai_sdk_helpers/structure/plan/task.py +9 -9
- openai_sdk_helpers/structure/prompt.py +2 -2
- openai_sdk_helpers/structure/responses.py +15 -15
- openai_sdk_helpers/structure/summary.py +3 -3
- openai_sdk_helpers/structure/translation.py +32 -0
- openai_sdk_helpers/structure/validation.py +2 -2
- openai_sdk_helpers/structure/vector_search.py +7 -7
- openai_sdk_helpers/structure/web_search.py +6 -6
- openai_sdk_helpers/tools.py +41 -15
- openai_sdk_helpers/utils/__init__.py +19 -5
- openai_sdk_helpers/utils/json/__init__.py +55 -0
- openai_sdk_helpers/utils/json/base_model.py +181 -0
- openai_sdk_helpers/utils/{json_utils.py → json/data_class.py} +33 -68
- openai_sdk_helpers/utils/json/ref.py +113 -0
- openai_sdk_helpers/utils/json/utils.py +203 -0
- openai_sdk_helpers/utils/output_validation.py +21 -1
- openai_sdk_helpers/utils/path_utils.py +34 -1
- openai_sdk_helpers/utils/registry.py +46 -8
- openai_sdk_helpers/vector_storage/storage.py +10 -0
- {openai_sdk_helpers-0.3.0.dist-info → openai_sdk_helpers-0.4.1.dist-info}/METADATA +7 -7
- openai_sdk_helpers-0.4.1.dist-info/RECORD +86 -0
- openai_sdk_helpers-0.3.0.dist-info/RECORD +0 -81
- {openai_sdk_helpers-0.3.0.dist-info → openai_sdk_helpers-0.4.1.dist-info}/WHEEL +0 -0
- {openai_sdk_helpers-0.3.0.dist-info → openai_sdk_helpers-0.4.1.dist-info}/entry_points.txt +0 -0
- {openai_sdk_helpers-0.3.0.dist-info → openai_sdk_helpers-0.4.1.dist-info}/licenses/LICENSE +0 -0
openai_sdk_helpers/__init__.py
CHANGED
|
@@ -33,7 +33,7 @@ from .utils.validation import (
|
|
|
33
33
|
validate_url_format,
|
|
34
34
|
)
|
|
35
35
|
from .structure import (
|
|
36
|
-
|
|
36
|
+
StructureBase,
|
|
37
37
|
SchemaOptions,
|
|
38
38
|
PlanStructure,
|
|
39
39
|
TaskStructure,
|
|
@@ -54,7 +54,7 @@ from .config import OpenAISettings
|
|
|
54
54
|
from .files_api import FilesAPIManager, FilePurpose
|
|
55
55
|
from .vector_storage import VectorStorage, VectorStorageFileInfo, VectorStorageFileStats
|
|
56
56
|
from .agent import (
|
|
57
|
-
|
|
57
|
+
AgentBase,
|
|
58
58
|
AgentConfiguration,
|
|
59
59
|
AgentEnum,
|
|
60
60
|
CoordinatorAgent,
|
|
@@ -65,7 +65,7 @@ from .agent import (
|
|
|
65
65
|
WebAgentSearch,
|
|
66
66
|
)
|
|
67
67
|
from .response import (
|
|
68
|
-
|
|
68
|
+
ResponseBase,
|
|
69
69
|
ResponseMessage,
|
|
70
70
|
ResponseMessages,
|
|
71
71
|
ResponseToolCall,
|
|
@@ -134,7 +134,7 @@ __all__ = [
|
|
|
134
134
|
"validate_choice",
|
|
135
135
|
"validate_safe_path",
|
|
136
136
|
# Main structure classes
|
|
137
|
-
"
|
|
137
|
+
"StructureBase",
|
|
138
138
|
"SchemaOptions",
|
|
139
139
|
"spec_field",
|
|
140
140
|
"PromptRenderer",
|
|
@@ -150,7 +150,7 @@ __all__ = [
|
|
|
150
150
|
"TaskStructure",
|
|
151
151
|
"PlanStructure",
|
|
152
152
|
"AgentEnum",
|
|
153
|
-
"
|
|
153
|
+
"AgentBase",
|
|
154
154
|
"AgentConfiguration",
|
|
155
155
|
"CoordinatorAgent",
|
|
156
156
|
"SummarizerAgent",
|
|
@@ -162,7 +162,7 @@ __all__ = [
|
|
|
162
162
|
"WebSearchStructure",
|
|
163
163
|
"VectorSearchStructure",
|
|
164
164
|
"ValidationResultStructure",
|
|
165
|
-
"
|
|
165
|
+
"ResponseBase",
|
|
166
166
|
"ResponseMessage",
|
|
167
167
|
"ResponseMessages",
|
|
168
168
|
"ResponseToolCall",
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from .base import
|
|
6
|
-
from .config import AgentConfiguration,
|
|
5
|
+
from .base import AgentBase
|
|
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
|
|
@@ -16,9 +16,9 @@ from .search.vector import VectorSearch
|
|
|
16
16
|
from .search.web import WebAgentSearch
|
|
17
17
|
|
|
18
18
|
__all__ = [
|
|
19
|
-
"
|
|
19
|
+
"AgentBase",
|
|
20
20
|
"AgentConfiguration",
|
|
21
|
-
"
|
|
21
|
+
"AgentRegistry",
|
|
22
22
|
"get_default_registry",
|
|
23
23
|
"AgentEnum",
|
|
24
24
|
"CoordinatorAgent",
|
openai_sdk_helpers/agent/base.py
CHANGED
|
@@ -3,16 +3,15 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Any, Dict, Optional, Protocol
|
|
6
|
+
from typing import Any, Callable, Dict, Optional, Protocol, cast
|
|
7
|
+
import uuid
|
|
7
8
|
|
|
8
9
|
from agents import (
|
|
9
10
|
Agent,
|
|
10
11
|
Handoff,
|
|
11
12
|
InputGuardrail,
|
|
12
13
|
OutputGuardrail,
|
|
13
|
-
RunResult,
|
|
14
14
|
RunResultStreaming,
|
|
15
|
-
Runner,
|
|
16
15
|
Session,
|
|
17
16
|
)
|
|
18
17
|
from agents.model_settings import ModelSettings
|
|
@@ -20,11 +19,19 @@ from agents.run_context import RunContextWrapper
|
|
|
20
19
|
from agents.tool import Tool
|
|
21
20
|
from jinja2 import Template
|
|
22
21
|
|
|
22
|
+
from ..utils.json.data_class import DataclassJSONSerializable
|
|
23
|
+
from ..structure.base import StructureBase
|
|
24
|
+
|
|
25
|
+
from ..utils import (
|
|
26
|
+
check_filepath,
|
|
27
|
+
log,
|
|
28
|
+
)
|
|
29
|
+
|
|
23
30
|
from .runner import run_async, run_streamed, run_sync
|
|
24
31
|
|
|
25
32
|
|
|
26
|
-
class
|
|
27
|
-
"""Protocol describing the configuration attributes for
|
|
33
|
+
class AgentConfigurationProtocol(Protocol):
|
|
34
|
+
"""Protocol describing the configuration attributes for AgentBase."""
|
|
28
35
|
|
|
29
36
|
@property
|
|
30
37
|
def name(self) -> str:
|
|
@@ -46,6 +53,10 @@ class AgentConfigurationLike(Protocol):
|
|
|
46
53
|
"""Template path."""
|
|
47
54
|
...
|
|
48
55
|
|
|
56
|
+
def resolve_prompt_path(self, prompt_dir: Path | None = None) -> Path | None:
|
|
57
|
+
"""Resolve the prompt template path."""
|
|
58
|
+
...
|
|
59
|
+
|
|
49
60
|
@property
|
|
50
61
|
def instructions(self) -> str | Path:
|
|
51
62
|
"""Instructions."""
|
|
@@ -57,12 +68,12 @@ class AgentConfigurationLike(Protocol):
|
|
|
57
68
|
...
|
|
58
69
|
|
|
59
70
|
@property
|
|
60
|
-
def
|
|
71
|
+
def input_structure(self) -> Optional[type[StructureBase]]:
|
|
61
72
|
"""Input type."""
|
|
62
73
|
...
|
|
63
74
|
|
|
64
75
|
@property
|
|
65
|
-
def
|
|
76
|
+
def output_structure(self) -> Optional[type[StructureBase]]:
|
|
66
77
|
"""Output type."""
|
|
67
78
|
...
|
|
68
79
|
|
|
@@ -97,10 +108,10 @@ class AgentConfigurationLike(Protocol):
|
|
|
97
108
|
...
|
|
98
109
|
|
|
99
110
|
|
|
100
|
-
class
|
|
111
|
+
class AgentBase(DataclassJSONSerializable):
|
|
101
112
|
"""Factory for creating and configuring specialized agents.
|
|
102
113
|
|
|
103
|
-
``
|
|
114
|
+
``AgentBase`` provides the foundation for building OpenAI agents with support
|
|
104
115
|
for Jinja2 prompt templates, custom tools, handoffs for agent delegation,
|
|
105
116
|
input and output guardrails for validation, session management for
|
|
106
117
|
conversation history, and both synchronous and asynchronous execution modes.
|
|
@@ -110,13 +121,13 @@ class BaseAgent:
|
|
|
110
121
|
--------
|
|
111
122
|
Create a basic agent from configuration:
|
|
112
123
|
|
|
113
|
-
>>> from openai_sdk_helpers.agent import
|
|
124
|
+
>>> from openai_sdk_helpers.agent import AgentBase, AgentConfiguration
|
|
114
125
|
>>> config = AgentConfiguration(
|
|
115
126
|
... name="my_agent",
|
|
116
127
|
... description="A custom agent",
|
|
117
128
|
... model="gpt-4o-mini"
|
|
118
129
|
... )
|
|
119
|
-
>>> agent =
|
|
130
|
+
>>> agent = AgentBase(config=config, default_model="gpt-4o-mini")
|
|
120
131
|
>>> result = agent.run_sync("What is 2+2?")
|
|
121
132
|
|
|
122
133
|
Use absolute path to template:
|
|
@@ -126,7 +137,7 @@ class BaseAgent:
|
|
|
126
137
|
... template_path="/absolute/path/to/template.jinja",
|
|
127
138
|
... model="gpt-4o-mini"
|
|
128
139
|
... )
|
|
129
|
-
>>> agent =
|
|
140
|
+
>>> agent = AgentBase(config=config, default_model="gpt-4o-mini")
|
|
130
141
|
|
|
131
142
|
Use async execution:
|
|
132
143
|
|
|
@@ -138,19 +149,35 @@ class BaseAgent:
|
|
|
138
149
|
|
|
139
150
|
Methods
|
|
140
151
|
-------
|
|
141
|
-
from_configuration(config, run_context_wrapper, prompt_dir, default_model)
|
|
142
|
-
Instantiate a ``BaseAgent`` from configuration.
|
|
143
152
|
build_prompt_from_jinja(run_context_wrapper)
|
|
144
153
|
Render the agent prompt using Jinja and optional context.
|
|
145
154
|
get_prompt(run_context_wrapper, _)
|
|
146
155
|
Render the agent prompt using the provided run context.
|
|
156
|
+
name
|
|
157
|
+
Return the name of this agent.
|
|
158
|
+
instructions_text
|
|
159
|
+
Return the resolved instructions for this agent.
|
|
160
|
+
tools
|
|
161
|
+
Return the tools configured for this agent.
|
|
162
|
+
output_structure
|
|
163
|
+
Return the output type configured for this agent.
|
|
164
|
+
model_settings
|
|
165
|
+
Return the model settings configured for this agent.
|
|
166
|
+
handoffs
|
|
167
|
+
Return the handoff configurations for this agent.
|
|
168
|
+
input_guardrails
|
|
169
|
+
Return the input guardrails configured for this agent.
|
|
170
|
+
output_guardrails
|
|
171
|
+
Return the output guardrails configured for this agent.
|
|
172
|
+
session
|
|
173
|
+
Return the session configured for this agent.
|
|
147
174
|
get_agent()
|
|
148
175
|
Construct the configured :class:`agents.Agent` instance.
|
|
149
|
-
run_async(input, context,
|
|
176
|
+
run_async(input, context, output_structure, session)
|
|
150
177
|
Execute the agent asynchronously and optionally cast the result.
|
|
151
|
-
run_sync(input, context,
|
|
178
|
+
run_sync(input, context, output_structure, session)
|
|
152
179
|
Execute the agent synchronously.
|
|
153
|
-
run_streamed(input, context,
|
|
180
|
+
run_streamed(input, context, output_structure, session)
|
|
154
181
|
Return a streaming result for the agent execution.
|
|
155
182
|
as_tool()
|
|
156
183
|
Return the agent as a callable tool.
|
|
@@ -160,16 +187,18 @@ class BaseAgent:
|
|
|
160
187
|
|
|
161
188
|
def __init__(
|
|
162
189
|
self,
|
|
163
|
-
|
|
190
|
+
*,
|
|
191
|
+
config: AgentConfigurationProtocol,
|
|
164
192
|
run_context_wrapper: Optional[RunContextWrapper[Dict[str, Any]]] = None,
|
|
193
|
+
data_path: Path | str | None = None,
|
|
165
194
|
prompt_dir: Optional[Path] = None,
|
|
166
195
|
default_model: Optional[str] = None,
|
|
167
196
|
) -> None:
|
|
168
|
-
"""Initialize the
|
|
197
|
+
"""Initialize the AgentBase using a configuration object.
|
|
169
198
|
|
|
170
199
|
Parameters
|
|
171
200
|
----------
|
|
172
|
-
config :
|
|
201
|
+
config : AgentConfigurationProtocol
|
|
173
202
|
Configuration describing this agent.
|
|
174
203
|
run_context_wrapper : RunContextWrapper or None, default=None
|
|
175
204
|
Optional wrapper providing runtime context for prompt rendering.
|
|
@@ -187,45 +216,41 @@ class BaseAgent:
|
|
|
187
216
|
if not model:
|
|
188
217
|
raise ValueError("Model is required to construct the agent.")
|
|
189
218
|
|
|
190
|
-
prompt_path
|
|
191
|
-
if config.template_path:
|
|
192
|
-
prompt_path = Path(config.template_path)
|
|
193
|
-
elif prompt_dir is not None:
|
|
194
|
-
prompt_path = prompt_dir / f"{name}.jinja"
|
|
195
|
-
else:
|
|
196
|
-
prompt_path = None
|
|
219
|
+
prompt_path = config.resolve_prompt_path(prompt_dir)
|
|
197
220
|
|
|
198
221
|
# Build template from file or fall back to instructions
|
|
199
222
|
if prompt_path is None:
|
|
200
|
-
|
|
201
|
-
if hasattr(config, "instructions_text"):
|
|
202
|
-
# AgentConfiguration has this property - use it for proper resolution
|
|
203
|
-
instructions_text = config.instructions_text
|
|
204
|
-
else:
|
|
205
|
-
# Fall back to resolving instructions ourselves
|
|
206
|
-
if isinstance(config.instructions, Path):
|
|
207
|
-
try:
|
|
208
|
-
instructions_text = config.instructions.read_text(
|
|
209
|
-
encoding="utf-8"
|
|
210
|
-
)
|
|
211
|
-
except OSError:
|
|
212
|
-
instructions_text = "" # Leave empty if file can't be read
|
|
213
|
-
else:
|
|
214
|
-
instructions_text = config.instructions
|
|
223
|
+
instructions_text = config.instructions_text
|
|
215
224
|
self._template = Template(instructions_text)
|
|
225
|
+
self._instructions = instructions_text
|
|
216
226
|
elif prompt_path.exists():
|
|
217
|
-
self._template = Template(prompt_path.read_text())
|
|
227
|
+
self._template = Template(prompt_path.read_text(encoding="utf-8"))
|
|
228
|
+
self._instructions = None
|
|
218
229
|
else:
|
|
219
230
|
raise FileNotFoundError(
|
|
220
231
|
f"Prompt template for agent '{name}' not found at {prompt_path}."
|
|
221
232
|
)
|
|
222
233
|
|
|
223
|
-
self.
|
|
234
|
+
self._name = name
|
|
235
|
+
self.uuid = uuid.uuid4()
|
|
224
236
|
self.description = description
|
|
225
237
|
self.model = model
|
|
226
238
|
|
|
227
|
-
|
|
228
|
-
|
|
239
|
+
# Resolve data_path with class name appended
|
|
240
|
+
class_name = self.__class__.__name__
|
|
241
|
+
if data_path is not None:
|
|
242
|
+
data_path_obj = Path(data_path)
|
|
243
|
+
if data_path_obj.name == class_name:
|
|
244
|
+
self._data_path = data_path_obj
|
|
245
|
+
else:
|
|
246
|
+
self._data_path = data_path_obj / class_name
|
|
247
|
+
else:
|
|
248
|
+
from ..environment import get_data_path
|
|
249
|
+
|
|
250
|
+
self._data_path = get_data_path(self.__class__.__name__)
|
|
251
|
+
|
|
252
|
+
self._input_structure = config.input_structure
|
|
253
|
+
self._output_structure = config.output_structure or config.input_structure
|
|
229
254
|
self._tools = config.tools
|
|
230
255
|
self._model_settings = config.model_settings
|
|
231
256
|
self._handoffs = config.handoffs
|
|
@@ -234,46 +259,6 @@ class BaseAgent:
|
|
|
234
259
|
self._session = config.session
|
|
235
260
|
self._run_context_wrapper = run_context_wrapper
|
|
236
261
|
|
|
237
|
-
# Store instructions if provided directly in config
|
|
238
|
-
self._instructions = getattr(config, "instructions", None)
|
|
239
|
-
|
|
240
|
-
@classmethod
|
|
241
|
-
def from_configuration(
|
|
242
|
-
cls,
|
|
243
|
-
config: AgentConfigurationLike,
|
|
244
|
-
*,
|
|
245
|
-
run_context_wrapper: Optional[RunContextWrapper[Dict[str, Any]]] = None,
|
|
246
|
-
prompt_dir: Optional[Path] = None,
|
|
247
|
-
default_model: Optional[str] = None,
|
|
248
|
-
) -> BaseAgent:
|
|
249
|
-
"""Create a BaseAgent instance from configuration.
|
|
250
|
-
|
|
251
|
-
Parameters
|
|
252
|
-
----------
|
|
253
|
-
config : AgentConfigurationLike
|
|
254
|
-
Configuration describing the agent.
|
|
255
|
-
run_context_wrapper : RunContextWrapper or None, default=None
|
|
256
|
-
Optional wrapper providing runtime context.
|
|
257
|
-
prompt_dir : Path or None, default=None
|
|
258
|
-
Optional directory holding prompt templates. Used when
|
|
259
|
-
``config.template_path`` is not provided or is relative. If
|
|
260
|
-
``config.template_path`` is an absolute path, this parameter is
|
|
261
|
-
ignored.
|
|
262
|
-
default_model : str or None, default=None
|
|
263
|
-
Optional fallback model identifier.
|
|
264
|
-
|
|
265
|
-
Returns
|
|
266
|
-
-------
|
|
267
|
-
BaseAgent
|
|
268
|
-
Instantiated agent.
|
|
269
|
-
"""
|
|
270
|
-
return cls(
|
|
271
|
-
config=config,
|
|
272
|
-
run_context_wrapper=run_context_wrapper,
|
|
273
|
-
prompt_dir=prompt_dir,
|
|
274
|
-
default_model=default_model,
|
|
275
|
-
)
|
|
276
|
-
|
|
277
262
|
def _build_prompt_from_jinja(self) -> str:
|
|
278
263
|
"""Render the instructions prompt for this agent.
|
|
279
264
|
|
|
@@ -328,6 +313,107 @@ class BaseAgent:
|
|
|
328
313
|
"""
|
|
329
314
|
return self.build_prompt_from_jinja(run_context_wrapper)
|
|
330
315
|
|
|
316
|
+
@property
|
|
317
|
+
def name(self) -> str:
|
|
318
|
+
"""Return the name of this agent.
|
|
319
|
+
|
|
320
|
+
Returns
|
|
321
|
+
-------
|
|
322
|
+
str
|
|
323
|
+
Name used to identify the agent.
|
|
324
|
+
"""
|
|
325
|
+
return self._name
|
|
326
|
+
|
|
327
|
+
@property
|
|
328
|
+
def instructions_text(self) -> str:
|
|
329
|
+
"""Return the resolved instructions for this agent.
|
|
330
|
+
|
|
331
|
+
Returns
|
|
332
|
+
-------
|
|
333
|
+
str
|
|
334
|
+
Rendered instructions text using the current run context.
|
|
335
|
+
"""
|
|
336
|
+
if self._instructions is not None:
|
|
337
|
+
return self._instructions
|
|
338
|
+
return self._build_prompt_from_jinja()
|
|
339
|
+
|
|
340
|
+
@property
|
|
341
|
+
def tools(self) -> Optional[list]:
|
|
342
|
+
"""Return the tools configured for this agent.
|
|
343
|
+
|
|
344
|
+
Returns
|
|
345
|
+
-------
|
|
346
|
+
list or None
|
|
347
|
+
Tool definitions configured for the agent.
|
|
348
|
+
"""
|
|
349
|
+
return self._tools
|
|
350
|
+
|
|
351
|
+
@property
|
|
352
|
+
def output_structure(self) -> Optional[type[StructureBase]]:
|
|
353
|
+
"""Return the output type configured for this agent.
|
|
354
|
+
|
|
355
|
+
Returns
|
|
356
|
+
-------
|
|
357
|
+
type[StructureBase] or None
|
|
358
|
+
Output type used to cast responses.
|
|
359
|
+
"""
|
|
360
|
+
return self._output_structure
|
|
361
|
+
|
|
362
|
+
@property
|
|
363
|
+
def model_settings(self) -> Optional[ModelSettings]:
|
|
364
|
+
"""Return the model settings configured for this agent.
|
|
365
|
+
|
|
366
|
+
Returns
|
|
367
|
+
-------
|
|
368
|
+
ModelSettings or None
|
|
369
|
+
Model settings applied to the agent.
|
|
370
|
+
"""
|
|
371
|
+
return self._model_settings
|
|
372
|
+
|
|
373
|
+
@property
|
|
374
|
+
def handoffs(self) -> Optional[list[Agent | Handoff]]:
|
|
375
|
+
"""Return the handoff configurations for this agent.
|
|
376
|
+
|
|
377
|
+
Returns
|
|
378
|
+
-------
|
|
379
|
+
list[Agent or Handoff] or None
|
|
380
|
+
Handoff configurations available to the agent.
|
|
381
|
+
"""
|
|
382
|
+
return self._handoffs
|
|
383
|
+
|
|
384
|
+
@property
|
|
385
|
+
def input_guardrails(self) -> Optional[list[InputGuardrail]]:
|
|
386
|
+
"""Return the input guardrails configured for this agent.
|
|
387
|
+
|
|
388
|
+
Returns
|
|
389
|
+
-------
|
|
390
|
+
list[InputGuardrail] or None
|
|
391
|
+
Input guardrails applied to the agent.
|
|
392
|
+
"""
|
|
393
|
+
return self._input_guardrails
|
|
394
|
+
|
|
395
|
+
@property
|
|
396
|
+
def output_guardrails(self) -> Optional[list[OutputGuardrail]]:
|
|
397
|
+
"""Return the output guardrails configured for this agent.
|
|
398
|
+
|
|
399
|
+
Returns
|
|
400
|
+
-------
|
|
401
|
+
list[OutputGuardrail] or None
|
|
402
|
+
Output guardrails applied to the agent.
|
|
403
|
+
"""
|
|
404
|
+
return self._output_guardrails
|
|
405
|
+
|
|
406
|
+
@property
|
|
407
|
+
def session(self) -> Optional[Session]:
|
|
408
|
+
"""Return the session configured for this agent.
|
|
409
|
+
|
|
410
|
+
Returns
|
|
411
|
+
-------
|
|
412
|
+
Session or None
|
|
413
|
+
Session configuration used for maintaining conversation history.
|
|
414
|
+
"""
|
|
415
|
+
return self._session
|
|
416
|
+
|
|
331
417
|
def get_agent(self) -> Agent:
|
|
332
418
|
"""Construct and return the configured :class:`agents.Agent` instance.
|
|
333
419
|
|
|
@@ -337,12 +423,12 @@ class BaseAgent:
|
|
|
337
423
|
Initialized agent ready for execution.
|
|
338
424
|
"""
|
|
339
425
|
agent_config: Dict[str, Any] = {
|
|
340
|
-
"name": self.
|
|
426
|
+
"name": self._name,
|
|
341
427
|
"instructions": self._build_prompt_from_jinja() or ".",
|
|
342
428
|
"model": self.model,
|
|
343
429
|
}
|
|
344
|
-
if self.
|
|
345
|
-
agent_config["output_type"] = self.
|
|
430
|
+
if self._output_structure:
|
|
431
|
+
agent_config["output_type"] = self._output_structure
|
|
346
432
|
if self._tools:
|
|
347
433
|
agent_config["tools"] = self._tools
|
|
348
434
|
if self._model_settings:
|
|
@@ -361,7 +447,7 @@ class BaseAgent:
|
|
|
361
447
|
input: str,
|
|
362
448
|
*,
|
|
363
449
|
context: Optional[Dict[str, Any]] = None,
|
|
364
|
-
|
|
450
|
+
output_structure: Optional[type[StructureBase]] = None,
|
|
365
451
|
session: Optional[Any] = None,
|
|
366
452
|
) -> Any:
|
|
367
453
|
"""Execute the agent asynchronously.
|
|
@@ -372,7 +458,7 @@ class BaseAgent:
|
|
|
372
458
|
Prompt or query for the agent.
|
|
373
459
|
context : dict or None, default=None
|
|
374
460
|
Optional dictionary passed to the agent.
|
|
375
|
-
|
|
461
|
+
output_structure : type[StructureBase] or None, default=None
|
|
376
462
|
Optional type used to cast the final output.
|
|
377
463
|
session : Session or None, default=None
|
|
378
464
|
Optional session for maintaining conversation history across runs.
|
|
@@ -381,17 +467,17 @@ class BaseAgent:
|
|
|
381
467
|
Returns
|
|
382
468
|
-------
|
|
383
469
|
Any
|
|
384
|
-
Agent result, optionally converted to ``
|
|
470
|
+
Agent result, optionally converted to ``output_structure``.
|
|
385
471
|
"""
|
|
386
|
-
if self.
|
|
387
|
-
|
|
472
|
+
if self._output_structure is not None and output_structure is None:
|
|
473
|
+
output_structure = self._output_structure
|
|
388
474
|
# Use session from parameter, fall back to config session
|
|
389
475
|
session_to_use = session if session is not None else self._session
|
|
390
476
|
return await run_async(
|
|
391
477
|
agent=self.get_agent(),
|
|
392
478
|
input=input,
|
|
393
479
|
context=context,
|
|
394
|
-
|
|
480
|
+
output_structure=output_structure,
|
|
395
481
|
session=session_to_use,
|
|
396
482
|
)
|
|
397
483
|
|
|
@@ -400,7 +486,7 @@ class BaseAgent:
|
|
|
400
486
|
input: str,
|
|
401
487
|
*,
|
|
402
488
|
context: Optional[Dict[str, Any]] = None,
|
|
403
|
-
|
|
489
|
+
output_structure: Optional[type[StructureBase]] = None,
|
|
404
490
|
session: Optional[Any] = None,
|
|
405
491
|
) -> Any:
|
|
406
492
|
"""Run the agent synchronously.
|
|
@@ -411,7 +497,7 @@ class BaseAgent:
|
|
|
411
497
|
Prompt or query for the agent.
|
|
412
498
|
context : dict or None, default=None
|
|
413
499
|
Optional dictionary passed to the agent.
|
|
414
|
-
|
|
500
|
+
output_structure : type[StructureBase] or None, default=None
|
|
415
501
|
Optional type used to cast the final output.
|
|
416
502
|
session : Session or None, default=None
|
|
417
503
|
Optional session for maintaining conversation history across runs.
|
|
@@ -420,15 +506,17 @@ class BaseAgent:
|
|
|
420
506
|
Returns
|
|
421
507
|
-------
|
|
422
508
|
Any
|
|
423
|
-
Agent result, optionally converted to ``
|
|
509
|
+
Agent result, optionally converted to ``output_structure``.
|
|
424
510
|
"""
|
|
511
|
+
if self._output_structure is not None and output_structure is None:
|
|
512
|
+
output_structure = self._output_structure
|
|
425
513
|
# Use session from parameter, fall back to config session
|
|
426
514
|
session_to_use = session if session is not None else self._session
|
|
427
515
|
return run_sync(
|
|
428
516
|
agent=self.get_agent(),
|
|
429
517
|
input=input,
|
|
430
518
|
context=context,
|
|
431
|
-
|
|
519
|
+
output_structure=output_structure,
|
|
432
520
|
session=session_to_use,
|
|
433
521
|
)
|
|
434
522
|
|
|
@@ -437,9 +525,9 @@ class BaseAgent:
|
|
|
437
525
|
input: str,
|
|
438
526
|
*,
|
|
439
527
|
context: Optional[Dict[str, Any]] = None,
|
|
440
|
-
|
|
528
|
+
output_structure: Optional[type[StructureBase]] = None,
|
|
441
529
|
session: Optional[Any] = None,
|
|
442
|
-
) -> RunResultStreaming:
|
|
530
|
+
) -> RunResultStreaming | StructureBase:
|
|
443
531
|
"""Stream the agent execution results.
|
|
444
532
|
|
|
445
533
|
Parameters
|
|
@@ -448,7 +536,7 @@ class BaseAgent:
|
|
|
448
536
|
Prompt or query for the agent.
|
|
449
537
|
context : dict or None, default=None
|
|
450
538
|
Optional dictionary passed to the agent.
|
|
451
|
-
|
|
539
|
+
output_structure : type[StructureBase] or None, default=None
|
|
452
540
|
Optional type used to cast the final output.
|
|
453
541
|
session : Session or None, default=None
|
|
454
542
|
Optional session for maintaining conversation history across runs.
|
|
@@ -461,16 +549,16 @@ class BaseAgent:
|
|
|
461
549
|
"""
|
|
462
550
|
# Use session from parameter, fall back to config session
|
|
463
551
|
session_to_use = session if session is not None else self._session
|
|
552
|
+
output_structure_to_use = output_structure or self._output_structure
|
|
464
553
|
result = run_streamed(
|
|
465
554
|
agent=self.get_agent(),
|
|
466
555
|
input=input,
|
|
467
556
|
context=context,
|
|
557
|
+
output_structure=output_structure_to_use,
|
|
468
558
|
session=session_to_use,
|
|
469
559
|
)
|
|
470
|
-
if
|
|
471
|
-
|
|
472
|
-
if output_type:
|
|
473
|
-
return result.final_output_as(output_type)
|
|
560
|
+
if output_structure_to_use and hasattr(result, "final_output_as"):
|
|
561
|
+
return cast(Any, result).final_output_as(output_structure_to_use)
|
|
474
562
|
return result
|
|
475
563
|
|
|
476
564
|
def as_tool(self) -> Tool:
|
|
@@ -483,16 +571,36 @@ class BaseAgent:
|
|
|
483
571
|
"""
|
|
484
572
|
agent = self.get_agent()
|
|
485
573
|
tool_obj: Tool = agent.as_tool(
|
|
486
|
-
tool_name=self.
|
|
574
|
+
tool_name=self._name, tool_description=self.description
|
|
487
575
|
)
|
|
488
576
|
return tool_obj
|
|
489
577
|
|
|
490
|
-
def
|
|
578
|
+
def as_response_tool(self) -> tuple[dict[str, Callable[..., Any]], dict[str, Any]]:
|
|
579
|
+
"""Return the agent as a callable response tool.
|
|
580
|
+
|
|
581
|
+
Returns
|
|
582
|
+
-------
|
|
583
|
+
Tool
|
|
584
|
+
Tool instance wrapping this agent for response generation.
|
|
585
|
+
"""
|
|
586
|
+
tool_handler = {self.name: self.run_sync}
|
|
587
|
+
tool_definition = {
|
|
588
|
+
"type": "function",
|
|
589
|
+
"name": self.name,
|
|
590
|
+
"description": self.description,
|
|
591
|
+
"strict": True,
|
|
592
|
+
"additionalProperties": False,
|
|
593
|
+
}
|
|
594
|
+
if self.output_structure:
|
|
595
|
+
tool_definition["parameters"] = self.output_structure.get_schema()
|
|
596
|
+
return tool_handler, tool_definition
|
|
597
|
+
|
|
598
|
+
def __enter__(self) -> AgentBase:
|
|
491
599
|
"""Enter the context manager for resource management.
|
|
492
600
|
|
|
493
601
|
Returns
|
|
494
602
|
-------
|
|
495
|
-
|
|
603
|
+
AgentBase
|
|
496
604
|
Self reference for use in with statements.
|
|
497
605
|
"""
|
|
498
606
|
return self
|
|
@@ -520,14 +628,47 @@ class BaseAgent:
|
|
|
520
628
|
|
|
521
629
|
Examples
|
|
522
630
|
--------
|
|
523
|
-
>>> agent =
|
|
631
|
+
>>> agent = AgentBase(config, default_model="gpt-4o-mini")
|
|
524
632
|
>>> try:
|
|
525
633
|
... result = agent.run_sync("query")
|
|
526
634
|
... finally:
|
|
527
635
|
... agent.close()
|
|
528
636
|
"""
|
|
529
|
-
|
|
530
|
-
|
|
637
|
+
log(f"Closing session {self.uuid} for {self.__class__.__name__}")
|
|
638
|
+
self.save()
|
|
639
|
+
|
|
640
|
+
def __repr__(self) -> str:
|
|
641
|
+
"""Return a string representation of the AgentBase.
|
|
642
|
+
|
|
643
|
+
Returns
|
|
644
|
+
-------
|
|
645
|
+
str
|
|
646
|
+
String representation including agent name and model.
|
|
647
|
+
"""
|
|
648
|
+
return f"<AgentBase name={self._name!r} model={self.model!r}>"
|
|
649
|
+
|
|
650
|
+
def save(self, filepath: str | Path | None = None) -> None:
|
|
651
|
+
"""Serialize the message history to a JSON file.
|
|
652
|
+
|
|
653
|
+
Saves the current message history to a specified file path in JSON format.
|
|
654
|
+
If no file path is provided, it saves to a default location based on
|
|
655
|
+
the agent's UUID.
|
|
656
|
+
|
|
657
|
+
Parameters
|
|
658
|
+
----------
|
|
659
|
+
filepath : str | Path | None, default=None
|
|
660
|
+
Optional file path to save the serialized history. If None,
|
|
661
|
+
uses a default filename based on the agent name.
|
|
662
|
+
"""
|
|
663
|
+
if filepath is not None:
|
|
664
|
+
target = Path(filepath)
|
|
665
|
+
else:
|
|
666
|
+
filename = f"{str(self.uuid).lower()}.json"
|
|
667
|
+
target = self._data_path / self._name / filename
|
|
668
|
+
|
|
669
|
+
checked = check_filepath(filepath=target)
|
|
670
|
+
self.to_json_file(filepath=checked)
|
|
671
|
+
log(f"Saved messages to {target}")
|
|
531
672
|
|
|
532
673
|
|
|
533
|
-
__all__ = ["
|
|
674
|
+
__all__ = ["AgentConfigurationProtocol", "AgentBase"]
|