Skip to content

Public surface (guardrail_calculus)

The builder/authoring API plus domain scalars. This layer is still being shaped by Phases 2–3, so several builders are documented by signature only for now.

guardrail_calculus

Public guardrail-calculus surface.

This module is mostly public re-export and high-level API assembly. The foundational nodes, predicates, dimensional protocols, and the local proxy _ live in the import-safe :mod:guardrail_kernel; concrete temporal values live in :mod:guardrail_calculus.dimensions; propositions and the typed check chain in :mod:guardrail_calculus.facts; the explanation DAG, solver utilities, and puzzle solving in the optional :mod:guardrail_solver package.

What remains defined here is the builder/authoring surface: domain scalars (Probability, Money), Routes, schema-rooted refs, IR serialization, and the agent/graph/subgraph/subject builders.

routes module-attribute

routes = RoutesFactory()

ref module-attribute

ref = RefFactory()

agent module-attribute

agent = AgentFactory()

subgraph module-attribute

subgraph = SubgraphFactory()

subject module-attribute

subject = SubjectFactory()

Probability dataclass

Bases: _SymbolicEquality, DimensionIdentity[Literal['Probability']]

A probability value constrained to [0, 1].

Attributes:

Name Type Description
value float

The probability float value.

Source code in src/guardrail_calculus/__init__.py
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
@typing.final
@dataclass(frozen=True, order=True)
class Probability(_SymbolicEquality, DimensionIdentity[Literal["Probability"]]):
    """A probability value constrained to [0, 1].

    Attributes:
        value: The probability float value.
    """
    value: float
    _dimension: typing.ClassVar[
        Dimension[Carrier[float]]
    ] = PROBABILITY

    def __post_init__(self) -> None:
        if not 0 <= self.value <= 1:
            raise ValueError("Probability must be between 0 and 1.")

    @property
    def label(self) -> str:
        return f"{self.value:.2f}"

value instance-attribute

value

label property

label

Money dataclass

Bases: _SymbolicEquality, DimensionIdentity[Literal['Money']]

Money representation containing currency code and integer amount.

Attributes:

Name Type Description
currency str

The currency identifier string.

amount int

The monetary amount.

Source code in src/guardrail_calculus/__init__.py
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
@typing.final
@dataclass(frozen=True, order=True)
class Money(_SymbolicEquality, DimensionIdentity[Literal["Money"]]):
    """Money representation containing currency code and integer amount.

    Attributes:
        currency: The currency identifier string.
        amount: The monetary amount.
    """
    currency: str
    amount: int
    _dimension: typing.ClassVar[
        Dimension[Carrier[int]]
    ] = MONEY

    GBP: typing.ClassVar = MONEY_CONSTRUCTORS.GBP
    USD: typing.ClassVar = MONEY_CONSTRUCTORS.USD

    @classmethod
    def _from_carrier(cls, value: int, unit: str) -> Money:
        return cls(currency=unit, amount=value)

    @property
    def label(self) -> str:
        return f"{self.currency} {self.amount}"

    def __add__(self, other: Any) -> Any:
        return _apply("+", self, other)

    def __sub__(self, other: Any) -> Any:
        return _apply("-", self, other)

    def __mul__(self, other: Any) -> Any:
        return _apply("*", self, other)

    def __rmul__(self, other: Any) -> Any:
        return _apply("*", other, self)

currency instance-attribute

currency

amount instance-attribute

amount

GBP class-attribute instance-attribute

GBP = GBP

USD class-attribute instance-attribute

USD = USD

label property

label

Routes dataclass

Represents a set of target destinations for graph routing.

Attributes:

Name Type Description
targets frozenset[object]

Set of successor destinations (strings or references).

is_out bool

True if routing out of a subgraph.

Source code in src/guardrail_calculus/__init__.py
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
@typing.final
@dataclass(frozen=True)
class Routes:
    """Represents a set of target destinations for graph routing.

    Attributes:
        targets: Set of successor destinations (strings or references).
        is_out: True if routing out of a subgraph.
    """
    targets: frozenset[object] = frozenset()
    is_out: bool = False

    def includes(self, target: object) -> Predicate[_Includes]:
        return Predicate(
            node=_Includes(self, target),
            label=f"{display_value(self)} includes {display_value(target)}",
        )

    @property
    def label(self) -> str:
        if self.is_out:
            return "routes.out"

        if not self.targets:
            return "routes.none()"

        return "routes.to(" + ", ".join(display_value(t) for t in self.targets) + ")"

