Rela AIRela AI Docs
Machine Agents

Technician handoff via WhatsApp

How the industrial event reaches the technician with full context — no re-identification, no context loss.

Technician handoff via WhatsApp

When the industrial agent detects a critical event and opens a task, the technician receives a WhatsApp with all the machine information. On reply, they can ask about manuals or report the task closure without re-identifying. This page describes the end-to-end flow.

Executive summary

The game changer: the technician no longer types "I'm Juan from the afternoon shift, machine 042 is failing". They reply to the same WhatsApp with "what's the procedure?" and the agent already knows who they are, which machine is failing, and which task is open.

Before the handoff the technician had to:

  1. Read the event WhatsApp.
  2. Open another window to look up the manual.
  3. Authenticate to the conversational agent with their ID to see restricted documents.
  4. Copy the asset_id manually into the query.

With the handoff: they reply to the same WhatsApp and everything is in context.

What it does

  • Removes identification friction. The phone that receives the WhatsApp is already tied to the registered personnel. The session is pre-authenticated with the technician's roles automatically.
  • Preserves context between agents. The industrial agent processes events; the WhatsApp agent converses. Without handoff, the latter has no idea what triggered the thread. With handoff, it does.
  • Scopes searches to the actual asset. When the technician asks "how do I clean it?", the agent answers about the AST-042 pump that's failing, not about any pump in the catalog.
  • Supports concurrent events. If a technician gets two tasks on different assets within the hour, both contexts stay active on the conversation and the agent distinguishes them on reply.

How it works

sequenceDiagram
    participant PLC as Sensor / PLC
    participant MA as Machine agent
    participant DB as MongoDB
    participant WA as WhatsApp
    participant T as Technician
    participant CA as Conversational agent

    PLC->>MA: Event (overheating, AST-042, critical)
    MA->>MA: assign_task → task MAN-001
    MA->>DB: push_machine_context(conv, asset_id, task_id, personnel_id)
    MA->>WA: send_whatsapp_message (deterministic template)
    WA->>T: "🔴 MAN-001 Asset AST-042 · overheating..."
    T->>WA: "what manual applies?"
    WA->>CA: webhook (conversation = Juan)
    CA->>DB: reads active machine_contexts + personnel roles
    CA->>CA: enriched prompt + pre-authenticated session
    CA->>DB: query manuals with implicit asset_id
    DB-->>CA: AST-042 manual section
    CA->>T: "Procedure 4.2: purge the coolant circuit..."

Step by step

  1. The industrial agent creates the task and notifies. When calling assign_task, the service stores three things on the technician's WhatsApp conversation:
    • personnel_id: who the recipient is.
    • machine_contexts[]: stack of active industrial contexts with asset_id, task_id, event_id, severity, diagnosis, 6-hour TTL.
    • The outbound message: deterministic template with severity, asset, task code, and an invitation to reply.
  2. The technician replies. Evolution API delivers the message to the Rela-ai webhook. The webhook finds the conversation by phone.
  3. The session is pre-authenticated. The webhook reads personnel_id, resolves the technician in _personnel, inherits their roles, and elevates the session to authenticated with preauth_source="personnel".
  4. The prompt is enriched. The conversational agent builds its prompt with: normal system prompt + active industrial contexts (one per open event) + user message.
  5. Queries are scoped to the asset. When the agent calls a query tool (manuals, procedures, history), the dispatcher injects asset_id from the active context as an implicit filter. The LLM doesn't have to repeat it.
  6. Closing is another tool. If the technician says "it's fixed", the agent calls update_task with status=done and the technician's notes. The task state flips; the related alert can close.

TTL and multi-context

Every entry in machine_contexts[] carries triggered_at and expires_at = triggered_at + 6h. The internal job POST /internal/cleanup-machine-context runs hourly and purges expired entries.

If two events arrive for the same technician on different assets, the stack has two active entries. The prompt shows the agent one block per event:

Active industrial context (2 open tickets)

[1] MAN-001 · Asset AST-042 · overheating (critical)
    Diagnosis: purge the coolant circuit...

[2] MAN-002 · Asset AST-105 · vibration anomaly (high)
    Diagnosis: bearing misaligned, adjust torque...

The technician says "the second one" and the agent knows they mean AST-105.

Configuration

The whole handoff is activated by configuring the machine agent notification under Machine agent → Notifications:

  1. Enable WhatsApp.
  2. Select the connected number.
  3. Pick Recipient = a technician registered in Personnel.

Selecting a registered technician (not "Custom number") is what activates pre-authentication and context preservation. If you pick a custom number without personnel, the WhatsApp still sends but the technician starts anonymously and won't be able to query collections with access_roles configured.

Technician roles

Technician roles live in _personnel.roles (string array). The system inherits them as-is into the session. If the technician has role technician and a manuals collection has access_roles: ["technician"], the query passes.

If a collection has access_roles not present in the technician's roles, the query fails with a natural-language reply: "I don't have permission to look up that information with your profile." — the agent never returns raw JSON to the user.

Limitations

  • The handoff requires the technician's phone in _personnel.phone to exactly match what the PLC sent to the agent. Different formats won't match.
  • A single WhatsApp number serves one conversational agent per tenant. You can't have two WhatsApp agents pointing at the same number.
  • Pre-authentication assumes the phone is a sufficient identity factor. If a technician loses their phone, anyone with that number can query until the record is updated or explicit OTP auth is added.
  • Expired contexts (older than 6 hours since push) are not rendered or used even if they remain in the array until the cleanup job runs.
  • asset_id only propagates if the event carries it in metadata.asset_id. Mismapped sensors don't propagate context.

Key benefits

  • Single WhatsApp thread, no double identification.
  • Agent answers scoped to the real asset from the first question.
  • Multi-ticket: the technician handles several open events without mixing.
  • Conversational task closure without opening the dashboard.
  • Automatic context expiration so old conversations don't bias future answers.

How to verify

The script scripts/e2e/machine_agent_demo/run_demo.py in the relaai-api repo runs the end-to-end flow against a real tenant (without sending real WhatsApp or calling Gemini). It validates that the context is persisted, the session is pre-authenticated with the right roles, and the cleanup purges expired entries.

On this page