DEV Community

CodeKing
CodeKing

Posted on

"My AI Assistant Stopped Working the Moment I Closed the Chat"

A lot of AI assistants only feel helpful while the chat window is still open.

You ask for something, watch it think, maybe answer one follow-up, and then you leave.

That is the moment the illusion breaks.

If the assistant cannot wake itself up later, run something in the background, and only come back to you when it actually needs you, it is not much of an assistant. It is just a chat box with good manners.

That was one of the more practical lessons while building CliGate, my local AI control plane for a resident assistant, scheduled work, channels, Claude Code, Codex, and model routing behind one localhost service.

The real bug was requiring the user to babysit the assistant

The old mental model was too chat-shaped.

A user message arrived. The assistant did some work. The answer came back into the same visible thread.

That works for interactive tasks, but it falls apart for the boring real ones:

  • send me a morning summary
  • publish a post tonight
  • check something while I am offline
  • keep going later and ping me only if you get stuck

In other words, the assistant needed a way to work without pretending the user was still sitting there.

A reminder was not enough

The first naive version of scheduled work is just:

at 8 PM -> send message
Enter fullscreen mode Exit fullscreen mode

That is fine for "drink water" reminders.

It is useless for anything that needs actual reasoning or tools.

What I wanted instead was:

at 8 PM -> wake the assistant with an instruction
-> let it run in the background
-> send me the result
-> if it needs input, route my reply back into that paused run
Enter fullscreen mode Exit fullscreen mode

That sounds small, but it changes what a scheduled task really is. It stops being a timer and starts being a delayed assistant run.

The assistant needed its own hidden workspace for each fire

One subtle bug showed up fast.

If every recurring run reused the same hidden conversation forever, the assistant started treating later fires like duplicates.

That is especially bad for recurring work. A scheduled publishing task should not say "already done" just because a previous run earlier that day used the same scope and saw similar history.

So I ended up separating two modes:

  • fresh context by default for recurring work
  • shared context only when explicitly useful

That means a recurring task can wake the assistant in its own background scope conversation, without polluting the user's visible chat and without inheriting the wrong assumptions from the last run.

In CliGate, that also made the scheduling model much easier to trust: each fire can be a clean round, while things like a running diary can still opt into shared context.

The tricky part was not starting the run. It was pausing honestly.

Background runs do not always finish cleanly.

Sometimes the assistant needs the user.

Maybe a credential is missing. Maybe a choice matters. Maybe a risky action needs confirmation.

If that happens inside a hidden scheduled-task scope, the run cannot just hang there forever.

So the assistant needed a bridge back to the user-facing conversation.

The model that finally felt right was:

  • scheduled run happens in a hidden scope conversation
  • visible conversations only get notifications
  • if the run pauses on the user, remember which scheduled task is waiting
  • when the user replies in the visible conversation, route that reply back to the paused background run

That was the difference between "background automation" and "a silent dead end."

The UI had to explain the tradeoff clearly

One thing I like about this setup is that the user-facing choice is simple.

A scheduled task can either:

  • notify user with a static message, or
  • invoke assistant with a real instruction

And when invoking the assistant, two more controls matter a lot:

  • optional working directory
  • whether runs share context or start fresh

That is enough surface area to be useful without turning scheduling into a mini workflow engine.

Most people do not want cron trivia. They want to say:

  • every morning, summarize this project
  • tonight, publish the draft
  • every weekday, check this thing and message me if it failed

That is the level an assistant should operate at.

The result was a more believable assistant

The biggest win was not technical elegance.

It was behavioral honesty.

The assistant no longer had to pretend every task was a live chat exchange.

Now it can:

  • wake up later
  • run unattended
  • keep background work out of the main conversation
  • push a result back when it is done
  • ask for help only when it actually needs help
  • continue from the user's reply instead of losing the thread

That made CliGate feel a lot less like "chat with extra steps" and a lot more like an actual local operator.

If you are building AI assistants, this is the line I would not blur: a scheduled reminder is not the same thing as a scheduled assistant run, and users feel the difference immediately.

Top comments (0)