fix: hide memory tool from cron agents
Cron agents are constructed with skip_memory=True, so the memory backend is not initialised — exposing the memory tool only gives the model an unbacked tool that fails at runtime with 'Memory is not available.' Add 'memory' to _resolve_cron_disabled_toolsets() so the tool is stripped from the schema before the model can call it. Fixes #38129. Co-authored-by: Paolo Shamoon <Paolo@Dylans-Mac-Studio.local>
This commit is contained in:
parent
ca120413fc
commit
03dc4aad52
|
|
@ -165,17 +165,19 @@ class CronPromptInjectionBlocked(Exception):
|
|||
def _resolve_cron_disabled_toolsets(cfg: dict) -> list[str]:
|
||||
"""Toolsets a cron-spawned agent must never receive.
|
||||
|
||||
Three protected toolsets are always disabled in cron context:
|
||||
Four protected toolsets are always disabled in cron context:
|
||||
- ``cronjob`` — would let a cron-spawned agent schedule more cron jobs
|
||||
- ``messaging`` — interactive, needs a live gateway session
|
||||
- ``clarify`` — interactive, blocks waiting for user input
|
||||
- ``memory`` — cron agents are constructed with ``skip_memory=True``, so
|
||||
exposing this tool only gives the model an unbacked tool that fails
|
||||
|
||||
User-level ``agent.disabled_toolsets`` from config.yaml is layered on top
|
||||
so per-job ``enabled_toolsets`` cannot bypass policy that applies to
|
||||
ordinary agent runs (#25752 — LLM-supplied enabled_toolsets was widening
|
||||
past config.yaml's denylist).
|
||||
"""
|
||||
disabled = ["cronjob", "messaging", "clarify"]
|
||||
disabled = ["cronjob", "messaging", "clarify", "memory"]
|
||||
agent_cfg = (cfg or {}).get("agent") or {}
|
||||
user_disabled = agent_cfg.get("disabled_toolsets") or []
|
||||
for name in user_disabled:
|
||||
|
|
|
|||
|
|
@ -533,6 +533,49 @@ class TestRunJobSessionPersistence:
|
|||
yield fake_db, mock_agent_cls
|
||||
|
||||
|
||||
def test_run_job_memory_toolset_disabled_in_cron(self, tmp_path):
|
||||
"""memory toolset must be disabled in cron sessions — issue #38129.
|
||||
|
||||
Cron agents are constructed with skip_memory=True, so the memory
|
||||
backend is not initialised. Exposing the memory tool only gives the
|
||||
model an unbacked tool that fails at runtime with
|
||||
"Memory is not available." Hiding it from the schema prevents that.
|
||||
"""
|
||||
job = {
|
||||
"id": "memory-hide-job",
|
||||
"name": "test",
|
||||
"prompt": "hello",
|
||||
}
|
||||
with self._run_job_patches(tmp_path) as (fake_db, mock_agent_cls):
|
||||
run_job(job)
|
||||
|
||||
kwargs = mock_agent_cls.call_args.kwargs
|
||||
assert "memory" in (kwargs["disabled_toolsets"] or []), (
|
||||
"memory toolset should be disabled in cron to match skip_memory=True"
|
||||
)
|
||||
|
||||
def test_run_job_disables_memory_even_when_per_job_enables_it(self, tmp_path):
|
||||
"""Cron runs pass skip_memory=True, so memory must not be exposed.
|
||||
|
||||
A cron job can request the memory tool through enabled_toolsets, but
|
||||
there is no MemoryStore injected for cron agents. Keep memory in the
|
||||
disabled set so AIAgent filters the unbacked tool out before the model
|
||||
can call it and receive "Memory is not available" failures.
|
||||
"""
|
||||
job = {
|
||||
"id": "memory-toolset-job",
|
||||
"name": "test",
|
||||
"prompt": "remember what you learn",
|
||||
"enabled_toolsets": ["memory", "file"],
|
||||
}
|
||||
with self._run_job_patches(tmp_path) as (fake_db, mock_agent_cls):
|
||||
run_job(job)
|
||||
|
||||
kwargs = mock_agent_cls.call_args.kwargs
|
||||
assert kwargs["skip_memory"] is True
|
||||
assert kwargs["enabled_toolsets"] == ["memory", "file"]
|
||||
assert "memory" in kwargs["disabled_toolsets"]
|
||||
|
||||
def test_tick_skips_due_jobs_while_dispatch_is_paused(self, tmp_path):
|
||||
"""The drain gate runs before advancing a due job's schedule."""
|
||||
from cron.scheduler import tick
|
||||
|
|
|
|||
Loading…
Reference in New Issue