Skip to content

Commit 9b1f6ed

Browse files
committed
docs: improve examples for auto runs
1 parent c851f82 commit 9b1f6ed

File tree

15 files changed

+216
-54
lines changed

15 files changed

+216
-54
lines changed

examples/agent_patterns/forcing_tool_use.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
ToolsToFinalOutputResult,
1616
function_tool,
1717
)
18+
from examples.auto_mode import is_auto_mode
1819

1920
"""
2021
This example shows how to force the agent to use a tool. It uses `ModelSettings(tool_choice="required")`
@@ -81,6 +82,13 @@ async def main(tool_use_behavior: Literal["default", "first_tool", "custom"] = "
8182
print(result.final_output)
8283

8384

85+
async def auto_demo() -> None:
86+
for behavior in ("default", "first_tool", "custom"):
87+
print(f"=== {behavior} ===")
88+
await main(behavior)
89+
print()
90+
91+
8492
if __name__ == "__main__":
8593
import argparse
8694

@@ -98,4 +106,7 @@ async def main(tool_use_behavior: Literal["default", "first_tool", "custom"] = "
98106
),
99107
)
100108
args = parser.parse_args()
101-
asyncio.run(main(args.tool_use_behavior))
109+
if is_auto_mode():
110+
asyncio.run(auto_demo())
111+
else:
112+
asyncio.run(main(args.tool_use_behavior))

examples/agent_patterns/human_in_the_loop_custom_rejection.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
1. A single sensitive tool requires human approval.
55
2. The first turn always issues that tool call.
66
3. Rejection uses a custom message via ``tool_error_formatter``.
7+
4. The example prints both the formatter output and the assistant's final reply.
78
"""
89

910
import asyncio
@@ -23,7 +24,7 @@ async def tool_error_formatter(args: ToolErrorFormatterArgs[None]) -> str | None
2324
"""Build a simple output message for rejected tool calls."""
2425
if args.kind != "approval_rejected":
2526
return None
26-
# The defualt one is "Tool execution was not approved."
27+
# The default message is "Tool execution was not approved."
2728
return "Publish action was canceled because approval was rejected."
2829

2930

@@ -33,12 +34,27 @@ async def publish_announcement(title: str, body: str) -> str:
3334
return f"Published announcement '{title}' with body: {body}"
3435

3536

37+
def _find_formatter_output(result: object) -> str | None:
38+
items = getattr(result, "new_items", None)
39+
if not isinstance(items, list):
40+
return None
41+
42+
for item in items:
43+
if getattr(item, "type", None) != "tool_call_output_item":
44+
continue
45+
output = getattr(item, "output", None)
46+
if isinstance(output, str):
47+
return output
48+
return None
49+
50+
3651
async def main() -> None:
3752
agent = Agent(
3853
name="Operations Assistant",
3954
instructions=(
4055
"When a user asks to publish an announcement, call the publish_announcement tool directly. "
41-
"Do not ask the user for approval in plain text; runtime approvals handle that."
56+
"Do not ask the user for approval in plain text; runtime approvals handle that. "
57+
"If the tool call is rejected, respond with the exact rejection message and nothing else."
4258
),
4359
model_settings=ModelSettings(tool_choice="publish_announcement"),
4460
tools=[publish_announcement],
@@ -69,6 +85,11 @@ async def main() -> None:
6985

7086
result = await Runner.run(agent, state, run_config=run_config)
7187

88+
formatter_output = _find_formatter_output(result)
89+
if formatter_output:
90+
print("\nFormatter output:")
91+
print(formatter_output)
92+
7293
print("\nFinal output:")
7394
print(result.final_output)
7495

examples/agent_patterns/input_guardrails.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,22 @@ async def main():
7070

7171
input_data: list[TResponseInputItem] = []
7272
auto_mode = is_auto_mode()
73+
scripted_inputs = [
74+
"What's the capital of California?",
75+
"Can you help me solve for x: 2x + 5 = 11",
76+
]
7377

7478
while True:
75-
user_input = input_with_fallback(
76-
"Enter a message: ",
77-
"What's the capital of California?",
78-
)
79+
if auto_mode:
80+
if not scripted_inputs:
81+
break
82+
user_input = scripted_inputs.pop(0)
83+
print(f"[auto-input] Enter a message: -> {user_input}")
84+
else:
85+
user_input = input_with_fallback(
86+
"Enter a message: ",
87+
"What's the capital of California?",
88+
)
7989
input_data.append(
8090
{
8191
"role": "user",
@@ -98,7 +108,7 @@ async def main():
98108
"content": message,
99109
}
100110
)
101-
if auto_mode:
111+
if auto_mode and not scripted_inputs:
102112
break
103113

104114
# Sample run:

examples/basic/agent_lifecycle_example.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
Tool,
1414
function_tool,
1515
)
16-
from examples.auto_mode import input_with_fallback
16+
from examples.auto_mode import input_with_fallback, is_auto_mode
1717

