Created
August 30, 2025 23:23
-
-
Save jwill9999/d946554fb305d8517f99d5c63445d64e to your computer and use it in GitHub Desktop.
An example of deep research
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Deep Research\n", | |
"\n", | |
"One of the classic cross-business Agentic use cases! This is huge." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"<table style=\"margin: 0; text-align: left; width:100%\">\n", | |
" <tr>\n", | |
" <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n", | |
" <img src=\"../assets/business.png\" width=\"150\" height=\"150\" style=\"display: block;\" />\n", | |
" </td>\n", | |
" <td>\n", | |
" <h2 style=\"color:#00bfff;\">Commercial implications</h2>\n", | |
" <span style=\"color:#00bfff;\">A Deep Research agent is broadly applicable to any business area, and to your own day-to-day activities. You can make use of this yourself!\n", | |
" </span>\n", | |
" </td>\n", | |
" </tr>\n", | |
"</table>" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# Imports\n", | |
"\n", | |
"from agents import Agent, WebSearchTool, trace, Runner, function_tool\n", | |
"from agents.model_settings import ModelSettings\n", | |
"from pydantic import BaseModel\n", | |
"from dotenv import load_dotenv\n", | |
"import asyncio\n", | |
"import os\n", | |
"from IPython.display import display, Markdown\n", | |
"from pprint import pprint\n", | |
"import requests\n", | |
"load_dotenv(override=True)\n", | |
"\n", | |
"# Constants\n", | |
"\n", | |
"pushover_user = os.getenv(\"PUSHOVER_USER\")\n", | |
"pushover_token = os.getenv(\"PUSHOVER_TOKEN\")\n", | |
"pushover_url = \"https://api.pushover.net/1/messages.json\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## OpenAI Hosted Tools\n", | |
"\n", | |
"OpenAI Agents SDK includes the following hosted tools:\n", | |
"\n", | |
"The `WebSearchTool` lets an agent search the web. \n", | |
"The `FileSearchTool` allows retrieving information from your OpenAI Vector Stores. \n", | |
"The `ComputerTool` allows automating computer use tasks like taking screenshots and clicking.\n", | |
"\n", | |
"### Important note - API charge of WebSearchTool\n", | |
"\n", | |
"This is costing me 2.5 cents per call for OpenAI WebSearchTool. That can add up to $2-$3 for the next 2 labs. We'll use low cost Search tools with other platforms, so feel free to skip running this if the cost is a concern.\n", | |
"\n", | |
"Costs are here: https://platform.openai.com/docs/pricing#web-search" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## We will be making 4 Agents:\n", | |
"\n", | |
"1. Search Agent - searches online given a search term using an OpenAI hosted tool\n", | |
"2. Planner Agent - given a query from the user, come up with searches\n", | |
"3. Report Agent - make a report on results\n", | |
"4. Push Agent - send a notification to the user's phone with a summary\n", | |
"\n", | |
"## Our First Agent: Search Agent\n", | |
"\n", | |
"Given a Search term, search for it on the internet and summarize results." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"INSTRUCTIONS = \"You are a research assistant. Given a search term, you search the web for that term and \\\n", | |
"produce a concise summary of the results. The summary must 2-3 paragraphs and less than 300 \\\n", | |
"words. Capture the main points. Write succintly, no need to have complete sentences or good \\\n", | |
"grammar. This will be consumed by someone synthesizing a report, so it's vital you capture the \\\n", | |
"essence and ignore any fluff. Do not include any additional commentary other than the summary itself.\"\n", | |
"\n", | |
"search_agent = Agent(\n", | |
" name=\"Search agent\",\n", | |
" instructions=INSTRUCTIONS,\n", | |
" tools=[WebSearchTool(search_context_size=\"low\")],\n", | |
" model=\"gpt-4.1-mini\",\n", | |
" model_settings=ModelSettings(tool_choice=\"required\"),\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"message = \"What are the most popular and successful AI Agent frameworks in May 2025\"\n", | |
"\n", | |
"with trace(\"Search\"):\n", | |
" result = await Runner.run(search_agent, message)\n", | |
"\n", | |
"display(Markdown(result.final_output))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Take a look at the trace\n", | |
"\n", | |
"https://platform.openai.com/traces" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Our Second Agent: Planner Agent\n", | |
"\n", | |
"Given a query, come up with 5 ideas for web searches that could be run.\n", | |
"\n", | |
"Use Structured Outputs as our way to ensure the Agent provides what we need." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# See note above about cost of WebSearchTool\n", | |
"\n", | |
"HOW_MANY_SEARCHES = 5\n", | |
"\n", | |
"INSTRUCTIONS = f\"You are a helpful research assistant. Given a query, come up with a set of web searches \\\n", | |
"to perform to best answer the query. Output {HOW_MANY_SEARCHES} terms to query for.\"\n", | |
"\n", | |
"# We use Pydantic objects to describe the Schema of the output\n", | |
"\n", | |
"class WebSearchItem(BaseModel):\n", | |
" reason: str\n", | |
" \"Your reasoning for why this search is important to the query.\"\n", | |
"\n", | |
" query: str\n", | |
" \"The search term to use for the web search.\"\n", | |
"\n", | |
"\n", | |
"class WebSearchPlan(BaseModel):\n", | |
" searches: list[WebSearchItem]\n", | |
" \"\"\"A list of web searches to perform to best answer the query.\"\"\"\n", | |
"\n", | |
"# We pass in the Pydantic object to ensure the output follows the schema\n", | |
"\n", | |
"planner_agent = Agent(\n", | |
" name=\"PlannerAgent\",\n", | |
" instructions=INSTRUCTIONS,\n", | |
" model=\"gpt-4.1-mini\",\n", | |
" output_type=WebSearchPlan,\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"\n", | |
"message = \"What are the most popular and successful AI Agent frameworks in May 2025\"\n", | |
"\n", | |
"with trace(\"Search\"):\n", | |
" result = await Runner.run(planner_agent, message)\n", | |
" pprint(result.final_output)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Our Third Agent: Writer Agent\n", | |
"\n", | |
"Take the results of internet searches and make a report" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"INSTRUCTIONS = (\n", | |
" \"You are a senior researcher tasked with writing a cohesive report for a research query. \"\n", | |
" \"You will be provided with the original query, and some initial research done by a research assistant.\\n\"\n", | |
" \"You should first come up with an outline for the report that describes the structure and \"\n", | |
" \"flow of the report. Then, generate the report and return that as your final output.\\n\"\n", | |
" \"The final output should be in markdown format, and it should be lengthy and detailed. Aim \"\n", | |
" \"for 5-10 pages of content, at least 1000 words.\"\n", | |
")\n", | |
"\n", | |
"\n", | |
"class ReportData(BaseModel):\n", | |
" short_summary: str\n", | |
" \"\"\"A short 2-3 sentence summary of the findings.\"\"\"\n", | |
"\n", | |
" markdown_report: str\n", | |
" \"\"\"The final report\"\"\"\n", | |
"\n", | |
" follow_up_questions: list[str]\n", | |
" \"\"\"Suggested topics to research further\"\"\"\n", | |
"\n", | |
"\n", | |
"writer_agent = Agent(\n", | |
" name=\"WriterAgent\",\n", | |
" instructions=INSTRUCTIONS,\n", | |
" model=\"gpt-4o-mini\",\n", | |
" output_type=ReportData,\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Our Fourth Agent: push notification\n", | |
"\n", | |
"Just to show how easy it is to make a tool!\n", | |
"\n", | |
"I'm using a nifty product called PushOver - to set this up yourself, visit https://pushover.net" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"@function_tool\n", | |
"def push(message: str):\n", | |
" \"\"\"Send a push notification with this brief message\"\"\"\n", | |
" payload = {\"user\": pushover_user, \"token\": pushover_token, \"message\": message}\n", | |
" requests.post(pushover_url, data=payload)\n", | |
" return {\"status\": \"success\"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"push" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"INSTRUCTIONS = \"\"\"You are a member of a research team and will be provided with a short summary of a report.\n", | |
"When you receive the report summary, you send a push notification to the user using your tool, informing them that research is complete,\n", | |
"and including the report summary you receive\"\"\"\n", | |
"\n", | |
"\n", | |
"push_agent = Agent(\n", | |
" name=\"Push agent\",\n", | |
" instructions=INSTRUCTIONS,\n", | |
" tools=[push],\n", | |
" model=\"gpt-4.1-mini\",\n", | |
" model_settings=ModelSettings(tool_choice=\"required\")\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### The next 3 functions will plan and execute the search, using planner_agent and search_agent" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"async def plan_searches(query: str):\n", | |
" \"\"\" Use the planner_agent to plan which searches to run for the query \"\"\"\n", | |
" print(\"Planning searches...\")\n", | |
" result = await Runner.run(planner_agent, f\"Query: {query}\")\n", | |
" print(f\"Will perform {len(result.final_output.searches)} searches\")\n", | |
" return result.final_output\n", | |
"\n", | |
"async def perform_searches(search_plan: WebSearchPlan):\n", | |
" \"\"\" Call search() for each item in the search plan \"\"\"\n", | |
" print(\"Searching...\")\n", | |
" tasks = [asyncio.create_task(search(item)) for item in search_plan.searches]\n", | |
" results = await asyncio.gather(*tasks)\n", | |
" print(\"Finished searching\")\n", | |
" return results\n", | |
"\n", | |
"async def search(item: WebSearchItem):\n", | |
" \"\"\" Use the search agent to run a web search for each item in the search plan \"\"\"\n", | |
" input = f\"Search term: {item.query}\\nReason for searching: {item.reason}\"\n", | |
" result = await Runner.run(search_agent, input)\n", | |
" return result.final_output" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### The next 2 functions write a report and send a push notification" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"async def write_report(query: str, search_results: list[str]):\n", | |
" \"\"\" Use the writer agent to write a report based on the search results\"\"\"\n", | |
" print(\"Thinking about report...\")\n", | |
" input = f\"Original query: {query}\\nSummarized search results: {search_results}\"\n", | |
" result = await Runner.run(writer_agent, input)\n", | |
" print(\"Finished writing report\")\n", | |
" return result.final_output\n", | |
"\n", | |
"async def send_push(report: ReportData):\n", | |
" \"\"\" Use the push agent to send a notification to the user \"\"\"\n", | |
" print(\"Pushing...\")\n", | |
" result = await Runner.run(push_agent, report.short_summary)\n", | |
" print(\"Push sent\")\n", | |
" return report" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Showtime!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"query =\"What are the most popular and successful AI Agent frameworks in May 2025\"\n", | |
"\n", | |
"with trace(\"Research trace\"):\n", | |
" print(\"Starting research...\")\n", | |
" search_plan = await plan_searches(query)\n", | |
" search_results = await perform_searches(search_plan)\n", | |
" report = await write_report(query, search_results)\n", | |
" await send_push(report) \n", | |
" print(\"Hooray!\")\n", | |
"display(Markdown(report.markdown_report))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### As always, take a look at the trace\n", | |
"\n", | |
"https://platform.openai.com/traces" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": ".venv", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.12.9" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment