Source code for klea_utils.nodes.guard
#!/usr/bin/env python3
"""
Guard node for safety checking
File: klea_utils/nodes/guard.py
Copyright 2026 Ankur Sinha
Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>
"""
import logging
from typing import Any, override
from langchain_core.messages import AIMessage
from pydantic import BaseModel
from ..llm import content_to_str
from .base import BaseLLMNode
[docs]
class GuardNode(BaseLLMNode):
model_type = "guard"
model_defaults = {"temperature": 0.3, "max_output_tokens": 1024}
"""Safety guard node that checks if user queries are safe to process.
Evaluates whether a query contains potentially harmful content
and returns a routing decision ("safe" or "unsafe").
Note: to be used with llama-guard, which always returns safe/unsafe.
To skip, do not set a model.
"""
def __init__(
self,
logger: logging.Logger,
label: str,
llm_models: dict[str, Any],
memory: bool = False,
):
"""Initialise the guard node.
:param logger: Logger instance
:param label: Human-readable label for UI progress display
:param llm_models: ``{role: LLMModel}`` dict (from ``BaseLangGraph.llm_models``)
:param memory: Whether to include conversation history in the prompt
"""
super().__init__(
logger=logger,
label=label,
llm_models=llm_models,
output_schema=None,
memory=memory,
)
@override
def _pre_exec(self, state: BaseModel) -> bool:
"""Skip execution if no guard model is configured."""
return bool(self._llm_entry.model_name)
@override
def _get_prompt_variables(self, state: BaseModel) -> dict:
"""Format prompt with the user's query."""
return {"query": state.query} # type: ignore
@override
def _get_system_prompt(self, state: BaseModel) -> str:
return ""
@override
def _update_state(self, result: AIMessage, state: BaseModel) -> dict[str, Any]:
"""Check result for safety and return routing decision."""
self.logger.debug(f"{result = }")
content = content_to_str(result.content)
if "unsafe" in content:
return {"guard_decision": "unsafe"}
return {"guard_decision": "safe"}
@override
def _get_default_error_result(self) -> str:
"""Unused: no schema in this node."""
return "safe"