Skip to content

Commit 74cd1f1

Browse files
test in progress
1 parent 38d466f commit 74cd1f1

1 file changed

Lines changed: 260 additions & 0 deletions

File tree

tests/integrations/openai_agents/test_openai_agents.py

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
ModelSettings,
1515
Usage,
1616
)
17+
from agents.computer import Computer
1718
from agents.exceptions import MaxTurnsExceeded, ModelBehaviorError
1819
from agents.items import (
1920
ResponseFunctionToolCall,
@@ -24,6 +25,46 @@
2425
from agents.tool import HostedMCPTool
2526
from agents.version import __version__ as OPENAI_AGENTS_VERSION
2627
from openai import AsyncOpenAI, InternalServerError
28+
from openai.types.responses.tool_param import CodeInterpreter, ImageGeneration
29+
30+
from sentry_sdk.integrations import DidNotEnable
31+
32+
try:
33+
from agents import (
34+
CodeInterpreterTool,
35+
ComputerTool,
36+
FileSearchTool,
37+
HostedMCPTool,
38+
ImageGenerationTool,
39+
LocalShellTool,
40+
WebSearchTool,
41+
)
42+
except ImportError:
43+
raise DidNotEnable("OpenAI Agents not installed")
44+
45+
try:
46+
from agents import ApplyPatchTool, ShellTool
47+
except ImportError:
48+
ShellTool = None
49+
ApplyPatchTool = None
50+
51+
try:
52+
from agents import ToolSearchTool
53+
except ImportError:
54+
ToolSearchTool = None
55+
56+
try:
57+
from agents import CustomTool
58+
except ImportError:
59+
CustomTool = None
60+
61+
try:
62+
from agents import ProgrammaticToolCallingTool
63+
except ImportError:
64+
ProgrammaticToolCallingTool = None
65+
66+
67+
from typing import Any, cast
2768

2869
import sentry_sdk
2970
from sentry_sdk import start_span
@@ -173,6 +214,225 @@ def test_agent_custom_model():
173214
)
174215

175216

