diff --git a/test/agent/scenarios/peer-monitor/agent.scm b/test/agent/scenarios/peer-monitor/agent.scm
new file mode 120000
index 0000000000000000000000000000000000000000..cdbbefc243d106018e833f508aad9fe005dcf7ba
--- /dev/null
+++ b/test/agent/scenarios/peer-monitor/agent.scm
@@ -0,0 +1 @@
+../../agent.scm
\ No newline at end of file
diff --git a/test/agent/scenarios/peer-monitor/jami b/test/agent/scenarios/peer-monitor/jami
new file mode 120000
index 0000000000000000000000000000000000000000..cb5e6e626ee4c910ed3d83b6e6ce1068fa95195d
--- /dev/null
+++ b/test/agent/scenarios/peer-monitor/jami
@@ -0,0 +1 @@
+../../jami
\ No newline at end of file
diff --git a/test/agent/scenarios/peer-monitor/run-scenario b/test/agent/scenarios/peer-monitor/run-scenario
new file mode 100755
index 0000000000000000000000000000000000000000..1130a5e819f7397dc9004569790aeb637fe1b02e
--- /dev/null
+++ b/test/agent/scenarios/peer-monitor/run-scenario
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+tmp=$(mktemp --directory)
+
+export XDG_CONFIG_HOME="$tmp"
+export XDG_CACHE_HOME="$tmp"
+export XDG_DATA_HOME="$tmp"
+export GUILE_AUTO_COMPILE=0
+export JAMI_LOG_FILE="$1.log"
+
+./scenario.scm $@
+
+rm -rf "$tmp"
+
diff --git a/test/agent/scenarios/peer-monitor/scenario.scm b/test/agent/scenarios/peer-monitor/scenario.scm
new file mode 100755
index 0000000000000000000000000000000000000000..29543adfc12989d91c3eed8482acd0ca7782cd28
--- /dev/null
+++ b/test/agent/scenarios/peer-monitor/scenario.scm
@@ -0,0 +1,172 @@
+#!/usr/bin/env -S ./agent.exe -e main -s
+!#
+
+(use-modules
+ (ice-9 match)
+ (ice-9 threads)
+ (ice-9 atomic)
+ (ice-9 format)
+ ((srfi srfi-19) #:prefix srfi-19:)
+ ((agent) #:prefix agent:)
+ ((jami account) #:prefix account:)
+ ((jami call) #:prefix call:)
+ ((jami signal) #:prefix jami:)
+ ((jami logger) #:prefix jami:))
+
+(define seconds-per-hour (* 60 60))
+(define seconds-per-day (* 24 second-per-hour))
+
+(define* (time-until-midnight #:optional (tz 0))
+  "Returns the number of seconds before midnight at timezone offset TZ."
+  (let ((now (srfi-19:current-date 0)))
+    (+ (* 3600 (- 23 (srfi-19:date-hour now)))
+       (* 60 (- 59 (srfi-19:date-minute now)))
+       (- 60 (srfi-19:date-second now)))))
+
+(define next-details!
+  "Returns the next details in the matrix of account's details."
+  (let* ((details-matrix
+          #((("Account.upnpEnabled" . "true")
+             ("TURN.enable"         . "true"))
+
+            (("Account.upnpEnabled" . "true")
+             ("TURN.enable"         . "false"))
+
+            (("Account.upnpEnabled" . "false")
+             ("TURN.enable"         . "true"))
+
+            (("Account.upnpEnabled" . "false")
+             ("TURN.enable"         . "false"))))
+         (i 0)
+         (len (array-length details-matrix)))
+    (lambda ()
+      (let ((details (array-ref details-matrix i)))
+        (set! i (euclidean-remainder (1+ i) len))
+        details))))
+
+(define (timestamp)
+  (srfi-19:date->string (srfi-19:current-date) "[~5]"))
+
+(define-syntax-rule (progress fmt args ...)
+  (jami:info "~a ~a" (timestamp) (format #f fmt args ...)))
+
+(define (setup-timer)
+
+  (progress "Setting up timer")
+
+  ;; Timer was triggered.  The agent now has a grace period of an hour to change
+  ;; its account's details.  After the grace period, the midnight timer is set
+  ;; again.
+  (sigaction SIGALRM (lambda _
+                       ;; Restart in one hour
+                       (setitimer ITIMER_REAL
+                                  0 0
+                                  seconds-per-hour 0)
+
+                       (sigaction SIGALRM (lambda _ (setup-timer)))
+
+                       (let ((account (fluid-ref agent:account-id))
+                             (details (next-details!)))
+                         (progress "SIGALRM - Chaning account details: ~a" details)
+                         (account:send-register account #f)
+                         (account:set-details account details)
+                         (account:send-register account #t))))
+
+  ;; Setup timer to trigger at next midnigh of UTC+0.  This means that peers can
+  ;; have different timezones and still synchronize at the same time.
+  (setitimer ITIMER_REAL
+             0 0
+             (time-until-midnight) 0)
+
+  ;; Resume execution of continuation.
+  (resume #t))
+
+(define resume #f)
+
+(define (active peer)
+
+  (define (call-peer timeout)
+    (let ((mtx (make-mutex))
+          (cnd (make-condition-variable))
+          (this-call-id "")
+          (continue (make-atomic-box #t)))
+      (jami:on-signal 'state-changed
+                      (lambda (call-id state code)
+                        (if (atomic-box-ref continue)
+                            (with-mutex mtx
+                              (if (and (string= this-call-id call-id)
+                                       (string= state "CURRENT"))
+                                  (begin
+                                    (signal-condition-variable cnd)
+                                    #f)
+                                  #t))
+                            #f)))
+      (with-mutex mtx
+        (set! this-call-id (call:place-call (fluid-ref agent:account-id) peer))
+        (let ((ret (wait-condition-variable cnd mtx
+                                            (+ (current-time) timeout))))
+          (unless ret (atomic-box-set! continue #f))
+          ret))))
+
+  (let ((account (fluid-ref agent:account-id))
+        (success 0)
+        (failure 0)
+        (reset (call/cc (lambda (k)
+                          (set! resume k)
+                          #f))))
+
+    (when reset
+        (let ((total (+ success failure)))
+          (progress "'(summary (total-call . ~a) (success-rate . ~a) (failure-rate . ~a))"
+                     total
+                     (/ success total)
+                     (/ failure total))
+          (set! success 0)
+          (set! failure 0)))
+
+    (while #t
+      (let ((result  (call-peer 30)))
+        (progress "Call: ~a"  (if result "PASS" "FAIL"))
+        (if result
+            (set! success (1+ success))
+            (set! failure (1+ failure)))
+        (account:send-register account #f)
+        (sleep 30)
+        (account:send-register account #t)
+        (sleep 30)))))
+
+(define (passive)
+
+  (jami:on-signal 'incoming-call
+                  (lambda (account-id call-id peer)
+                    (progress "Receiving call from ~a" peer)
+                    (call:accept call-id)
+                    #t))
+
+  (jami:on-signal 'incoming-call/media
+                  (lambda (account-id call-id peer media-lst)
+                    (call:accept call-id media-lst)
+                    #t))
+
+  (let ((continue (call/cc (lambda (k)
+                             (set! resume k)
+                             #t))))
+        (while continue
+            (pause))))
+
+(define (main args)
+
+  (let ((behavior (cdr args)))
+    (set! resume
+          (match behavior
+            (("passive" archive) (lambda _
+                                   (agent:ensure-account-from-archive
+                                    archive)
+                                   (passive)))
+            (("active" archive peer) (lambda _
+                                       (agent:ensure-account-from-archive
+                                        archive)
+                                       (active peer)))
+            (_ (throw 'bad-argument args)))))
+
+  (setup-timer))