Skip to content

ui-sdk: give chat agents schedule_task, list and cancel tools on both backends #916

Open

Description

@schlessera

Context

Delivered prerequisite outputs: #914. Their output references remain relevant, but they are no longer active blockers.

Part of #912. A chat agent asked to "do this again on Monday" has no tool for it. The chat-UI tool set is a stable contract (docs/integration-contract.md:1133). New tools follow the query_activity path:

  • the SDK contract in packages/ui-sdk/src/tool-contracts/bridge.ts:386,
  • a BackendBridge handler (packages/ui-sdk/src/server/backend.ts:186-191),
  • the host bridge (packages/ui-server/src/ws/bridge.ts:233-234),
  • registration in the Claude backend (packages/ui-backend-claude/src/ask-user-tool.ts:112-113) and in pi (packages/ui-backend-pi/src/bridge-tools.ts:205-213).

The local missing capability is the reason for these tools; no specific vendor scheduler availability or account requirement is asserted. Under approved Execution A, stored tasks reach the existing Queue execution path and retain the configured inference backend dependencies.

Scope

  • Selected technical specification: scheduled-task decision and prepared consumer contracts. These are concrete technical deliverables under the six settled maintainer policies, not installed commands/routes/tools or runtime proof. ui-server: decide how a scheduled agent task runs while autonomous dispatch is gated #913 is delivered and verified via CONTRACT: docs: record scheduled task boundaries #980; this record dependency is cleared. The core: manage Markdown schedules through an authenticated host CLI #914/ui-server: verify the full async lifecycle before enabling autonomous dispatch #689 outputs are delivered; no store blocker or new design wait remains on these tools. Production activation is separate under ui-server: enable autonomous dispatch in production behind a supported switch #1595. No release commitment or production dispatch is inferred. Implement mcp__brain-ui__schedule_task ({key,definition}, confirm class), list_scheduled_tasks (list paging/filter input, read class) and cancel_scheduled_task ({id,key}, confirm class) using the exact shared response/error schemas. Show a self-contained future prompt, full bounded scope and immutable materialized timing/limits/default-off success preference; caller tool scope is proposed data, not granted membership.
  • Host context supplies creator/client-zone fallback and verified operator decision; models cannot supply approvalId/actor/executionPolicy/profile/trust/billing. Existing trusted permission/Action review obtains approval; no model-visible approval tool or implicit authenticated-agent grant. Verify canonical-to-actual descriptor mapping and nonempty strict schemas/eager executors at both real backend registrations, including revoked/forged/changed/replayed proposals and voice/no-grant denial. CLI/PWA parity uses the same host receipts.
  • schedule_task takes exactly {key,definition} under the strict prepared schema and returns the shared add/task envelope, including nextDueAt and actual execution availability. Scope.tools is proposed bounded data, never a caller-granted allowlist. Host resolution uses explicit valid zone, validated client zone or disclosed UTC. Under approved Authority A, creation requires explicit authenticated operator approval of the exact recurring operation/tool/input/target/egress envelope and variable-input bounds. Store immutable approval provenance and enforce current revocation/expiry each run; calling this tool or providing the prompt is not an implicit blanket grant. Changed scope requires cancellation and a newly approved schedule. The host obtains the creator from the authenticated turn, never a model-supplied principal, profile, allowlist or trust field. The tool description tells the model to write the prompt self-contained, because the run has none of the current conversation.
  • list_scheduled_tasks and cancel_scheduled_task.
  • Expose Delivery A success-notify preference (default off, explicit requested per-schedule opt-in) and recorded authenticated results/run links in the shared task/list payload. A notification option grants no execution authority and cannot select arbitrary push recipients/payloads. No unsolicited Chat insertion or extra inference is used to report a recorded result.
  • Approved Budget A caps the whole occurrence at three model-bearing operations and each admitted attempt at 10 minutes, using existing shared daily admission and persistent counters. Model input cannot raise caps, reset them through a follow-up, choose emergency capacity or manufacture billing identity; expose actual unavailable/exhausted outcomes.
  • All three use the authoritative consumer path exposed by core: manage Markdown schedules through an authenticated host CLI #914 and approved Queue Execution A. Store B selects Markdown definitions with a server approval/runtime ledger; concrete schema/host API examples follow the selected specification above; execution has no second store or separate direct core AgentRunner/cron fallback.
  • Apply approved Timing A (single/latest recent catch-up, no overlap, 24-hour original-due freshness, future/unstarted-only schedule cancellation and unknown-effect investigation). The cancellation tool cannot claim to stop a live attempt or undo an effect; return truthful running and cancelled-future state.
  • Default zone can use the existing optional ClientEnvironment.timeZone (packages/ui-sdk/src/protocol.ts:223-245) if validated and available, after an explicit valid zone; otherwise disclose UTC fallback. Explicit invalid zones fail. Offset/Z future ISO instants and DST skip-gap/first-fold-once recurrence follow Timing A. Do not let the model silently invent the user's local zone. Keep target paths root-bound and treat the stored prompt as task data, not new permission.
  • Permission class on pi, and the allowlist on Claude, matching the other bridge tools.

Out of scope

  • Execution (the ui-server task) and the PWA list.
  • Editing a schedule in place: cancel and re-create.

Settled policies

All six #912/#913 policies are settled and recorded in docs/decisions/scheduled-tasks.md (#913, PR #980): Execution A, Authority A, Budget A, Timing A, Delivery A and Store B. #914 delivered the authenticated host-managed Markdown/approval path these tools call. No dependency remains: the three tools can be built now, independently of #915's execution and #1595's activation. Model input or a raw file cannot approve recurring scope, reset counters or select a privileged actor; creation, grant and cancel classes enforce Authority A and Timing A through the existing approval boundary. Exact schemas and field names are technical work, not a new product ruling.

Acceptance criteria

  • Actual backend executors create/list/cancel the same host-managed Markdown definition and server approval/receipt/occurrence records visible through authenticated CLI/PWA. File edits/restores or model-supplied scope/provenance cannot activate changed definitions; root containment and current principal/approval checks fail visibly. No second store, direct runner or inferred create approval is used.
  • Both actual backend registrations expose the three tools under the same names, with matching nonempty input/output/error contracts and executors. Tests assert schema and attached executor/actual invocation, not only the absence of a deferred-loading property.
  • Actual tool invocation obtains the creator from the verified turn and records explicit operator approval for the bounded recurring envelope. A forged creator/profile/trust field, missing approval, changed scope or replay cannot mint broader authority; approval provenance survives supported reopen. Voice cannot grant tools.
  • Host-level invalid time/cron/zone/path, denied authority, missing capability and creator revocation cases fail visibly without writing schedules. Model input cannot choose a privileged principal, broaden targets or enable general autonomous dispatch.
  • Retrying a creation/cancel invocation or replaying it after reconnect follows the approved receipt policy; it cannot accidentally create a second recurring schedule or cancel someone else's task.
  • A test proves a task scheduled through the tool appears in brain schedule list --json, and a task cancelled through the tool disappears from due.
  • The tool names and descriptions are listed in docs/integration-contract.md under the chat-UI tools section.

Verification

Use bun run test for ui-sdk, both backend registrations, real host bridge and the selected core CLI/store with scripted runtimes. Invoke each actual registered executor with nonempty fictional task payloads, observe the same persisted state through CLI JSON, then cancel and verify due is empty while cancelled history remains. Mutate one backend registration/authority gate and fail the intended assertion. The later PWA/live-agent check is separately authorized if it requires inference; keyless registration/store proof does not count as live model behavior.

Contract impact

Additive: three proposed mcp__brain-ui__* tool names and their selected payload/error contracts, supported SDK bridge methods and host integration. Keep contract, update docs/integration-contract.md in the same CONTRACT: commit, update the relevant API report and add minor changesets for changed SDK/backend/server packages. Do not widen the AgentRunner seam implicitly.

