fix(agents): give every ControlHub mode the Cron tool - #2215
Merged
Conversation
Asked to sweep a set of channels every 30 minutes, a Cowork-mode agent replied that it had no cron tool and fell back to chaining long `wait` calls. It was telling the truth: `Cron` was in Claw's tool list and nowhere else, so in Cowork, Team, DeepResearch, and the four shared coding modes the agent could not see it at all. Deferred exposure is not the cause — deferred tools are advertised by name — the tool simply was not in those modes' `default_tools`. ControlHub's `wait` documentation now tells the agent to schedule repeating work with Cron instead of holding the turn open, and ControlHub ships in all of those modes, so the guidance pointed at a tool the agent did not have. - Add `Cron` to Cowork, Team, DeepResearch, and `shared_coding_mode_tools` (agentic / debug / multitask / plan), so it is available everywhere ControlHub is. - Cover the pairing with an invariant test over the built-in modes; it caught the shared coding baseline, which the first pass had missed. - Say in ControlHub's description what to do if Cron is genuinely absent, rather than leaving a chain of long waits as the silent fallback. Scheduling stays behind the normal permission gate — Cron is not read-only and emits a `custom_tool` intent — so this widens what the agent can propose, not what it can do unattended.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Problem
Asked to sweep a set of channels every 30 minutes, a Cowork-mode agent answered:
It was telling the truth.
Cronappeared in exactly one mode'sdefault_tools— Claw — and nowhere else:shared_coding_mode_tools)Deferred exposure is not the cause — deferred tools are advertised to the model by name in the
<deferred_tools>listing, so the agent would have seenCronhad it been in the list. It simply was not.This also left #2212 pointing at a tool that often is not there: ControlHub's
waitdocumentation now says to schedule repeating work with theCrontool instead of holding the turn open, and ControlHub ships in every mode in that table. The agent got told to use a tool it did not have, and quietly fell back to chaining hour-long waits — the exact pattern that guidance exists to prevent.Changes
Cronto every mode that carriesControlHub— Cowork, Team, DeepResearch, andshared_coding_mode_tools()(agentic / debug / multitask / plan). Claw already had it.waitcalls as the unspoken fallback.Scope note
This widens what the agent can propose, not what it can do unattended.
CronTool::is_readonly()isfalseand it does not overridepermission_intents, so everyadd/update/remove/runemits acustom_toolintent and goes through the normal permission gate. Cron also stays denied in connection-scoped transient sessions, which this PR does not touch.Testing
cargo test -p bitfun-core --lib— 1948 passed, 0 failed.cargo fmt --checkandcargo clippyunchanged from base (7 pre-existing fmt diffs, 11 pre-existingMutexGuard held across awaitfindings, none in files this PR touches).