A scheduled deployment fires a fresh session on a cron cadence — the agent runs without you. Each firing can carry its own outcome, nesting the bounded grade→iterate loop inside every recurring run.
See ../../references/loops-and-workflows.md.
| Answer | Shape | Tool |
|---|---|---|
| "every morning / weekly / nightly" | recurring cron deployment | deployment_builder.py + cron_validator.py |
| "when X happens" | event-driven curl (documented, not scheduled) | deployment_builder.py (message only) |
| "only when I ask" | on-demand (no deployment) | none — just re-send a user.message |
python3 scripts/cron_validator.py --cron "0 9 * * *" --timezone Europe/Berlin
Invalid cron/timezone → exit 1. Read the DST note: wall-clock semantics mean
spring-forward times are skipped and fall-back times fire twice — avoid
02:00–03:00 in DST zones if exactly-once matters.python3 scripts/deployment_builder.py \
--sheet ./my-agent/build-sheet.json --agent-id agent_123 --env-id env_456 \
--nest-outcome --out ./my-agent/payloads/deployment.json
--nest-outcome includes the rubric so each firing self-grades. The tool
prints the BYOK curl to create it and to test it once with the manual run
endpoint before trusting the schedule.run, read the verdict, only then
leave the cron in place. Pin the agent version in the deployment once it passes.python3 scripts/next_directions_writer.py \
--sheet ./my-agent/build-sheet.json --loop-shape cron-loop --last-verdict satisfied --out-dir ./my-agent
goal_state.py set --phase wrap-up, then invoke
the wrap-up skill.run first. Never commit a schedule you haven't fired once.always_ask MCP, limited networking where you
can, read_only untrusted memory, max_iterations per firing, workspace spend
limit. There is no spend cap inside CMA.scripts/deployment_builder.py — POST /v1/deployments payload (+ test-run curl).scripts/cron_validator.py — 5-field cron + IANA tz + DST note.scripts/next_directions_writer.py — write/refresh NEXT-DIRECTIONS.md.