Contracts¶
Guide the model with pre/post conditions in ~5 minutes. Requires Python 3.10+ and pip install alloy-ai
.
Background: Contracts in Alloy follow Design by Contract (DbC) — a software correctness methodology where components declare preconditions and postconditions.
DbC in Alloy
@require
: preconditions checked before a tool runs (receivesinspect.BoundArguments
).@ensure
: postconditions checked after a tool runs (receives the tool’s result).- On failure, Alloy surfaces the contract message back to the model as the tool’s output (not a hard exception) so the model can adjust (e.g., call a prerequisite or fix args).
- Raise normal exceptions for non‑contract failures you want to stop the workflow; Alloy will surface a brief error back to the model.
Require (preconditions)¶
@require(predicate, message)
runs before the tool. The predicate receives inspect.BoundArguments
.
from alloy import tool, require
@tool
@require(lambda ba: ba.arguments.get("x", 0) >= 0, "x must be non-negative")
def sqrt_floor(x: int) -> int:
import math
return int(math.sqrt(x))
Ensure (postconditions)¶
@ensure(predicate, message)
runs after the tool with the tool’s result.
from alloy import tool, ensure
@tool
@ensure(lambda ok: ok is True, "Save must succeed")
def save_to_production(data: dict) -> bool:
return True
Workflow example¶
import datetime
from alloy import command, tool, require, ensure
@tool
@ensure(lambda d: isinstance(d, dict) and "validated_at" in d, "Must add validated_at")
def validate_data(data: dict) -> dict:
d = dict(data)
d["validated_at"] = datetime.datetime.now(datetime.timezone.utc).isoformat()
return d
@tool
@require(lambda ba: "validated_at" in ba.arguments.get("data", {}), "Run validate_data first")
@ensure(lambda ok: ok is True, "Save must succeed")
def save_to_production(data: dict) -> bool:
return True
@command(output=str, tools=[validate_data, save_to_production])
def process_order(order: dict) -> str:
return f"Validate then save this order: {order}"
Behavior: on contract failure, Alloy surfaces the message back to the model as the tool’s result (not a hard exception) so the model can adjust (e.g., call a prerequisite) — keeping the loop recoverable and explicit.
Further reading - Design by Contract (Wikipedia)