targets class-attribute instance-attribute

targets = frozenset()

is_out class-attribute instance-attribute

is_out = False

label property

label

includes

includes(target)
Source code in src/guardrail_calculus/__init__.py
575
576
577
578
579
def includes(self, target: object) -> Predicate[_Includes]:
    return Predicate(
        node=_Includes(self, target),
        label=f"{display_value(self)} includes {display_value(target)}",
    )

RoutesFactory

Factory to build Routes instances using helper methods.

Source code in src/guardrail_calculus/__init__.py
592
593
594
595
596
597
598
599
600
601
602
class RoutesFactory:
    """Factory to build [Routes][guardrail_calculus.Routes] instances using helper methods."""
    @property
    def out(self) -> Routes:
        return Routes(is_out=True)

    def none(self) -> Routes:
        return Routes()

    def to(self, *targets: object) -> Routes:
        return Routes(targets=frozenset(targets))

out property

out

none

none()
Source code in src/guardrail_calculus/__init__.py
598
599
def none(self) -> Routes:
    return Routes()

to

to(*targets)
Source code in src/guardrail_calculus/__init__.py
601
602
def to(self, *targets: object) -> Routes:
    return Routes(targets=frozenset(targets))

RefFactory

Source code in src/guardrail_calculus/__init__.py
808
809
810
class RefFactory:
    def __getitem__[T](self, schema_type: type[T]) -> T:
        return cast(T, Proxy(schema_type))

AgentBuilder dataclass

Builder for constructing an AgentBlock.

Attributes:

Name Type Description
output_type type[OutputsT] | None

Optional class representing outputs.

rules tuple[AgentRule, ...]

Tuple of accumulated rules.

pending_given Prop[Any] | None

The pending given predicate.

Source code in src/guardrail_calculus/__init__.py
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
@dataclass(frozen=True)
class AgentBuilder[OutputsT]:
    """Builder for constructing an [AgentBlock][guardrail_calculus.AgentBlock].

    Attributes:
        output_type: Optional class representing outputs.
        rules: Tuple of accumulated rules.
        pending_given: The pending given predicate.
    """
    output_type: type[OutputsT] | None = None
    rules: tuple[AgentRule, ...] = ()
    pending_given: Prop[Any] | None = None

    def given(self, value: Boolish_Bound | Prop[Any]) -> AgentBuilder[OutputsT]:
        return dataclasses.replace(self, pending_given=prop(value))

    def then(
        self,
        *values: Boolish_Bound | Prop[Any],
    ) -> AgentBuilder[OutputsT]:
        rule = AgentRule(
            given=self.pending_given,
            consequences=tuple(prop(value) for value in values),
        )
        return AgentBuilder(
            output_type=self.output_type,
            rules=(*self.rules, rule),
            pending_given=None,
        )

    def block(self) -> AgentBlock[OutputsT]:
        return AgentBlock(output_type=self.output_type, rules=self.rules)

output_type class-attribute instance-attribute

output_type = None

rules class-attribute instance-attribute

rules = ()

pending_given class-attribute instance-attribute

pending_given = None

given

given(value)
Source code in src/guardrail_calculus/__init__.py
907
908
def given(self, value: Boolish_Bound | Prop[Any]) -> AgentBuilder[OutputsT]:
    return dataclasses.replace(self, pending_given=prop(value))

then

then(*values)
Source code in src/guardrail_calculus/__init__.py
910
911
912
913
914
915
916
917
918
919
920
921
922
def then(
    self,
    *values: Boolish_Bound | Prop[Any],
) -> AgentBuilder[OutputsT]:
    rule = AgentRule(
        given=self.pending_given,
        consequences=tuple(prop(value) for value in values),
    )
    return AgentBuilder(
        output_type=self.output_type,
        rules=(*self.rules, rule),
        pending_given=None,
    )

block

block()
Source code in src/guardrail_calculus/__init__.py
924
925
def block(self) -> AgentBlock[OutputsT]:
    return AgentBlock(output_type=self.output_type, rules=self.rules)

