### Example Console Output for Lifecycle Execution Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/run_lifecycle This output demonstrates the execution flow of the 'run_lifecycle.py' script. It shows the sequence of events logged by the custom `ExampleHooks`, including agent starts and ends, tool calls, and agent handoffs, along with associated usage statistics. ```bash $ python examples/basic/lifecycle_example.py Enter a max number: 250 ### 1: Agent Start Agent started. Usage: 0 requests, 0 input tokens, 0 output tokens, 0 total tokens ### 2: Tool random_number started. Usage: 1 requests, 148 input tokens, 15 output tokens, 163 total tokens ### 3: Tool random_number ended with result 101. Usage: 1 requests, 148 input tokens, 15 output tokens, 163 total tokens ### 4: Handoff from Start Agent to Multiply Agent. Usage: 2 requests, 323 input tokens, 30 output tokens, 353 total tokens ### 5: Agent Multiply Agent started. Usage: 2 requests, 323 input tokens, 30 output tokens, 353 total tokens ### 6: Tool multiply_by_two started. Usage: 3 requests, 504 input tokens, 46 output tokens, 550 total tokens ### 7: Tool multiply_by_two ended with result 202. Usage: 3 requests, 504 input tokens, 46 output tokens, 550 total tokens ### 8: Agent Multiply Agent ended with output number=202. Usage: 4 requests, 714 input tokens, 63 output tokens, 777 total tokens Done! ``` -------------------------------- ### Agent Configuration and Execution Flow in Python Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/agent_lifecycle Demonstrates the setup of two agents: 'Multiply Agent' and 'Start Agent'. The 'Multiply Agent' uses the 'multiply_by_two' tool, while the 'Start Agent' uses the 'random_number' tool and can hand off to the 'Multiply Agent'. The `main` function orchestrates the execution, taking user input for the random number range and running the 'Start Agent' via the `Runner` class. ```python class FinalResult(BaseModel): number: int multiply_agent = Agent( name="Multiply Agent", instructions="Multiply the number by 2 and then return the final result.", tools=[multiply_by_two], output_type=FinalResult, # output_type + tools doesn't work with gemini hooks=CustomAgentHooks(display_name="Multiply Agent"), ) start_agent = Agent( name="Start Agent", instructions="Generate a random number. If it's even, stop. If it's odd, hand off to the multiply agent.", tools=[random_number], handoffs=[multiply_agent], output_type=FinalResult, # output_type + tools doesn't work with gemini hooks=CustomAgentHooks(display_name="Start Agent"), ) async def main() -> None: user_input = input("Enter a max number: ") await Runner.run( start_agent, input=f"Generate a random number between 0 and {user_input}.", run_config=config, ) print("Done!") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Using Hosted Tools: WebSearchTool and FileSearchTool in Python Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Example of initializing an Agent with WebSearchTool and FileSearchTool to search the web and local files. This agent can then be used to answer queries based on search results and file content. ```Python from agents import Agent, Runner, WebSearchTool, FileSearchTool agent = Agent( name="Assistant", tools=[ WebSearchTool(), FileSearchTool(max_num_results=3, vector_store_ids=["VECTOR_STORE_ID"]), ], ) result = await Runner.run(agent, "Which coffee shop should I go to, considering my preferences and today\'s weather in SF?") print(result.final_output) ``` -------------------------------- ### Complete Agent Workflow Example in Python Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide A comprehensive example integrating agents, tools, handoffs, and guardrails. This demonstrates a `triage_agent` that can hand off to language agents or a weather agent, utilizing a homework guardrail and the `get_weather` tool. The `Runner.run_sync` method is used to execute the workflow. ```python from agents import Agent, Runner, function_tool, handoff, input_guardrail, GuardrailFunctionOutput, InputGuardrailTripwireTriggered async def homework_guardrail(ctx, agent, input_text: str): # Simple check for math homework in user query triggered = "homework" in input_text.lower() return GuardrailFunctionOutput( output_info=None, tripwire_triggered=triggered ) @function_tool def get_weather(city: str) -> str: return f"The weather in {city} is sunny." spanish_agent = Agent( name="Spanish", instructions="You only answer in Spanish.", ) english_agent = Agent( name="English", instructions="You only answer in English.", ) weather_agent = Agent( name="Weather Agent", instructions="You provide weather info.", tools=[get_weather] ) triage_agent = Agent( name="Triage", instructions="Call the right agent based on the language and request.", handoffs=[spanish_agent, handoff(english_agent), weather_agent], input_guardrails=[homework_guardrail] ) result = Runner.run_sync(triage_agent, "What's the weather in Tokyo?") print(result.final_output) ``` -------------------------------- ### Python Agent Setup and Handoff Example Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/main This snippet defines two agents, Agent A and Agent B, and configures a handoff from A to B. Agent A has access to function tools and a custom input filter for the handoff, while Agent B is a simple agent that prints a message upon starting. The script initializes an asynchronous OpenAI client for a Gemini model and uses a Runner to execute the agent interaction. ```python from agents import ( Agent, Runner, handoff, enable_verbose_stdout_logging, OpenAIChatCompletionsModel, AsyncOpenAI, set_tracing_disabled, function_tool, ) # type: ignore from agents.handoffs import HandoffInputData import os import dotenv import asyncio 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/", ) model = OpenAIChatCompletionsModel(model="gemini-2.0-flash", openai_client=client) enable_verbose_stdout_logging() # Define some example function tools @function_tool def tool_1(): """First parallel tool""" return "Result from tool 1" @function_tool def tool_2(): """Second parallel tool""" return "Result from tool 2" @function_tool def tool_3(): """Third parallel tool""" return "Result from tool 3" # Custom input filter that modifies pre_handoff_items and prints debug info def custom_input_filter(handoff_input_data: HandoffInputData) -> HandoffInputData: print("=== BEFORE FILTERING ===") print( f"Input history length: {len(handoff_input_data.input_history) if isinstance(handoff_input_data.input_history, tuple) else 'string'}" ) print(f"Pre-handoff items count: {len(handoff_input_data.pre_handoff_items)}") print(f"New items count: {len(handoff_input_data.new_items)}") # Clear pre_handoff_items to demonstrate filtering filtered_data = HandoffInputData( input_history=handoff_input_data.input_history, pre_handoff_items=(), # Clear pre_handoff_items new_items=handoff_input_data.new_items, ) print("=== AFTER FILTERING ===") print( f"Input history length: {len(filtered_data.input_history) if isinstance(filtered_data.input_history, tuple) else 'string'}" ) print(f"Pre-handoff items count: {len(filtered_data.pre_handoff_items)}") print(f"New items count: {len(filtered_data.new_items)}") return filtered_data # Agent B with debug printing class DebugAgent(Agent): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) async def _on_agent_start(self, context): print("=== AGENT B RECEIVED INPUT ===") # This would show what Agent B actually receives after filtering print("Agent B starting with context") # Agent B (target of handoff) agent_b = DebugAgent( name="Agent B", instructions="You are Agent B, handling tasks after handoff.", model=model, ) # Agent A (source agent with tools and handoff) agent_a = Agent( name="Agent A", instructions="You are Agent A. Use your tools and then handoff to Agent B.", tools=[tool_1, tool_2, tool_3], model=model, handoffs=[ handoff( agent=agent_b, input_filter=custom_input_filter, # This modifies pre_handoff_items ) ], ) # Run the scenario async def main(): result = await Runner.run( agent_a, input="Please use all your tools and then handoff to Agent B" ) print(f"Final result: {result.final_output}") print(f"Final agent: {result.last_agent.name}") print(result) asyncio.run(main()) ``` -------------------------------- ### Add MCP Server to an Agent (Python) Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Shows how to initialize an Agent with a list of MCP servers. The SDK automatically calls `list_tools()` on these servers at the start of each run, making their tools available to the agent. ```python agent = Agent( name="Assistant", instructions="Use the tools provided by MCP servers.", mcp_servers=[mcp_server] ) ``` -------------------------------- ### Integrate LiteLLM for Model Flexibility Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Shows how to use the `LitellmModel` class to easily access over 100 different models through the LiteLLM integration. This requires installing the `openai-agents[litellm]` package. You can specify any LiteLLM-compatible model name and its corresponding API key. It supports various providers wrapped by LiteLLM. ```bash pip install "openai-agents[litellm]" ``` ```python from agents.extensions.models.litellm_model import LitellmModel from agents import Agent, Runner agent = Agent( name="Assistant", instructions="You respond in haikus.", model=LitellmModel(model="anthropic/claude-3-5-sonnet-20240620", api_key="YOUR_API_KEY"), tools=[get_weather], ) result = await Runner.run(agent, "What's the weather in Tokyo?") print(result.final_output) ``` -------------------------------- ### Python: Install LiteLLM for Non-OpenAI Models Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Provides the command to install the necessary extras for using LiteLLM with the openai-agents library. This enables integration with various non-OpenAI LLM providers. ```bash pip install "openai-agents[litellm]" ``` -------------------------------- ### Create a Basic Agent Object Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Illustrates how to create an 'Agent' object from the OpenAI Agents SDK. An agent is initialized with a name and specific instructions that guide its behavior. ```python from agents import Agent, Runner agent = Agent(name="Assistant", instructions="You are a helpful assistant.") ``` -------------------------------- ### Create Multiple Agents with Different Instructions Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Shows how to define multiple 'Agent' objects, each with a unique name and a distinct set of instructions. This example creates a Spanish-speaking agent and an English-speaking agent. ```python spanish_agent = Agent(name="Spanish", instructions="You only respond in Spanish.") english_agent = Agent(name="English", instructions="You only respond in English.") ``` -------------------------------- ### Example Agent Lifecycle Execution Output Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/agent_lifecycle This section provides a sample console output from running the 'agent_lifecycle_example.py' script. It shows the sequence of events logged by the custom agent hooks, including agent starts, tool calls and their results, handoffs between agents, and the final output. This output helps visualize the agent's execution flow and interactions. ```shell $ python examples/basic/agent_lifecycle_example.py Enter a max number: 250 ### (Start Agent) 1: Agent Start Agent started ### (Start Agent) 2: Agent Start Agent started tool random_number ### (Start Agent) 3: Agent Start Agent ended tool random_number with result 37 ### (Start Agent) 4: Agent Start Agent handed off to Multiply Agent ### (Multiply Agent) 1: Agent Multiply Agent started ### (Multiply Agent) 2: Agent Multiply Agent started tool multiply_by_two ### (Multiply Agent) 3: Agent Multiply Agent ended tool multiply_by_two with result 74 ### (Multiply Agent) 4: Agent Multiply Agent ended with output number=462 Done! ``` -------------------------------- ### Manually Start and Finish Traces Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide This Python code shows how to manually initiate and conclude traces using `trace.start()` and `trace.finish()`. While functional, using the `with trace(...)` context manager is generally recommended for cleaner code and automatic trace management. This method requires the `trace` object from the `agents` library. ```python from agents import trace tr = trace.start("MyTrace", mark_as_current=True) # Do some work... trace.finish(tr, reset_current=True) ``` -------------------------------- ### Basic RunConfig Setup and Usage Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpAgentsRunConfig Demonstrates how to create a RunConfig object with basic settings like model and workflow name, and then pass it to the Runner.run() method to execute an agent with these configurations. ```python from agents import Runner, RunConfig # Create your configuration config = RunConfig( model="gpt-4", # Use GPT-4 for all agents workflow_name="Email Assistant", tracing_disabled=False # Keep tracing on ) # Run your agent with the config result = await Runner.run( my_agent, "Help me write an email", run_config=config ) ``` -------------------------------- ### Python: Initialize Agents with LiteLLM Models Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Demonstrates how to initialize agents to use non-OpenAI models via LiteLLM. It shows examples for Anthropic's Claude and Google's Gemini models, specifying the model identifier prefixed with 'litellm/'. ```python claude_agent = Agent(model="litellm/anthropic/claude-3-5-sonnet-20240620", instructions="...") gemini_agent = Agent(model="litellm/gemini/gemini-2.5-flash-preview-04-17", instructions="...") ``` -------------------------------- ### Create a Python Project and Virtual Environment Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Sets up a new project directory and creates a Python virtual environment named 'env'. This isolates project dependencies. ```bash mkdir my-project cd my-project python3 -m venv env ``` -------------------------------- ### Python AI Agent Quickstart with Guardrail and Triage Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/quickstart This Python script demonstrates a quickstart for building AI agents using the 'agents' library. It sets up a math tutor and a history tutor agent, protected by a 'homework_guardrail' that uses a guardrail agent to determine if a query is homework-related. A 'triage_agent' then routes the user's input to the appropriate specialist agent or triggers the guardrail. It relies on Pydantic for output models and OpenAI's client for interacting with the Gemini API. ```python from pydantic import BaseModel from agents import ( Agent, GuardrailFunctionOutput, Runner, set_tracing_disabled, OpenAIChatCompletionsModel, InputGuardrail, RunConfig, ) import os from openai import AsyncOpenAI import dotenv import asyncio dotenv.load_dotenv() set_tracing_disabled(True) GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY") if not GEMINI_API_KEY: raise ValueError("API key not found!!") client = AsyncOpenAI( api_key=GEMINI_API_KEY, base_url="https://generativelanguage.googleapis.com/v1beta/openai/", ) model = OpenAIChatCompletionsModel(model="gemini-2.0-flash", openai_client=client) config = RunConfig(model=model, model_provider=client) class HomeworkOutput(BaseModel): is_homework: bool reasoning: str guardrail_agent = Agent( name="Guardrail check", instructions="Check if the user is asking about homework.", output_type=HomeworkOutput, ) math_tutor_agent = Agent( name="Math Tutor", handoff_description="Specialist agent for math questions", instructions="You provide help with math problems. Explain your reasoning at each step and include examples", ) history_tutor_agent = Agent( name="History Tutor", handoff_description="Specialist agent for historical questions", instructions="You provide assistance with historical queries. Explain important events and context clearly.", ) async def homework_guardrail(ctx, agent, input_data): result = await Runner.run( guardrail_agent, input_data, context=ctx.context, run_config=config ) final_output = result.final_output_as(HomeworkOutput) print(final_output) return GuardrailFunctionOutput( output_info=final_output, tripwire_triggered=not final_output.is_homework, ) triage_agent = Agent( name="Triage Agent", instructions="You determine which agent to use based on the user's homework question", handoffs=[history_tutor_agent, math_tutor_agent], input_guardrails=[ InputGuardrail(guardrail_function=homework_guardrail), ], ) async def main(): # result = Runner.run_streamed(triage_agent, "What is 2 + 2?", run_config=config) # async for event in result.stream_events(): # if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent): # print(event.data.delta, end="", flush=True) result = await Runner.run(triage_agent, "what is life", run_config=config) print(result.final_output) if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Python Gemini API Client Setup Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/testing2222 Initializes the Gemini API client using environment variables for authentication. It loads the API key from a '.env' file and configures an asynchronous OpenAI client pointed to the Gemini API base URL. This setup is crucial for enabling the agent to communicate with the Gemini language model. ```python from dotenv import load_dotenv from agents import \ Agent, Runner, function_tool, RunConfig, AsyncOpenAI, OpenAIChatCompletionsModel, load_dotenv() import os # Load environment variables gemini_api_key = os.getenv("GEMINI_API_KEY") if not gemini_api_key: raise ValueError("GEMINI_API_KEY is not set. Please define it in your .env file.") # Setup Gemini client external_client = AsyncOpenAI( api_key=gemini_api_key, base_url="https://generativelanguage.googleapis.com/v1beta/openai/", ) # Preferred Gemini model setup model = OpenAIChatCompletionsModel( model="gemini-2.0-flash", openai_client=external_client ) # Runner config (you can export this) config = RunConfig( model=model, model_provider=external_client, # tracing_disabled=True ) ``` -------------------------------- ### Python Open Router Configuration Setup Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/open_router_config This Python script configures the Open Router API for use with the openai-agents library. It handles importing necessary modules, loading API keys from environment variables, setting the base URL, and initializing the chat completion model. It requires the 'openai-agents' package to be installed. ```python import os try: from dotenv import load_dotenv, find_dotenv from agents import AsyncOpenAI, OpenAIChatCompletionsModel from agents.run import RunConfig except ImportError: raise ImportError( "\nThis package requires 'openai-agents' to be installed.\n" "\nPlease install it first using pip:\n" "\npip install openai-agents\n" "\nFor more information, visit: https://openai.github.io/openai-agents-PyDeepOlympus/quickstart/\n" ) # Load environment variables load_dotenv(find_dotenv()) API_KEY = os.environ.get("OPENROUTER_API_KEY") BASE_URL = "https://openrouter.ai/api/v1" MODEL = "openai/gpt-4o-mini" model = OpenAIChatCompletionsModel( model=MODEL, openai_client=AsyncOpenAI(api_key=API_KEY, base_url=BASE_URL) ) # Runner config (you can export this) config = RunConfig(model=model) ``` -------------------------------- ### Install OpenAI Agents SDK using Pip Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/openai_agents_sdk Installs the OpenAI Agents SDK using the pip package manager. This is a prerequisite for using the SDK. ```bash pip install openai-agents ``` -------------------------------- ### Python Agent Lifecycle Hooks and Runner Example Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/run_lifecycle This Python script defines custom hooks to monitor agent and tool lifecycles. It demonstrates agent initialization, tool execution, and agent handoffs using the Runner class. Dependencies include asyncio, random, pydantic, and specific components from the 'agents' library. ```python import asyncio import random from typing import Any from pydantic import BaseModel from agents import ( Agent, RunContextWrapper, RunHooks, Runner, Tool, Usage, function_tool, ) from open_router_config import config class ExampleHooks(RunHooks): def __init__(self): self.event_counter = 0 def _usage_to_str(self, usage: Usage) -> str: return f"{usage.requests} requests, {usage.input_tokens} input tokens, {usage.output_tokens} output tokens, {usage.total_tokens} total tokens" async def on_agent_start(self, context: RunContextWrapper, agent: Agent) -> None: self.event_counter += 1 print( f"### {self.event_counter}: Agent {agent.name} started. Usage: {self._usage_to_str(context.usage)}" ) async def on_agent_end( self, context: RunContextWrapper, agent: Agent, output: Any ) -> None: self.event_counter += 1 print( f"### {self.event_counter}: Agent {agent.name} ended with output {output}. Usage: {self._usage_to_str(context.usage)}" ) async def on_tool_start( self, context: RunContextWrapper, agent: Agent, tool: Tool ) -> None: self.event_counter += 1 print( f"### {self.event_counter}: Tool {tool.name} started. Usage: {self._usage_to_str(context.usage)}" ) async def on_tool_end( self, context: RunContextWrapper, agent: Agent, tool: Tool, result: str ) -> None: self.event_counter += 1 print( f"### {self.event_counter}: Tool {tool.name} ended with result {result}. Usage: {self._usage_to_str(context.usage)}" ) async def on_handoff( self, context: RunContextWrapper, from_agent: Agent, to_agent: Agent ) -> None: self.event_counter += 1 print( f"### {self.event_counter}: Handoff from {from_agent.name} to {to_agent.name}. Usage: {self._usage_to_str(context.usage)}" ) hooks = ExampleHooks() ### @function_tool def random_number(max: int) -> int: """Generate a random number up to the provided max.""" return random.randint(0, max) @function_tool def multiply_by_two(x: int) -> int: """Return x times two.""" return x * 2 class FinalResult(BaseModel): number: int multiply_agent = Agent( name="Multiply Agent", instructions="Multiply the number by 2 and then return the final result.", tools=[multiply_by_two], output_type=FinalResult, ) start_agent = Agent( name="Start Agent", instructions="Generate a random number. If it's even, stop. If it's odd, hand off to the multiplier agent.", tools=[random_number], output_type=FinalResult, handoffs=[multiply_agent], ) async def main() -> None: user_input = input("Enter a max number: ") await Runner.run( start_agent, hooks=hooks, input=f"Generate a random number between 0 and {user_input}.", run_config=config, ) print("Done!") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Hello World: Create and Run an Agent Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Demonstrates the basic usage of the OpenAI Agents SDK by creating a simple agent and running a task. The agent is given instructions, and the Runner executes the task, returning the final output. Requires the OPENAI_API_KEY environment variable to be set. ```python from agents import Agent, Runner agent = Agent(name="Assistant", instructions="You are a helpful assistant") result = Runner.run_sync(agent, "Write a haiku about recursion in programming.") print(result.final_output) # Code within the code, # Functions calling themselves, # Infinite loop's dance. ``` -------------------------------- ### Define a Basic Agent in Python Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide This snippet shows how to create a basic agent with a name and instructions using the `Agent` class from the `agents` library. It initializes an agent named 'Assistant' with a simple instruction to be a helpful assistant. This is the fundamental step for setting up any agent in the system. ```python from agents import Agent agent = Agent( name="Assistant", instructions="You are a helpful assistant.", ) ``` -------------------------------- ### Install OpenAI Agents Visualization Tools Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Install the optional dependencies required for visualizing agent structures with Graphviz. This package enables the `draw_graph` function for creating visual representations of agent and tool interactions. ```bash pip install "openai-agents[viz]" ``` -------------------------------- ### Run a Simple Agent with Instructions - Python Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/simple_agent This Python script initializes a basic agent with custom instructions and executes it using a synchronous runner. It takes user input and prints the agent's final output. Dependencies include the 'agents' library and a 'local_config' module. ```python from agents import Agent, Runner from local_config import config def main(): agent = Agent( name="assistant", instructions="You are a helpful assistant.", ) result = Runner.run_sync( agent, input='hello', run_config=config ) print(result.final_output) if __name__ == "__main__": main() ``` -------------------------------- ### Connect to MCP Server and List Tools (Python) Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Demonstrates connecting to a local MCP server using MCPServerStdio and retrieving available tools. It utilizes a context manager for server lifecycle management. ```python async with MCPServerStdio(params={"command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", samples_dir]}) as server: tools = await server.list_tools() # Use the tools as needed ``` -------------------------------- ### Setup Database Connection (Python) Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/subscription_management_application Asynchronously sets up the database connection pool using `asyncpg` for PostgreSQL. It includes error handling and a fallback mechanism to an in-memory SQLite database for demonstration purposes if the primary database connection fails. This function initializes the necessary database tables. ```python async def setup_database(self): """Setup database connection and initialize tables""" database_url = os.getenv("DATABASE_URL", "postgresql://localhost/subscription_app") try: self.db_pool = await asyncpg.create_pool(database_url, min_size=1, max_size=10) await init_database(self.db_pool) print("Database initialized successfully") except Exception as e: print(f"Database setup failed: {e}") # Fallback to SQLite for demo print("Falling back to in-memory demo mode") self.db_pool = None ``` -------------------------------- ### Implement and Use RunHooks in Python Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/run_hooks This snippet defines a custom RunHooks class and uses it with an Agent Runner. It shows how to hook into events like LLM calls, agent lifecycle, and tool executions. The example includes a simple agent setup with a weather tool and demonstrates running the agent with the custom hooks. ```python from agents import Agent, Runner, function_tool, RunContextWrapper, RunHooks, TContext, TResponseInputItem, ModelResponse from typing import Optional, Any from open_router_config import config class HelloRunHooks(RunHooks): async def on_llm_start( self, context: RunContextWrapper[TContext], agent: Agent[TContext], system_prompt: Optional[str], input_items: list[TResponseInputItem], ) -> None: """Called just before invoking the LLM for this agent.""" print('on_llm_start') async def on_llm_end( self, context: RunContextWrapper[TContext], agent: Agent[TContext], response: ModelResponse, ) -> None: """Called immediately after the LLM call returns for this agent.""" print('on_llm_end') async def on_agent_start(self, context: RunContextWrapper[TContext], agent: Any) -> None: """Called before the agent is invoked. Called each time the current agent changes.""" print('on_agent_start') async def on_agent_end( self, context: RunContextWrapper[TContext], agent: Any, output: Any, ) -> None: """Called when the agent produces a final output.""" print('on_agent_end') async def on_handoff( self, context: RunContextWrapper[TContext], from_agent: Any, to_agent: Any, ) -> None: """Called when a handoff occurs.""" print('on_handoff') async def on_tool_start( self, context: RunContextWrapper[TContext], agent: Any, tool: Any, ) -> None: """Called concurrently with tool invocation.""" print('on_tool_start') async def on_tool_end( self, context: RunContextWrapper[TContext], agent: Any, tool: Any, result: str, ) -> None: """Called after a tool is invoked.""" print('on_tool_tool') @function_tool def get_weather(city: str) -> str: """A simple function to get the weather for a user.""" return f"The weather for {city} is sunny." news_agent: Agent = Agent( name="NewsAgent", instructions="You are a helpful news assistant.", ) base_agent: Agent = Agent( name="WeatherAgent", instructions="You are a helpful assistant. Talk about weather and let news_agent handle the news things", tools=[get_weather], handoffs=[news_agent] ) res = Runner.run_sync( starting_agent=base_agent, input="What's the latest news about Qwen Code - seems like it can give though time to claude code.", hooks=HelloRunHooks(), run_config=config ) print(res.last_agent.name) print(res.final_output) ``` -------------------------------- ### Define Output Guardrail (Python) Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Defines an output guardrail function using the `@output_guardrail` decorator. This example censors outputs containing the phrase 'secretcode'. It returns a `GuardrailFunctionOutput` object indicating if the tripwire was triggered. ```python from agents import output_guardrail, GuardrailFunctionOutput @output_guardrail async def censor_inappropriate(ctx, agent, output: str) -> GuardrailFunctionOutput: trigger = "secretcode" in output return GuardrailFunctionOutput( output_info=None, tripwire_triggered=trigger ) ``` -------------------------------- ### Customize Agent Handoff with `handoff()` (Python) Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Provides an example of customizing agent handoffs using the `handoff()` function. This allows for custom tool names, descriptions, and callback functions executed upon handoff. ```python from agents import Agent, handoff, RunContextWrapper def on_handoff(ctx: RunContextWrapper[None]): print("Handoff called!") handoff_obj = handoff( agent=agent2, on_handoff=on_handoff, tool_name_override="custom_handoff_tool", tool_description_override="Custom description" ) agent1 = Agent( name="My agent", instructions="Good Agent", handoffs=[handoff_obj] ) ``` -------------------------------- ### Prepend Recommended Handoff Prompt Instructions Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide This snippet demonstrates how to prepend recommended prompt instructions for handoffs to an agent's existing instructions. By using `agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX`, you ensure that the LLM understands how to handle handoff scenarios correctly within its prompts. ```python from agents import Agent from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX billing_agent = Agent( name="Billing agent", instructions=f"{RECOMMENDED_PROMPT_PREFIX} Then proceed with billing help." ) ``` -------------------------------- ### Set OpenAI API Key Environment Variable Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Sets the OPENAI_API_KEY environment variable, which is required for the SDK to authenticate with the OpenAI API. The example shows the command for Unix-like systems and notes the equivalent for Windows. ```bash export OPENAI_API_KEY=sk-... # On Windows, use: set OPENAI_API_KEY=sk-... ``` -------------------------------- ### Initialize Agents and Environment Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/practice Initializes necessary libraries and configurations for agent-based operations, including environment variable loading, disabling tracing, and setting up the OpenAI API key. ```python import os import dotenv from agents import ( AsyncOpenAI, OpenAIChatCompletionsModel, Agent, Runner, set_tracing_disabled, function_tool, handoff, RunContextWrapper, ) from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX from pydantic import BaseModel from rich.console import Console from rich.markdown import Markdown class QueryResult(BaseModel): query: str urls: list[str] class SearchResultsOutputType(BaseModel): results: list[QueryResult] def get_dict(self) -> dict[str, list[str]]: return {item.query: item.urls for item in self.results} dotenv.load_dotenv() set_tracing_disabled(disabled=True) api_key = os.environ.get("OPENROUTER_API_KEY") ``` -------------------------------- ### Define Input Guardrail (Python) Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Defines an input guardrail function using the `@input_guardrail` decorator. This example blocks inputs containing 'solve for x' by setting `tripwire_triggered` to True. It returns a `GuardrailFunctionOutput` indicating if the tripwire was triggered. ```python from agents import input_guardrail, GuardrailFunctionOutput @input_guardrail async def block_homework(ctx, agent, input_data: str) -> GuardrailFunctionOutput: is_math_homework = "solve for x" in input_data.lower() return GuardrailFunctionOutput( output_info=None, tripwire_triggered=is_math_homework ) ``` -------------------------------- ### Define Agent Handoffs in Python Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide This example shows how to configure an agent to hand off work to other agents. The `handoffs` parameter accepts a list of agents or customized handoff configurations. This is useful for routing tasks to specialized agents, like language-specific ones. ```python from agents import Agent, handoff # Assume spanish_agent and english_agent are already defined sspanish_agent = Agent( name="Spanish", instructions="You only answer in Spanish." ) english_agent = Agent( name="English", instructions="You only answer in English." ) triage_agent = Agent( name="Triage", instructions="Handoff to the correct language agent based on the query.", handoffs=[spanish_agent, handoff(english_agent)] ) ``` -------------------------------- ### Dynamic Agent Instructions with User Context (Python) Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/premium_basic_user_example This Python code defines a UserContext dataclass and demonstrates how to dynamically set agent instructions based on whether a user is a premium subscriber. It uses the Agents library to create an assistant agent whose instructions change based on the provided user context. The main function runs a streamed interaction with the assistant, processing different event types like agent updates and tool/message outputs. ```python import asyncio from agents import Agent, ItemHelpers, Runner, RunContextWrapper from open_router_config import config from dataclasses import dataclass @dataclass class UserContext: name: str is_premium_user: bool age: int daniel = UserContext("Daniel", True, 19) ahmad = UserContext("Ahmad", False, 21) def dynamic_instructions( ctx: RunContextWrapper[UserContext], _: Agent[UserContext] ) -> str: if ctx.context.is_premium_user: return "You are a premium agent, You can help the user with premium features." return "You are a basic agent, You can help the user with basic tasks." assistant = Agent( name="assistant", instructions=dynamic_instructions, ) async def main(): msg = "Who are you?" result = Runner.run_streamed(assistant, msg, run_config=config, context=daniel) async for event in result.stream_events(): # We'll ignore the raw responses event deltas if event.type == "raw_response_event": continue elif event.type == "agent_updated_stream_event": print(f"Agent updated: {event.new_agent.name}") continue elif event.type == "run_item_stream_event": if event.item.type == "tool_call_item": print("-- Tool was called") elif event.item.type == "tool_call_output_item": print(f"-- Tool output: {event.item.output}") elif event.item.type == "message_output_item": print( f"-- Message output:\n {ItemHelpers.text_message_output(event.item)}" ) else: pass # Ignore other event types if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Implement Guardrail using a Mini-Agent (Python) Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Provides a detailed example of implementing an input guardrail that utilizes another agent (`Guardrail check`) to determine if the input is homework. It uses `Runner.run` to execute the mini-agent and returns a `GuardrailFunctionOutput` based on the mini-agent's result. ```python from pydantic import BaseModel from agents import Agent, Runner, GuardrailFunctionOutput, InputGuardrailTripwireTriggered, input_guardrail, RunContextWrapper class MathHomeworkOutput(BaseModel): is_math_homework: bool reasoning: str guardrail_agent = Agent( name="Guardrail check", instructions="Check if the user is asking for math homework.", output_type=MathHomeworkOutput, ) @input_guardrail async def math_guardrail(ctx: RunContextWrapper[None], agent: Agent, input_text: str): result = await Runner.run(guardrail_agent, input_text, context=ctx.context) return GuardrailFunctionOutput( output_info=result.final_output, tripwire_triggered=result.final_output.is_math_homework, ) agent = Agent( name="Customer support", instructions="You help with customer questions.", input_guardrails=[math_guardrail], ) ``` -------------------------------- ### Initialize Billing Agent with Handoff Prompt - Python Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/practice Initializes a 'Billing agent' using the Agents SDK. It configures the agent with a name and instructions, incorporating a RECOMMENDED_PROMPT_PREFIX from a handoff prompt extension. The code demonstrates basic agent setup for systems involving agent coordination. ```python from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX billing_agent = Agent( name="Billing agent", instructions=f"""{RECOMMENDED_PROMPT_PREFIX} .""", ) print(RECOMMENDED_PROMPT_PREFIX) ``` -------------------------------- ### Filter Handoff Input with SDK Extensions Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide This example shows how to use `agents.extensions.handoff_filters.remove_all_tools` to filter the conversation history provided to a new agent during a handoff. This ensures the target agent, in this case, an 'FAQ agent', only sees relevant user messages and not internal tool calls. ```python from agents import Agent, handoff from agents.extensions import handoff_filters agent = Agent(name="FAQ agent") handoff_obj = handoff( agent=agent, input_filter=handoff_filters.remove_all_tools # Removes tool items ) ``` -------------------------------- ### Start Interactive Command-Line Session (Python) Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/subscription_management_application Initiates an interactive command-line interface for the Subscription Assistant. This method first sets up the database, then enters a loop to prompt the user for input, handle commands like 'quit' and 'help', manage user logins (allowing demo users 1, 2, or 3), and process conversation queries. ```python async def start_interactive_session(self): """Start interactive command-line session""" await self.setup_database() print("šŸš€ Subscription Assistant Started!") print("Type 'quit' to exit, 'help' for commands") print("-" * 50) current_uid = None session = None try: while True: if current_uid is None: uid = input("\nšŸ‘¤ Enter your User ID (1, 2, or 3 for demo): ").strip() if uid.lower() == 'quit': break if uid in ['1', '2', '3']: current_uid = uid session = SQLiteSession(f"user_{uid}_session") print(f"āœ… Logged in as User {uid}") continue else: print("āŒ Invalid User ID. Use 1, 2, or 3 for demo.") continue query = input(f"\nšŸ’¬ User {current_uid}: ").strip() if query.lower() == 'quit': break elif query.lower() == 'help': print(""" Available commands: - Ask about your subscription plan - Check usage limits - Get plan features - Ask about upgrades - 'logout' to switch users - 'quit' to exit ") continue ``` -------------------------------- ### Python: Deterministic Chaining Agent Orchestration Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Shows a deterministic chaining approach to agent orchestration, where the flow is controlled by Python code. This method is predictable and efficient for well-defined pipelines. The example chains a research agent to find topics, then a writer agent to draft content based on the research. ```python # Or code-driven chaining: outline = await Runner.run(research_agent, "Find topics on climate change.") draft = await Runner.run(writer_agent, outline.to_input_list()) print(draft.final_output) ``` -------------------------------- ### Initialize Subscription Assistant Application (Python) Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/subscription_management_application Initializes the `SubscriptionAssistantApp` class, setting up the database connection pool and creating an agent with specific tools and instructions for managing user subscriptions. It defines the tools available to the agent, such as viewing user plans and checking usage limits. ```python class SubscriptionAssistantApp: def __init__(self): self.db_pool = None self.config = config # Create agent with all tools self.agent = Agent[UserContext]( name="Subscription Assistant", instructions='''You are a helpful subscription management assistant. Always use the available tools to get accurate, up-to-date information about the user's account. Be friendly, informative, and proactive in helping users understand their subscription status. If users ask about upgrades, provide clear information about benefits.''', tools=[show_user_plan, get_plan_features, check_usage_limits, upgrade_plan_info], # output_type=UserEvent ) ``` -------------------------------- ### Python: Autonomous Planning Agent Orchestration Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide Illustrates how to use an agent for autonomous planning, where the agent decides the steps to achieve a goal. This is suitable for open-ended tasks where the agent can leverage tools like web search or code execution. The example shows an agent planning tasks to organize a party. ```python # LLM-driven agent decides steps: result = await Runner.run(autonomous_agent, "Plan tasks to organize a party.") ``` -------------------------------- ### Define and Run Agents with Runner in Python Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/testing Python code demonstrating the setup and execution of agents using the `Agent` and `Runner` classes. It defines a `hello` tool and two agents: `say_hello_agent` with `Child_Agent_Hooks` and a main `agent` that uses `say_hello_agent` as a tool. The `main` function runs the `agent` with a specific input and configuration. ```python config = RunConfig(model=model, model_provider=client) @function_tool def hello(): return "Hello! from Say Hello Agent/Tool" say_hello_agent = Agent( name="say_hello_agent", instructions="You are a say hello agent, You use tools to respond.", tools=[hello], # model=model, hooks=Child_Agent_Hooks(), ) agent = Agent( name="agent", instructions="You are a friendly assistant, You use tools to respond.", tools=[say_hello_agent.as_tool("say_hello_tool", "A say hello tool")], # model=model, hooks=Agent_Hooks(), ) async def main(): result = await Runner.run(agent, "Say Hello!", hooks=Run_Hooks(), run_config=config) print(result.final_output) asyncio.run(main()) ``` -------------------------------- ### Initialize and Run a Sales Agent in Python Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/practice/agents1 This snippet demonstrates initializing a 'sells_agent' using the 'Agent' class. The agent is given instructions to use the 'get_user_data' tool and is provided with a 'UserContext'. The script then uses 'Runner.run_sync' to execute the agent's task and prints the final output. ```python user_context = UserContext("123", True) sells_agent = Agent[UserContext]( name="sells_agent", instructions="You are a sells agent, USE get_user_data tool to get the USER DATA and PURCHASES, dont wait or ask just do it directly", tools=[get_user_data], # model=model ) config.tracing_disabled = False result = Runner.run_sync( sells_agent, "What i the USER has bought?", context=user_context, run_config=config ) print(result.final_output) ``` -------------------------------- ### Inject User Name into Agent Instructions Source: https://danielhashmi.github.io/PyEpicOdyssey/OpAgentsOlympus/OpenAI_Agents_SDK_Guide This example shows how to dynamically set the agent's instructions by embedding external data, such as a user's name, directly into the system prompt string. This allows the LLM to be aware of specific contextual information provided at runtime. It requires the `Agent` class from the `agents` library. ```python agent = Agent( name="Assistant", instructions=f"The user is named {user_info.name}. Help them with their question." ) ```