Repository navigation
test(harness): an OpenAI Agents SDK reference agent for the hosted path (TH-8800) #301
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
khushalsonawat
wants to merge
3
commits into
feat/TH-8804-source-subfolder
Choose a base branch
from
feat/th-8800-openai-agents-reference
base: feat/TH-8804-source-subfolder
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
00ab58f
test(harness): an OpenAI Agents SDK reference agent for the hosted pa…
khushalsonawat 802bbe3
ci: run the OpenAI Agents SDK reference tests in sdk-smoke (TH-8800)
khushalsonawat 5d45834
test(harness): share the reference agents' test helpers, and refuse a…
khushalsonawat File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 3.12 |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # OpenAI Agents SDK support agent | ||
|
|
||
| A customer support chat agent built on the OpenAI Agents SDK. It has three tools over a | ||
| small in-memory set of orders: `look_up_order`, `start_return` and `return_policy`. | ||
|
|
||
| ## How the kit runs it | ||
|
|
||
| The kit calls `agent_callback` in `agent.py` once per turn with the whole conversation. The | ||
| function runs the agent through `Runner.run` and returns `{"content": ...}` only. Tool calls | ||
| are not returned: the SDK runs the tools itself, and the kit's tool tracer records each call | ||
| made to the three tool functions. | ||
|
|
||
| ## Environment | ||
|
|
||
| - `OPENAI_API_KEY`: the key for the endpoint (required for a turn). | ||
| - `OPENAI_BASE_URL`: the endpoint's base URL (required whenever a key is set; a turn is refused otherwise, so the key is never sent to the OpenAI API by default). Set it to the model gateway for the default model. | ||
| - `OPENAI_MODEL`: the model name, default `vertex_ai/gemini-3.7-flash` (a gateway name). | ||
|
|
||
| The endpoint must speak chat completions. Install with `pip install -r requirements.txt` on | ||
| Python 3.12. `agent-simulate` is in the requirements because the kit's callback bridge imports | ||
| `fi.simulate.AgentInput`. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| import os | ||
|
|
||
| from agents import ( | ||
| Agent, | ||
| OpenAIChatCompletionsModel, | ||
| RunConfig, | ||
| Runner, | ||
| function_tool, | ||
| set_tracing_disabled, | ||
| ) | ||
| from openai import AsyncOpenAI | ||
|
|
||
| MODEL = os.getenv("OPENAI_MODEL", "vertex_ai/gemini-3.7-flash") | ||
|
|
||
| # The SDK exports its own traces to OpenAI by default, using OPENAI_API_KEY, which here is | ||
| # the gateway's key: off, so no trace or key is sent to OpenAI. | ||
| set_tracing_disabled(True) | ||
|
|
||
| _ORDERS = { | ||
| "A1001": {"item": "trail running shoes", "status": "delivered", "return": None}, | ||
| "A1002": {"item": "rain jacket", "status": "shipped", "return": None}, | ||
| "A1003": {"item": "water bottle", "status": "delivered", "return": None}, | ||
| } | ||
|
|
||
|
|
||
| @function_tool | ||
| def look_up_order(order_id: str) -> str: | ||
| """Look up an order by its id and report its item, status and any return.""" | ||
| order = _ORDERS.get(order_id) | ||
| if order is None: | ||
| return f"No order {order_id} exists." | ||
| returned = order["return"] or "none" | ||
| return f"Order {order_id}: {order['item']}, status {order['status']}, return: {returned}." | ||
|
|
||
|
|
||
| @function_tool | ||
| def start_return(order_id: str, reason: str) -> str: | ||
| """Start a return for a delivered order, giving the customer's reason.""" | ||
| order = _ORDERS.get(order_id) | ||
| if order is None: | ||
| return f"No order {order_id} exists." | ||
| if order["status"] != "delivered": | ||
| return f"Order {order_id} is {order['status']} and cannot be returned yet." | ||
| if order["return"] is not None: | ||
| return f"Order {order_id} already has a return started." | ||
| order["return"] = reason | ||
| return f"Return started for order {order_id}: {reason}." | ||
|
|
||
|
|
||
| @function_tool | ||
| def return_policy() -> str: | ||
| """State the store's return policy.""" | ||
| return "Delivered items can be returned within 30 days for a full refund." | ||
|
|
||
|
|
||
| agent = Agent( | ||
| name="Support agent", | ||
| instructions=( | ||
| "You are a customer support agent for an online store. Use the tools to look up " | ||
| "orders and start returns, and never guess an order's status. Answer briefly." | ||
| ), | ||
| tools=[look_up_order, start_return, return_policy], | ||
| ) | ||
|
|
||
|
|
||
| async def agent_callback(agent_input): | ||
| # The runner puts the new user message at the end of `messages`, so the list is the | ||
| # whole conversation as it stands. | ||
| input_list = [ | ||
| {"role": message["role"], "content": message["content"]} | ||
| for message in agent_input.messages | ||
| ] | ||
| api_key = os.getenv("OPENAI_API_KEY") | ||
| base_url = os.getenv("OPENAI_BASE_URL") | ||
| # With no base URL the client falls back to api.openai.com and would send the key there. | ||
| if api_key and not base_url: | ||
| raise RuntimeError( | ||
| "OPENAI_API_KEY is set but OPENAI_BASE_URL is empty: set OPENAI_BASE_URL to the " | ||
| "endpoint the key belongs to." | ||
| ) | ||
| # Each request runs in its own event loop, and the SDK does not close a client it was | ||
| # handed, so the client lives and dies with the call. | ||
| async with AsyncOpenAI(base_url=base_url, api_key=api_key) as client: | ||
| # A model object, because the SDK's default provider rejects a prefixed name | ||
| # such as vertex_ai/..., and this endpoint speaks chat completions. | ||
| model = OpenAIChatCompletionsModel(model=MODEL, openai_client=client) | ||
| result = await Runner.run(agent, input_list, run_config=RunConfig(model=model)) | ||
| # Content only: tool calls in the reply would be run by the caller against its own | ||
| # world and the agent called again. | ||
| return {"content": str(result.final_output)} |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| openai-agents==0.24.0 | ||
| agent-simulate==0.1.3 | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3. Nothing in
agent.pyimportsagent-simulate, so a reader will take this pin as unused. It's needed because the kit's callback bridge importsfi.simulate.AgentInput. One line in the README saying so would do.