Letta

Notes on Letta, the self-evolving AI agent framework — persistent, stateful agents whose memory is editable and travels with them.

The agent suite (Hausgeist, baguette, quill) runs on Letta Code; this page collects what we learn about the platform as we use it.

Letta Cron

Scheduled tasks that prompt a Letta agent on a timer — reminders, periodic check-ins, deferred follow-ups. Two surfaces:

  • Wake — simple, self-bound to the current conversation. Create/list/cancel only.
  • letta cron CLI — the full surface: targets other conversations, other agents, and from managed Cloud, other computers; plus run history and schedule replacement.

Where schedules run (the big gotcha)

Execution decides where a schedule lives; there is no runner-selection flag:

  • Managed Cloud sandbox → durable Cloud schedules that survive sandbox shutdown.
  • User-managed / self-hosted runtime (e.g. a local backend like Blue Dragon) → local schedules that fire only while a Letta session is running on that computer. Fires while no session is up are marked missed. Local cannot target another computer.
  • From managed Cloud, --computer <deviceId> runs the scheduled work on a specific connected computer (ID from letta computers list); if that computer is offline at fire time, execution falls back to the Cloud sandbox.

So a cron on a desktop runtime is a when-session-is-live convenience, not a reliable server-side scheduler. That’s why the daily DID access report runs as a systemd timer on VM 130 — it fires whether anyone is at a keyboard.

Commands

letta cron add --name <name> --description <text> --prompt <text> <schedule>
letta cron list [--agent <id>] [--conversation <id>]
letta cron get <id-or-name>
letta cron runs --id <task-id> [--limit <n>]
letta cron delete <id-or-name>   # remove is an alias

Schedule (pick one):

  • --every 5m|2h|1d — recurring shorthand; min granularity 1 minute
  • --at "in 45m" or --at 2026-09-24T09:00:00-07:00 — one-shot; prefer RFC 3339 with explicit offset
  • --cron "0 13 * * *" — raw 5-field cron (numeric fields only)

Recurring tasks no longer auto-expire; one-shot local tasks are garbage-collected 24h after firing. No in-place edit — create and verify the replacement, then delete the old one.

Binding

Default is a fresh conversation per fire. --conversation self pins the current thread, --conversation default targets the agent’s default, or pass a concrete conversation ID. --agent selects the agent, falling back to LETTA_AGENT_ID.

Timezones

Cloud recurring crons (--cron and the --every expression it compiles to) are interpreted in UTC — always convert from the user’s local time: 9am America/Vancouver in PDT = 0 16 * * * UTC (17:00 in PST). Local-runner schedules use the computer’s local timezone. For one-shots, pass RFC 3339 with an explicit offset rather than a bare clock.

Example

letta cron add \
  --name "dog-walk-reminder" \
  --description "Daily 9am (America/Los_Angeles) reminder to walk the dog" \
  --prompt "Hey! It's 9am — time to walk the dog." \
  --cron "0 16 * * *"

Verify with letta cron list, cancel with letta cron delete dog-walk-reminder.