1818

1919
class CustomAgentHooks(AgentHooks):
@@ -67,6 +67,15 @@ def random_number(max: int) -> int:
6767
"""
6868
Generate a random number from 0 to max (inclusive).
6969
"""
70+
if is_auto_mode():
71+
if max <= 0:
72+
print("[debug] auto mode returning deterministic value 0")
73+
return 0
74+
value = min(max, 37)
75+
if value % 2 == 0:
76+
value = value - 1 if value > 1 else 1
77+
print(f"[debug] auto mode returning deterministic odd number {value}")
78+
return value
7079
return random.randint(0, max)
7180

7281

examples/basic/previous_response_id.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import asyncio
22

33
from agents import Agent, Runner
4-
from examples.auto_mode import input_with_fallback
4+
from examples.auto_mode import input_with_fallback, is_auto_mode
55

66
"""This demonstrates usage of the `previous_response_id` parameter to continue a conversation.
77
The second run passes the previous response ID to the model, which allows it to continue the
@@ -16,6 +16,7 @@
1616

1717

1818
async def main():
19+
print("=== Non-streaming Example ===")
1920
agent = Agent(
2021
name="Assistant",
2122
instructions="You are a helpful assistant. be VERY concise.",
@@ -35,6 +36,7 @@ async def main():
3536

3637

3738
async def main_stream():
39+
print("=== Streaming Example ===")
3840
agent = Agent(
3941
name="Assistant",
4042
instructions="You are a helpful assistant. be VERY concise.",
@@ -60,8 +62,13 @@ async def main_stream():
6062

6163

6264
if __name__ == "__main__":
63-
is_stream = input_with_fallback("Run in stream mode? (y/n): ", "n")
64-
if is_stream == "y":
65+
if is_auto_mode():
66+
asyncio.run(main())
67+
print()
6568
asyncio.run(main_stream())
6669
else:
67-
asyncio.run(main())
70+
is_stream = input_with_fallback("Run in stream mode? (y/n): ", "n")
71+
if is_stream == "y":
72+
asyncio.run(main_stream())
73+
else:
74+
asyncio.run(main())

examples/financial_research_agent/manager.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,27 @@ async def _perform_searches(self, search_plan: FinancialSearchPlan) -> Sequence[
7777
tasks = [asyncio.create_task(self._search(item)) for item in search_plan.searches]
7878
results: list[str] = []
7979
num_completed = 0
80+
num_succeeded = 0
81+
num_failed = 0
8082
for task in asyncio.as_completed(tasks):
8183
result = await task
8284
if result is not None:
8385
results.append(result)
86+
num_succeeded += 1
87+
else:
88+
num_failed += 1
8489
num_completed += 1
90+
status = f"Searching... {num_completed}/{len(tasks)} finished"
91+
if num_failed:
92+
status += f" ({num_succeeded} succeeded, {num_failed} failed)"
8593
self.printer.update_item(
86-
"searching", f"Searching... {num_completed}/{len(tasks)} completed"
94+
"searching",
95+
status,
8796
)
88-
self.printer.mark_item_done("searching")
97+
summary = f"Searches finished: {num_succeeded}/{len(tasks)} succeeded"
98+
if num_failed:
99+
summary += f", {num_failed} failed"
100+
self.printer.update_item("searching", summary, is_done=True)
89101
return results
90102

91103
async def _search(self, item: FinancialSearchItem) -> str | None:

examples/mcp/filesystem_example/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ async def run(mcp_server: MCPServer):
2020
print(result.final_output)
2121

2222
# Ask about books
23-
message = "What is my #1 favorite book?"
23+
message = "Read favorite_books.txt and tell me my #1 favorite book."
2424
print(f"\n\nRunning: {message}")
2525
result = await Runner.run(starting_agent=agent, input=message)
2626
print(result.final_output)
2727

2828
# Ask a question that reads then reasons.
29-
message = "Look at my favorite songs. Suggest one new song that I might like."
29+
message = "Read favorite_songs.txt and suggest one new song that I might like."
3030
print(f"\n\nRunning: {message}")
3131
result = await Runner.run(starting_agent=agent, input=message)
3232
print(result.final_output)

examples/memory/advanced_sqlite_session_example.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ async def main():
146146

147147
# === PART 3: Conversation Branching ===
148148
print("\n=== PART 3: Conversation Branching ===")
149-
print("Let's explore a different path from turn 2...")
149+
print("Let's explore a different path starting before turn 2...")
150150

151151
# Show available turns for branching
152152
print("\nAvailable turns for branching:")
@@ -159,10 +159,10 @@ async def main():
159159
branch_id = await session.create_branch_from_turn(2)
160160
print(f"Created branch: {branch_id}")
161161

162-
# Show what's in the new branch (should have conversation up to turn 2)
162+
# Show what's in the new branch (it should contain items created before turn 2)
163163
branch_items = await session.get_items()
164164
print(f"Items copied to new branch: {len(branch_items)}")
165-
print("New branch contains:")
165+
print("New branch starts before turn 2 and contains:")
166166
for i, item in enumerate(branch_items, 1): # type: ignore[assignment]
167167
role = str(item.get("role", item.get("type", "unknown")))
168168
if item.get("type") == "function_call":

examples/reasoning_content/main.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
"""
2-
Example demonstrating how to use the reasoning content feature with models that support it.
2+
Example demonstrating how to access reasoning summaries when a model returns them.
33
44
Some models, like gpt-5, provide a reasoning_content field in addition to the regular content.
5-
This example shows how to access and use this reasoning content from both streaming and non-streaming responses.
5+
This example shows how to access that content from both streaming and non-streaming responses,
6+
and how to handle responses that do not include a reasoning summary.
67
78
To run this example, you need to:
89
1. Set your OPENAI_API_KEY environment variable
@@ -61,6 +62,8 @@ async def stream_with_reasoning_content():
6162
# Green for regular content
6263
print(f"\033[32m{event.delta}\033[0m", end="", flush=True)
6364
regular_content += event.delta
65+
if not reasoning_content:
66+
print("\n(No reasoning summary deltas were returned.)")
6467
print("\n")
6568

