Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions azure/durable_functions/openai_agents/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def wait_for_external_event(self, event_name: str):
"""Wait for an external event in the orchestration."""
return self._context.wait_for_external_event(event_name)

def activity_as_tool(
def create_activity_tool(
self,
activity_func: Callable,
*,
Expand All @@ -68,7 +68,14 @@ def activity_as_tool(
Tool: An OpenAI Agents SDK Tool object

"""
activity_name = activity_func._function._name
if activity_func._function is None:
raise ValueError("The provided function is not a valid Azure Function.")

if (activity_func._function._trigger is not None
and activity_func._function._trigger.activity is not None):
activity_name = activity_func._function._trigger.activity
else:
activity_name = activity_func._function._name

async def run_activity(ctx: RunContextWrapper[Any], input: str) -> Any:
if retry_options:
Expand All @@ -81,7 +88,6 @@ async def run_activity(ctx: RunContextWrapper[Any], input: str) -> Any:

schema = function_schema(
func=activity_func._function._func,
name_override=activity_name,
docstring_style=None,
description_override=description,
use_docstring_info=True,
Expand Down
36 changes: 35 additions & 1 deletion tests/orchestrator/openai_agents/test_openai_agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,26 @@ def openai_agent_use_tool(context):
agent = Agent(
name="Assistant",
instructions="You only respond in haikus.",
tools=[context.activity_as_tool(get_weather, retry_options=None)]
tools=[context.create_activity_tool(get_weather, retry_options=None)]
)

result = Runner.run_sync(agent, "Tell me the weather in Seattle.", )

return result.final_output;

@app.activity_trigger(input_name="city", activity="get_weather_with_explicit_name")
def get_named_weather(city: str) -> Weather:
print("[debug] get_weather called")
return Weather(city=city, temperature_range="14-20C", conditions="Sunny with wind.")

@app.function_name("openai_agent_use_tool_with_explicit_name")
@app.orchestration_trigger(context_name="context")
@app.durable_openai_agent_orchestrator(model_retry_options=None)
def openai_agent_use_tool_with_explicit_name(context):
agent = Agent(
name="Assistant",
instructions="You only respond in haikus.",
tools=[context.create_activity_tool(get_named_weather, retry_options=None)]
)

result = Runner.run_sync(agent, "Tell me the weather in Seattle.", )
Expand Down Expand Up @@ -172,6 +191,21 @@ def test_openai_agent_use_tool_activity_start():
assert_valid_schema(result)
assert_orchestration_state_equals(expected, result)

def test_openai_agent_use_explicitly_named_tool_activity_start():
context_builder = ContextBuilder('test_openai_agent_use_tool_start')
add_activity_completed_events(context_builder, 0, '{"output":[{"arguments":"{\\"args\\":\\"Seattle, WA\\"}","call_id":"call_mEdywElQTNpxAdivuEFjO0cT","name":"get_named_weather","type":"function_call","id":"fc_68b9ecc0ff9c819f863d6cf9e0a1b4e101011fd6f5f8c0a6","status":"completed"}],"usage":{"requests":1,"input_tokens":57,"input_tokens_details":{"cached_tokens":0},"output_tokens":17,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":74},"response_id":"resp_68b9ecc092e0819fb79b97c11aacef2001011fd6f5f8c0a6"}')

result = get_orchestration_state_result(
context_builder, openai_agent_use_tool_with_explicit_name, uses_pystein=True)

expected_state = base_expected_state()
add_activity_action(expected_state, "{\"input\":[{\"content\":\"Tell me the weather in Seattle.\",\"role\":\"user\"}],\"model_settings\":{\"temperature\":null,\"top_p\":null,\"frequency_penalty\":null,\"presence_penalty\":null,\"tool_choice\":null,\"parallel_tool_calls\":null,\"truncation\":null,\"max_tokens\":null,\"reasoning\":null,\"metadata\":null,\"store\":null,\"include_usage\":null,\"response_include\":null,\"extra_query\":null,\"extra_body\":null,\"extra_headers\":null,\"extra_args\":null},\"tracing\":0,\"model_name\":null,\"system_instructions\":\"You only respond in haikus.\",\"tools\":[{\"name\":\"get_named_weather\",\"description\":\"\",\"params_json_schema\":{\"properties\":{\"city\":{\"title\":\"City\",\"type\":\"string\"}},\"required\":[\"city\"],\"title\":\"get_named_weather_args\",\"type\":\"object\",\"additionalProperties\":false},\"strict_json_schema\":true}],\"output_schema\":null,\"handoffs\":[],\"previous_response_id\":null,\"prompt\":null}")
add_activity_action(expected_state, "{\"args\":\"Seattle, WA\"}", activity_name="get_weather_with_explicit_name")
expected = expected_state.to_json()

assert_valid_schema(result)
assert_orchestration_state_equals(expected, result)

def test_openai_agent_use_tool_activity_completed():
context_builder = ContextBuilder('test_openai_agent_use_tool_start')
add_activity_completed_events(context_builder, 0, '{"output":[{"arguments":"{\\"args\\":\\"Seattle, WA\\"}","call_id":"call_mEdywElQTNpxAdivuEFjO0cT","name":"get_weather","type":"function_call","id":"fc_68b9ecc0ff9c819f863d6cf9e0a1b4e101011fd6f5f8c0a6","status":"completed"}],"usage":{"requests":1,"input_tokens":57,"input_tokens_details":{"cached_tokens":0},"output_tokens":17,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":74},"response_id":"resp_68b9ecc092e0819fb79b97c11aacef2001011fd6f5f8c0a6"}')
Expand Down