
Prepping meals is fun. Planning meals is not. But not planning meals is even worse, and scrambling to cook chicken nuggets or waiting for takeout to be delivered leads to a grumpy, not exactly well-fed family. When I'm organized I create a weekly meal plan, get everything delivered ahead of time and know exactly what we'll be eating each night. However that planning takes an annoying amount of time and focus.
I decided there are better things to do with my time. So I did what any reasonable person would do: I automated it.
I could have just used Claude manually and added ingredients by hand. But I wanted something that ran itself every Saturday without me remembering. That's where Prefect came in.
I chose it because it lets me schedule and run code remotely without managing servers or dealing with infrastructure. The pythonic interface meant I could write normal Python (just decorators and functions) without wrestling with YAML configs or visual workflows. Prefect gives me built-in observability so I can see exactly what happened at each step. Retries happen automatically with exponential backoff, so when Claude times out or the MCP server hiccups, the workflow just recovers on its own.
What sealed it for me was how naturally it handles dynamic workflows. If the user provides feedback, I just write a normal Python if statement to regenerate and re-post to Slack. It's not special or complicated. It's just code. I added Pydantic Logfire on top to see deeper into what Claude is actually doing: token usage, API latency, user behavior patterns. Between Prefect's monitoring and Logfire's tracing, I have real visibility into whether this system is working.
The workflow breaks into tasks: parse natural language dietary preferences into JSON, call Claude to generate two meals under 20 minutes with ingredient overlap, post to Slack, wait for approval/feedback, optionally regenerate, then add ingredients to Todoist via the hosted MCP server. I used Claude Code to generate the initial structure, then tuned the prompts.
Prefect's task decorators made this straightforward to build:
1@task(
2 name="parse_preferences",
3 retries=2,
4 retry_delay_seconds=10,
5 persist_result=True,
6)
7async def parse_preferences_task(preferences_text: str) -> DietaryPreferences:
8 """Parse dietary preferences from natural language."""
9 with logfire.span("task:parse_preferences"):
10 return await parse_dietary_preferences(preferences_text)For the Claude integration, I wrapped Pydantic AI agents with PrefectAgent for durable execution with automatic retries:
1# Wrap with PrefectAgent for durable execution
2prefect_agent = PrefectAgent(
3 agent,
4 model_task_config=TaskConfig(
5 retries=2,
6 retry_delay_seconds=[10.0, 20.0],
7 timeout_seconds=60.0,
8 ),
9)
10The feedback handling is just normal Python. No special workflow syntax needed:
1# Check approval status
2if approval_input.approved:
3 approval_received = True
4 logfire.info("Meal plan approved")
5
6elif approval_input.regenerate and approval_input.feedback:
7 # User provided feedback, regenerate
8 feedback_text = approval_input.feedback
9 regeneration_count += 1
10 logfire.info("Regenerating meal plan with feedback",
11 feedback=feedback_text)The key prompts are straightforward. One parses preferences: "vegetarian, no mushrooms, Mediterranean flavors, quick stir-fries" becomes structured JSON. Another generates meals: given those preferences, create two different recipes that share 4-6 ingredients to reduce shopping list friction. The Prefect flow orchestrates these tasks, handles retries if Claude times out, and manages the state persistence around the approval gate. I scheduled it to run Saturday at 5 PM using Prefect Cloud's managed execution.
Then I hit a problem. My flow was failing silently somewhere in the middle of execution. Normally, I'd copy the error logs, paste them into Claude Code, ask for help debugging, then copy the fix back to my repository. That context-switching was annoying.
Instead, I opened an issue in GitHub, assigned it to a Copilot agent, and gave it access to both my code and my Prefect Cloud workspace. It debugged the problem and fixed it without me leaving GitHub.
When I hit issues with the Todoist integration, I used the Prefect MCP to help debug. I deployed the Prefect MCP server to FastMCP Cloud for remote access:
Then I added the MCP server to my GitHub Copilot configuration:
1{
2 "mcpServers": {
3 "magnificent-alligator": {
4 "type": "http",
5 "url": "https://magnificent-alligator.fastmcp.app/mcp",
6 "headers": {
7 "Authorization": "Bearer $COPILOT_MCP_FASTMCP"
8 },
9 "tools": ["*"]
10 }
11 }
12}
13The authorization token is passed as an environment variable, keeping credentials secure. Now Copilot can query my Prefect Cloud workspace directly.
Instead of manually chasing logs, I opened a GitHub issue and assigned it to a Copilot agent with this description: "The meal planning flow is failing. Investigate the latest run and fix the issue."
Copilot had access to:
It queried the flow run logs directly using the MCP tools and found the problem immediately: I was using snake_case for a variable name (meal_preferences) in one part of the code, but referencing it with kebab-case (meal-preferences) elsewhere. This mismatch was causing the workflow to fail when trying to pass data between tasks. The MCP helped me identify this by reading my flow run logs directly. It also helped me draft parts of the core flow logic initially, which saved me from having to switch back and forth to the docs while learning Prefect-specific elements like variable handling.
The key difference here was that I didn't have to copy logs, switch to Claude Code, paste them, wait for a response, then copy the fix back. The agent read the logs directly from my system and knew exactly what was wrong.
Copilot suggested updating the variable name to use snake_case consistently throughout. It created a pull request with the fix. I merged it, and the flow ran successfully on the next scheduled run.
This was a small debugging task, but it showed me something important: having an AI agent with direct access to your actual system state is much more useful than having it work blind with copied logs and context. Copilot could have guessed at what was wrong. Instead, it read the actual logs from the failed flow run and could see exactly what the problem was.
The real value was eliminating the context-switching. No more copying from Prefect Cloud, pasting into Claude Code, copying the fix back. The agent just lived in GitHub, read my system state directly, and solved the problem there.
I'm planning a few improvements. First, integrate AnyList instead of Todoist for ingredients. AnyList connects directly to online grocery delivery services, so approved meals flow straight into my shopping workflow without manual copying. Second, use a recipe MCP tool to give Claude access to a broader recipe database and real-time ingredient availability. Third, set up a second schedule for my husband so he can plan his weeks too, running Friday evenings so we can coordinate around each other's preferences.
The code is on GitHub. If you're dealing with similar cognitive load around routine tasks, automation might be worth the effort. Not necessarily to save time, but to reclaim mental space for things that actually matter.








