#14659·AutoGPT

Experts: let a template ship scheduled routines, and let the first turn enable them

Author: ntindleCreated Sep 17, 2026Updated Sep 17, 2026

Problem

A roster template can declare exactly one kind of scheduled work: a preload, which is {slug, cron} pointing at a published marketplace graph (seed.py:45). If no graph exists for the job, the job cannot ship.

That is the wrong shape for most standing work. Converting the two muse-made-bots packages behind #14636 surfaced 21 routines — 8 for Casey, 13 for Max — that are all "read a source, compute state, stage a draft, stay quiet if there's nothing, dedupe against the last run". None of them needed a graph. All 21 became prose, because prose is the only slot a template has.

The visible damage: day_one rows advertised real clock times copied from the source crons ("Weekdays 9:00 AM", "Daily 8:30 AM + 1 PM") with nothing scheduled behind them. A user hires Casey, reads that her queue gets swept every weekday morning, and nothing ever fires. Those timings were stripped for honesty in 52ec2eff25, which fixed the lie but not the gap — the profile now promises less than the expert could actually do.

What already exists (this is mostly wiring, not new machinery)

  • schedule_followup fires a copilot turn on a 5-field cron in the user's timezone. It is not in TOOL_GROUPS, so no group gate hides it — it is already live in expert sessions.
  • CopilotTurnJobArgs (executor/scheduler.py:1503) already persists expert_id, cron and session_id on one job. Per its own comment: None on session_id mints a fresh chat at fire time, and "a non-null value pins the followup to an existing session owned by the same user and in the persisted persona scope." Recurring + pinned is legal today; nothing rejects the combination.
  • The fire path fails closed when the expert was archived between scheduling and firing.
  • manage_schedules is already scoped: "Personal AutoPilot manages every schedule on the account; an expert only its own"session.expert_id is None or job.expert_id == session.expert_id.

So an expert can already set one of these up in conversation. What it cannot do is arrive with one.

Proposal — routines on RosterEntry

A third list beside bundled_skills and preloads:

class RoutineSeed(TypedDict):
    title: str
    cron: str      # 5-field, evaluated in the user's timezone
    prompt: str    # the routine body: what the turn should do
    pinned: bool   # reuse one thread, or a fresh chat per fire

Materialized at hire alongside _install_preloads, building the same CopilotTurnJobArgs that schedule_followup already builds. Two properties it must inherit:

  1. Off until switched on. The source packages are explicit — "routines stay off until you switch them on" — and a cadence that fires unattended from the day of hire is a much bigger promise than a skill.
  2. The same review gate as preloads. seed.py:51 already warns that a cadence may only carry work that acts on nothing outside the platform, and that "the marketplace reviewer is that gate; nothing here enforces it." A seeded routine is a prompt rather than a reviewed graph, so this needs a real answer, not an inherited comment.

Let the first turn set them up

kickoff_turn_disabled_tools() refuses every tool except expert_onboarding on a hire's first turn. That is the one moment designed for establishing how the expert will work, and it is the moment the expert cannot offer or enable a routine — it has to wait for turn two, by which point the user has moved on.

The first run should be able to schedule and enable these. Either relax the kickoff block for the scheduling tools specifically, or let the expert_onboarding card carry the offer and act on the answer.

Normal experts need to know this exists

Independent of seeding, three small fixes:

  1. The tool description contradicts the system prompt. prompting.py:226 gets it right — delay_seconds for one-shot, cron for recurring, session_id orthogonal. schedule_followup's own docstring and parameter description pair recurring↔fresh-chat and pinned↔one-shot ("this is the right value for 'remind me here in 20 minutes'", and null is "for recurring morning brief / daily digest patterns"). The model sees both. Make the tool text match the prompt.
  2. <expert_identity> never mentions standing work. It covers identity, voice, boundaries, protected rules and the first turn. Nothing tells an expert that proposing a recurring routine in its own domain is part of the job, so generic "remind me" guidance never becomes "shall I sweep your queue every weekday?".
  3. list_schedules should be reachable and obvious from an expert session so the user can see what a hire actually set up.

Open questions

  • pinned default interacts with a flag. Flag.GRAPHITI_MEMORY defaults to False and is_feature_enabled returns the default when LaunchDarkly is unreachable. With memory off, a fresh-chat routine has no idea it ran yesterday — no dedupe, no "third time this week", which is exactly what the source routines' dedupe logs exist to prevent. With memory off the pinned thread is the memory. Either pin by default, or have a seeded routine declare its memory dependency.
  • A pinned thread grows forever. A daily brief on one session accumulates history and re-reads it every fire. Wants a compaction or windowing story before it becomes the default.
  • Timezone. Preload crons already resolve in the user's timezone; routines should do the same, and the source packages defer timezone to install time ("Ask the importing user for: timezone") rather than baking it.

Why it's worth doing

Today an expert's answer to "what will you do for me unattended" is entirely its preload list, which is capped by what happens to be published in the marketplace. Casey ships two preloads, neither of which is on the nine-item menu her own onboarding skill offers. With routines, the 21 converted routines become real, day_one can name times that are true, and the next machine-built expert stops losing its standing work in translation.

Generated with Claude Code

Source: Significant-Gravitas/AutoGPT