Alter your tracker's nosyreaction.py detectors script to change the nosyreaction function to be:

 def nosyreaction(db, cl, nodeid, oldvalues):
    ''' A standard detector is provided that watches for additions to the
        "messages" property.

        When a new message is added, the detector sends it to all the users on
        the "nosy" list for the issue that are not already on the "recipients"
        list of the message.

        Those users are then appended to the "recipients" property on the
        message, so multiple copies of a message are never sent to the same
        user.

        The journal recorded by the hyperdatabase on the "recipients" property
        then provides a log of when the message was sent to whom.
    '''
    # send a copy of all new messages to the nosy list
    msgs = determineNewMessages(cl, nodeid, oldvalues)
    for msgid in msgs:
        try:
            cl.nosymessage(nodeid, msgid, oldvalues)
        except roundupdb.MessageSendError, message:
            raise roundupdb.DetectorError, message
    if not msgs:
        try:
            cl.nosymessage(nodeid, None, oldvalues)
        except roundupdb.MessageSendError, message:
            raise roundupdb.DetectorError, message

But a message for every change may be too much for you. Another route is to just require a message for certain changes. An example is to require a message when changing the assigned_to field. Put the following code into an auditor to require that the users enters a message when changing the assigned_to field:

 if 'assigned_to' in new_values and 'messages' not in new_values :
     raise Reject, "Changing assigned_to requires a message"