diff --git a/nanobot/agent/tools/cron.py b/nanobot/agent/tools/cron.py index fe1dce6..d360b14 100644 --- a/nanobot/agent/tools/cron.py +++ b/nanobot/agent/tools/cron.py @@ -14,12 +14,17 @@ class CronTool(Tool): self._cron = cron_service self._channel = "" self._chat_id = "" + self._in_cron_context = False def set_context(self, channel: str, chat_id: str) -> None: """Set the current session context for delivery.""" self._channel = channel self._chat_id = chat_id + def set_cron_context(self, active: bool) -> None: + """Mark whether the tool is executing inside a cron job callback.""" + self._in_cron_context = active + @property def name(self) -> str: return "cron" @@ -72,6 +77,8 @@ class CronTool(Tool): **kwargs: Any, ) -> str: if action == "add": + if self._in_cron_context: + return "Error: cannot schedule new jobs from within a cron job execution" return self._add_job(message, every_seconds, cron_expr, tz, at) elif action == "list": return self._list_jobs() diff --git a/nanobot/cli/commands.py b/nanobot/cli/commands.py index 2662e9f..42c0c2d 100644 --- a/nanobot/cli/commands.py +++ b/nanobot/cli/commands.py @@ -296,6 +296,7 @@ def gateway( # Set cron callback (needs agent) async def on_cron_job(job: CronJob) -> str | None: """Execute a cron job through the agent.""" + from nanobot.agent.tools.cron import CronTool from nanobot.agent.tools.message import MessageTool reminder_note = ( "[Scheduled Task] Timer finished.\n\n" @@ -303,12 +304,20 @@ def gateway( f"Scheduled instruction: {job.payload.message}" ) - response = await agent.process_direct( - reminder_note, - session_key=f"cron:{job.id}", - channel=job.payload.channel or "cli", - chat_id=job.payload.to or "direct", - ) + # Prevent the agent from scheduling new cron jobs during execution + cron_tool = agent.tools.get("cron") + if isinstance(cron_tool, CronTool): + cron_tool.set_cron_context(True) + try: + response = await agent.process_direct( + reminder_note, + session_key=f"cron:{job.id}", + channel=job.payload.channel or "cli", + chat_id=job.payload.to or "direct", + ) + finally: + if isinstance(cron_tool, CronTool): + cron_tool.set_cron_context(False) message_tool = agent.tools.get("message") if isinstance(message_tool, MessageTool) and message_tool._sent_in_turn: