Skip to main content

Employee App (Claway App)

The Claway employee app gives every rostered employee a first-class chat client — mobile (iOS/Android), desktop (macOS/Windows), and web, one Flutter codebase — alongside the WhatsApp channel. An employee's 1:1 conversation with the agent is one unified thread across WhatsApp and the app: history, context, and memory are shared, and the agent replies on whichever channel the employee last spoke on.

Enabling the employee plane​

  1. Set a signing secret in .env (a credential — never config.yaml):

    EMPLOYEE_JWT_SECRET=$(openssl rand -hex 32)
  2. Enable the plane in config.yaml:

    employee_auth:
    enabled: true
    workspace_name: "Acme Ltd"
    otp:
    channel: whatsapp # login codes are sent via your own WhatsApp connector
    unified_dm_platform: whatsapp # whatsapp_cloud for Meta Cloud API tenants
    host: 127.0.0.1 # 0.0.0.0 for direct LAN/VPN access (behind TLS)
    port: 8643
  3. Restart the gateway. The plane refuses to start without a strong EMPLOYEE_JWT_SECRET and warns loudly when unified_dm_platform mismatches the enabled WhatsApp adapter, or when the roster has no active admin.

Rostering employees​

Enrollment is fail-closed: only phones an admin has rostered can ever receive a login code. The first admin is added:

  • on a Claway Box, by the activation page (required "Admin mobile");
  • in OPS → Users ("No App admin yet — add one");
  • on the box, as the service user: claway employees add --phone '+852 9123 4567' --role admin --name Alice;
  • by HQ, through the panel's employees.add_admin (only while the roster has no active admin).

Active rostered employees with a phone may also message the bot on WhatsApp: the DM allowlist the bridge enforces is the operator's own list plus the roster ($CLAWAY_HOME/whatsapp/roster_allowlist.json, kept in step automatically, no restart). Disabling someone removes only that roster entry — numbers the operator allowlisted by hand are never touched.

After that, admins manage the roster from the app's Admin section (add/disable employees, devices, usage) or via POST /app/v1/admin/employees.

Login flow​

Phone number → 6-digit code delivered through the company's own WhatsApp connector (the code arriving at the exact WhatsApp account being linked is itself the identity check; SIM-swap-resistant) → 15-min access token + 30-day rotating refresh token per device.

Connection modes​

  • Direct — the app connects straight to http(s)://<instance>:8643. LAN, VPN, or public endpoint; zero intermediaries.
  • Relay — for instances behind NAT and for store push notifications, configure employee_auth.relay.url (and EMPLOYEE_RELAY_TOKEN in .env). The instance dials OUT to the Claway App Relay; the relay routes opaque frames by workspace id and holds only push tokens — never rosters, OTPs, or message content. Push bodies are redacted by default (push_redaction: true).

Groups​

  • App groups: employees + the agent in one shared conversation. respond_mode: mention (default) makes the agent answer only when @'d, like a WhatsApp group; all answers every message.
  • Bridged groups: an admin can link an app group to an existing WhatsApp group (Admin → group → link, or POST /app/v1/groups/{id}/link with the group JID). Messages flow both ways — app-side messages appear in the WhatsApp group prefixed [Name], agent replies go to the WhatsApp group and mirror into the app. Full context merge across both sides requires group_sessions_per_user: false in the gateway config (the plane warns at link time otherwise).

Protocol​

Client developers: the full REST + WebSocket contract is in docs/app-client-protocol.md in the repository.