nanoclaw
Agent-to-messaging bridge. Connects Claude Code agents to WhatsApp/Telegram/Discord groups, with scheduled task execution.
Goals
Make the Claude Code agent reachable from a phone — so that sending a WhatsApp message kicks off a pipeline run, receives a response, or sets a reminder — without building or hosting any of the messaging infrastructure ourselves.
Effectiveness
Works. This entire conversation is running through nanoclaw. Message delivery is reliable; scheduled tasks fire on time; the send_message tool lets the agent push updates mid-run rather than waiting until the end. The group registration and multi-channel model (WhatsApp, Telegram, Discord under one interface) is clean.
What made it effective
send_messageduring execution is the key feature. Long-running tasks (podcast pipeline, inertia mill) can acknowledge the request immediately and send results when done, rather than making the user wait in silence for minutes.schedule_taskwith cron or interval expressions covers both recurring jobs (nightly inertia mill) and one-time reminders without requiring any external scheduler.context_mode: "isolated"vs"group"is a useful distinction — pipeline runs don't need chat history; follow-ups do. This prevents unnecessary context bloat on automated tasks.- Group registration via
register_groupwith a trigger word means multiple groups can be served by the same agent, each with its own conversation history.
Bonus utility
The list_tasks / pause_task / resume_task / cancel_task tools make the scheduler inspectable and controllable from within the same conversation. No separate admin interface needed.
Friction / pain points / surprises
send_message is the only way to communicate with teammates. Plain text output from a sub-agent is not visible to the team lead or other agents. Easy to forget — a sub-agent can produce extensive reasoning and all of it disappears unless it explicitly calls send_message. Required re-reading the skill documentation to understand the messaging model.
once schedule timestamps must omit the Z suffix. Pass a local time without UTC marker. Passing a UTC timestamp silently schedules at the wrong time. The documentation says this but it's easy to reach for ISO format by habit.
No visibility into whether a scheduled task's last run succeeded or failed. list_tasks shows the task exists and its next run time; it doesn't show the outcome of the previous run. Diagnosing a task that "ran but did nothing" requires reading the task's output file directly.