Same here. T::Struct and T::Enums at API boundaries has been the sweet spot—typed request/response models, runtime validation at ingress/egress.
I’ve been using this pattern for API clients[0] and CLIs[1]: define the shape once with Sorbet, get automatic JSON Schema generation when you need it.
[0] https://github.com/vicentereig/exa-ruby [1] https://github.com/vicentereig/lf-cli