A cron can trigger anything. A daily job could read the queue, call the language model, and post the result to LinkedIn. Zero friction, zero delay, zero human latency between generate and publish.
We chose not to build that.
Instead, every draft the marketing agent writes lands in Telegram as an inert message with two inline-keyboard buttons: ✅ Publish and ❌ Reject. Only Alaa's tap sends the final POST to the platform API. If she's offline, nothing ships.
This is not a beta guardrail we'll remove later. It's a permanent architectural choice, and the reason is simple: you can't recall tone.
Last week the agent drafted a LinkedIn post celebrating a Ghalia milestone. The facts were correct—booking link, client count, testimonial. But the phrasing felt slightly off for that day's context: a client had privately shared tough family news, and while unrelated to the post topic, the timing would have felt insensitive.
A cron would have published at 09:00 UTC. The inline keyboard let Alaa delay until the afternoon, reframe one line, and ship when it made sense.
The model generates. The human decides. We hard-code that boundary into the tool set itself—no `publish_now()` function exists in the agent's schema. The only write operation is `submit_draft`, which resolves to a Telegram message.
This means slower publishing. It also means we've never had to issue a retraction.