Skip to content

Thread the per-iteration watchdog signal into webActionTools (extract tool's LLM call) #533

@lmorchard

Description

@lmorchard

Background

#521 added a per-iteration watchdog: WebAgent exposes this.currentIterationSignal (the caller's abortSignal combined with the iteration's watchdog AbortController) and threads it into the directly-issued iteration LLM calls — the action streamText and the validation generateTextWithRetry. When the watchdog fires, those in-flight calls are aborted.

Gap

The agent's tools are created once, before the loop, in runMainLoop:

const webActionTools = createWebActionTools({
  ...
  abortSignal: this.abortSignal, // external signal only, captured at creation time
  ...
});

So the extract tool (which runs its own generateTextWithRetry) uses the external abort signal, not the per-iteration watchdog signal. When the watchdog fires mid-extract, that in-flight LLM request is not cancelled.

Impact

Low — not a hang risk. The Promise.race in runWithIterationWatchdog still bounds the overall iteration, so a stuck extract can't freeze the task. The only downside is best-effort cleanup: an extract LLM call already abandoned by a timed-out iteration keeps running in the background until it completes on its own (one orphaned request, GC'd when the page/process ends).

Suggested approach

Give the tools access to the current per-iteration signal rather than a static one captured at creation. Options:

  • Pass a () => AbortSignal | undefined accessor into createWebActionTools that returns this.currentIterationSignal ?? this.abortSignal, and have the extract tool read it at call time; or
  • Recreate (or rebind the signal on) the relevant tools per iteration.

Prefer the accessor — it's the smallest change and keeps tool creation outside the loop.

Context

Surfaced in Copilot's review of #521; the docstring on runWithIterationWatchdog was updated there to scope the watchdog signal accurately (action stream + validation only). This issue tracks closing the remaining gap for extract.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions