-
Notifications
You must be signed in to change notification settings - Fork 455
Fix logs tool: context deadline exceeded without workflow_name filter #46554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
f8250c7
Initial plan
Copilot d5e0633
Fix logs tool timeout without workflow_name filter
Copilot 55feb0c
Clarify timeoutReached=false for Canceled case in orchestrator download
Copilot da1e3db
docs(adr): add ADR-46554 for dynamic MCP logs tool timeout computation
github-actions[bot] 7aef8a5
fix: propagate ctx errors from listWorkflowRunsWithPagination; remove…
Copilot 290e647
Merge branch 'main' into copilot/cli-tools-test-logs-timeout-fix
pelikhan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
48 changes: 48 additions & 0 deletions
48
docs/adr/46554-dynamic-timeout-computation-for-mcp-logs-tool.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # ADR-46554: Dynamic Timeout Computation for the MCP Logs Tool | ||
|
|
||
| **Date**: 2026-07-19 | ||
| **Status**: Draft | ||
| **Deciders**: pelikhan, copilot-swe-agent | ||
|
|
||
| --- | ||
|
|
||
| ### Context | ||
|
|
||
| The `agenticworkflows logs` MCP tool timed out (hitting the MCP gateway's 60-second hard limit) whenever it was called without a `--workflow_name` filter. Three compounding issues caused this: (1) `BatchSizeForAllWorkflows` was set to 250, which paginated as three sequential GitHub API calls per batch (the GitHub API caps per-page results at 100), producing 45–60+ seconds of latency on large repositories; (2) `fetchWorkflowRunBatch` called the GitHub API with `Context: nil`, meaning the subprocess had no deadline and could not be cancelled by the caller's context; (3) a static `timeout` schema default was registered in the MCP tool schema, causing the go-sdk to pre-fill `args.Timeout` before the handler ran, bypassing the per-request runtime computation that would have applied a higher floor for all-workflow queries. | ||
|
|
||
| ### Decision | ||
|
|
||
| We will compute the MCP logs tool timeout dynamically at request time based on two parameters: the effective `count` and whether `workflowName` is empty. When no workflow filter is provided, a minimum floor of 5 minutes (`defaultMCPLogsMinTimeoutMinutesAllWorkflows`) is enforced, because unfiltered GitHub API queries scan all workflow runs and are significantly slower on large repositories. The static MCP schema default for `timeout` is removed so the go-sdk cannot pre-fill the value and short-circuit the runtime computation. Additionally, `BatchSizeForAllWorkflows` is reduced from 250 to 100 (the GitHub API's `per_page` maximum) so each batch requires only a single API round-trip, and the request context is threaded into `fetchWorkflowRunBatch` to allow graceful cancellation distinguishing internal deadline expiry from external context cancellation. | ||
|
|
||
| ### Alternatives Considered | ||
|
|
||
| #### Alternative 1: Increase or Remove the MCP Gateway Timeout Limit | ||
|
|
||
| Configure the MCP gateway to allow a longer (or unlimited) per-tool timeout so that the existing logic with `BatchSizeForAllWorkflows = 250` and no context propagation could still succeed on large repositories. This was not chosen because the 60-second limit is an external constraint of the MCP gateway infrastructure that the tool cannot unilaterally change. Relying on a large external timeout also hides performance problems rather than fixing them; a slow tool would remain slow for users even if it eventually completed. | ||
|
|
||
| #### Alternative 2: Parallelise GitHub API Calls Within a Batch | ||
|
|
||
| Instead of reducing `BatchSizeForAllWorkflows` from 250 to 100, keep the larger batch and issue the three required API pages concurrently. This would reduce the wall-clock time for a 250-run batch to approximately the latency of one API call. This was not chosen because it adds concurrency complexity and risk (rate-limiting, partial-failure handling) to code that was otherwise sequential by design. Aligning with the API's per-page maximum of 100 is simpler, predictable, and sufficient to keep individual batch fetches within acceptable latency bounds. | ||
|
|
||
| #### Alternative 3: Cache Workflow Run Listings Between Requests | ||
|
|
||
| Introduce a short-lived cache of recent `gh run list` results so that consecutive calls (e.g. from retried or paginated MCP requests) avoid redundant API round-trips. This would reduce latency for repeated queries at the cost of potentially serving stale data. This was not chosen because it introduces state management complexity and cache invalidation risk in a tool that needs to return current data; the simpler approach of aligning batch size with API limits is sufficient for the latency problem at hand. | ||
|
|
||
| ### Consequences | ||
|
|
||
| #### Positive | ||
| - The MCP logs tool no longer times out on large repositories when `--workflow_name` is omitted, making the common fleet-wide log inspection use-case reliable. | ||
| - The distinction between internal deadline expiry (`context.DeadlineExceeded`) and external cancellation (`context.Canceled`) is now surfaced to callers, enabling better error handling and partial-result recovery. | ||
| - Removing the static schema default makes the timeout computation self-consistent: the value callers see in the MCP schema (no default) matches the actual runtime behaviour (computed per-request). | ||
|
|
||
| #### Negative | ||
| - Reducing `BatchSizeForAllWorkflows` from 250 to 100 means that retrieving a large number of runs requires more loop iterations, which slightly increases total latency when the repository has many workflow runs and the result count is large. | ||
| - Removing the static schema default for `timeout` means MCP clients that relied on schema introspection to determine a default timeout value will no longer find one; they must accept that the timeout is opaque and server-determined. | ||
|
|
||
| #### Neutral | ||
| - The `effectiveMCPLogsToolTimeoutMinutes` function signature now accepts a `workflowName string` parameter; all call sites must be updated accordingly (done in this PR). | ||
| - Tests for timeout computation are extended with a `workflowName` dimension, increasing test coverage but also test verbosity. | ||
|
|
||
| --- | ||
|
|
||
| *ADR created by [adr-writer agent]. Review and finalize before changing status from Draft to Accepted.* |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[/tdd] The
"very large count exceeds all-workflow minimum"test hardcodeswant: 7with a comment// ceil(250/40) = 7— tying the test to implementation arithmetic rather than the exported constant.💡 Suggestion
If
mcpLogsRunsPerDefaultTimeoutMinuteor the ceiling formula ever changes, this test will silently mismatch without the reader noticing. Consider:or at minimum:
This keeps the test honest without coupling it to a magic number.
@copilot please address this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 7aef8a5. Replaced the hardcoded
7with(250 + mcpLogsRunsPerDefaultTimeoutMinute - 1) / mcpLogsRunsPerDefaultTimeoutMinuteso the expected value stays in sync with the constant automatically.