Skip to content

Opagentsdiff Run Sync And Run

Source code in OpAgentsOlympus/practice/OpAgentsDiff_run_sync_and_run.py
OpAgentsOlympus/practice/OpAgentsDiff_run_sync_and_run.py
import asyncio
import os
import time
import dotenv
import threading
from agents import Agent, Runner, function_tool, OpenAIChatCompletionsModel, AsyncOpenAI, set_tracing_disabled # type: ignore

dotenv.load_dotenv()
set_tracing_disabled(True)

api_key = os.environ.get("GEMINI_API_KEY")
client = AsyncOpenAI(
    api_key=api_key,
    base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
)
llm = OpenAIChatCompletionsModel(model='gemini-1.5-flash', openai_client=client)

@function_tool
def echo(text: str) -> str:
    return text

def spin_blocking():
    """A blocking spinner that runs in the main thread - this WON'T work with run_sync"""
    while True:
        print("⟳", end="", flush=True)
        time.sleep(0.1)
        # This loop blocks the entire thread

def spin_threaded():
    """A spinner that runs in a separate thread - the only way to get concurrency with run_sync"""
    while not stop_spinner:
        print("⟳", end="", flush=True)
        time.sleep(0.1)

def main_with_run_sync():
    global stop_spinner
    stop_spinner = False

    # Start spinner in a separate thread (only way to get concurrency with run_sync)
    spinner_thread = threading.Thread(target=spin_threaded, daemon=True)
    spinner_thread.start()

    agent = Agent(
        name="EchoAgent",
        instructions="Echo whatever the user says.",
        tools=[echo],
        model=llm,
    )

    print("Starting agent (run_sync)…", end="")
    start_time = time.time()

    # This blocks the entire thread until completion
    result = Runner.run_sync(agent, "Hello, world!")

    end_time = time.time()
    stop_spinner = True

    print("\nAgent done!")
    print(f"Time taken: {end_time - start_time:.2f} seconds")
    print("Final output:", result.final_output)

async def main_with_async():
    """For comparison - the original async version"""
    async def spin():
        while True:
            print("⟳", end="", flush=True)
            await asyncio.sleep(0.1)

    spinner = asyncio.create_task(spin())

    agent = Agent(
        name="EchoAgent",
        instructions="Echo whatever the user says.",
        tools=[echo],
        model=llm,
    )

    print("Starting agent (async)…", end="")
    start_time = time.time()
    result = await Runner.run(agent, "Hello, world!")
    end_time = time.time()
    spinner.cancel()
    print("\nAgent done!")
    print(f"Time taken: {end_time - start_time:.2f} seconds")
    print("Final output:", result.final_output)

def demonstrate_blocking_issue():
    """This demonstrates why run_sync blocks everything"""
    print("=== DEMONSTRATING run_sync BLOCKING ISSUE ===")
    print("This will NOT show a spinner because run_sync blocks the thread:")

    agent = Agent(
        name="EchoAgent",
        instructions="Echo whatever the user says.",
        tools=[echo],
        model=llm,
    )

    print("Starting agent…", end="")

    # Try to start a spinner - this won't work because run_sync will block
    # spin_blocking()  # If you uncomment this, it will block before run_sync even starts

    start_time = time.time()
    result = Runner.run_sync(agent, "Hello, world!")  # This blocks everything
    end_time = time.time()

    # We can't start both spinner and the agent with run_sync at the same time!
    print("Agent done! (no spinner was shown)")
    print(f"Time taken: {end_time - start_time:.2f} seconds")
    print("Final output:", result.final_output)

if __name__ == "__main__":
    choice = input("Choose demo:\n1. run_sync with threading workaround\n2. async version (original)\n3. demonstrate blocking issue\nEnter 1, 2, or 3: ")

    if choice == "1":
        main_with_run_sync()
    elif choice == "2":
        asyncio.run(main_with_async())
    elif choice == "3":
        demonstrate_blocking_issue()
    else:
        print("Invalid choice, running blocking demonstration:")
        demonstrate_blocking_issue()