Series 6 — Part 10 of 10

The relay pattern allows a client to ask the WhatsApp AI agent a question, the bot to forward it to the lawyer, the lawyer to reply via WhatsApp, and the bot to forward that reply to the client — all with a full audit trail. This article covers relay detection, forwarding, and the audit log requirements.

The Relay Flow

Client → the WhatsApp AI agent → [forwards to Lawyer] → Lawyer replies → the WhatsApp AI agent → [forwards to Client]
   ↑                                                                              ↑
   │                              AUDIT LOG                                      │
   └──────────────────── both sides logged with correlation ID ─────────────────┘

Forwarding a Client Question to the Lawyer

class RelayHandler
{
    public function relayToLawyer(
        string $clientQuestion,
        int    $matterId,
        PersonaInterface $clientPersona,
        PDO    $pdo
    ): string {
        $matter = get_matter_summary($matterId, $pdo);
        $lawyer = get_assigned_lawyer($matterId, $pdo);

        if (!$lawyer || !$lawyer['wa_number']) {
            return "I'll need to check this with your lawyer. I'll follow up with you shortly.";
        }

        $relayMessage = "⚡ *Relay from the WhatsApp AI agent* ⚡\n\n"
            . "*Matter:* " . $matter['ref_number'] . " — " . $matter['title'] . "\n"
            . "*Client:* " . $clientPersona->getName() . "\n\n"
            . "*Question:* " . $clientQuestion . "\n\n"
            . "_Reply to this message to send your response to the client._";

        $relayId = log_relay_sent($matterId, $clientPersona->getUserId(), $lawyer['id'],
                                   $clientQuestion, $pdo);

        send_whatsapp_text($lawyer['wa_number'], $relayMessage);

        return "I've forwarded your question to " . $lawyer['full_name'] . ". "
             . "They'll get back to you as soon as possible.";
    }

    public function detectRelayReply(string $lawyerMessage, int $lawyerUserId, PDO $pdo): ?array
    {
        // A relay reply starts with a specific marker or is in response to a relay
        // Check if there's a pending relay for this lawyer in the last 48 hours
        $stmt = $pdo->prepare(
            'SELECT * FROM relay_log WHERE lawyer_id = ? AND status = \'pending\'
             AND created_at > DATE_SUB(NOW(), INTERVAL 48 HOUR)
             ORDER BY created_at DESC LIMIT 1'
        );
        $stmt->execute([$lawyerUserId]);
        return $stmt->fetch() ?: null;
    }

    public function forwardReplyToClient(array $relay, string $lawyerReply, PDO $pdo): void
    {
        $client = get_user($relay['client_id'], $pdo);

        $clientMessage = "📋 *Response from your lawyer:*\n\n" . $lawyerReply;

        send_whatsapp_text($client['wa_number'], $clientMessage);

        // Update relay log — both sides of the relay are now complete
        $pdo->prepare(
            'UPDATE relay_log SET status = \'completed\', lawyer_reply = ?, completed_at = NOW()
             WHERE id = ?'
        )->execute([$lawyerReply, $relay['id']]);
    }
}

The Relay Audit Log

CREATE TABLE relay_log (
  id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  team_id         INT UNSIGNED NOT NULL,
  matter_id       BIGINT UNSIGNED NOT NULL,
  client_id       INT UNSIGNED NOT NULL,
  lawyer_id       INT UNSIGNED NOT NULL,
  client_question TEXT NOT NULL,
  lawyer_reply    TEXT DEFAULT NULL,
  status          ENUM('pending','completed','expired') NOT NULL DEFAULT 'pending',
  created_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  completed_at    DATETIME DEFAULT NULL,
  wa_client_msg_id VARCHAR(255) DEFAULT NULL,  -- traceability
  wa_lawyer_msg_id VARCHAR(255) DEFAULT NULL
);

What to Watch For

  • Relay expiry — If a lawyer doesn't reply within 48 hours, mark the relay as expired and notify the client that they should contact the office directly.
  • Relay reply disambiguation — If a lawyer has multiple pending relays, the system needs to ask which one they're replying to. Use numbered references in the relay message if multiple are pending.
  • Professional conduct — The relay creates an indirect communication channel. The lawyer must review the relayed question before it goes to the client, or the relay bypasses professional supervision. See S6-ADV6.