{"slug": "model-a-sales-reminder-as-a-state-machine-not-a-prompt", "title": "Model a Sales Reminder as a State Machine, Not a Prompt", "summary": "Tej Pandya, founder of GrowEasy.ai, published a design sketch arguing that sales reminder agents should be modeled as explicit state machines rather than relying on conversation history as the record of what an agent owes. The sketch stores appointment revision, confirmed time, consent state, contact route and reminder status, invalidates pending work tied to older revisions, and treats refusal or revoked consent as stop conditions. Pandya recommends re-checking eligibility before sending, using idempotency keys for retried side effects, and testing cancellation, duplicate webhooks and lost responses against resulting records rather than the agent's wording.", "body_md": "By Tej Pandya, founder of GrowEasy.ai\n\nA reminder agent needs somewhere to store what it owes. If the only record is the conversation, developers cannot reliably tell whether an action was planned, attempted or completed.\n\nThis example is a design sketch for an appointment-led sales workflow. It is not a deployed customer result or a GrowEasy.ai feature claim.\n\nStore an appointment revision, confirmed time, consent state, contact route and reminder status. A change to the appointment should invalidate pending work tied to an older revision.\n\nThe model can extract a proposed time from a message. Application logic validates it before updating the record. Unknown consent stays unknown; it is not filled from the model's confidence.\n\nAn illustrative transition sketch:\n\n``` php\nrequested -> confirmed -> reminder_eligible -> attempted\nattempted -> delivered | retryable_error | permanent_error\nretryable_error -> reconciled | retry_pending | needs_human\nneeds_human -> assigned -> accepted -> completed\n```\n\nThese states are not a universal standard. Choose them around the real work and the provider's actual receipts. Do not interpret \"delivered\" as \"attended\".\n\nWhen a request times out, it may already have succeeded. Look up the provider result or reuse a supported idempotency key before repeating the side effect.\n\nA key might identify the appointment revision and reminder type. It must not suppress a genuinely new reminder after the buyer changes the appointment.\n\nTemporal's documentation recommends idempotent Activities because retry behavior can repeat execution. Durable state and safe side effects solve different problems; you need both.\n\nBefore a reminder sends, re-check current appointment state, consent, permitted time and destination. A job that was eligible when queued may no longer be eligible when it runs.\n\nTreat refusal and revoked consent as stop conditions. Distinguish temporary transport errors from permanent failures. A retry budget is an application decision, not something the model should improvise indefinitely.\n\nAn exception record needs a question, current evidence, requested time and owner. Assignment is not acceptance. An overdue unaccepted task should remain visible to the team.\n\nDo not tell the buyer that a callback is confirmed if the application only emitted a notification. Gate that sentence on the state that proves a responsible person and valid time exist.\n\nTest a cancellation after queueing, duplicate webhook delivery, two workers claiming the same job, a provider success followed by a lost response, an unavailable owner and an explicit request for a person.\n\nCheck the resulting records and external actions, not only the agent's wording. Compare the design with a simpler deterministic baseline. Anthropic's workflow guidance is useful here: add model-driven flexibility where it is needed rather than turning every predictable step into an autonomous decision.\n\nA clean state machine cannot fix bad rules. It can make those rules, and their failures, visible enough to test.\n\nSources:\n\n[https://www.anthropic.com/engineering/building-effective-agents](https://www.anthropic.com/engineering/building-effective-agents)\n\n[https://docs.temporal.io/activity-definition](https://docs.temporal.io/activity-definition)\n\n[https://temporal.io/blog/idempotency-and-durable-execution](https://temporal.io/blog/idempotency-and-durable-execution)", "url": "https://wpnews.pro/news/model-a-sales-reminder-as-a-state-machine-not-a-prompt", "canonical_source": "https://dev.to/tej_pandya_a973bc2256ba93/model-a-sales-reminder-as-a-state-machine-not-a-prompt-5ck8", "published_at": "2026-10-10 12:39:13+00:00", "updated_at": "2026-10-10 12:46:12.670568+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "artificial-intelligence", "large-language-models"], "entities": ["Tej Pandya", "GrowEasy.ai", "Temporal", "Anthropic"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/model-a-sales-reminder-as-a-state-machine-not-a-prompt", "markdown": "https://wpnews.pro/news/model-a-sales-reminder-as-a-state-machine-not-a-prompt.md", "text": "https://wpnews.pro/news/model-a-sales-reminder-as-a-state-machine-not-a-prompt.txt", "jsonld": "https://wpnews.pro/news/model-a-sales-reminder-as-a-state-machine-not-a-prompt.jsonld"}}