Contracts¶
Contracts provide typed input/output validation for vertices. They enforce that handlers receive the expected types and return the expected shape.
VertexContract¶
from honey_badgeria.back.contracts import VertexContract
contract = VertexContract(
inputs={"user_id": "int", "email": "str"},
outputs={"user": "dict", "error": "str"},
version="1.0",
effect="pure",
)
Validating Inputs¶
# Valid input
contract.validate_input({"user_id": 123, "email": "alice@example.com"})
# OK — no exception
# Invalid type
contract.validate_input({"user_id": "not_an_int", "email": "alice@example.com"})
# Raises ContractInputError!
# Missing key
contract.validate_input({"user_id": 123})
# Raises ContractInputError! (missing "email")
Validating Outputs¶
# Valid output
contract.validate_output({"user": {"id": 1}, "error": None})
# OK
# Missing key
contract.validate_output({"user": {"id": 1}})
# Raises ContractOutputError! (missing "error")
Supported Types¶
The contract system maps type names to Python types:
| Type Name | Python Type |
|---|---|
str |
str |
int |
int |
float |
float |
bool |
bool |
dict |
dict |
list |
list |
tuple |
tuple |
set |
set |
bytes |
bytes |
none |
NoneType |
Data Binding References¶
Unknown type names (like "fetch.user_id") are skipped during validation. This is by design — they are data-binding references, not type constraints:
contract = VertexContract(
inputs={"user_id": "fetch.user_id"}, # Data binding, not type
outputs={},
)
contract.validate_input({"user_id": 42}) # Skipped — no type check
Using Contracts in Flows¶
Contracts are derived from the inputs and outputs declared in your YAML:
validate_user:
handler: vertices.users.validate
effect: pure
version: "1"
inputs:
username: str # Type declaration → contract checks type
email: str # Type declaration → contract checks type
outputs:
is_valid: bool # Contract validates output has this key and type
errors: list
When the execution engine runs validate_user:
- Inputs are resolved from the DataStore.
- A
VertexContractis constructed from the vertex'sinputsandoutputs. contract.validate_input(resolved_inputs)checks types.- The handler executes.
contract.validate_output(handler_result)checks the return value.
Exceptions¶
| Exception | When |
|---|---|
ContractInputError |
Input doesn't match declared types or is missing |
ContractOutputError |
Output doesn't match declared types or is missing |
ContractError |
Base class for both |