In your second example, if you run `send_message(id=1, body)` once and then run `send_message(id=1, body)` again, it behaves differently the second time than the first time, despite receiving the same input. So `send_message` is idempotent, but its behavior is not determined by its inputs (i.e. it is not pure).
If you imagine the hidden state that `send_message` reads and writes to be part of the input, then when you run it the second time, its inputs have changed. So it wouldn't be correct to say you're running it multiple times "on the same input".
These details are not obvious from the given definition, and that's why I say it's uncomfortably close to purity. Idempotence is very much not about purity (though you can have both), and that's why I like the author's goal-oriented explanation better: it makes the role of state very explicit.