AgentBlock dataclass

A constructed agent block with a set of rules.

Attributes:

Name Type Description
output_type type[OutputsT] | None

Optional class representing outputs.

rules tuple[AgentRule, ...]

Tuple of rules inside the agent.

Source code in src/guardrail_calculus/__init__.py
882
883
884
885
886
887
888
889
890
891
@dataclass(frozen=True)
class AgentBlock[OutputsT]:
    """A constructed agent block with a set of rules.

    Attributes:
        output_type: Optional class representing outputs.
        rules: Tuple of rules inside the agent.
    """
    output_type: type[OutputsT] | None
    rules: tuple[AgentRule, ...]

output_type instance-attribute

output_type

rules instance-attribute

rules

AgentRule dataclass

A rule inside an agent containing a premise and a set of consequences.

Attributes:

Name Type Description
given Prop[Any] | None

Optional premise proposition.

consequences tuple[Prop[Any], ...]

Sequence of consequences to apply.

Source code in src/guardrail_calculus/__init__.py
870
871
872
873
874
875
876
877
878
879
@dataclass(frozen=True)
class AgentRule:
    """A rule inside an agent containing a premise and a set of consequences.

    Attributes:
        given: Optional premise proposition.
        consequences: Sequence of consequences to apply.
    """
    given: Prop[Any] | None
    consequences: tuple[Prop[Any], ...]

given instance-attribute

given

consequences instance-attribute

consequences

GraphBlock dataclass

A constructed graph block.

Attributes:

Name Type Description
vertices Mapping[str, object]

Mapping from vertex names to blocks.

Source code in src/guardrail_calculus/__init__.py
990
991
992
993
994
995
996
997
@dataclass(frozen=True)
class GraphBlock:
    """A constructed graph block.

    Attributes:
        vertices: Mapping from vertex names to blocks.
    """
    vertices: Mapping[str, object]

vertices instance-attribute

vertices

SubgraphBlock dataclass

A constructed subgraph block.

Attributes:

Name Type Description
output_type type[OutputsT] | None

Optional class representing outputs.

vertices Mapping[str, object]

Mapping from vertex names to sibling blocks.

Source code in src/guardrail_calculus/__init__.py
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
@dataclass(frozen=True)
class SubgraphBlock[OutputsT]:
    """A constructed subgraph block.

    Attributes:
        output_type: Optional class representing outputs.
        vertices: Mapping from vertex names to sibling blocks.
    """
    output_type: type[OutputsT] | None
    vertices: Mapping[str, object]

output_type instance-attribute

output_type

vertices instance-attribute

vertices

graph

graph(**vertices)

Construct a GraphBlock with the given vertices.

Parameters:

Name Type Description Default
**vertices object

Key-value mapping of vertex blocks.

{}

Returns:

Type Description
GraphBlock

The constructed GraphBlock.

Source code in src/guardrail_calculus/__init__.py
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
def graph(**vertices: object) -> GraphBlock:
    """Construct a [GraphBlock][guardrail_calculus.GraphBlock] with the given vertices.

    Args:
        **vertices: Key-value mapping of vertex blocks.

    Returns:
        The constructed GraphBlock.
    """
    return GraphBlock(vertices=vertices)

validate_routes_out

validate_routes_out(block, *, in_subgraph=False)

Validate that routes.out is only used inside subgraphs.

Parameters:

Name Type Description Default
block AgentBlock[Any]

The agent block to validate.

required
in_subgraph bool

True if nested inside a subgraph.

False

Raises:

Type Description
ValueError

If routes.out is used outside a subgraph.

Source code in src/guardrail_calculus/__init__.py
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
def validate_routes_out(
    block: AgentBlock[Any],
    *,
    in_subgraph: bool = False,
) -> None:
    """Validate that `routes.out` is only used inside subgraphs.

    Args:
        block: The agent block to validate.
        in_subgraph: True if nested inside a subgraph.

    Raises:
        ValueError: If `routes.out` is used outside a subgraph.
    """
    for rule in block.rules:
        for consequence in rule.consequences:
            if _is_routes_out_assignment(consequence) and not in_subgraph:
                raise ValueError("routes.out is only valid inside a subgraph.")