Skip to content

scanner

agent_cover.instrumentation.raw_strings.scanner

Raw string heuristic scanner.

Not all prompts use PromptTemplate classes. Many developers use simple global string variables or f-strings. This module scans your codebase for string variables that match specific naming conventions.

Heuristics

By default, it looks for variables starting with prefixes like PROMPT_ or ending with suffixes like _TEMPLATE.

It handles f-strings by creating a robust regex that matches the variable content, replacing {variables} with wildcard patterns (.*?).

Examples:

If your code has:

# my_agent.py
SALES_PROMPT = "Hello {user}, buy this!"
This scanner detects SALES_PROMPT and creates a coverage target that matches any runtime string starting with "Hello " and ending with ", buy this!".

Attributes

DEFAULT_PREFIXES = ['PROMPT_', 'TEMPLATE_', 'SYS_MSG_', 'SYSTEM_MESSAGE'] module-attribute

Default prefixes used to identify potential prompt variables.

DEFAULT_SUFFIXES = ['_PROMPT', '_TEMPLATE'] module-attribute

Default suffixes used to identify potential prompt variables.

Classes

Functions

scan_raw_string_prompts(registry=None, root_path=None, module_iterator=None, source_reader=None)

Scans for raw string prompts in Python modules and registers them.

It iterates through all loaded modules in sys.modules that reside within root_path. For each string variable matching the configured prefixes/suffixes, it: 1. Calculates a regex pattern for runtime matching. 2. Registers it in the AgentRegistry.

Parameters:

Name Type Description Default
registry Optional[AgentRegistry]

An optional AgentRegistry instance. If not provided, it defaults to the global registry.

None
root_path Optional[str]

An optional root path to start the scan from. If not provided, it defaults to the current working directory.

None
module_iterator Optional[Callable[[], Dict[str, Any]]]

An optional callable for iterating through loaded modules. Defaults to _default_module_iterator.

None
source_reader Optional[Callable[[str], List[str]]]

An optional callable for reading source file contents. Defaults to _default_source_reader.

None
Source code in src/agent_cover/instrumentation/raw_strings/scanner.py
def scan_raw_string_prompts(
    registry: Optional[AgentRegistry] = None,
    root_path: Optional[str] = None,
    module_iterator: Optional[Callable[[], Dict[str, Any]]] = None,
    source_reader: Optional[Callable[[str], List[str]]] = None,
) -> None:
    """Scans for raw string prompts in Python modules and registers them.

    It iterates through all loaded modules in `sys.modules` that reside within
    `root_path`. For each string variable matching the configured prefixes/suffixes,
    it:
    1.  Calculates a regex pattern for runtime matching.
    2.  Registers it in the [`AgentRegistry`][agent_cover.registry.AgentRegistry].

    Args:
        registry: An optional AgentRegistry instance. If not provided, it
            defaults to the global registry.
        root_path: An optional root path to start the scan from. If not
            provided, it defaults to the current working directory.
        module_iterator: An optional callable for iterating through
            loaded modules.  Defaults to _default_module_iterator.
        source_reader: An optional callable for reading source file
            contents.  Defaults to _default_source_reader.
    """
    if registry is None:
        registry = get_registry()
    if root_path is None:
        root_path = os.getcwd()  # Default Prod
    if module_iterator is None:
        module_iterator = _default_module_iterator
    if source_reader is None:
        source_reader = _default_source_reader

    active_prefixes = tuple(DEFAULT_PREFIXES + _custom_prefixes)
    active_suffixes = tuple(DEFAULT_SUFFIXES + _custom_suffixes)

    modules_snapshot = module_iterator()

    for mod_name, mod in modules_snapshot.items():
        if not hasattr(mod, "__file__") or not mod.__file__:
            continue
        mod_file = os.path.abspath(mod.__file__)

        if not mod_file.startswith(root_path) or "site-packages" in mod_file:
            continue

        file_lines = None

        for name, val in list(vars(mod).items()):
            if not isinstance(val, str):
                continue

            match_prefix = name.startswith(active_prefixes)
            match_suffix = name.endswith(active_suffixes)

            if not (match_prefix or match_suffix):
                continue

            if len(val) < 10:
                continue

            if file_lines is None:
                file_lines = source_reader(mod_file)

            line_num = _find_variable_line_number(name, file_lines)
            if line_num == 0:
                continue

            clean_content = val.strip()
            regex_pattern = _create_robust_regex(clean_content)

            raw_id = f"RAW:{mod_file}::{name}"
            canonical_id = registry.get_canonical_id(clean_content, raw_id)

            if canonical_id not in registry.definitions:
                logger.debug(
                    f"[AgentCover][SCAN] Found {name} at line {line_num} in {mod_file}"
                )
                registry.register_definition(
                    key=canonical_id,
                    kind="PROMPT",
                    metadata={
                        "class": "StringConstant",
                        "preview": clean_content[:40],
                        "raw_content": clean_content,
                        "regex_pattern": regex_pattern,
                        "line_number": line_num,
                    },
                )

set_custom_prefixes(prefixes)

Sets custom prefixes for identifying prompt variables.

Parameters:

Name Type Description Default
prefixes list[str]

A list of string prefixes.

required
Source code in src/agent_cover/instrumentation/raw_strings/scanner.py
def set_custom_prefixes(prefixes: list[str]) -> None:
    """Sets custom prefixes for identifying prompt variables.

    Args:
        prefixes: A list of string prefixes.
    """
    global _custom_prefixes
    _custom_prefixes = [p.strip() for p in prefixes if p.strip()]

set_custom_suffixes(suffixes)

Sets custom suffixes for identifying prompt variables.

Parameters:

Name Type Description Default
suffixes list[str]

A list of string suffixes.

required
Source code in src/agent_cover/instrumentation/raw_strings/scanner.py
def set_custom_suffixes(suffixes: list[str]) -> None:
    """Sets custom suffixes for identifying prompt variables.

    Args:
        suffixes: A list of string suffixes.
    """
    global _custom_suffixes
    _custom_suffixes = [s.strip() for s in suffixes if s.strip()]