From ca742909cd50739786d6cdcc2f1688295d1380a9 Mon Sep 17 00:00:00 2001 From: "kindralai[bot]" Date: Sun, 19 Jul 2026 10:36:36 +0000 Subject: [PATCH] fix: clear scheduled job context before each invocation (#301) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recurring jobs accumulate conversation history across invocations — each run appends to the same context key, causing growing token costs, cache misses, and degraded relevance. Send a /new command to clear the job's context key before each invocation, in both run_agent_task() and run_subagent_task(). The respond=True parameter is required because respond=False would just record the command as an inbound message without processing it; the 'Conversation cleared.' response is discarded since the caller doesn't deliver it. Note: the issue suggested respond=False, but the _process_impl respond-gate returns early before reaching the /new handler when respond is False. Closes #301 --- humux/core/scheduler.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/humux/core/scheduler.py b/humux/core/scheduler.py index 289c8bbe..c1244fe8 100644 --- a/humux/core/scheduler.py +++ b/humux/core/scheduler.py @@ -74,6 +74,21 @@ async def run_agent_task( "only." ) + # Clear previous context for recurring jobs (#301): each invocation starts fresh + # so history doesn't accumulate across runs (growing token costs, cache misses, + # degraded relevance). The /new command clears session/injection history alike; + # respond=True is required (respond=False would just record the command as an + # inbound message without processing it). The "Conversation cleared." response + # is discarded — we only care about the side effect. + if job_id: + await agent.process( + message="/new", + channel="system", + user_id="scheduler", + chat_id=f"scheduler:{job_id}", + respond=True, + ) + log.info("Scheduler running agent task: %s", task[:100]) # A "telegram:" job is generated AS that agent (#29) so the bot # that delivers it also writes it — while keeping the "system" execution mode @@ -163,6 +178,16 @@ async def run_subagent_task( f"scheduler:{job_id}" if (job_id and not origin_user_id) else (origin_user_id or owner or "scheduler") ) + # Clear previous context for recurring subagent jobs (#301): same rationale + # as run_agent_task — each invocation starts with a clean slate. + if job_id: + await agent.process( + message="/new", + channel="system", + user_id=str(_ctx_user), + chat_id=str(_ctx_chat), + respond=True, + ) result = await agent.run_subagent( task=task, agent_name=agent_name or "",