2026-10-24: replaced the superseded "Settled policy and dependency handoff" ("Keep both blockers" for delivered #913/#914) with the settled policies and the fact that this task has no remaining dependency; dated reconciliation notes moved to a comment.

Activity

  1. added
    type: featA new capability or a change in user-visible behaviour.
    area: ui-sdkWire protocol, runtime schemas, the server and client SDK surfaces.
    area: backendsAgentBackend implementations and the seam they share.
    blockedWaiting on another issue or an upstream dependency. Say which in the body.
    contractTouches the integration contract: CONTRACT: commit, contract doc updated in the same commit.
    on Oct 3, 2026
  2. added
    priority: p2Wanted, not scheduled. Pulled in when a milestone has room.
    needs: decisionBlocked on a maintainer or designer ruling, not on code.
    area: ui-serverHono app factory: turn coordinator, auth, session catalog, routes, cron.
    securityAuth, isolation, egress, secrets, or anything in the threat model.
    on Oct 3, 2026
  3. schlessera commented on Oct 3, 2026

    @schlessera
    OwnerAuthor

    Triage — 2026-10-03. Removed the implied approval of future runs, tied creator identity to the authenticated host turn and clarified optional client-zone data. Added the missing server area and meaningful actual-registration/host/CLI parity and duplicate/authorization tests. Tool payload/permission/receipt choices await #913; added needs: decision, priority: p2 and security.

  4. schlessera commented on Oct 3, 2026

    @schlessera
    OwnerAuthor

    Execution-branch reconciliation — 2026-10-04.

    The maintainer selected A for scheduled work on #912, also settling the execution branch in #913. Due occurrences use the existing Queue admission/authority/lifetime/budgets and autonomous AgentBackend boundary, triggered through its existing server runtime/tick and recovery/backstop infrastructure. One occurrence has one dispatch owner; cron may wake/recover that same path. No independent core AgentRunner/cron execution or interim runner migration is approved. Production execution waits for #689's integrated proof under docs/decisions/async-collaboration.md.

    The body now follows this selected branch. Creation/future-run authority, caps, timing/recovery, delivery and schedule-definition store/consumer contracts remain open; keep needs: decision and actual dependencies, plus any design need. No readiness, enabled autonomy, release commitment or implementation is claimed. #913 already owns the durable scheduled-tasks record; record this choice there after the remaining rulings without asking for execution again.

    Replaced an unsupported vendor-scheduler comparison with the concrete local missing-tool use case. No vendor availability/account claim is needed to justify these tools.

  5. schlessera commented on Oct 3, 2026

    @schlessera
    OwnerAuthor

    Authority-branch reconciliation — 2026-10-04.

    The maintainer selected A. Review and approve the exact recurring operation, tools, input bounds, targets and permitted egress once at creation, including which inputs may vary. Future occurrences use that immutable envelope intersected with current authority/revocation/expiry and admission checks. Changed prompt/scope requires cancellation and a newly approved schedule. Authenticated chat/CLI creation is not an implicit blanket grant; verified operator approval and creator provenance must be recorded without trusting a model/client principal/profile/trust string. Voice still cannot grant tools.

    Additional permission or ordinary answers checkpoint to a durable Action and unwind; validated resolution creates at most one separately admitted continuation. No indefinitely live ask promise, automatic expansion of scope or blind replay of completed effects. This schedule-specific recurring approval must be recorded and reconciled with existing authority records through #913; current generic Queue/chat grants do not already implement it. Runtime containment and #689 remain production gates.

    Updated the current brief. Execution A and Authority A are settled; budgets, timing/recovery, delivery and authoritative store/consumer contracts remain open. Keep needs: decision and actual dependencies/design needs without readiness, enabled autonomy or a release commitment. Concrete creator credential/approval schema/runtime enforcement details follow the selected policy rather than reopening it.

  6. schlessera commented on Oct 4, 2026

    @schlessera
    OwnerAuthor

    Budget-branch reconciliation — 2026-10-04.

    The maintainer selected A, including the common budget rules. Initial dispatch, retry/redo, yielded attempts, separately dispatched compaction and approved Action continuations all share the same occurrence limit, including when a new Queue item is created. Reload/restart cannot reset counters/deadlines. The host owns the attempt deadline, aborts at expiry and waits for actual backend unwind before releasing claim/lifetime or settling charges. Lower task-specific limits remain possible; capacity is not permission to replay an unknown effect.

    Scheduled work uses existing shared operator-configured daily autonomous operation/spend caps, charged usage plus active reservations. Zero/absent operations remains disabled; no implicit enablement, new schedule-only pool or privileged emergency reserve. Subscription work still consumes operation capacity; missing usage/prices remain conservatively charged, observed overruns stop later over-cap work, and admission does not promise a provider-enforced invoice ceiling.

    Updated the current brief and required persistent-counter/deadline/runtime controls. Execution A, Authority A and Budget A are settled; timing/recovery, delivery and authoritative store/consumer contracts remain open. Keep needs: decision and actual dependencies/design needs without readiness, enabled autonomy or a release commitment. #913 owns the durable record after the remaining rulings.

  7. schlessera commented on Oct 4, 2026

    @schlessera
    OwnerAuthor

    Timing-branch reconciliation — 2026-10-04.

    The maintainer selected A, including the common recovery rules. Keep one outstanding occurrence per schedule; otherwise catch up only the latest missed due instant within 24 hours and record older/busy instants as skipped/coalesced. Queued/running/retrying/human-wait work does not overlap. The occurrence expires 24 hours after its original due instant; retries/resolutions cannot reset freshness or revive cancelled/expired work. Existing Budget A counters/deadlines and current Authority A still bind.

    Schedule cancellation stops future/unstarted work idempotently and does not stop an already-started attempt or undo effects; running stop is a distinct supported host action with honest drain. Recover charges/receipts/lifetime first. A possible effect without authoritative completion/idempotency proof pauses automatic dispatch for that schedule and creates durable investigation; no blind repeat or arbitrary exactly-once claim.

    Explicit valid IANA zone wins, else validated client zone, else disclosed UTC; explicit invalid zone fails. First-create one-offs require a future ISO instant with Z/offset; recorded matching creation retries return the original receipt. Cron skips DST gaps and runs a repeated local time once at its earlier due instant. Existing tick/boot ownership remains one Queue path; due time is eligibility, not an exact-second start guarantee.

    Updated the current brief and timing/cancellation/unknown-effect validation. Execution A, Authority A, Budget A and Timing A are settled; delivery and authoritative store/consumer contracts remain open. Preserve needs: decision, actual dependencies/design needs and #689 without readiness, enablement or release commitment. #913 owns the durable record after the remaining rulings.

  8. schlessera commented on Oct 4, 2026

    @schlessera
    OwnerAuthor

    Delivery-branch reconciliation — 2026-10-04.

    The maintainer selected A for both one-off and recurring tasks, including the common delivery rules. Actual results/outcomes remain authenticated and durable in Activity/schedule detail; failures/stuck/needs-human Actions use the existing notice paths. Success uses existing completion intents only with explicit per-schedule opt-in. Preserve origin autonomous with additive schedule/occurrence/run correlation, deduplicate final notices across attempts/restarts, and retain generic scheduled-work push labels without prompt/title/path/result leakage. Existing watching, suppression, retry/backoff and push permissions still bind; intent/provider acceptance is not proof of user receipt/read.

    No unsolicited original-Chat insertion, extra model turn, new notification kind or service is approved. Suppressed/unavailable push never erases the recorded result. Updated the current brief and related design premise. Execution A, Authority A, Budget A, Timing A and Delivery A are settled; the final policy decision is authoritative schedule-definition storage and the CLI/host consumer boundary. Keep needs: decision and actual dependencies/design gates without readiness, enablement or release commitment. #913 owns the durable record and matching contract preparation after that ruling.

  9. added
    agent-readyContext and acceptance criteria are complete enough for an agent to take this unattended.
    and removed
    needs: decisionBlocked on a maintainer or designer ruling, not on code.
    on Oct 4, 2026
  10. schlessera commented on Oct 4, 2026

    @schlessera
    OwnerAuthor

    Final policy reconciliation — 2026-10-04.

    The maintainer selected B, including the common consumer/recovery rules. Dedicated root-contained Markdown files own definitions; the existing UI operational database owns immutable approval fingerprints/provenance, creator/occurrence/claim/counter/charge/Action/receipt/notification state. File edits/restores cannot grant or revive authority; dispatch requires matching approved scope and current authority, with durable file/DB compensation and quarantined drift. All supported CLI/chat/PWA consumers use one authenticated host path. No direct DB/core-runner/offline-activation fallback; due is read-only. Editing stays cancel-and-create; cancelled history/create-cancel receipts prevent replay. Coordinated content Git/operational backup and gated restore reconcile current authority/lost workers/unknown effects before dispatch.

    All six policies are now selected: Execution A, Authority A, Budget A, Timing A, Delivery A and Store B. Updated this brief and removed needs: decision. #913 still delivers the durable record and technical directory/schema/CLI/HTTP/tool examples; those are deliverables under the selected policies, not further generic maintainer choices. Existing dependency/design/system-proof requirements remain open; no implementation, record completion, production enablement or release commitment is inferred.

    The complete implementation brief is agent-ready but still blocked by its actual prerequisite outputs; preserve the existing dependency labels/lines. Technical code changes and runtime mutation receipts remain future work.

  11. schlessera commented on Oct 4, 2026

    @schlessera
    OwnerAuthor

    Technical reconciliation — 2026-10-04. #913 now has a concrete documentation draft in #980, pinned to signed head a4d701c4db7d03c18608c6b12891f5e5d020c63f. Folded the chosen directory/schema, immutable approval/provenance and file/DB compensation, strict CLI/HTTP/tool/result/error/receipt contracts into this brief; corrected stale execution/origin/provenance wording where applicable. #917's self-contained design prompt consumes the concrete types and preserves its missing interaction design.

    This is planned-only contract preparation, not package implementation, a verified operator grant or enabled execution. #913 stays open until its required checks and merge; #914–#917's other dependencies/design need and #689 remain. No release commitment or running-host proof is inferred.

  12. removed
    blockedWaiting on another issue or an upstream dependency. Say which in the body.
    on Oct 12, 2026
  13. schlessera commented on Oct 24, 2026

    @schlessera
    OwnerAuthor

    History moved out of the body on 2026-10-24, when superseded dependency and design instructions were removed from the active specification. These notes were current at their dates; every ruling they record is folded into the body.

    2026-10-03 triage: source verified at main 1d1fcc72a7e06352e8b5ee020b3910864babc5db; the proposed bridge mutation differs from the read-only activity precedent, and no future authority is inferred from a chat turn. Added the owning area: ui-server, security, wanted-unscheduled priority and explicit unresolved decision; native parent/blockers remain.

    2026-10-04 maintainer execution reconciliation: selected Execution A on #912/#913 and folded the single Queue execution branch into this brief. Independent cron/core-runner execution and interim migration are rejected; production enablement still waits for #689. Authority, budgets, timing/recovery, delivery and store/consumer contracts remain unresolved; preserve needs: decision, existing blockers and any design need, without readiness or a release commitment.

    2026-10-04 maintainer authority reconciliation: selected Authority A on #912/#913, including explicit operator approval of the recurring operation/tool/input/target/egress envelope, immutable scope with current revocation/expiry checks, authentic creator provenance and durable Action/checkpoint/unwind for additional needs. Folded that ruling into this brief and required negative/continuation controls where applicable. Budgets, timing/recovery, delivery and store/consumer contracts remain open; preserve needs: decision, blockers and any design need without readiness, enablement or a release commitment.

    2026-10-04 maintainer budget reconciliation: selected Budget A on #912/#913, including 10-minute host deadlines per admitted attempt, three model-bearing operations per occurrence across retry/yield/compaction/continuation/new Queue items, persistent counters, shared configured daily autonomous caps and conservative accounting/unwind. This does not enable admission or promise a provider invoice ceiling. Timing/recovery, delivery and store/consumer contracts remain open; preserve needs: decision, blockers and design needs without readiness or a release commitment.

    2026-10-04 maintainer timing reconciliation: selected Timing A on #912/#913 including latest/single catch-up within 24 hours, one outstanding occurrence/no overlap, original-due 24-hour freshness including human wait, future/unstarted-only schedule cancellation with distinct live-stop behavior, unknown-effect investigation and explicit/client/UTC zone, future offset one-off and skip-gap/first-fold-once DST rules. Folded these policies into the brief; delivery and store/consumer contracts remain open. Preserve needs: decision, blockers/design needs and #689 without readiness, enablement or a release commitment.

    2026-10-04 maintainer delivery reconciliation: selected Delivery A on #912/#913: per-schedule success alerts opt-in, authenticated Activity/schedule results, existing failure/stuck/Actions/completion paths, origin autonomous plus occurrence correlation, generic minimized push and existing suppression/retry/permission honesty. No unsolicited Chat insertion/new service is approved. The final authoritative definition-store/CLI boundary remains open; preserve needs: decision, blockers/design needs and #689 without readiness, enablement or a release commitment.

    2026-10-04 maintainer final storage reconciliation: selected Store B on #912/#913: root-contained Markdown definitions plus the existing UI approval/runtime ledger, canonical approved-fingerprint validation, durable file/DB compensation, one authenticated host-backed CLI/chat/PWA path, read-only due, idempotent retained create/cancel history and coordinated Git/operational restore. All six policy questions are settled; removed needs: decision. Keep actual record/implementation/design/proof dependencies without claiming completed work, production enablement or a release commitment.

    2026-10-04 #913 technical reconciliation: the six settled policies now have a concrete record and planned-only contract draft. Corrected stale command/origin/provenance wording where applicable; no implementation, enabled dispatch, runtime/system proof, design approval or release commitment is inferred. Dependencies remain until verified delivery.

    Current record delivery and dependency state — 2026-10-04

    #913 is complete: #980 merged as 38f3c10a3947b9b00574cc9123a0e64d1a1022ed, with thirteen executed current-head/live-base Depot checks, matching squash parent/tested tree/main ancestry and all twelve automatic main-push jobs verified. The durable record and future consumer contracts supply the selected specification. These are design/contract preparation, not shipped schedule commands or enabled execution.

    Only the #913 record prerequisite is cleared. The #914 output is delivered; implement the selected authenticated backend-neutral creation path with all original authority/schema/negative controls.

    Earlier dated reconciliation notes record policy selection and dependency state at that time. The delivery state above supersedes their pending-record language; the original implementation scope and acceptance criteria are unchanged.

    Updated 2026-10-12: removed completed blocker declarations, retained delivered-output context and all remaining prerequisites; readiness and existing rulings preserved.

    Updated 2026-10-12: completed the active scheduling-specification correction: #689 is delivered proof and #1595 owns activation; historical rulings and approved schedule semantics remain intact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-readyContext and acceptance criteria are complete enough for an agent to take this unattended.area: backendsAgentBackend implementations and the seam they share.area: ui-sdkWire protocol, runtime schemas, the server and client SDK surfaces.area: ui-serverHono app factory: turn coordinator, auth, session catalog, routes, cron.contractTouches the integration contract: CONTRACT: commit, contract doc updated in the same commit.priority: p2Wanted, not scheduled. Pulled in when a milestone has room.securityAuth, isolation, egress, secrets, or anything in the threat model.type: featA new capability or a change in user-visible behaviour.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions