Skip to content

feat(scheduler): per-task model preset override#1462

Open
SinisterMinister wants to merge 7 commits intoagent0ai:mainfrom
SinisterMinister:feature/scheduler-per-task-model
Open

feat(scheduler): per-task model preset override#1462
SinisterMinister wants to merge 7 commits intoagent0ai:mainfrom
SinisterMinister:feature/scheduler-per-task-model

Conversation

@SinisterMinister
Copy link
Copy Markdown

Summary

Adds a per-task model preset override to the Task Scheduler, allowing each scheduled, ad-hoc, or planned task to run with a specific model preset instead of always using the global default.

Changes

Backend

  • helpers/task_scheduler.py — adds model: str | None field to BaseTask; update method uses an ellipsis sentinel so None is a valid explicit value; serialization/deserialization includes the field; applies chat_model_override on the agent context before running a task
  • api/scheduler_task_create.py — reads optional model from the create payload and sets it on the new task
  • api/scheduler_task_update.py — reads optional model from the update payload (empty string → None)
  • tools/scheduler.py — passes model kwarg through all three task creation helpers (create_scheduled_task, create_adhoc_task, create_planned_task)

Frontend

  • webui/components/modals/scheduler/scheduler-store.js — adds model to the default editing-task shape and to composeEditingTask / buildPayloadFromEditingTask; fetches available model presets from the _model_config plugin on store init
  • webui/components/modals/scheduler/scheduler-task-editor.html — adds a Model Preset <select> dropdown to both the scheduled and ad-hoc/planned task editor panels, populated from the fetched presets

Behaviour

  • If a task has no model set (the default), it runs with the global model — no change from current behaviour
  • If a model preset is selected, the scheduler sets chat_model_override on the task's agent context before calling monologue(), overriding the model for that run only
  • The dropdown shows — Global default — as the first option and lists all configured presets below it
  • The selected preset name is persisted with the task and survives restarts

Testing

  • Created a scheduled task with a non-default model preset; confirmed the correct model was used during execution
  • Edited the task back to "Global default"; confirmed the override was cleared
  • Verified the dropdown correctly restores the saved value when re-opening the editor

SinisterMinister and others added 7 commits April 5, 2026 18:56
Allows specifying a model preset (e.g. Haiku, Cost Efficient) on
individual scheduled, ad-hoc, and planned tasks. When set, the
chat model override is applied to the task agent context before
the monologue runs, keeping utility/embedding models unchanged.

Changes:
- BaseTask: add optional model field (preset name string)
- _run_task_wrapper: apply chat_model_override before monologue
- serialize/deserialize: include model field
- scheduler_task_create API: accept model param
- scheduler_task_update API: accept model param
- scheduler tool: all create methods accept model kwarg
- scheduler-store.js: fetch presets, include model in payload
- scheduler-task-editor.html: add Model Preset dropdown to forms
- Normalize model field from null to empty string in composeEditingTask
  so it correctly matches the empty <option value=''> in the select
- Add :selected binding to each option in x-for so Alpine.js correctly
  reflects the saved model value even if x-model evaluates before
  x-for options are rendered (Alpine rendering order race condition)
…enders

Alpine.js evaluates x-model on <select> before x-for creates the dynamic
<option> elements. Even with correct editingTask.model, no matching option
exists in DOM yet so the select falls back to global default.

Adding x-effect with  defers the value assignment until AFTER
Alpine finishes rendering all child elements, at which point the x-for
options exist and .value correctly selects the saved preset.
fetchModelPresets was calling /model_presets which doesn't exist.
Plugin API endpoints follow the path /plugins/<plugin>/<handler>.
Correct URL is /plugins/_model_config/model_presets.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant