Reasoning Engine
Pluggable evaluator registry and safe rewrite engine
The Reasoning Engine provides extensibility for Praxom through a pluggable evaluator architecture and a deterministic rewrite engine for safe payload transformations.
How It Works
Evaluator Base (evaluator_base.py)
The ConstraintEvaluator abstract base class defines the interface for all constraint evaluators:
class ConstraintEvaluator(ABC):
@abstractmethod
def evaluate(self, payload: dict, constraint: dict) -> EvaluationResult:
"""Evaluate a constraint against a payload."""
...
@abstractmethod
def supports(self, constraint_type: str) -> bool:
"""Whether this evaluator handles the given constraint type."""
...The EvaluationResult dataclass carries:
passed— Whether the constraint was satisfiedverdict— ALLOW, DENY, REWRITE, or ESCALATEreason— Human-readable explanationrewrites— List of safe field transformations (for REWRITE verdicts)
Evaluator Registry (evaluator_registry.py)
The registry manages pluggable constraint evaluators:
from pramiti.contexts.praxom.enforcement.infrastructure.evaluator_registry import EvaluatorRegistry
registry = EvaluatorRegistry()
# Built-in evaluators are auto-registered:
# - JsonPredicateEvaluator (auto-tier)
# - ShaclConstraintEvaluator (formal-tier)The registry supports entry-point based plugin discovery via importlib.metadata, allowing third-party evaluators to be installed as pip packages and automatically registered.
Rewrite Engine (rewrite_engine.py)
The rewrite engine applies deterministic, safe transformations to action payloads when a constraint returns a REWRITE verdict:
Supported rewrite operations:
| Operation | Description | Example |
|---|---|---|
cap_value | Cap a numeric field at a maximum | {"op": "cap_value", "field": "amount", "max": 10000} |
mask_field | Replace a field with a masked value | {"op": "mask_field", "field": "ssn", "mask": "***-**-****"} |
set_default | Set a field to a default value if missing | {"op": "set_default", "field": "priority", "value": "low"} |
remove_field | Remove a field from the payload | {"op": "remove_field", "field": "internal_notes"} |
The engine detects conflicts when multiple rewrites target the same field and raises an error rather than silently applying inconsistent transformations.
from pramiti.contexts.praxom.enforcement.domain.rewrite_engine import apply_rewrites
modified_payload = apply_rewrites(
payload=original_payload,
rewrites=[
{"op": "cap_value", "field": "arguments.amount", "max": 10000},
{"op": "mask_field", "field": "arguments.ssn", "mask": "***-**-****"}
]
)Architecture
Proposed Action
↓
Evaluator Registry
├── JsonPredicateEvaluator → EvaluationResult
├── ShaclConstraintEvaluator → EvaluationResult
└── [Custom Evaluator] → EvaluationResult
↓
Merge Results → PolicyDecision
↓ (if REWRITE)
Rewrite Engine → Modified Payload
↓
Execute with modified payloadConfiguration
Custom evaluators can be registered via Python entry points:
# In your package's pyproject.toml
[project.entry-points."epistom.praxom.evaluators"]
my_evaluator = "my_package.evaluator:MyCustomEvaluator"Technical Details
- All rewrite operations are deterministic — no randomness, no LLM involvement
- Conflict detection prevents contradictory rewrites (e.g., cap_value to 100 and set_default to 200 on the same field)
- The evaluator registry auto-discovers plugins at startup via
importlib.metadata.entry_points() - Field resolution uses the
field_resolver.pymodule for dot-notation path access in nested payloads - Rewrites are recorded in the attestation — the original and modified payloads are both preserved for audit