7171import io .reactivex .rxjava3 .core .Completable ;
7272import io .reactivex .rxjava3 .core .Flowable ;
7373import io .reactivex .rxjava3 .core .Maybe ;
74+ import io .reactivex .rxjava3 .core .Scheduler ;
7475import io .reactivex .rxjava3 .core .Single ;
7576import io .reactivex .rxjava3 .subjects .CompletableSubject ;
7677import java .util .ArrayList ;
@@ -96,6 +97,7 @@ public class Runner {
9697 @ Nullable private final EventsCompactionConfig eventsCompactionConfig ;
9798 @ Nullable private final ContextCacheConfig contextCacheConfig ;
9899 private final @ Nullable ResumabilityConfig resumabilityConfig ;
100+ @ Nullable private final Scheduler scheduler ;
99101 private final ConcurrentMap <String , Completable > activeSessionCompletables =
100102 new MapMaker ().weakValues ().makeMap ();
101103
@@ -108,6 +110,7 @@ public static class Builder {
108110 private BaseSessionService sessionService = new InMemorySessionService ();
109111 @ Nullable private BaseMemoryService memoryService = null ;
110112 private List <? extends Plugin > plugins = ImmutableList .of ();
113+ @ Nullable private Scheduler scheduler = null ;
111114
112115 @ CanIgnoreReturnValue
113116 public Builder app (App app ) {
@@ -162,6 +165,25 @@ public Builder plugins(Plugin... plugins) {
162165 return this ;
163166 }
164167
168+ /**
169+ * Sets the {@link Scheduler} for the work ADK hands off to worker threads in this runner's
170+ * invocations: the sub-agents of a {@code ParallelAgent}, tool calls in {@link
171+ * RunConfig.ToolExecutionMode#PARALLEL_SUBSCRIBE} mode, and the hop that starts the live send
172+ * loop. The runs that an {@code AgentTool} nests inherit it. An agent-level {@code
173+ * ParallelAgent.Builder#scheduler} or {@code LlmAgent.Builder#executor} takes precedence.
174+ * {@code null} (the default) selects {@code Schedulers.io()}.
175+ *
176+ * <p>Only these hand-offs are affected; work that completes asynchronously elsewhere (model
177+ * clients, session services, MCP, plugins) stays on its own threads. {@code
178+ * Schedulers.trampoline()} runs the hand-offs inline, so sub-agents and tools are subscribed
179+ * sequentially, but anything they start asynchronously can still overlap.
180+ */
181+ @ CanIgnoreReturnValue
182+ public Builder scheduler (@ Nullable Scheduler scheduler ) {
183+ this .scheduler = scheduler ;
184+ return this ;
185+ }
186+
165187 public Runner build () {
166188 BaseAgent buildAgent ;
167189 String buildAppName ;
@@ -213,7 +235,8 @@ public Runner build() {
213235 buildPlugins ,
214236 buildEventsCompactionConfig ,
215237 buildContextCacheConfig ,
216- buildResumabilityConfig );
238+ buildResumabilityConfig ,
239+ scheduler );
217240 }
218241 }
219242
@@ -295,6 +318,30 @@ protected Runner(
295318 @ Nullable EventsCompactionConfig eventsCompactionConfig ,
296319 @ Nullable ContextCacheConfig contextCacheConfig ,
297320 @ Nullable ResumabilityConfig resumabilityConfig ) {
321+ this (
322+ agent ,
323+ appName ,
324+ artifactService ,
325+ sessionService ,
326+ memoryService ,
327+ plugins ,
328+ eventsCompactionConfig ,
329+ contextCacheConfig ,
330+ resumabilityConfig ,
331+ /* scheduler= */ null );
332+ }
333+
334+ private Runner (
335+ BaseAgent agent ,
336+ String appName ,
337+ BaseArtifactService artifactService ,
338+ BaseSessionService sessionService ,
339+ @ Nullable BaseMemoryService memoryService ,
340+ List <? extends Plugin > plugins ,
341+ @ Nullable EventsCompactionConfig eventsCompactionConfig ,
342+ @ Nullable ContextCacheConfig contextCacheConfig ,
343+ @ Nullable ResumabilityConfig resumabilityConfig ,
344+ @ Nullable Scheduler scheduler ) {
298345 this .agent = agent ;
299346 this .appName = appName ;
300347 this .artifactService = artifactService ;
@@ -304,6 +351,7 @@ protected Runner(
304351 this .eventsCompactionConfig = createEventsCompactionConfig (agent , eventsCompactionConfig );
305352 this .contextCacheConfig = contextCacheConfig ;
306353 this .resumabilityConfig = resumabilityConfig ;
354+ this .scheduler = scheduler ;
307355 }
308356
309357 /**
@@ -1217,6 +1265,7 @@ private InvocationContext.Builder newInvocationContextBuilder(Session session, B
12171265 .eventsCompactionConfig (this .eventsCompactionConfig )
12181266 .contextCacheConfig (this .contextCacheConfig )
12191267 .resumabilityConfig (this .resumabilityConfig )
1268+ .scheduler (this .scheduler )
12201269 .agent (agent );
12211270 }
12221271
0 commit comments