Agents are more useful when they do not wait for you to type. LangChain's Managed Deep Agents now supports background scheduling: declare a cron expression in a file, deploy, and your agent runs on a schedule inside LangSmith.
This guide walks through the documented format, the strict rules that trip people up, how state works across runs, and a reliability checklist. It builds on our earlier coverage of LangChain Deep Agents 0.7 and how teams score production agent traces with LangSmith.
TL;DR
| Question | Answer |
|---|---|
| What is new? | Cron-style schedules for Managed Deep Agents |
| Where are they defined? | schedules/ directory, one file per schedule |
| Schedule name? | The filename |
| Function? | define_schedule from managed_deepagents |
| Cron format? | Standard five-field cron; no seconds |
| Timezone? | Optional; defaults to UTC |
| Payload? | Exactly one of prompt or input |
| State? | Ephemeral thread by default; persistent thread optional |
| Deploy? | mda deploy; schedules are provisioned as LangSmith crons |
| Test? | Schedules do not run under mda dev |
| Availability | Public beta; LangSmith Cloud, US region only |
The minimal example
From LangChain's documentation:
from managed_deepagents import define_schedule
schedule = define_schedule(
cron="0 8 * * 1-5",
timezone="America/Los_Angeles",
prompt="Write the daily digest.",
)
Save it as, for example, schedules/daily_digest.py. The file name becomes the managed schedule name. This schedule fires at 08:00, Monday through Friday, Pacific time, and sends "Write the daily digest." to the agent as a user message.
Project layout
my-agent/
agent.py # your Deep Agent definition
schedules/
daily_digest.py # one schedule per file
weekly_review.py
One schedule per file keeps changes reviewable: a pull request that adds weekly_review.py is a pull request that adds a job. Removing a file and redeploying removes the corresponding managed cron, according to the docs.
Parameters
| Parameter | Required | Meaning |
|---|---|---|
cron | Yes | Five-field cron: minute, hour, day of month, month, day of week |
timezone | No | IANA timezone name; defaults to UTC |
prompt | One of prompt or input | Text sent as a user message |
input | One of prompt or input | Structured LangGraph input data |
thread | No | Ephemeral by default; {"mode": "persistent", "id": "<thread-uuid>"} for durable state |
deliver_to | No | Routes results to Slack via channel ID |
Use prompt for natural-language jobs and input when your agent expects structured fields. Never provide both.
Cron cheat sheet
Standard five-field cron. Seconds-based syntax is invalid.
| Expression | Meaning |
|---|---|
0 8 * * 1-5 | 08:00 every weekday |
*/15 * * * * | Every 15 minutes |
0 9 * * 1 | 09:00 every Monday |
30 6 1 * * | 06:30 on the first day of each month |
0 0 * * 0 | Midnight every Sunday |
Set timezone explicitly for anything human-facing. UTC by default means "8 AM" may arrive at a different local hour, and daylight saving changes can surprise you when you leave timezone unspecified.
The rule that will trip you up: static declarations only
The docs are strict: "Use literals, lists, dictionaries, and references to top-level literal constants. Do not read environment variables, call functions, use **kwargs, or compute schedule values dynamically."
That means the platform reads your schedule file without executing arbitrary code, which makes deployment predictable and safe, but also means you cannot do this:
# Not allowed: computed value and environment lookup
import os
schedule = define_schedule(
cron=os.environ["DIGEST_CRON"],
prompt=build_prompt(),
)
Instead:
# Allowed: literals and top-level literal constants
DIGEST_PROMPT = "Write the daily digest."
schedule = define_schedule(
cron="0 8 * * 1-5",
timezone="America/Los_Angeles",
prompt=DIGEST_PROMPT,
)
If you need dynamic behavior, put it inside the agent: let the agent read configuration or fetch data at run time, and keep the schedule file as a fixed trigger.
State across runs: ephemeral vs persistent threads
By default each scheduled run uses an ephemeral thread: it starts fresh, does its work and leaves no conversational memory for the next run. That is right for stateless jobs like "summarize yesterday's tickets."
For jobs that should remember, such as a weekly report that compares against last week, use a persistent thread:
schedule = define_schedule(
cron="0 9 * * 1",
timezone="America/New_York",
prompt="Prepare the weekly review and compare with last week.",
thread={"mode": "persistent", "id": "<thread-uuid>"},
)
Two cautions from the docs. The persistent thread must be created manually in LangSmith Studio before you deploy. And a thread that grows forever will grow context; plan for summarization or periodic rotation, as we discuss in harness engineering concepts.
Deploying and testing
Deploy with mda deploy. When you add, change or remove schedules, run it without --no-wait so the CLI can reconcile schedules once the deployment reaches DEPLOYED status. The CLI provisions each schedule as a LangSmith cron after the deployment is live.
Test carefully: schedules never execute under mda dev. To check behavior:
- Invoke the agent directly in LangSmith Studio with the same prompt or input.
- Deploy to a non-production environment and set a near-term cron, such as a few minutes ahead.
- Confirm the run appears in traces, the output is correct and any delivery (such as Slack) works.
Because scheduled runs are unattended, trace review matters more than usual. Pair schedules with production trace scoring and the evaluation tooling in LangChain's Jev agent evals benchmark.
Reliability checklist for scheduled agents
Design
- Make jobs idempotent. If a run happens twice or is retried, the result should not duplicate emails or tickets.
- Give each job a narrow purpose. One schedule, one outcome.
- Write an explicit finish line in the prompt: what artifact must exist when done.
- Add a stop rule: if data is missing, report and stop instead of improvising.
Safety
- Use least-privilege tools. A scheduled agent should not hold credentials it does not need.
- Keep write actions behind approval when stakes are high. Unattended does not mean unsupervised.
- Treat inputs as untrusted. If the job reads email or web content, prompt injection is possible; see indirect prompt injection.
Operations
- Alert on failures and empty outputs.
- Set budgets. A misconfigured
*/1cron with a large model is an expensive mistake. Check spending after the first week. - Log schedule changes in code review. They are production changes.
- Watch beta limits. Public beta and US-only availability may affect data residency requirements.
Writing a good scheduled prompt
Unattended prompts fail in different ways from interactive ones, so write them like a runbook.
Role: You prepare the weekday engineering digest.
Inputs: Use your connected tools to read tickets closed since the last business day.
Output: A digest with three sections (Shipped, Blocked, Needs decision), each item one line with a link.
Rules: If a tool call fails twice, stop and report which source failed. Never invent items.
Finish line: The digest is written and, if delivery is configured, posted once.
Four habits make this work. State the inputs the agent may use. Define the output shape so downstream readers can rely on it. Add failure rules so an outage produces a clear report instead of a confident guess. Give a finish line so the run ends.
Common mistakes
- Testing with
mda devand concluding it is broken. Schedules never run there. - Forgetting the timezone. A 08:00 UTC job arrives at 01:00 in Los Angeles.
- Using
*/1in production. Every minute is rarely what you meant. - Dynamic values in the schedule file. Computed or environment-based values are not allowed.
- Persistent thread not created. The thread must exist in LangSmith Studio before deployment.
- Deploying with
--no-waitafter schedule changes. The CLI needs to reconcile once the deployment reachesDEPLOYED. - No owner. Every schedule should have a named owner who reads the alerts.
Use cases that fit
- Daily digest of support tickets, PRs or metrics.
- Weekly review that compares against previous state on a persistent thread.
- Monitoring agents that check dashboards and report anomalies.
- Data hygiene jobs like deduplicating records.
- Research briefs that collect new papers or news in a topic.
For non-LangChain equivalents, see how Claude Code loops and Cursor loops handle recurring work, how goal mode gives agents completion conditions, and how Cursor's event-driven cloud agents wake on signals instead of clocks. Schedules are the simplest trigger: time. Events are the smartest: something happened.
What people are asking
"Can I schedule more than one job?" Yes. One file per schedule, each with its own name.
"Can the schedule use my secrets?" Not in the schedule file. Keep secrets in the agent's configured environment and tools.
"Is this GA?" No. It is public beta, on LangSmith Cloud in the US region only.
"How do I stop a job?" Delete its file and redeploy without --no-wait.
Bottom line
Scheduling turns a Deep Agent from something you talk to into something that works while you sleep. The format is simple and strict: one file per schedule, static declarations, five-field cron, deploy to activate. Test outside mda dev, design for idempotence, and review traces early.
Details reflect LangChain's documentation as of September 24, 2026. Managed Deep Agents is in public beta and syntax may change.
Related reading
- LangChain Deep Agents 0.7: a leaner harness
- LangSmith Jev: score production agent traces
- LangChain Jev agent evals benchmark
- How to run loops in Claude Code
- Goal mode for AI agents: complete guide
- Cursor event-driven cloud agents
- Top 10 harness engineering concepts
- Official: Add schedules to Managed Deep Agents
