Repository navigation
feat(mcp): one scheduling tool set for agents - #224
Conversation
…ater Scheduled tasks that stop doing anything piled up forever. An hourly sweep on the existing scheduler tick now archives a task (turns it off and records why) after 10 days as a fired one-time task, paused task, failing task (3+ consecutive failures over 10 days) or task whose thread was archived, and a never-triggered webhook after 30 days. Archived tasks are deleted 30 days after archiving, with their webhook deliveries. Re-enabling or saving restores one, and a restored webhook keeps its URL. Fork migration 23 adds the archive and failure-counter columns and sets agent tasks that legacy imports left on new_thread to continue. Thread auto-archive now skips threads with an enabled bound schedule, which would otherwise fail every later run. Web and mobile Settings get an Active/Archived filter with the reason, the deletion date and Restore. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: unavailable · PR result: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
jayleaton
left a comment
There was a problem hiding this comment.
VERDICT #224: CHANGES
No new handler/schema regression found: both run ID names remain accepted and freshSession reaches the update service. Resolve the required red budget check; an exact smaller wording is inline. Reviewed head a8bd85b.
Repository check:changed against #222 passed, including 37-package typecheck and 11 test files. Scheduling eval dry runs built all 3 added cases; eval grader tests passed (481). Paid behavior evals were not run, as the PR body explicitly scopes those out.
… started The sweep reads task rows and active runs once. A manual run that started while the sweep waited on an earlier row's thread lookup left archived_at unchanged, so the delete removed the running task. The delete now requires the row's read updated_at and a non-running status, and holds the run reservation so a run cannot start mid-delete. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
a8bd85b to
e7d0f17
Compare
jayleaton
left a comment
There was a problem hiding this comment.
VERDICT #224: MERGE
Reviewed e7d0f17 against e1e6d06. check:changed passes: formatting, lint, both knip passes, GraphQL, 37-package typecheck and 11 focused test files. The budget comparison passes without a label override: 60391 bytes against main’s 60396.
The stdio owner-handover test passed 5/5 isolated runs on this head and 3/3 on its base. The failing CI log reports “Launcher exited: ... read ECONNRESET”. The test, transport, launcher, owner, bridge, entry point, server registration loop and dependencies are unchanged; this test lists tools and replaces an owner, never calling scheduling. The scheduling catalog gains an optional create parameter/description, with no handover protocol change. I found no functional link to this diff; the unchanged transport treats ECONNRESET as fatal, consistent with a pre-existing handover flake. The CI failure did not reproduce locally.
This layer passes review independently. The stack remains blocked by the new cleanup-reservation finding on #222.
…'s delivery Cleanup took the run reservation while deleting, so a webhook restored and triggered in that window was refused as already running and its accepted delivery was recorded as dispatch_failed. Cleanup now only skips tasks that are running; the updated_at and status guards on the delete already drop it when a run, restore or edit lands first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
e7d0f17 to
b4cce2f
Compare
A run reads the task, then marks it running by id alone. If the task was deleted and recreated under the same id in between, as cleanup plus an idempotent create replay can do, the old run started on the replacement and stamped its history. The start now also matches the created_at it read and aborts when the row was replaced. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In-process agents saw two scheduling tool sets: schedule_task and friends, and the T3 Agents t3_*_scheduled_task tools, which had fewer triggers and no idempotent retry. The unprefixed set is now the one set: schedule_task advertises cron and says enabled=true restores an archived task, list_scheduled_tasks leaves archived tasks out unless includeArchived and reports why and when each is deleted, and run_scheduled_task_now takes scheduledTaskId like the others. In-process, the five t3_* schedule tools stay one release as one-line deprecated aliases; the standalone gateway keeps them for outside clients, and t3_create_scheduled_task takes an idempotencyKey. Also fixes schedule_task dropping freshSession on update, labels the t3_* schedule tools in the timeline instead of the retired update_scheduled_task, and corrects the docs that said linked machines can manage scheduled tasks. Adds three mcp-tool-use eval cases: cron, agent target, restore archived. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The scheduling tool descriptions added 326 bytes to every agent's tool list. Shorter wording keeps cron, agent routing, restore and the scheduledTaskId name, and measures 60391 bytes against main's 60396. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
b4cce2f to
e3fbc4e
Compare
Summary
In-process agents saw two scheduling tool sets with different powers. The unprefixed set is now the one set; the
t3_*set stays for outside clients.schedule_task + advertises {type:'cron',expression,timezone}; "enabled=true … restores an archived one"; "For an agent, pass profileId" + update now passes freshSession through (was dropped by the handler) list_scheduled_tasks + includeArchived (default false) result + archived: {reason, deletesAt} run_scheduled_task_now + scheduledTaskId (taskId kept as the older name) delete_scheduled_task unchanged in-process t3_list/create/update/delete/run_scheduled_task - full gateway descriptions + "Deprecated: use `schedule_task` with `profileId`." (one line each, one release) gateway t3_create_scheduled_task + idempotencyKey → stable commandId, so a retry returns the same task timeline labels - update_scheduled_task (retired) + the five t3_* schedule toolsDocs:
remote-access.mdno longer says linked machines can manage scheduled tasks (they can't, perinternals/remote.mdandlinkOrigin.ts), and says in-T3 agents useschedule_task+profileId;orchestrator-mcp-server.mdcovers cron, agents, archive/restore and the deprecated aliases.agentContextBudget.json: tool list 60396 → 60391 bytes.Sits on #222.
Evidence
Unit tests, written first. With the implementation reverted to #222 (patch kept aside, then reapplied): 6 failing —
adds every tool … lifecycle alias(deprecated descriptions),lists archived tasks only when asked,a caller cannot rewrite …(freshSession dropped),run_scheduled_task_now takes scheduledTaskId,labels the T3 Agents schedule tools, gatewayturns runAt or cron into a schedule(idempotencyKey). After: server MCP 103/103, shared 5/5, mcp-gateway 115/115.vp run check:changed: all 10 steps pass.Evals (
evals/mcp-tool-use/cases/pull-requests.ndjson, three newbadcases):schedule-cron-month-daysschedule_taskwithschedule.type: cron,expression ~1,15, neverfixed_timeschedule-agent-uses-schedule-task(agentsTools: true)schedule_taskwithprofileId: reviewer, nevert3_create_scheduled_taskt3_create_scheduled_taskdescription is the only one that mentions agents + cronschedule-restore-archivedlist_scheduled_tasks {includeArchived: true}thenschedule_task {scheduledTaskId, enabled: true}, never a new taskincludeArchiveddoes not exist on the old text--dry-runbuilds all three on the old text and the new text (exit 0).mcp-tool-use/run.test.ts: 481 passed.Merge Danger
Door: two-way. Tool text and an optional parameter; no stored state changes. An outside agent that calls an in-process
t3_*_scheduled_tasktool still works, it only reads a shorter description.Blast Radius: agents
Every agent's tool list changes, but stays under main's size (60391 bytes against 60396). Agents that relied on
list_scheduled_tasksreturning archived tasks now needincludeArchived. The three eval cases above cover the new text.Implemented by Claude Opus 5.5 in Claude Code (T3 Code).
🤖 Generated with Claude Code