Messages are collections of typed data, with a defined layout, including an ID.
These messages are not only opaque data. They can also contain port rights to be passed to another task. Port rights are either copied or moved. Notice that port receive right must be moved but not copied because there can't be more than one task that holds the receive right to a port. The receiving task creates new local port name to the port rights it received.
Some data in the message can be out-of-line data. In the message, these are references to memory regions (memory objects) that are virtually copied. When the message is received in a task, these virtual copies become part of the task by mapping them into the receiver's virtual address space. Another key concept that is applied is using copy-on-write, which means that data is not copied immediately, but only when it is changed. This is primarily used to send large blocks of data efficiently, as it is too expensive to store them in the kernel address space: extra copied need only be made at the moment that the memory regions begin to diverge, by threads modifying them.