Skip to content

Commit 046c287

Browse files
committed
LLM: run.py: add support for configurable default Runner
- Introduce a DEFAULT_RUNNER global and a set_default_runner() function to allow callers to specify a default Runner for agent runs. - Update Runner.run, run_sync, and run_streaming to use DEFAULT_RUNNER if set, otherwise fallback to DefaultRunner. - Add detailed docstrings to run, run_sync, and run_streaming methods for clarity on agent execution flow and exceptions.
1 parent 616192e commit 046c287

File tree

1 file changed

+96
-3
lines changed

1 file changed

+96
-3
lines changed

src/agents/run.py

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@
4646
from .util import _coro, _error_tracing
4747

4848
DEFAULT_MAX_TURNS = 10
49+
DEFAULT_RUNNER: Runner | None = None
50+
51+
52+
def set_default_runner(runner: Runner) -> None:
53+
"""
54+
Set the default runner to use for the agent run.
55+
"""
56+
global DEFAULT_RUNNER
57+
DEFAULT_RUNNER = runner
4958

5059

5160
@dataclass
@@ -161,7 +170,34 @@ async def run(
161170
run_config: RunConfig | None = None,
162171
previous_response_id: str | None = None,
163172
) -> RunResult:
164-
return await DefaultRunner().run_impl(
173+
"""Run a workflow starting at the given agent. The agent will run in a loop until a final
174+
output is generated. The loop runs like so:
175+
1. The agent is invoked with the given input.
176+
2. If there is a final output (i.e. the agent produces something of type
177+
`agent.output_type`, the loop terminates.
178+
3. If there's a handoff, we run the loop again, with the new agent.
179+
4. Else, we run tool calls (if any), and re-run the loop.
180+
In two cases, the agent may raise an exception:
181+
1. If the max_turns is exceeded, a MaxTurnsExceeded exception is raised.
182+
2. If a guardrail tripwire is triggered, a GuardrailTripwireTriggered exception is raised.
183+
Note that only the first agent's input guardrails are run.
184+
Args:
185+
starting_agent: The starting agent to run.
186+
input: The initial input to the agent. You can pass a single string for a user message,
187+
or a list of input items.
188+
context: The context to run the agent with.
189+
max_turns: The maximum number of turns to run the agent for. A turn is defined as one
190+
AI invocation (including any tool calls that might occur).
191+
hooks: An object that receives callbacks on various lifecycle events.
192+
run_config: Global settings for the entire agent run.
193+
previous_response_id: The ID of the previous response, if using OpenAI models via the
194+
Responses API, this allows you to skip passing in input from the previous turn.
195+
Returns:
196+
A run result containing all the inputs, guardrail results and the output of the last
197+
agent. Agents may perform handoffs, so we don't know the specific type of the output.
198+
"""
199+
runner = DEFAULT_RUNNER or DefaultRunner()
200+
return await runner.run_impl(
165201
starting_agent,
166202
input,
167203
context=context,
@@ -183,7 +219,37 @@ def run_sync(
183219
run_config: RunConfig | None = None,
184220
previous_response_id: str | None = None,
185221
) -> RunResult:
186-
return DefaultRunner().run_sync_impl(
222+
"""Run a workflow synchronously, starting at the given agent. Note that this just wraps the
223+
`run` method, so it will not work if there's already an event loop (e.g. inside an async
224+
function, or in a Jupyter notebook or async context like FastAPI). For those cases, use
225+
the `run` method instead.
226+
The agent will run in a loop until a final output is generated. The loop runs like so:
227+
1. The agent is invoked with the given input.
228+
2. If there is a final output (i.e. the agent produces something of type
229+
`agent.output_type`, the loop terminates.
230+
3. If there's a handoff, we run the loop again, with the new agent.
231+
4. Else, we run tool calls (if any), and re-run the loop.
232+
In two cases, the agent may raise an exception:
233+
1. If the max_turns is exceeded, a MaxTurnsExceeded exception is raised.
234+
2. If a guardrail tripwire is triggered, a GuardrailTripwireTriggered exception is raised.
235+
Note that only the first agent's input guardrails are run.
236+
Args:
237+
starting_agent: The starting agent to run.
238+
input: The initial input to the agent. You can pass a single string for a user message,
239+
or a list of input items.
240+
context: The context to run the agent with.
241+
max_turns: The maximum number of turns to run the agent for. A turn is defined as one
242+
AI invocation (including any tool calls that might occur).
243+
hooks: An object that receives callbacks on various lifecycle events.
244+
run_config: Global settings for the entire agent run.
245+
previous_response_id: The ID of the previous response, if using OpenAI models via the
246+
Responses API, this allows you to skip passing in input from the previous turn.
247+
Returns:
248+
A run result containing all the inputs, guardrail results and the output of the last
249+
agent. Agents may perform handoffs, so we don't know the specific type of the output.
250+
"""
251+
runner = DEFAULT_RUNNER or DefaultRunner()
252+
return runner.run_sync_impl(
187253
starting_agent,
188254
input,
189255
context=context,
@@ -204,7 +270,34 @@ def run_streamed(
204270
run_config: RunConfig | None = None,
205271
previous_response_id: str | None = None,
206272
) -> RunResultStreaming:
207-
return DefaultRunner().run_streaming_impl(
273+
"""Run a workflow starting at the given agent in streaming mode. The returned result object
274+
contains a method you can use to stream semantic events as they are generated.
275+
The agent will run in a loop until a final output is generated. The loop runs like so:
276+
1. The agent is invoked with the given input.
277+
2. If there is a final output (i.e. the agent produces something of type
278+
`agent.output_type`, the loop terminates.
279+
3. If there's a handoff, we run the loop again, with the new agent.
280+
4. Else, we run tool calls (if any), and re-run the loop.
281+
In two cases, the agent may raise an exception:
282+
1. If the max_turns is exceeded, a MaxTurnsExceeded exception is raised.
283+
2. If a guardrail tripwire is triggered, a GuardrailTripwireTriggered exception is raised.
284+
Note that only the first agent's input guardrails are run.
285+
Args:
286+
starting_agent: The starting agent to run.
287+
input: The initial input to the agent. You can pass a single string for a user message,
288+
or a list of input items.
289+
context: The context to run the agent with.
290+
max_turns: The maximum number of turns to run the agent for. A turn is defined as one
291+
AI invocation (including any tool calls that might occur).
292+
hooks: An object that receives callbacks on various lifecycle events.
293+
run_config: Global settings for the entire agent run.
294+
previous_response_id: The ID of the previous response, if using OpenAI models via the
295+
Responses API, this allows you to skip passing in input from the previous turn.
296+
Returns:
297+
A result object that contains data about the run, as well as a method to stream events.
298+
"""
299+
runner = DEFAULT_RUNNER or DefaultRunner()
300+
return runner.run_streaming_impl(
208301
starting_agent,
209302
input,
210303
context=context,

0 commit comments

Comments
 (0)