217+
class DummyEditor:
218+
def create_file(self, operation):
219+
return None
220+
221+
def update_file(self, operation):
222+
return None
223+
224+
def delete_file(self, operation):
225+
return None
226+
227+
228+
class TrackingComputer(Computer):
229+
def __init__(self):
230+
self.calls = []
231+
232+
@property
233+
def environment(self):
234+
return "mac"
235+
236+
@property
237+
def dimensions(self):
238+
return (1, 1)
239+
240+
def screenshot(self):
241+
self.calls.append("screenshot")
242+
return "img"
243+
244+
def click(self, _x, _y, _button):
245+
self.calls.append("click")
246+
247+
def double_click(self, _x, _y):
248+
self.calls.append("double_click")
249+
250+
def scroll(self, _x, _y, _scroll_x, _scroll_y):
251+
self.calls.append("scroll")
252+
253+
def type(self, _text):
254+
self.calls.append("type")
255+
256+
def wait(self):
257+
self.calls.append("wait")
258+
259+
def move(self, _x, _y):
260+
self.calls.append("move")
261+
262+
def keypress(self, _keys):
263+
self.calls.append("keypress")
264+
265+
def drag(self, _path):
266+
self.calls.append("drag")
267+
268+
269+
@pytest.mark.parametrize("span_streaming", [True, False])
270+
@pytest.mark.parametrize("stream_gen_ai_spans", [True, False])
271+
@pytest.mark.asyncio
272+
async def test_tool_definitions(
273+
sentry_init,
274+
capture_events,
275+
capture_items,
276+
test_agent,
277+
nonstreaming_responses_model_response,
278+
get_model_response,
279+
stream_gen_ai_spans,
280+
span_streaming,
281+
):
282+
client = AsyncOpenAI(api_key="test-key")
283+
model = OpenAIResponsesModel(model="gpt-4", openai_client=client)
284+
285+
def some_function(a: str, b: list[int]) -> str:
286+
return "hello"
287+
288+
tools = [
289+
agents.function_tool(some_function, defer_loading=True),
290+
WebSearchTool(),
291+
FileSearchTool(vector_store_ids=[]),
292+
ComputerTool(computer=TrackingComputer()),
293+
HostedMCPTool(
294+
tool_config=cast(
295+
Any,
296+
{
297+
"type": "mcp",
298+
"server_label": "docs_server",
299+
"server_url": "https://example.com/mcp",
300+
},
301+
)
302+
),
303+
ImageGenerationTool(
304+
tool_config=cast(
305+
ImageGeneration, {"type": "image_generation", "model": "gpt-image-1"}
306+
)
307+
),
308+
CodeInterpreterTool(
309+
tool_config=cast(
310+
CodeInterpreter, {"type": "code_interpreter", "container": "python"}
311+
)
312+
),
313+
LocalShellTool(executor=lambda req: "ok"),
314+
]
315+
316+
if CustomTool is not None:
317+
tools.append(
318+
CustomTool(
319+
name="custom",
320+
description="Custom tool",
321+
on_invoke_tool=lambda _context, _input: "ok",
322+
)
323+
)
324+
325+
if ApplyPatchTool is not None:
326+
tools.append(ApplyPatchTool(editor=DummyEditor()))
327+
328+
if ShellTool is not None:
329+
tools.append(ShellTool(executor=lambda req: "ok"))
330+
331+
if ToolSearchTool is not None:
332+
tools.append(ToolSearchTool())
333+
334+
if ProgrammaticToolCallingTool is not None:
335+
tools.append(ProgrammaticToolCallingTool())
336+
337+
agent = test_agent.clone(model=model, tools=tools)
338+
339+
response = get_model_response(
340+
nonstreaming_responses_model_response, serialize_pydantic=True
341+
)
342+
343+
if span_streaming:
344+
with patch.object(
345+
agent.model._client._client,
346+
"send",
347+
return_value=response,
348+
) as _:
349+
sentry_init(
350+
integrations=[OpenAIAgentsIntegration()],
351+
disabled_integrations=[StdlibIntegration],
352+
traces_sample_rate=1.0,
353+
send_default_pii=False,
354+
stream_gen_ai_spans=stream_gen_ai_spans,
355+
trace_lifecycle="stream",
356+
)
357+
358+
items = capture_items("span")
359+
360+
result = await agents.Runner.run(
361+
agent,
362+
"Test input",
363+
run_config=test_run_config,
364+
)
365+
366+
assert result is not None
367+
assert result.final_output == "Hello, how can I help you?"
368+
369+
sentry_sdk.flush()
370+
spans = [item.payload for item in items]
371+
ai_client_span = next(
372+
span for span in spans if span["attributes"]["sentry.op"] == OP.GEN_AI_CHAT
373+
)
374+
375+
assert ai_client_span["attributes"][SPANDATA.GEN_AI_TOOL_DEFINITIONS] == 1.0
376+
elif stream_gen_ai_spans:
377+
with patch.object(
378+
agent.model._client._client,
379+
"send",
380+
return_value=response,
381+
) as _:
382+
sentry_init(
383+
integrations=[OpenAIAgentsIntegration()],
384+
traces_sample_rate=1.0,
385+
send_default_pii=False,
386+
stream_gen_ai_spans=stream_gen_ai_spans,
387+
)
388+
389+
items = capture_items("span", "transaction")
390+
391+
result = await agents.Runner.run(
392+
agent,
393+
"Test input",
394+
run_config=test_run_config,
395+
)
396+
397+
assert result is not None
398+
assert result.final_output == "Hello, how can I help you?"
399+
400+
spans = [item.payload for item in items if item.type == "span"]
401+
ai_client_span = next(
402+
span for span in spans if span["attributes"]["sentry.op"] == OP.GEN_AI_CHAT
403+
)
404+
405+
assert ai_client_span["attributes"][SPANDATA.GEN_AI_TOOL_DEFINITIONS] == 1.0
406+
else:
407+
with patch.object(
408+
agent.model._client._client,
409+
"send",
410+
return_value=response,
411+
) as _:
412+
sentry_init(
413+
integrations=[OpenAIAgentsIntegration()],
414+
traces_sample_rate=1.0,
415+
send_default_pii=False,
416+
stream_gen_ai_spans=stream_gen_ai_spans,
417+
)
418+
events = capture_events()
419+
420+
result = await agents.Runner.run(
421+
agent,
422+
"Test input",
423+
run_config=test_run_config,
424+
)
425+
426+
assert result is not None
427+
assert result.final_output == "Hello, how can I help you?"
428+
429+
(transaction,) = events
430+
spans = transaction["spans"]
431+
ai_client_span = next(span for span in spans if span["op"] == OP.GEN_AI_CHAT)
432+
433+
assert ai_client_span["data"][SPANDATA.GEN_AI_TOOL_DEFINITIONS] == 1.0
434+
435+
176436
@pytest.mark.parametrize("span_streaming", [True, False])
177437
@pytest.mark.parametrize("stream_gen_ai_spans", [True, False])
178438
@pytest.mark.asyncio

0 commit comments

Comments
 (0)