6669

examples/research_bot/manager.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,29 @@ async def _perform_searches(self, search_plan: WebSearchPlan) -> list[str]:
6666
with custom_span("Search the web"):
6767
self.printer.update_item("searching", "Searching...")
6868
num_completed = 0
69+
num_succeeded = 0
70+
num_failed = 0
6971
tasks = [asyncio.create_task(self._search(item)) for item in search_plan.searches]
7072
results = []
7173
for task in asyncio.as_completed(tasks):
7274
result = await task
7375
if result is not None:
7476
results.append(result)
77+
num_succeeded += 1
78+
else:
79+
num_failed += 1
7580
num_completed += 1
81+
status = f"Searching... {num_completed}/{len(tasks)} finished"
82+
if num_failed:
83+
status += f" ({num_succeeded} succeeded, {num_failed} failed)"
7684
self.printer.update_item(
77-
"searching", f"Searching... {num_completed}/{len(tasks)} completed"
85+
"searching",
86+
status,
7887
)
79-
self.printer.mark_item_done("searching")
88+
summary = f"Searches finished: {num_succeeded}/{len(tasks)} succeeded"
89+
if num_failed:
90+
summary += f", {num_failed} failed"
91+
self.printer.update_item("searching", summary, is_done=True)
8092
return results
8193

8294
async def _search(self, item: WebSearchItem) -> str | None:

0 commit comments

Comments
 (0)