Other than integration with the rest of the Nix/NixOS ecosystem, how is NixOps different from Puppet? Reading briefly through the examples, it seems very oriented towards provisioning machine instances rather than provisioning behavior across networks or multi-machine services, which is something that Puppet really excels at. What features does this offer in addition to ones that Puppet provides? That said, I've been…
With the nix system you can fully declaratively state your entire fleet of machines, from your highest level application configs all the way down to kernel patches.
When you run nixops, your machines become exactly as specified.
That this works reliably is a novelty: most other configuration management tools work like "action runners" that try in a best-effort fashion to achieve the desired state, but that doesn't always work (for example in Ansible, declaring a package as installed installs it, but NOT declaring a package will not uninstall it).
It is made possible because the nix system is designed from the bottom up to be declarative. That makes it different from Puppet.