From deae147795d1166d51d6ff14fa55c55c0563a576 Mon Sep 17 00:00:00 2001 From: PeninsulaInd Date: Tue, 17 Feb 2026 16:38:11 -0600 Subject: [PATCH] Hide clickup_task_id from LLM tool schema to prevent hallucination MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed clickup_task_id from write_press_releases function signature so the LLM cannot see or fabricate a task ID. The parameter is now passed through ctx by the ToolRegistry — the scheduler sets it in args, and execute() moves it into the ctx dict before filtering. Only system-injected task IDs can reach the tool. Co-Authored-By: Claude Opus 4.6 --- cheddahbot/tools/__init__.py | 6 +++++- cheddahbot/tools/press_release.py | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/cheddahbot/tools/__init__.py b/cheddahbot/tools/__init__.py index c1dd3f6..3aa90be 100644 --- a/cheddahbot/tools/__init__.py +++ b/cheddahbot/tools/__init__.py @@ -152,13 +152,17 @@ class ToolRegistry: # Inject context if the function expects it sig = inspect.signature(tool_def.func) if "ctx" in sig.parameters: - args["ctx"] = { + ctx = { "config": self.config, "db": self.db, "agent": self.agent, "memory": self.agent._memory, "agent_registry": self.agent_registry, } + # Pass scheduler-injected metadata through ctx (not LLM-visible) + if "clickup_task_id" in args: + ctx["clickup_task_id"] = args.pop("clickup_task_id") + args["ctx"] = ctx # Filter args to only params the function accepts (plus **kwargs) has_var_keyword = any( diff --git a/cheddahbot/tools/press_release.py b/cheddahbot/tools/press_release.py index 48ccc39..f57b68f 100644 --- a/cheddahbot/tools/press_release.py +++ b/cheddahbot/tools/press_release.py @@ -403,7 +403,6 @@ def write_press_releases( url: str = "", lsi_terms: str = "", required_phrase: str = "", - clickup_task_id: str = "", ctx: dict | None = None, ) -> str: """Run the full press-release pipeline and return results + cost summary.""" @@ -412,6 +411,9 @@ def write_press_releases( agent = ctx["agent"] + # clickup_task_id is injected via ctx by the ToolRegistry (never from LLM) + clickup_task_id = ctx.get("clickup_task_id", "") + # ── ClickUp: set "in progress" and post starting comment ──────────── cu_client = None if clickup_task_id: