From 40e81063fcc222afb8f7f0e4ef711905177c3d9d Mon Sep 17 00:00:00 2001 From: allocsys <225476909+allocsys@users.noreply.github.com> Date: Thu, 10 Sep 2026 07:51:18 +0330 Subject: [PATCH 1/4] delegate_agent: replace anti-hammering explanation with simple sleep-60s poll instruction --- connectors/delegate/agent/agent_tools.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connectors/delegate/agent/agent_tools.js b/connectors/delegate/agent/agent_tools.js index d9e99ff1..cf2197b8 100644 --- a/connectors/delegate/agent/agent_tools.js +++ b/connectors/delegate/agent/agent_tools.js @@ -14,7 +14,7 @@ export function register(server) { "NOT: web access -> use delegate_research (task param, wide mode) instead. NOT: any write -> read-only by design.\n" + "USE FOR: e.g. 'why is CI failing on PR #42', 'summarize what changed in this repo over the last week' -- cases needing 5-10+ manual cross-system calls otherwise.\n" + "RESUME: failed/partial run -> response includes resume_run_id -> pass back to continue from last completed step instead of restarting.\n" + - "ASYNC, DO NOT POLL REPEATEDLY: a fresh call may return a run_id immediately while work continues server-side. Check status with resume_run_id ONCE, then stop -- space out polls instead of hammering it; polling faster does not finish it faster. If still running, end your turn (do other work, or wait for the user's next message) and resume later. Only a resume_run_id call returns the final answer, so you must check back eventually -- just not repeatedly in the same turn.\n" + + "ASYNC: a fresh call may return a run_id immediately while work continues server-side. If still running, sleep 60 seconds before polling again if you have nothing else to do, then call again with the same resume_run_id. Only a resume_run_id call returns the final answer.\n" + "POLLING vs PUSHING (async/QStash mode only -- see below): to just check progress on a resume_run_id, call with NO max_steps -- this is always read-only, even in the rare case where the background worker chain has stalled (you'll get a 'stalled' status instead of a stored answer, never a silent extra step). Only pass max_steps when you actually want to advance the investigation further right now (raising the ceiling on a resumed run, or nudging a stalled one forward) -- an explicit max_steps is what authorizes real work to happen on that call. This distinction only applies when the async worker is configured; in synchronous mode there is no separate poll state at all -- every resume_run_id call continues the loop immediately regardless of max_steps, same as always.", { task: z.string().optional().describe("The investigation task/question, described with enough context (repo names, time ranges, etc.) for Gemini to act without needing to ask you anything back -- it can't. Ignored when resume_run_id resolves to a live checkpoint (the original task from that run is reused). Optional ONLY when resume_run_id is given and its checkpoint is still live; required otherwise -- omitting it on a fresh run (no resume_run_id, or an expired one) returns an error rather than silently proceeding with no task."), From 1a667627642147a167bb67b8eb4cb7b71752de93 Mon Sep 17 00:00:00 2001 From: allocsys <225476909+allocsys@users.noreply.github.com> Date: Thu, 10 Sep 2026 07:51:27 +0330 Subject: [PATCH 2/4] delegate_editor: replace anti-hammering explanation with simple sleep-60s poll instruction --- connectors/delegate/editor/editor_tools.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connectors/delegate/editor/editor_tools.js b/connectors/delegate/editor/editor_tools.js index 71cccdd8..c2b84e85 100644 --- a/connectors/delegate/editor/editor_tools.js +++ b/connectors/delegate/editor/editor_tools.js @@ -67,7 +67,7 @@ export function register(server) { "PREREQUISITE: `branch` MUST already exist and MUST NOT be the repo's default branch -- checked live against the GitHub API before any tool call, never trusted from the argument alone. No branch yet -> call create_branch first.\n" + "CANNOT open, approve, or merge pull requests -- this tool has no create_pull_request/merge_pull_request in its own function set, structurally, not just by convention. A human reviews the branch's diff afterward; this tool only gets it ready for that review.\n" + "RESUME: failed/partial run -> response includes resume_run_id -> pass back to continue from the last completed step instead of restarting.\n" + - "ASYNC -- DO NOT HAMMER THIS: a fresh call may return a run_id immediately while the run keeps stepping server-side in the background. Check status with resume_run_id ONCE, then STOP -- go do other work (other tasks, other tool calls, or just respond to the user) and check back later. A single step realistically takes several seconds to tens of seconds end-to-end (QStash delivery plus the step itself), so calling resume_run_id again right away, or more than once in the same turn, does not finish it any faster -- it only burns a call for the same 'still running' answer. Only a resume_run_id call returns the final result, so you do need to check back eventually -- just not immediately, and not repeatedly.\n" + + "ASYNC: a fresh call may return a run_id immediately while the run keeps stepping server-side in the background. If still running, sleep 60 seconds before polling again if you have nothing else to do, then call again with the same resume_run_id. Only a resume_run_id call returns the final result.\n" + "POLLING vs PUSHING (async/QStash mode only -- see below): to just check progress on a resume_run_id, call with NO max_steps -- this is always read-only, even in the rare case where the background worker chain has stalled (you'll get a stalled status instead of a stored answer, never a silent extra step or write). Only pass max_steps when you actually want to advance the run further right now (raising the ceiling on a resumed run, or nudging a stalled one forward) -- an explicit max_steps is what authorizes real work (including further commits) to happen on that call. This distinction only applies when the async worker is configured; in synchronous mode there is no separate poll state at all -- every resume_run_id call continues the loop immediately regardless of max_steps, same as always.", { owner: z.string().optional().describe(`Repository owner. Defaults to "${DEFAULT_OWNER}" if omitted.`), From d4ea541e94684ec4b6793c2a363bd5d35484952e Mon Sep 17 00:00:00 2001 From: allocsys <225476909+allocsys@users.noreply.github.com> Date: Thu, 10 Sep 2026 07:51:36 +0330 Subject: [PATCH 3/4] list_workflow_runs: replace anti-hammering explanation with simple sleep-30s poll instruction --- connectors/github/actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connectors/github/actions.js b/connectors/github/actions.js index 1a5ea885..991cea2b 100644 --- a/connectors/github/actions.js +++ b/connectors/github/actions.js @@ -11,7 +11,7 @@ export function register(server) { server.tool( "list_workflow_runs", "List recent GitHub Actions workflow runs for a repository.\n" + - "DO NOT POLL REPEATEDLY: a queued/in-progress run takes real wall-clock time to finish (queue time plus job runtime -- often 30s to several minutes, not instant) -- calling this again immediately in a tight loop to watch a run complete does not make it finish faster, it just burns calls for the same unchanged status. Check once; if the run you care about is still queued/in_progress, space out the next check meaningfully (do other work, or end your turn and check back later) instead of re-calling this right away.", + "If the run you care about is still queued/in_progress, sleep 30 seconds before checking again if you have nothing else to do, then call this again.", { owner: z.string().optional().describe(`Repository owner. Defaults to "${DEFAULT_OWNER}" if omitted.`), repo: z.string().describe("Repository name"), From 5ada85d4bd874b5310d61895c49629aa4610c594 Mon Sep 17 00:00:00 2001 From: allocsys <225476909+allocsys@users.noreply.github.com> Date: Thu, 10 Sep 2026 07:54:59 +0330 Subject: [PATCH 4/4] get_check_runs, get_combined_status: add sleep-30s poll instruction --- connectors/github/ci_control.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/connectors/github/ci_control.js b/connectors/github/ci_control.js index 2bd70d58..23c0feaa 100644 --- a/connectors/github/ci_control.js +++ b/connectors/github/ci_control.js @@ -88,7 +88,8 @@ export function register(server) { server.tool( "get_check_runs", "DOES: Individual check/status entries (pass/fail dots) for a commit/branch/tag -- the data behind GitHub's green check / red X.\n" + - "NOT: a list of Actions runs -> use list_workflow_runs for that.", + "NOT: a list of Actions runs -> use list_workflow_runs for that.\n" + + "If checks are still pending, sleep 30 seconds before checking again if you have nothing else to do, then call this again.", { owner: z.string().optional().describe(`Repository owner. Defaults to "${DEFAULT_OWNER}" if omitted.`), repo: z.string().describe("Repository name"), @@ -108,7 +109,8 @@ export function register(server) { server.tool( "get_combined_status", - "DOES: Combined commit status for a ref -- overall pass/fail/pending rollup + each individual status context (the legacy Status API some CI systems/integrations use instead of, or alongside, Actions check-runs).", + "DOES: Combined commit status for a ref -- overall pass/fail/pending rollup + each individual status context (the legacy Status API some CI systems/integrations use instead of, or alongside, Actions check-runs).\n" + + "If the overall state is still pending, sleep 30 seconds before checking again if you have nothing else to do, then call this again.", { owner: z.string().optional().describe(`Repository owner. Defaults to "${DEFAULT_OWNER}" if omitted.`), repo: z.string().describe("Repository name"),