Self-Scheduled Follow-ups

Self-Scheduled Follow-ups (schedule_followup)

schedule_followup is a built-in tool that lets an agent, mid-task, schedule a continuation of its own work — in the same session, carrying the context it needs to resume. It is pre-injected into every LLM agent automatically; there is no YAML flag to enable it.

Use it when an agent decides "I need to come back to this" — a data source that isn't ready yet, a submission it should verify later, or a long task it wants to checkpoint and continue in a fresh turn.

What it does

When an agent calls schedule_followup, LeafMesh writes a durable follow-up record to the configured persistence backend (Redis or Postgres) and, when the time arrives, wakes the target agent again in the same session. The resumed turn receives the reason and context the agent supplied, plus the session's existing state, prior yields, and conversation history — so it continues as if the work never paused.

Parameters

ParameterTypeDefaultDescription
reasonstring*(required)*Why the follow-up exists and what to do on resume. Shown to the woken agent and to operators.
contextobject{}Compact JSON the resumed turn needs (partial findings, ids, next step). Size-capped at 16 KB.
targetstring"self"Which agent to wake. "self", or another agent name in the caller's can_call set.
whenstring"now""now" (immediate fresh turn), a relative delay ("+30m", "+2h", "+1d"), or an absolute ISO-8601 UTC time ("2026-07-18T09:00Z").
dedup_keystring*(none)*Idempotency key — a second schedule with the same key while one is still pending is a no-op.

Returns { followup_id, when, fires_at, session_id, target }.

Timing

  • now — the continuation runs immediately as a fresh turn in the same session.
  • Deferred (+30m, ISO time) — the record sits durably until due; the scheduler fires it at the right time, exactly once, even across restarts or multiple workers. Absolute times are UTC.

Guardrails (built-in defaults, tunable, never required)

GuardrailDefaultPer-agent override
Chain depth (continuations of continuations)5max_followup_depth
Follow-ups per session20max_followups_per_session
context payload size16 KBLEAFMESH_FOLLOWUP_CONTEXT_MAX_KB (env)
Allowed targetsself + can_call setschedule_targets

An agent may only target itself or an agent in its can_call set. The manager may schedule a follow-up on behalf of an agent that left work unfinished, but never for itself, and never a duplicate when one is already pending for that agent.

Operator inbox

Pending and past follow-ups are visible and controllable through the API:

MethodEndpointPurpose
GET/api/followups?session_id=<id>List pending follow-ups for a session
GET/api/followups/{followup_id}?session_id=<id>One record (any status)
DELETE/api/followups/{followup_id}?session_id=<id>Cancel a not-yet-fired follow-up

A follow-up record carries followup_id, from_agent, target, reason, context, when, fires_at, and status (scheduled, fired, cancelled, or dropped). If a session expires before its follow-up fires, the follow-up is dropped and logged rather than waking a dead session.

Example

# Inside a researcher agent that hit a rate-limited source:
schedule_followup(
    reason="Re-check the census API — rate-limited until ~09:00, need the 2025 table",
    context={"source_url": "https://…/census/2025", "next_step": "merge 2025 table into the draft"},
    when="+30m",
)
# → { "followup_id": "fu:…", "fires_at": "2026-07-18T09:00:00+00:00", "target": "researcher_agent" }

Thirty minutes later the researcher runs again, in the same session, with the reason and context in front of it and its earlier findings still available.

Relationship to wake_up

wake_up is a declarative cron the YAML author writes ahead of time (a fixed schedule). schedule_followup is imperative — the agent decides at runtime that it needs to return to a task. They complement each other and use independent machinery.

Always available — and how to turn it off

The tool reaches the model on every LLM turn, whether or not the agent declares structured yields — an agent mid-contract can still decide to come back later. Opting a specific agent out is one config line:

agents: formatter_agent: name: "formatter_agent" schedule_followup: false # this agent never self-schedules

Studio and the Playground both expose this as the Self-scheduling toggle.

Last updated: 11/10/2026