Feed silence for AI agents

Report interfaces whose latest message exceeds a silence threshold.

Feed-silence monitoring compares each interface's latest recorded message time with a configured threshold. This page builds a service that returns the latest arrival and silence status of every MLLP channel and exposes it as an MCP tool, so you can ask your AI whether any feed has gone silent.

Start with Expose services as MCP - it creates the clinical MCP gateway and the API key that this page builds on. The service below reads the same clinical audit log that every MLLP channel already writes to.

Write the service

self.audit.last_seen returns the newest event time of each channel. The service compares each time with its declared threshold. The docstring and declared output become the tool's definition as described under Expose services as MCP:

# -*- coding: utf-8 -*-

# stdlib
from datetime import datetime

# Zato
from zato.common.audit_log.api import AuditSource
from zato.server.service import Service

# #####################################################################
# #####################################################################

# The feed-silence threshold in minutes.
_silence_threshold_minutes = 30

# #####################################################################
# #####################################################################

class FeedSilence(Service):
    """ Returns, per interface, when its last HL7 message arrived and
    whether the interface has been silent for longer than the threshold.
    """
    name = 'interface.feed-silence'

    output = 'threshold_minutes', 'has_silent_feeds', 'interfaces'

    def handle(self) -> 'None':

        # Get the newest event time of each HL7 channel ..
        last_seen = self.audit.last_seen(AuditSource.MLLP_Channel)

        # .. establish the comparison time and response accumulators ..
        now = datetime.now()
        interfaces = []
        has_silent_feeds = False

        # .. compare each interface against the silence threshold ..
        for interface, last_received_at_iso in sorted(last_seen.items()):

            # .. compute how long ago its last message arrived ..
            last_received_at = datetime.fromisoformat(last_received_at_iso)
            since_last = now - last_received_at
            minutes_since_last = int(since_last.total_seconds() / 60)

            # .. check whether that exceeds the threshold ..
            is_silent = minutes_since_last > _silence_threshold_minutes

            # .. retain whether any interface exceeded it ..
            if is_silent:
                has_silent_feeds = True

            # .. add the status of this interface to the result ..
            interfaces.append({
                'interface': interface,
                'last_received_at': last_received_at_iso,
                'minutes_since_last': minutes_since_last,
                'is_silent': is_silent,
            })

        # .. and return the declared tool response.
        self.response.payload = {
            'threshold_minutes': _silence_threshold_minutes,
            'has_silent_feeds': has_silent_feeds,
            'interfaces': interfaces,
        }

Add the tool to the gateway

Assign the new service to the clinical gateway created under Expose services as MCP:

  1. Go to AI > MCP gateways and open the clinical gateway
  2. In the Services picker, drag interface.feed-silence to the Assigned zone
  3. Click OK

Verify the lookup

You can now ask your AI:

Has any feed gone silent?
Yes - Results from Lab exceeded the 30-minute threshold. Its latest result arrived at 05:34, 176 minutes ago. ADT from Registration remains within the threshold, with its latest message recorded 4 minutes ago.

Behind this exchange, the model selected interface.feed-silence and called it without any input, because the tool declares none. With the lab feed silent since early morning, the tool returned:

{
  "threshold_minutes": 30,
  "has_silent_feeds": true,
  "interfaces": [
    {
      "interface": "ADT from Registration",
      "last_received_at": "2026-03-16T08:27:12",
      "minutes_since_last": 4,
      "is_silent": false
    },
    {
      "interface": "Results from Lab",
      "last_received_at": "2026-03-16T05:34:51",
      "minutes_since_last": 176,
      "is_silent": true
    }
  ]
}

And this is the same question when every feed is within the threshold:

Has any feed gone silent?
No - every feed is within the 30-minute threshold.

This time, the tool returned no silent feeds, which is how AI knew all of them were healthy:

{
  "threshold_minutes": 30,
  "has_silent_feeds": false,
  "interfaces": [
    {
      "interface": "ADT from Registration",
      "last_received_at": "2026-03-16T08:27:12",
      "minutes_since_last": 4,
      "is_silent": false
    },
    {
      "interface": "Results from Lab",
      "last_received_at": "2026-03-16T08:25:03",
      "minutes_since_last": 6,
      "is_silent": false
    }
  ]
}

Push notifications

Note that the tool from this chapters is called by AI on demand, when someone asks a question.

To be notified the moment a feed goes silent, without anyone asking, configure alerting - it watches the same audit log and sends a notification when a feed exceeds its silence threshold.


Schedule a meaningful demo

Book a demo with an expert who will help you build meaningful systems that match your ambitions

"We evaluated 12 integration platforms and Zato was the only one to score 100%."

Philip Zuñiga, Assistant Professor, University of the Philippines