fix(policies): load Windows-generated ToolGuard modules - #14374
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThe PR adds a ToolGuard module-path compatibility helper, applies it during lazy loading, tests Windows separator normalization, and updates the embedded component asset metadata. ChangesToolGuard compatibility
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 9✅ Passed checks (9 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Test Coverage AdvisorNo source changes detected without accompanying tests. Thanks for keeping coverage up! 🎉
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lfx/src/lfx/components/models_and_agents/policies/module_utils.py`:
- Around line 21-33: Update the converter compatibility check in
_import_toolguard so both “policies.guard” and the known legacy forward-slash
result are treated as supported and leave the existing converter unchanged. Only
install the local file_to_module_name fallback when neither result matches, and
broaden the converter exception handling to catch unsupported or unexpected
exceptions without aborting _import_toolguard().
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 48bab9da-77bc-4fe0-850c-8cc168b69982
📒 Files selected for processing (4)
src/backend/tests/unit/components/models_and_agents/policies/test_policies_component.pysrc/lfx/src/lfx/_assets/component_index.jsonsrc/lfx/src/lfx/components/models_and_agents/policies/module_utils.pysrc/lfx/src/lfx/components/models_and_agents/policies_component.py
| probe = r"policies\guard.py" | ||
| try: | ||
| if converter(probe) == "policies.guard": | ||
| return | ||
| except (TypeError, ValueError): | ||
| # A future ToolGuard may change the private helper's contract. In that | ||
| # case, do not replace behavior we no longer understand. | ||
| return | ||
|
|
||
| def file_to_module_name(file_path: str | Path) -> str: | ||
| return str(file_path).removesuffix(".py").replace("\\", ".").replace("/", ".") | ||
|
|
||
| runtime_module.__dict__["_file_to_module_name"] = file_to_module_name |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
uv run python - <<'PY'
from pathlib import Path
import toolguard.runtime.runtime as runtime
converter = runtime._file_to_module_name
for value in ("policies/guard.py", r"policies\guard.py", Path("policies/guard.py")):
try:
print(repr(value), "->", repr(converter(value)))
except Exception as exc:
print(repr(value), "raised", type(exc).__name__, str(exc))
PYRepository: langflow-ai/langflow
Length of output: 198
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Repository files around toolguard/runtime:"
git ls-files | rg '(^|/)runtime\.py$|toolguard|guard\.py|module_utils\.py' | head -200
echo
echo "Candidate module_utils.py:"
file="$(git ls-files | rg '(^|/)module_utils\.py$' | grep 'lfx/components/models_and_agents/policies/module_utils.py' || true)"
if [ -n "${file:-}" ]; then
wc -l "$file"
sed -n '1,120p' "$file" | cat -n
fi
echo
echo "Search for ensure_toolguard_module_path_compat and _file_to_module_name:"
rg -n "ensure_toolguard_module_path_compat|_file_to_module_name|ToolGuard|toolguard" . --glob '!**/.git/**' | head -300Repository: langflow-ai/langflow
Length of output: 50376
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import urllib.request
from urllib.parse import quote
import tarfile
from io import BytesIO
url = "https://files.pythonhosted.org/packages/1b/12/e78f303f2c306de58bb72c21a58b19f3dd4bb45aae2a5b6a61717255cae8ba7/toolguard-0.2.21.tar.gz"
print("Downloading", url)
with urllib.request.urlopen(url, timeout=30) as r:
data = r.read()
print("Downloaded", len(data), "bytes")
with tarfile.open(fileobj=BytesIO(data), mode="r:gz") as tf:
names = [name for name in tf.getnames() if name.endswith("/runtime.py") or name.endswith("/runtime/__init__.py")]
print("runtime files:", names)
for name in names:
print("\n---", name, "---")
text = tf.extractfile(name).read().decode("utf-8", errors="replace")
for i, line in enumerate(text.splitlines(), 1):
if "_file_to_module_name" in line or "FileTwin" in line or "normalize" in line.lower():
lo=max(1,i-8); hi=min(len(text.splitlines()),i+12)
lines=text.splitlines()
for j in range(lo,hi+1):
print(f"{j:4d}\t{lines[j-1]}")
print()
PY
python3 - <<'PY'
import urllib.request
import tempfile
import os
def ensure_path_imports(path):
parent = os.path.dirname(os.path.abspath(path))
if parent not in __import__("sys").path:
__import__("sys").path.insert(0, parent)
return lambda: __import__("sys").path.remove(parent)
return lambda: None
if not os.path.exists("/tmp/toolguard-0.2.21"):
import urllib.request, tarfile
url = "https://files.pythonhosted.org/packages/1b/12/e78f303f2c306de58bb72c21a58b19f3dd4bb45aae2a5b6a61717255cae8ba7/toolguard-0.2.21.tar.gz"
with urllib.request.urlopen(url, timeout=30) as r:
data = r.read()
with tempfile.NamedTemporaryFile(delete=False, suffix=".tar.gz") as f:
f.write(data)
tmp = f.name
tarfile.open(tmp, "r:gz").extractall("/tmp/toolguard-0.2.21")
os.unlink(tmp)
import sys, types
sys.modules.pop("toolguard", None)
for k in list(sys.modules):
if k.startswith("toolguard"):
del sys.modules[k]
unregister = ensure_path_imports("/tmp/toolguard-0.2.21/toolguard-0.2.21")
import toolguard.runtime
print("runtime module file:", getattr(toolguard.runtime, "__file__", None))
print("has runtime._file_to_module_name:", hasattr(toolguard.runtime.runtime, "_file_to_module_name"))
if hasattr(toolguard.runtime.runtime, "_file_to_module_name"):
converter = toolguard.runtime.runtime._file_to_module_name
for path in ("policies/guard.py", r"policies\guard.py"):
print(path, "->", repr(converter(path)))
import pathlib
try:
print(repr(pathlib.Path("policies/guard.py")), "->", repr(converter(pathlib.Path("policies/guard.py"))))
except Exception as exc:
print(repr(pathlib.Path("policies/guard.py")), "raised", type(exc).__name__, str(exc))
else:
candidate = None
import inspect
for name in dir(toolguard.runtime.runtime):
obj = getattr(toolguard.runtime.runtime, name)
if callable(obj) and "_file_to_module_name" in (getattr(obj, "__qualname__", "") or ""):
print(name)
try:
print(inspect.getsource(obj))
except Exception as exc:
print("source_error", exc)
unregister()
PY
python3 - <<'PY'
from pathlib import Path
def converter(path):
return str(path).removesuffix(".py").replace("\\", ".")
print("legacy converter:")
for value in ("policies/guard.py", r"policies\guard.py"):
try:
print(repr(value), "->", repr(converter(value)))
except Exception as exc:
print(repr(value), "raised", type(exc).__name__, str(exc))
current = "policies.guard" # installed ToolGuard result to patch on
def patched(file_path: str | Path) -> str:
return str(file_path).removesuffix(".py").replace("\\", ".").replace("/", ".")
print("if current is patched:")
for value in ("policies/guard.py", r"policies\guard.py", Path("policies/guard.py")):
try:
print(repr(value), "->", repr(patched(value)))
except Exception as exc:
print(repr(value), "raised", type(exc).__name__, str(exc))
PYRepository: langflow-ai/langflow
Length of output: 2590
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import urllib.request
import tarfile
import tempfile
import os
import pathlib
url = "https://files.pythonhosted.org/packages/1b/12/e78f303f2c306de58bb72c21a58b19f3dd4bb45aae2a5b6a61717255cae8ba7/toolguard-0.2.21.tar.gz"
print("Downloading", url)
unpin_ssl = __import__("urllib3.util.ssl_")
try:
unpin_ssl.create_urllib3_context = lambda ciphers=None: None
except Exception:
pass
with urllib.request.urlopen(url, timeout=30, context=pathlib.Path("/tmp")._accessor._ssl_context if hasattr(pathlib.Path("/tmp")._accessor, "_ssl_context") else None) as r:
data = r.read()
print("Downloaded", len(data), "bytes")
with tempfile.TemporaryDirectory() as td:
with tarfile.open(fileobj=bytes(data), mode="r:gz") as tf:
tf.extractall(td, filter="data")
tg = pathlib.Path(td)
for root, _, files in os.walk(tg):
if "runtime.py" in files or "guard.py" in files:
p = pathlib.Path(root, files[0])
print("\n---", p, "---")
text = p.read_text(encoding="utf-8", errors="replace").splitlines()
for i, line in enumerate(text, 1):
if "_file_to_module_name" in line or "FileTwin" in line or "normalize" in line.lower():
lo=max(1,i-8); hi=min(len(text),i+12)
for j in range(lo, hi+1):
print(f"{j:4d}\t{text[j-1]}")
print()
# Local import from extracted source.
sys = __import__("sys")
venv_py = next((p / "bin" / "python" if (p / "bin" / "python").exists() else p / "python3") for p in tg.glob("*/"))
print("venv python:", venv_py)
PYRepository: langflow-ai/langflow
Length of output: 424
🌐 Web query:
pypi toolguard 0.2.21 runtime.py _file_to_module_name
💡 Result:
The package toolguard (version 0.2.21) on PyPI is a tool designed for policy adherence and guarding AI agent tools [1][2]. It analyzes policy documents to generate deterministic Python code that enforces operational constraints during tool invocation [1][3]. Regarding the specific reference to runtime.py and _file_to_module_name, historical records of the AgentToolkit/toolguard repository indicate that the internal structure of the library has undergone modifications related to how modules are loaded and mapped from file paths [4]. Previously, the library contained utility functions such as load_module_from_path, which handled file-to-module transformations [4]. However, development activity—specifically commit e4237bf—shows a transition toward using importlib and custom path-to-module logic (e.g., path_to_module) rather than the earlier implementation patterns that may have included functions named _file_to_module_name [4]. It is important to distinguish this package (AgentToolkit/toolguard) from another project on PyPI named py-toolguard, which is an unrelated project focused on security interception and fuzzing for AI agents [5][6][7]. The two projects are distinct in scope, ownership, and functionality [1][5].
Citations:
- 1: https://pypi.org/project/toolguard/0.2.21/
- 2: https://pypistats.org/packages/toolguard
- 3: https://pypi.org/project/toolguard/0.2.20/
- 4: AgentToolkit/toolguard@e4237bf
- 5: https://pypi.org/project/py-toolguard/
- 6: https://github.com/Harshit-J004/toolguard
- 7: https://pypi.org/project/py-toolguard/6.1.1/
🌐 Web query:
AgentToolkit/toolguard e4237bf runtime _file_to_module_name
💡 Result:
The term _file_to_module_name is not a documented function or component within the AgentToolkit/toolguard project [1][2][3]. The repository AgentToolkit/toolguard is a tool for generating deterministic Python code to enforce operational policies on AI agent tools, featuring toolguard.buildtime and toolguard.runtime modules [1][3]. While the query references e4237bf, this appears to be a git commit hash [4]. Research indicates this specific hash does not correspond to a version or artifact within the AgentToolkit/toolguard repository, which uses different commit patterns and release versioning (e.g., ece4a29 for version 0.2.13) [5][6]. The identifier file_to_module_name is commonly found in Python metaprogramming and dynamic module loading utilities (such as in external projects unrelated to toolguard like auger) to map file system paths to Python module names [7]. It is not a standard part of the AgentToolkit/toolguard codebase [1][3].
Citations:
- 1: https://github.com/AgentToolkit/toolguard
- 2: https://github.com/AgentToolkit/toolguard/blob/e44de6d17826baa3228022464dd3d90252fe62df/README.md
- 3: https://github.com/AgentToolkit/toolguard/blob/5340fbe64a241916318c2faafcc2b4c109273e9d/README.md
- 4: https://android.googlesource.com/platform/packages/apps/TV/+/refs/heads/aml_art_341810020%5E1..refs/heads/aml_art_341810020/
- 5: AgentToolkit/toolguard@ece4a29
- 6: AgentToolkit/toolguard@c100e52
- 7: Example throws AttributeError laffra/auger#23
🌐 Web query:
GitHub AgentToolkit/toolguard v0.2.21 runtime.py
💡 Result:
ToolGuard is an open-source library within the AgentToolkit GitHub repository designed to provide deterministic, interpretable policy adherence for AI agents at the tool level [1][2]. Version 0.2.21 of this toolkit was released on June 30, 2026 [3]. The library operates by analyzing policy documents and OpenAPI specifications to generate guard specifications (ToolGuardSpec) and executable Python code [1][4]. These guards are designed to be executed prior to tool invocation to ensure compliance with predefined business rules [1][2]. Within the ToolGuard architecture, the runtime module (found in toolguard/runtime.py) is a core component of the Runtime API [1][2]. Its primary functions include: 1. Runtime Enforcement: Executing pre-tool activation policy constraints before a tool is invoked [2][5]. 2. ToolguardRuntime: Providing the mechanism to execute guards (specifically via methods like guard_toolcall) [1][2]. 3. Error Handling: Raising a PolicyViolationException if a tool invocation violates defined policies [1][2]. 4. Invoker Support: Supporting various invoker types, such as ToolFunctionsInvoker (for Python functions), ToolMethodsInvoker (for class methods), and LangchainToolInvoker (for LangChain tools) [1][2]. To utilize the runtime capabilities, developers typically load generated guards using functions such as load_toolguards and integrate them into their tool invocation workflows via the provided invokers [1][2].
Citations:
- 1: https://github.com/AgentToolkit/toolguard
- 2: https://github.com/AgentToolkit/toolguard/blob/5340fbe64a241916318c2faafcc2b4c109273e9d/README.md
- 3: AgentToolkit/toolguard@e31b21c
- 4: https://github.com/AgentToolkit/toolguard/blob/3fa9563d127da74286b11f3347ed6fcfb0fc89e5/README.md
- 5: https://github.com/AgentToolkit/toolguard/blob/e44de6d17826baa3228022464dd3d90252fe62df/README.md
🌐 Web query:
"toolguard\>=0.2.20" "toolguard" "0.2.21"
💡 Result:
There are multiple distinct software projects and entities identified by the name or a variation of "ToolGuard" as of August 2026. The specific versions "0.2.20" and "0.2.21" refer to a Python package available on PyPI [1]. The package named toolguard on PyPI is a utility focused on policy adherence and code generation for guarding AI agent tools [1]. It provides APIs to: 1. Generate guard specifications from policy text (Buildtime API) [1]. 2. Enforce these operational policies during tool invocation (Runtime API) [1]. It should not be confused with other similarly named projects: - py-toolguard: A separate package (currently v6.1.1) described as a "Cloudflare for AI Agents" that includes a 7-layer security interceptor and observability dashboard [2][3][4][5]. - ToolGuard (toolguard.ai): A security gateway platform for Model Context Protocol (MCP) servers, which isolates secrets and enforces policies at the gateway level [6][7][8]. - Other entities: There are unrelated businesses named "Toolsguard" (a workshop management software) [9] and "TradeGuard" (an insurance/compliance platform) [10]. If you are working with the package that uses version 0.2.21, you are likely using the library for defining and enforcing deterministic Python-based guard specifications for AI tool calls [1].
Citations:
- 1: https://pypi.org/project/toolguard/
- 2: https://pypi.org/project/py-toolguard/
- 3: https://github.com/Harshit-J004/toolguard
- 4: https://pypi.org/project/py-toolguard/6.1.1/
- 5: https://github.com/harshit-j004/toolguard
- 6: https://toolguard.ai/
- 7: https://toolguard.ai/docs/
- 8: https://toolguard.ai/getting-started.html
- 9: https://toolsguard.com
- 10: https://linkedin.com/company/tradeguardins
🌐 Web query:
raw.githubusercontent.com Harshit-J004 toolguard 0.2.21 toolguard/runtime/runtime.py
💡 Result:
ToolGuard is a security and observability framework for AI agents, often described as a "Cloudflare for AI Agents" [1][2]. Developed by Harshit Joshi (GitHub user Harshit-J004), the project provides a 7-layer security interceptor, real-time observability, and automated reliability testing for AI tool chains and Model Context Protocol (MCP) implementations [1][3]. The specific path referenced, toolguard/runtime/runtime.py, is part of the ToolGuard codebase hosted in the Harshit-J004/toolguard repository [1][4]. Key characteristics of ToolGuard as of August 2026: - Architecture: Initially a local Python library [5], it evolved into a distributed, language-agnostic enterprise firewall in version 6.1.0 [6]. This version introduced an HTTP Proxy Sidecar, Redis-based distributed state management, and support for asynchronous webhook-based human-in-the-loop approvals [6]. - Security Features: It implements various protections including semantic analysis, injection prevention, schema drift detection, and identity spoofing detection [6][5]. - Ecosystem: The package is published on PyPI as py-toolguard [2]. Development has focused on enabling agents to operate safely in production environments, specifically addressing challenges like hallucinations, prompt injection, and destructive tool calls [1][2]. - Recent Updates: Version 6.1.1, released in April 2026, focused on hardening concurrency for the proxy by implementing threadpool offloading and improving resilience against network issues in distributed deployments [7]. The project repository is accessible at https://github.com/Harshit-J004/toolguard [1].
Citations:
- 1: https://github.com/Harshit-J004/toolguard
- 2: https://pypi.org/project/py-toolguard/
- 3: https://github.com/Harshit-J004
- 4: https://github.com/harshit-j004/toolguard
- 5: https://github.com/Harshit-J004/toolguard/releases/tag/v6.0.0
- 6: https://github.com/Harshit-J004/toolguard/releases/tag/v6.1.0
- 7: https://github.com/Harshit-J004/toolguard/releases/tag/v6.1.1
🌐 Web query:
raw.githubusercontent.com Harshit-J004 toolguard 0.2.21 runtime runtime.py _file_to_module_name
💡 Result:
The function _file_to_module_name is located in the toolguard.runtime module of the toolguard package (version 0.2.21) [1]. This version of toolguard appears to be part of an earlier codebase (associated with the AgentToolkit/toolguard repository) [2][3], which is distinct from the more recent "Cloudflare for AI Agents" project by Harshit-J004 (which uses the package name py-toolguard and is currently on version 6.1.1) [4][5][6][7]. In the context of toolguard v0.2.21, runtime.py provides the runtime API for executing security guards during tool invocations [1][3]. The _file_to_module_name function is an internal utility used within the runtime framework to map filesystem paths to Python module identifiers for dynamic loading [1][2][3]. Documentation for v0.2.21 highlights the following components of the Runtime API [1][3]: - load_toolguards: Loads generated guards for runtime use. - ToolguardRuntime.guard_toolcall: Executes a guard before tool invocation. - ToolFunctionsInvoker: Invoker for Python functions. - ToolMethodsInvoker: Invoker for class methods. - LangchainToolInvoker: Invoker for LangChain tools. - PolicyViolationException: Exception raised upon policy violation. If you are working with the newer py-toolguard (v6.x.x) by Harshit-J004, note that the library architecture has evolved into a distributed, language-agnostic enterprise firewall [6], and reliance on internal path-to-module mapping functions may differ significantly or be deprecated in favor of its HTTP proxy sidecar and enterprise-grade infrastructure [6][7].
Citations:
- 1: https://pypi.org/project/toolguard/0.2.21/
- 2: AgentToolkit/toolguard@e4237bf
- 3: https://github.com/AgentToolkit/toolguard/blob/5340fbe64a241916318c2faafcc2b4c109273e9d/README.md
- 4: https://github.com/Harshit-J004/toolguard
- 5: https://pypi.org/project/py-toolguard/
- 6: https://github.com/Harshit-J004/toolguard/releases/tag/v6.1.0
- 7: https://github.com/Harshit-J004/toolguard/releases/tag/v6.1.1
🌐 Web query:
site:raw.githubusercontent.com AgentsTool toolguard 0.2.21 _file_to_module_name
💡 Result:
There is no widely recognized technical package or library named "AgentsTool" or "toolguard" version 0.2.21 that provides a function named _file_to_module_name. The term "ToolGuard" appears as a specific class or component within several distinct and unrelated AI agent development projects, such as pydantic-ai-shields [1] and others involved in AI governance or safety [2][3][4]. Similarly, patterns like _file_to_module_name are common internal utility functions in Python for mapping file paths to module structures [5][6][7], but they are not standardized or associated with a single public package under the name "AgentsTool". It is likely that the query refers to: 1. A proprietary, internal, or highly specific custom tool. 2. A misunderstanding or conflation of components from different AI agent frameworks (e.g., OpenAI's agent tools [8][9], Pydantic AI harness [1], or Microsoft's Agent Governance Toolkit [4]). If you are encountering this in a specific codebase, it is recommended to search for the definition of _file_to_module_name within your local project files, as it is likely a local helper function rather than a public API.
Citations:
- 1: https://raw.githubusercontent.com/pydantic/pydantic-ai-harness/main/README.md
- 2: https://raw.githubusercontent.com/hashgraph-online/hol-guard/main/README.md
- 3: https://raw.githubusercontent.com/auraguardhq/aura-guard/main/standalone/aura_guard_standalone.py
- 4: https://raw.githubusercontent.com/microsoft/agent-governance-toolkit/main/README.md
- 5: https://raw.githubusercontent.com/hhatto/autopep8/main/test/inspect_example.py
- 6: https://raw.githubusercontent.com/jtackaberry/rtk/master/tools/luaknit.py
- 7: https://raw.githubusercontent.com/huggingface/transformers/main/src/transformers/models/auto/auto_factory.py
- 8: https://raw.githubusercontent.com/openai/openai-agents-python/main/src/agents/tool.py
- 9: https://raw.githubusercontent.com/openai/openai-agents-python/main/README.md
🌐 Web query:
"https://raw.githubusercontent.com/AgencyNetworkTool/toolguard/0.2.21" "_file_to_module_name"
💡 Result:
In the context of the AgencyNetworkTool/toolguard library (specifically version 0.2.21), _file_to_module_name refers to a utility function used to convert a filesystem path into a valid Python module import string [1]. While the exact implementation of this function has evolved in the codebase [1], its primary purpose is to enable the dynamic loading of Python files as modules. The function typically performs the following logic: 1. It takes a file path (e.g., /path/to/my_tool.py) as input [1]. 2. It strips the file extension and replaces directory separators (such as / or ) with the dot notation required for Python imports (e.g., path.to.my_tool) [1]. 3. This converted string is then passed to Python's importlib.import_module or related import utilities to programmatically load the file's contents for inspection or execution [1]. This mechanism is central to toolguard's ability to analyze and guard AI agent tools by dynamically importing and introspecting function definitions from specified source files [1]. Note that there are multiple projects named toolguard [2][3][4], and this specific functionality is associated with the AgentToolkit/toolguard repository [1][3].
Citations:
- 1: AgentToolkit/toolguard@e4237bf
- 2: https://pypi.org/project/py-toolguard/
- 3: https://github.com/AgentToolkit/toolguard
- 4: https://github.com/Harshit-J004/toolguard
🌐 Web query:
raw.githubusercontent.com AgencyNetworkTool toolguard 0.2.21 _file_to_module_name
💡 Result:
The reference to _file_to_module_name in the context of toolguard 0.2.21 pertains to internal utilities within the AgentToolkit/toolguard library, which is a deterministic tool-level policy enforcement framework for AI agents [1][2][3]. In version 0.2.21, the library's internal code structure included utility functions—often found in modules such as toolguard.utils.py or similar helper files—that managed the mapping of file paths to Python module names for dynamic code loading [4]. Specifically, these helpers are used by the library's buildtime API to load and analyze tool definitions from local Python files [5][4]. While _file_to_module_name was part of the internal implementation to facilitate these imports (often using importlib.util), the codebase has evolved; for example, subsequent commits shifted toward direct usage of importlib.path_to_module or similar standard library patterns to handle file-to-module resolution more robustly [4]. If you are interacting with this library, toolguard is designed to be used via its primary Buildtime and Runtime APIs rather than by calling internal utility functions directly [5][3]. The library generates ToolGuardSpec objects and Python code to enforce operational policies before tool invocation, ensuring agentic actions remain within defined compliance boundaries [1][5].
Citations:
- 1: https://github.com/AgentToolkit/toolguard
- 2: https://github.com/AgentToolkit/toolguard/blob/e44de6d17826baa3228022464dd3d90252fe62df/README.md
- 3: https://pypi.org/project/toolguard/0.2.21/
- 4: AgentToolkit/toolguard@e4237bf
- 5: https://github.com/AgentToolkit/toolguard/blob/5340fbe64a241916318c2faafcc2b4c109273e9d/README.md
Only patch the known legacy converter behavior.
Handle the existing forward-slash result as unchanged too. If the current converter("policies\guard.py") returns "policies.guard", the patch still overwrites it on Windows and drops legacy behavior. Also use an unsupported-case except so an unexpected converter exception does not abort _import_toolguard().
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/lfx/src/lfx/components/models_and_agents/policies/module_utils.py` around
lines 21 - 33, Update the converter compatibility check in _import_toolguard so
both “policies.guard” and the known legacy forward-slash result are treated as
supported and leave the existing converter unchanged. Only install the local
file_to_module_name fallback when neither result matches, and broaden the
converter exception handling to catch unsupported or unexpected exceptions
without aborting _import_toolguard().
Source: Coding guidelines
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## release-1.11.2 #14374 +/- ##
==================================================
+ Coverage 61.44% 61.59% +0.14%
==================================================
Files 2452 2398 -54
Lines 239862 238187 -1675
Branches 36330 35735 -595
==================================================
- Hits 147395 146707 -688
+ Misses 90661 89674 -987
Partials 1806 1806
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Summary
Root cause
The flow attached to #14050 contains generated
FileTwinpaths with Windows\\separators. ToolGuard 0.2.21 only maps/to Python module dots, so Guard mode raisesModuleNotFoundErrorwhile loading those policies from memory. In agent execution, the retries surface as the reported long run and eventualJob queue ... missingerror.This release-scoped compatibility patch leaves the generated files unchanged and updates only ToolGuard's module-name conversion when a behavior probe shows that it is needed. Future ToolGuard versions containing the upstream fix are left untouched.
The Generate-mode Anthropic
thinking.thinkingsymptom is already fixed onrelease-1.11.2by #14092 and follow-ups #14145 / #14157. This PR addresses the remaining Guard-mode half without a broader dependency bump.Upstream permanent fix: AgentToolkit/toolguard#29
Test plan
git diff --checkFixes #14050
Summary by CodeRabbit