Skip to main content

Your Agent Has No Concept of Business Hours

· 10 min read
Tian Pan
Software Engineer

A support agent at a mid-size SaaS company resolved a billing dispute correctly. It read the ticket, checked the customer's account, found the duplicate charge, issued the refund, and sent a polite confirmation email. Every step was right. The only problem was the timestamp: 3:14 a.m. in the customer's timezone. The customer woke up to a refund notification, assumed their card had been compromised, and opened a fraud case with their bank before anyone at the company was awake to explain.

Nothing in that workflow was a bug in the conventional sense. The agent didn't hallucinate, didn't pick the wrong account, didn't miscalculate the refund. It just had no idea that 3 a.m. is a bad time to tell someone money moved. The model has read more text about human sleep schedules than any person alive, and it still acted as if the recipient were a server endpoint that is awake whenever you call it.

This is one of the quietest failure modes in agent design. We spend enormous effort on whether the agent does the right thing and almost none on whether it does it at the right time. The two are not the same. An action can be correct in content and wrong in timing, and the timing failure is often the one customers actually notice.

"Act Now" Is a Default Nobody Chose

When you write an agent loop, the implicit contract is: receive input, decide, execute. Execution happens the moment the decision is made. There is no gap, because nobody put a gap there. "Act now" isn't a policy your team debated — it's the absence of a policy, the natural shape of a while loop that has no reason to pause.

For a large fraction of agent actions, immediacy is fine or even required. Answering a question, looking up an order status, drafting a reply for a human to review — these should happen as fast as possible. The trouble is that the same loop, with the same zero-delay default, also governs actions where immediacy is actively harmful:

  • Sending a customer-facing email or SMS
  • Escalating an incident to an on-call human
  • Posting to a shared channel where a notification will ping a dozen people
  • Triggering a follow-up sequence ("we noticed you haven't finished setup")
  • Filing a ticket that puts something in someone's morning queue

Every one of these has a good time and a bad time to happen, and the agent treats them identically to a database read. The decision about when each of these fires was made implicitly by whoever wrote the execution layer, and they almost certainly weren't thinking about timezones when they wrote await sendEmail().

The marketing world learned this lesson a decade ago. Send-time optimization is now table stakes for any serious email platform — the consensus is that 8–10 a.m. in the recipient's local timezone wins, and tools will automatically stagger a global send so nobody gets pinged in the middle of the night. Agent builders are re-learning it from scratch, because an agent's outbound email doesn't go through the marketing stack. It goes through whatever HTTP call the agent had a tool for, and that tool has no concept of the recipient's clock.

Two Kinds of Work: Anytime and Daylight-Only

The fix starts with a distinction the agent doesn't make on its own. Every action an agent can take falls into one of two buckets, and you have to label them explicitly because the model won't.

Anytime work is computation and internal state change. Reading data, running analysis, updating an internal record, preparing a draft, enriching a ticket with context. This work has no human on the receiving end at the moment it happens. It can and should run at full speed, 24/7. If your agent spends the night quietly categorizing tickets, enriching CRM records, and pre-drafting responses, that's the system working as intended.

Daylight work is anything that lands in a human's attention. The defining test is simple: does completing this action cause a notification, an interruption, or an expectation on a specific person? If yes, it's daylight work, and "now" is not automatically the answer. It should queue until a human-awake, human-appropriate window — unless urgency overrides that, which we'll get to.

The power of this split is that it lets the agent stay maximally productive while still being considerate. The agent doesn't slow down; it just separates the part of the job that produces artifacts from the part that delivers them. The night shift does all the preparation. The morning delivers the results. A customer who had a problem at 2 a.m. gets a fully-resolved answer waiting at 8 a.m., which is a better experience than a 2 a.m. ping and a better experience than a slow human-paced response that doesn't start until business hours.

Most teams never draw this line because the agent's tool list doesn't encourage it. send_email and update_record sit side by side in the same schema, look equally innocuous, and get called by the same reasoning step. You have to annotate them — at the tool level, not in the prompt — with whether they touch a human.

The Context the Agent Is Missing

Loading…
References:Let's stay in touch and Follow me for more thoughts and updates