Course / Module 21

Multimodal journeys

Designing tasks that move across voice, chat, screens, images and documents: choosing the right modality, carrying context and identity, handling images and files, and testing cross-channel flows.

13 min study timeDesignCodeLast reviewed Markdown version

In short

  • A journey is the whole task, not one channel. Design the seams.
  • Use voice for intent and confirmation, screens for choices, and images or files for evidence.

What you will learn

  • Map a journey across channels and modalities, with explicit handoff points
  • Choose the right modality for each step
  • Carry context, identity and consent safely between channels
  • Design image and document steps with confirmation and privacy in mind
  • Test cross-channel journeys end to end

From channels to journeys

Customers don't think in channels. They think in tasks: "file a claim," "change my trip," "fix my bill." A multimodal journey is a task that spans voice, chat, apps, web pages, images and documents. The craft is in the seams: how context, identity and trust move when the modality changes.

Choose the right modality for each step

Modality Strong at Weak at
Voice Stating goals, quick confirmations, hands-free use Lists, comparisons, long or sensitive entry
Chat Asynchronous conversation, links, short forms Complex layouts, high urgency
Screen or app Choices, comparison, rich input, secure entry Open-ended explanation
Image or video Evidence (damage, a product, a document), location Interpretation without confirmation
Document upload Structured data from existing papers Quality varies, privacy risk
Notification or message Reminders, status, re-engagement Anything needing a long reply

Switch only when it helps

Every modality change adds friction. Switch because the next step is clearly better elsewhere (a photo, a card number, a comparison), not because a channel exists.

Map the journey

Draw a swimlane diagram with one lane per channel and mark every handoff. For each seam, define:

  1. Why the switch happens, and how you explain it to the user.
  2. What travels: a summary of the task, collected values, the identity level reached and consent given.
  3. How it travels: a signed, expiring reference to context on your server, not a pile of data in a link.
  4. How they return: a way back, and what happens if they never complete the step.
  5. What if it fails: a fallback (module 11).
Phone call: intent and identityText message: secure linkWeb page: photo upload and detailsChat: confirmation and status updatesHuman review if needed

An insurance claim across five touchpoints. The seams are where journeys break.

Moving from a call to a photo
To process the damage claim I need photos of the car. It's easier on your phone than by voice. May I text you a secure link?
Yes, please.
Sent to the number ending 4421. The link works for 30 minutes. I'll stay on the line, or you can hang up and I'll update you by message when the photos arrive.
  • Step-up authentication. Verify identity at the level the next action needs, and re-verify when moving to a riskier action.
  • Short-lived, single-purpose links and one-time codes. Never place personal data in a URL.
  • Channel-appropriate content. Don't send sensitive details over channels that are easy to intercept.
  • Consent per channel and purpose. Permission to talk on the phone isn't permission to text (module 13).
  • Data minimization. Pass references, not records.

A signed, expiring resume token is a simple building block:

python
import base64, hashlib, hmac, json, time

SECRET = b"load-from-your-secret-manager"          # never hard-code in production

def make_resume_token(journey_id: str, step: str, ttl_seconds: int = 1800) -> str:
    payload = {"j": journey_id, "s": step, "exp": int(time.time()) + ttl_seconds}
    body = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=")
    sig = hmac.new(SECRET, body.encode(), hashlib.sha256).hexdigest()
    return f"{body}.{sig}"

def read_resume_token(token: str) -> dict | None:
    try:
        body, sig = token.split(".")
        expected = hmac.new(SECRET, body.encode(), hashlib.sha256).hexdigest()
        if not hmac.compare_digest(sig, expected):
            return None
        payload = json.loads(base64.urlsafe_b64decode(body + "=" * (-len(body) % 4)))
        return payload if payload["exp"] > time.time() else None
    except Exception:
        return None

The token only names the journey and step. The actual task state lives on your server, behind authentication.

Images and documents

Modern models can interpret images and documents, which opens strong journeys and new risks.

Images - Good uses: damage and condition evidence, product identification, reading labels and screens, location context. - Failure modes: blur, poor light, the wrong object, misreading text, over-confident descriptions. - Design: guide the capture ("show the whole bumper, in daylight"), check quality before analysis, say what the assistant sees and ask the user to confirm, and keep humans in the loop for decisions with consequences. - Privacy: faces, documents and background details, plus location data embedded in files. Collect only what you need, tell people how it's used and how long it's kept.

Documents - Extract fields, then show them and ask for confirmation or correction before acting. - Validate against rules (dates in range, totals that add up, required fields present). - Treat uploaded files as untrusted input: they can contain hidden instructions (module 18).

Screen and rich responses

Chat doesn't have to be text only. Cards, buttons, forms and carousels can make choices clearer. Emerging standards extend protocols such as MCP with ways for tools to return interface components (the 2026-07-28 MCP specification formalized extensions including MCP Apps). Support varies by client, so design a plain-text equivalent for every rich response (module 8).

Architecture

Channel adapters: voice, chat, app, web, messagingNormalization layerConversation and journey service with shared stateAssistant, tools and knowledgeRendering per channel

One journey state, many renderers.

Keep a journey ID that follows the customer across channels, a shared state store for the task, and per-channel rendering so the same decision appears as speech, a message or a screen as appropriate.

Test cross-channel journeys

  • End-to-end scenarios that cross channels, with time gaps between steps.
  • Resume tests: expired links, a second device, a different channel, a returning user.
  • Failure injection: upload fails, link never opened, call drops mid-step (module 11).
  • Security tests: reused or tampered tokens, wrong-person access.
  • Accessibility: every step has an alternative for people who can't see, hear or speak.
  • Analytics keyed by journey ID: drop-off at each seam, time between steps, and completion by path (module 17).

Key takeaways

  • A journey is the whole task, not one channel. Design the seams.
  • Use voice for intent and confirmation, screens for choices, and images or files for evidence.
  • Carry a minimal, secure bundle of context across every switch.
  • Every modality change needs a reason, consent and a way back.

Knowledge check