Skip to content

OpenAI Agents basic examples #223

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: jssmith/openai-samples-reorg
Choose a base branch
from
Open
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
58 changes: 56 additions & 2 deletions openai_agents/basic/README.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left two comments at #226 that apply here as well

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Simple examples to get started with OpenAI Agents SDK integrated with Temporal w

*Adapted from [OpenAI Agents SDK basic examples](https://github.com/openai/openai-agents-python/tree/main/examples/basic)*

Before running these examples, be sure to review the [prerequisites and background on the integration](../README.md).

## Running the Examples

First, start the worker (supports all basic examples):
Expand All @@ -14,12 +16,64 @@ uv run openai_agents/basic/run_worker.py
Then run individual examples in separate terminals:

### Hello World Agent
Basic agent that only responds in haikus:
```bash
uv run openai_agents/basic/run_hello_world_workflow.py
```

### Tools Agent
Agent with access to external tools (weather API):
Agent with access to external tools (simulated weather API):
```bash
uv run openai_agents/basic/run_tools_workflow.py
```
```

### Agent Lifecycle with Hooks
Demonstrates agent lifecycle events and handoffs between agents:
```bash
uv run openai_agents/basic/run_agent_lifecycle_workflow.py
```

### Lifecycle with Usage Tracking
Shows detailed usage tracking with RunHooks (requests, tokens, etc.):
```bash
uv run openai_agents/basic/run_lifecycle_workflow.py
```

### Dynamic System Prompts
Agent with dynamic instruction generation based on context (haiku/pirate/robot):
```bash
uv run openai_agents/basic/run_dynamic_system_prompt_workflow.py
```

### Non-Strict Output Types
Demonstrates different JSON schema validation approaches:
```bash
uv run openai_agents/basic/run_non_strict_output_workflow.py
```

Note: `CustomOutputSchema` is not supported by the Temporal OpenAI Agents SDK integration and is omitted in this example.

### Image Processing - Local
Process local image files with AI vision:
```bash
uv run openai_agents/basic/run_local_image_workflow.py
```

### Image Processing - Remote
Process remote image URLs with AI vision:
```bash
uv run openai_agents/basic/run_remote_image_workflow.py
```

### Previous Response ID
Demonstrates conversation continuity using response IDs:
```bash
uv run openai_agents/basic/run_previous_response_id_workflow.py
```

## Omitted Examples

The following examples from the [reference repository](https://github.com/openai/openai-agents-python/tree/main/examples/basic) are not included in this Temporal adaptation:

- **Session** - Stores state in local SQLite database, not appropriate for distributed workflows
- **Stream Items/Stream Text** - Streaming is not supported in Temporal OpenAI Agents SDK integration
19 changes: 19 additions & 0 deletions openai_agents/basic/activities/image_activities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import base64

from temporalio import activity


@activity.defn
async def read_image_as_base64(image_path: str) -> str:
"""
Read an image file and convert it to base64 string.

Args:
image_path: Path to the image file

Returns:
Base64 encoded string of the image
"""
with open(image_path, "rb") as image_file:
encoded_string = base64.b64encode(image_file.read()).decode("utf-8")
return encoded_string
15 changes: 15 additions & 0 deletions openai_agents/basic/activities/math_activities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import random

from temporalio import activity


@activity.defn
async def random_number(max_value: int) -> int:
"""Generate a random number up to the provided maximum."""
return random.randint(0, max_value)


@activity.defn
async def multiply_by_two(x: int) -> int:
"""Simple multiplication by two."""
return x * 2
Binary file added openai_agents/basic/media/image_bison.jpg
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we feel about adding media files to this repository? This one is 235k.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions openai_agents/basic/run_agent_lifecycle_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import asyncio

from temporalio.client import Client

from openai_agents.basic.workflows.agent_lifecycle_workflow import (
AgentLifecycleWorkflow,
)


async def main() -> None:
client = await Client.connect("localhost:7233")

user_input = input("Enter a max number: ")
max_number = int(user_input)

result = await client.execute_workflow(
AgentLifecycleWorkflow.run,
max_number,
id="agent-lifecycle-workflow",
task_queue="openai-agents-basic-task-queue",
)

print(f"Final result: {result}")
print("Done!")


if __name__ == "__main__":
asyncio.run(main())
41 changes: 41 additions & 0 deletions openai_agents/basic/run_dynamic_system_prompt_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import asyncio

from temporalio.client import Client
from temporalio.contrib.openai_agents import OpenAIAgentsPlugin

from openai_agents.basic.workflows.dynamic_system_prompt_workflow import (
DynamicSystemPromptWorkflow,
)


async def main():
client = await Client.connect(
"localhost:7233",
plugins=[
OpenAIAgentsPlugin(),
],
)

user_message = "Tell me a joke."

result = await client.execute_workflow(
DynamicSystemPromptWorkflow.run,
user_message,
id="dynamic-prompt-workflow",
task_queue="openai-agents-basic-task-queue",
)
print(result)
print()

# Run with specific style
result = await client.execute_workflow(
DynamicSystemPromptWorkflow.run,
args=[user_message, "pirate"],
id="dynamic-prompt-pirate-workflow",
task_queue="openai-agents-basic-task-queue",
)
print(result)


if __name__ == "__main__":
asyncio.run(main())
2 changes: 1 addition & 1 deletion openai_agents/basic/run_hello_world_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async def main():
HelloWorldAgent.run,
"Tell me about recursion in programming.",
id="my-workflow-id",
task_queue="openai-agents-task-queue",
task_queue="openai-agents-basic-task-queue",
)
print(f"Result: {result}")

Expand Down
31 changes: 31 additions & 0 deletions openai_agents/basic/run_lifecycle_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import asyncio

from temporalio.client import Client
from temporalio.contrib.openai_agents import OpenAIAgentsPlugin

from openai_agents.basic.workflows.lifecycle_workflow import LifecycleWorkflow


async def main():
client = await Client.connect(
"localhost:7233",
plugins=[
OpenAIAgentsPlugin(),
],
)

user_input = input("Enter a max number: ")
max_number = int(user_input)

result = await client.execute_workflow(
LifecycleWorkflow.run,
max_number,
id="lifecycle-workflow",
task_queue="openai-agents-basic-task-queue",
)

print(f"Final result: {result}")


if __name__ == "__main__":
asyncio.run(main())
32 changes: 32 additions & 0 deletions openai_agents/basic/run_local_image_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import asyncio
import os

from temporalio.client import Client
from temporalio.contrib.openai_agents import OpenAIAgentsPlugin

from openai_agents.basic.workflows.local_image_workflow import LocalImageWorkflow


async def main():
client = await Client.connect(
"localhost:7233",
plugins=[
OpenAIAgentsPlugin(),
],
)

# Use the media file from the original example
image_path = os.path.join(os.path.dirname(__file__), "media/image_bison.jpg")

result = await client.execute_workflow(
LocalImageWorkflow.run,
args=[image_path, "What do you see in this image?"],
id="local-image-workflow",
task_queue="openai-agents-basic-task-queue",
)

print(f"Agent response: {result}")


if __name__ == "__main__":
asyncio.run(main())
35 changes: 35 additions & 0 deletions openai_agents/basic/run_non_strict_output_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import asyncio

from temporalio.client import Client
from temporalio.contrib.openai_agents import OpenAIAgentsPlugin

from openai_agents.basic.workflows.non_strict_output_workflow import (
NonStrictOutputWorkflow,
)


async def main():
client = await Client.connect(
"localhost:7233",
plugins=[
OpenAIAgentsPlugin(),
],
)

input_message = "Tell me 3 short jokes."

result = await client.execute_workflow(
NonStrictOutputWorkflow.run,
input_message,
id="non-strict-output-workflow",
task_queue="openai-agents-basic-task-queue",
)

print("=== Non-Strict Output Type Results ===")
for key, value in result.items():
print(f"{key}: {value}")
print()


if __name__ == "__main__":
asyncio.run(main())
35 changes: 35 additions & 0 deletions openai_agents/basic/run_previous_response_id_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import asyncio

from temporalio.client import Client
from temporalio.contrib.openai_agents import OpenAIAgentsPlugin

from openai_agents.basic.workflows.previous_response_id_workflow import (
PreviousResponseIdWorkflow,
)


async def main():
client = await Client.connect(
"localhost:7233",
plugins=[
OpenAIAgentsPlugin(),
],
)

first_question = "What is the largest country in South America?"
follow_up_question = "What is the capital of that country?"

result = await client.execute_workflow(
PreviousResponseIdWorkflow.run,
args=[first_question, follow_up_question],
id="previous-response-id-workflow",
task_queue="openai-agents-basic-task-queue",
)

print("\nFinal results:")
print(f"1. {result[0]}")
print(f"2. {result[1]}")


if __name__ == "__main__":
asyncio.run(main())
33 changes: 33 additions & 0 deletions openai_agents/basic/run_remote_image_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import asyncio

from temporalio.client import Client
from temporalio.contrib.openai_agents import OpenAIAgentsPlugin

from openai_agents.basic.workflows.remote_image_workflow import RemoteImageWorkflow


async def main():
client = await Client.connect(
"localhost:7233",
plugins=[
OpenAIAgentsPlugin(),
],
)

# Use the URL from the original example
image_url = (
"https://upload.wikimedia.org/wikipedia/commons/0/0c/GoldenGateBridge-001.jpg"
)

result = await client.execute_workflow(
RemoteImageWorkflow.run,
args=[image_url, "What do you see in this image?"],
id="remote-image-workflow",
task_queue="openai-agents-basic-task-queue",
)

print(f"Agent response: {result}")


if __name__ == "__main__":
asyncio.run(main())
2 changes: 1 addition & 1 deletion openai_agents/basic/run_tools_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async def main():
ToolsWorkflow.run,
"What is the weather in Tokio?",
id="tools-workflow",
task_queue="openai-agents-task-queue",
task_queue="openai-agents-basic-task-queue",
)

print(f"Result: {result}")
Expand Down
Loading
Loading