MCPcopy Index your code
hub / github.com/CopilotKit/CopilotKit / runAgent

Method runAgent

packages/core/src/core/run-handler.ts:302–405  ·  view source on GitHub ↗

* Run an agent

({
    agent,
    forwardedProps,
    resume,
  }: CopilotKitCoreRunAgentParams)

Source from the content-addressed store, hash-verified

300 * Run an agent
301 */
302 async runAgent({
303 agent,
304 forwardedProps,
305 resume,
306 }: CopilotKitCoreRunAgentParams): Promise<RunAgentResult> {
307 // Agent ID is guaranteed to be set by validateAndAssignAgentId
308 if (agent.agentId) {
309 void this._internal.suggestionEngine.clearSuggestions(agent.agentId);
310 }
311
312 // Re-apply core headers (merged on top of the agent's own headers) so a
313 // late header update is picked up without clobbering per-agent headers.
314 this._internal.applyHeadersToAgent(agent);
315
316 // Detach any active run (e.g. a long-lived connectAgent pipeline) before
317 // starting a new run. We await the detach to ensure the previous pipeline
318 // has fully finalized — its activeRunCompletionPromise resolves once the
319 // observable finalize block runs, which happens synchronously after the
320 // takeUntil signal completes the chain. This prevents a race where the new
321 // runAgent() overwrites activeRunDetach$ / activeRunCompletionPromise before
322 // the old pipeline can clean up, causing dropped runs.
323 //
324 // Historical note: an earlier version used fire-and-forget (`void`) here
325 // because awaiting caused a deadlock when connectAgent's
326 // ConnectNotImplementedError cleanup was still in-flight. That deadlock
327 // was resolved in @ag-ui/client ≥0.0.42 where the catchError path
328 // (ConnectNotImplementedError → EMPTY) always runs the finalize block,
329 // so the completion promise now resolves reliably.
330 if (agent.detachActiveRun) {
331 await agent.detachActiveRun();
332 }
333
334 // Set up abort controller and agent.abortRun() intercept only for the
335 // top-level call. Recursive follow-up calls from processAgentResult
336 // reuse the same controller.
337 const isTopLevel = this._runDepth === 0;
338 let originalAbortRun: (() => void) | undefined;
339
340 if (isTopLevel) {
341 this._runAbortController = new AbortController();
342
343 // Intercept agent.abortRun() so that calling it directly (not via
344 // stopAgent) also aborts in-flight tool execution and prevents
345 // follow-up runs.
346 const controller = this._runAbortController;
347 originalAbortRun = agent.abortRun.bind(agent);
348 agent.abortRun = () => {
349 controller.abort();
350 originalAbortRun!();
351 };
352
353 // Notify subscribers (e.g. the inspector) about the agent that is about
354 // to run. Per-thread clones are not in the agent registry, so
355 // onAgentsChanged never fires for them and they would otherwise be
356 // invisible to subscribers. Fired once per top-level run; recursive
357 // follow-up runs reuse the same instance and need no re-notification.
358 await this._internal.notifySubscribers(
359 (subscriber) =>

Callers 2

processAgentResultMethod · 0.95
runToolMethod · 0.95

Calls 10

buildFrontendToolsMethod · 0.95
processAgentResultMethod · 0.95
applyHeadersToAgentMethod · 0.65
notifySubscribersMethod · 0.65
runAgentMethod · 0.65
getContextForAgentMethod · 0.65
emitErrorMethod · 0.65
clearSuggestionsMethod · 0.45
detachActiveRunMethod · 0.45

Tested by

no test coverage detected