Skip to content

feat(mcp): one scheduling tool set for agents - #224

Merged
jayleaton merged 6 commits into
mainfrom
feat/schedules-mcp-20261113
Nov 13, 2026
Merged

jayleaton merged 6 commits into
mainfrom
feat/schedules-mcp-20261113

Conversation

@jayleaton

@jayleaton jayleaton commented Nov 13, 2026 •

Copy link
Copy Markdown
Owner

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 tools

Docs: remote-access.md no longer says linked machines can manage scheduled tasks (they can't, per internals/remote.md and linkOrigin.ts), and says in-T3 agents use schedule_task + profileId; orchestrator-mcp-server.md covers 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, gateway turns 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 new bad cases):

Case Must Fails on old text because
schedule-cron-month-days schedule_task with schedule.type: cron, expression ~1,15, never fixed_time old schedule description lists only interval / fixed_time / once / webhook
schedule-agent-uses-schedule-task (agentsTools: true) schedule_task with profileId: reviewer, never t3_create_scheduled_task old t3_create_scheduled_task description is the only one that mentions agents + cron
schedule-restore-archived list_scheduled_tasks {includeArchived: true} then schedule_task {scheduledTaskId, enabled: true}, never a new task includeArchived does not exist on the old text
  • --dry-run builds all three on the old text and the new text (exit 0). mcp-tool-use/run.test.ts: 481 passed.
  • Paid runs are out of scope for this PR, by maintainer decision. The three cases stay in the file for the next eval run.

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_task tool 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_tasks returning archived tasks now need includeArchived. The three eval cases above cover the new text.

Implemented by Claude Opus 5.5 in Claude Code (T3 Code).

🤖 Generated with Claude Code

…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>
@github-actions github-actions Bot added vouch:trusted Author is trusted by repo permissions or the VOUCHED list. size:L labels Nov 13, 2026
@github-actions

github-actions Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 5.0 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 21.5 KiB — 24.4 KiB ✅
Codex Live turn messages — 1 — 8 ✅
Claude Total thread wire — 5.0 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 21.9 KiB — 24.4 KiB ✅
Claude Live turn messages — 1 — 8 ✅

Baseline: unavailable · PR result: e3fbc4e · Source CI: success

Scenario and decoded snapshot size

10 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.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@jayleaton jayleaton added the agent-context-increase Approves a measured increase to the agent context budget label Nov 13, 2026
@jayleaton
jayleaton marked this pull request as ready for review November 13, 2026 03:42

@jayleaton jayleaton left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@jayleaton
jayleaton force-pushed the feat/schedules-mcp-20261113 branch from a8bd85b to e7d0f17 Compare November 13, 2026 05:28
@jayleaton

Copy link
Copy Markdown
Owner Author

Fixed in e7d0f17: rebased on #222, and the scheduling tool text is trimmed to 60391 bytes, under main's 60396.

@jayleaton jayleaton left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
jayleaton and others added 3 commits November 13, 2026 13:25
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>
@jayleaton
jayleaton force-pushed the feat/schedules-mcp-20261113 branch from b4cce2f to e3fbc4e Compare November 13, 2026 06:27
@jayleaton
jayleaton changed the base branch from feat/schedules-cleanup-20261113 to main November 13, 2026 06:39
@jayleaton
jayleaton merged commit aa65f1b into main Nov 13, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-context-increase Approves a measured increase to the agent context budget size:L vouch:trusted Author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant