{"id":7933,"date":"2026-05-05T17:37:49","date_gmt":"2026-05-05T21:37:49","guid":{"rendered":"https:\/\/engineering.jhu.edu\/cmts\/?p=7933"},"modified":"2026-05-05T18:31:29","modified_gmt":"2026-05-05T22:31:29","slug":"from-chatbot-to-multichannel-ai-infrastructure","status":"publish","type":"post","link":"https:\/\/engineering.jhu.edu\/cmts\/from-chatbot-to-multichannel-ai-infrastructure\/","title":{"rendered":"From Chatbot to Multichannel AI Infrastructure: Expanding JayAI"},"content":{"rendered":"\n<!-- Paste this into a WordPress Custom HTML block -->\n<style>\n.wh-featured-image.wp-post-image {\n  display: none !important;\n}\n<\/style>\n<style>\n  .jayai-post {\n    --jp-ink: #122033;\n    --jp-muted: #52657a;\n    --jp-blue: #075db8;\n    --jp-navy: #08315f;\n    --jp-wash: #f6f9fc;\n    --jp-line: #d7e1eb;\n    font-family: \"Aptos\", \"Segoe UI\", system-ui, sans-serif;\n    color: var(--jp-ink);\n    max-width: 1120px;\n    margin: 0 auto;\n  }\n\n  .jayai-post * {\n    box-sizing: border-box;\n  }\n\n  .jayai-post .jayai-hero {\n    background:\n      radial-gradient(circle at top left, rgba(7, 93, 184, 0.14), transparent 34%),\n      linear-gradient(135deg, #ffffff 0%, #f4f9ff 100%);\n    border: 1px solid var(--jp-line);\n    border-radius: 24px;\n    padding: clamp(24px, 4vw, 44px);\n    margin: 0 0 28px;\n    box-shadow: 0 18px 50px rgba(18, 32, 51, 0.08);\n  }\n\n  .jayai-post h1 {\n    margin: 0 0 16px;\n    color: var(--jp-navy);\n    font-size: clamp(2rem, 4vw, 3.35rem);\n    line-height: 1.02;\n    letter-spacing: -0.045em;\n  }\n\n  .jayai-post .lead {\n    margin: 0;\n    color: var(--jp-muted);\n    font-size: clamp(1.05rem, 1.6vw, 1.28rem);\n    line-height: 1.55;\n    max-width: 850px;\n  }\n\n  .jayai-post .article-section {\n    margin: 30px 0;\n  }\n\n  .jayai-post h2 {\n    margin: 0 0 12px;\n    color: var(--jp-navy);\n    font-size: clamp(1.35rem, 2vw, 1.8rem);\n    letter-spacing: -0.025em;\n  }\n\n  .jayai-post p,\n  .jayai-post li {\n    color: var(--jp-muted);\n    font-size: 1.02rem;\n    line-height: 1.65;\n  }\n\n  .jayai-post p {\n    margin: 0 0 16px;\n  }\n\n  .jayai-post ul,\n  .jayai-post ol {\n    margin: 10px 0 0 1.3rem;\n    padding: 0;\n  }\n\n  .jayai-post li {\n    margin: 8px 0;\n  }\n\n  .jayai-post strong {\n    color: var(--jp-ink);\n  }\n\n  .jayai-post .callout {\n    margin: 24px 0;\n    padding: 16px 18px;\n    border-left: 5px solid var(--jp-blue);\n    border-radius: 14px;\n    background: #f0f7ff;\n  }\n\n  .jayai-post .callout p {\n    margin: 0;\n    color: #21364e;\n  }\n\n  .jayai-post .compact-grid {\n    display: grid;\n    grid-template-columns: repeat(3, minmax(0, 1fr));\n    gap: 14px;\n    margin: 18px 0 0;\n  }\n\n  .jayai-post .compact-card {\n    border: 1px solid var(--jp-line);\n    border-radius: 16px;\n    background: #ffffff;\n    padding: 16px;\n  }\n\n  .jayai-post .compact-card h3 {\n    margin: 0 0 8px;\n    color: var(--jp-ink);\n    font-size: 1rem;\n  }\n\n  .jayai-post .compact-card p {\n    margin: 0;\n    font-size: 0.96rem;\n  }\n\n  .jayai-post .note {\n    color: #66788a;\n    font-size: 0.93rem;\n  }\n\n  .jayai-post .scenario {\n    margin: 22px 0;\n    padding: 18px 20px;\n    border: 1px solid var(--jp-line);\n    border-radius: 18px;\n    background: #ffffff;\n    box-shadow: 0 12px 34px rgba(18, 32, 51, 0.06);\n  }\n\n  .jayai-post .scenario p {\n    margin: 0;\n  }\n\n  @media (max-width: 820px) {\n    .jayai-post .compact-grid {\n      grid-template-columns: 1fr;\n    }\n  }\n<\/style>\n<style>\n  .jayai-diagrams {\n    --ink: #122033;\n    --muted: #52657a;\n    --blue: #075db8;\n    --blue-2: #0b76d1;\n    --sky: #eaf5ff;\n    --navy: #08315f;\n    --green: #16855d;\n    --green-soft: #e8f7f0;\n    --gold: #c98518;\n    --gold-soft: #fff5df;\n    --line: #b9c8d8;\n    --card: #ffffff;\n    --wash: #f6f9fc;\n    font-family: \"Aptos\", \"Segoe UI\", system-ui, sans-serif;\n    color: var(--ink);\n    max-width: 1120px;\n    margin: 0 auto;\n  }\n\n  .jayai-diagrams * {\n    box-sizing: border-box;\n  }\n\n  .jayai-diagrams .intro {\n    margin: 0 0 24px;\n    color: var(--muted);\n    font-size: 1.05rem;\n    line-height: 1.55;\n  }\n\n  .jayai-diagrams .diagram-card {\n    background:\n      radial-gradient(circle at top left, rgba(7, 93, 184, 0.10), transparent 32%),\n      linear-gradient(180deg, #ffffff 0%, var(--wash) 100%);\n    border: 1px solid #d7e1eb;\n    border-radius: 22px;\n    box-shadow: 0 18px 50px rgba(18, 32, 51, 0.08);\n    margin: 26px 0;\n    padding: 24px;\n    overflow-x: auto;\n  }\n\n  .jayai-diagrams h2 {\n    margin: 0 0 8px;\n    font-size: clamp(1.35rem, 2vw, 1.75rem);\n    letter-spacing: -0.02em;\n    color: var(--navy);\n  }\n\n  .jayai-diagrams .caption {\n    margin: 0 0 18px;\n    color: var(--muted);\n    line-height: 1.5;\n  }\n\n  .jayai-diagrams svg {\n    display: block;\n    width: 100%;\n    height: auto;\n  }\n\n  .jayai-diagrams .box-title {\n    font: 700 18px\/1.2 \"Aptos\", \"Segoe UI\", sans-serif;\n    fill: var(--ink);\n  }\n\n  .jayai-diagrams .box-title-small {\n    font: 700 15px\/1.2 \"Aptos\", \"Segoe UI\", sans-serif;\n    fill: var(--ink);\n  }\n\n  .jayai-diagrams .box-text {\n    font: 500 13px\/1.3 \"Aptos\", \"Segoe UI\", sans-serif;\n    fill: var(--muted);\n  }\n\n  .jayai-diagrams .box-text-dark {\n    font: 600 13px\/1.3 \"Aptos\", \"Segoe UI\", sans-serif;\n    fill: #24364a;\n  }\n\n  .jayai-diagrams .label {\n    font: 700 12px\/1 \"Aptos\", \"Segoe UI\", sans-serif;\n    text-transform: uppercase;\n    letter-spacing: 0.08em;\n    fill: #55708c;\n  }\n\n  .jayai-diagrams .pill-text {\n    font: 700 13px\/1 \"Aptos\", \"Segoe UI\", sans-serif;\n    fill: #ffffff;\n  }\n\n  .jayai-diagrams .takeaway {\n    margin: 18px 0 0;\n    padding: 14px 16px;\n    border-left: 5px solid var(--blue);\n    border-radius: 14px;\n    background: #f0f7ff;\n    color: #21364e;\n    line-height: 1.45;\n  }\n\n  .jayai-diagrams .takeaway strong {\n    color: var(--navy);\n  }\n\n  @media (max-width: 760px) {\n    .jayai-diagrams .diagram-card {\n      padding: 16px;\n      border-radius: 18px;\n    }\n\n    .jayai-diagrams svg {\n      min-width: 760px;\n    }\n  }\n<\/style>\n\n<article class=\"jayai-post\">\n    <p class=\"lead\">\n      Launched in April, JayAI began as a website chat assistant for Johns Hopkins Engineering for Professionals. Since then, we&#8217;ve extended the same backend to an AI voice assistant on the main EP phone line, and an AI ticket assistant that drafts replies for staff review. This experience taught us a lesson about building a trusted AI foundation that can support multiple service channels without creating separate systems for each one.\n    <\/p>\n\n  <section class=\"article-section\">\n    <h2>Why this matters<\/h2>\n    <p>\n      Most users don&#8217;t think in terms of internal systems. They visit a website, send an email, call an office, or submit a ticket because they need an answer. Internally, those may be different workflows but, to the user, they are all part of the same service experience.\n    <\/p>\n    <p>\n      The important design choice was to avoid turning each channel into its own disconnected AI tool. Each channel has its own interface and safeguards, but each one connects back to the same governed backend: trusted knowledge, retrieval, routing logic, and tools.\n    <\/p>\n    <div class=\"scenario\">\n      <p>\n        For example, a prospective student might ask about the engineering management program through the website, call the office, or send an email that becomes a support ticket. Those should not be three separate support experiences with three separate sources of truth. They should be three entry points into the same trusted service layer.\n      <\/p>\n    <\/div>\n    <div class=\"callout\">\n      <p>Recognizing the need is the primary condition for design. \u2013Charles Eames<\/p>\n    <\/div>\n  <\/section>\n\n  <section class=\"article-section\">\n    <h2>The pattern<\/h2>\n    <p>\n      A practical multichannel AI system has three layers: user-facing channels, channel-specific workflows, and a shared knowledge foundation underneath. Each channel can have a different experience and different safeguards, while still drawing from the same trusted base.\n    <\/p>\n    <p>\n      Not every question should be handled the same way. Some answers should come from deterministic rules or structured data because they need to be exact and repeatable. Other questions benefit from retrieval and synthesis because the user needs explanation, comparison, or guidance. The shared backend makes that distinction once, then applies it consistently across channels.\n    <\/p>\n    <div class=\"compact-grid\">\n      <div class=\"compact-card\">\n        <h3>Website chat<\/h3>\n        <p>Visitors on ep.jhu.edu get answers grounded in EP content, with links back to the source.<\/p>\n      <\/div>\n      <div class=\"compact-card\">\n        <h3>Phone \/ voice<\/h3>\n        <p>Callers get a spoken answer, a transfer to the right office, or a structured callback the team can act on.<\/p>\n      <\/div>\n      <div class=\"compact-card\">\n        <h3>Email \/ ticket<\/h3>\n        <p>Each incoming email gets a draft response with supporting context, ready for staff to review, edit, and send.<\/p>\n      <\/div>\n    <\/div>\n    <p>\n      The email\/ticket workflow is intentionally review-first: JayAI prepares a draft and supporting context, but staff remain responsible for judgment, approval, escalation, and final response.\n    <\/p>\n  <\/section>\n\n  <div class=\"jayai-diagrams\">\n<section class=\"diagram-card\" aria-labelledby=\"business-diagram-title\">\n    <h2 id=\"business-diagram-title\">Business View: One AI Foundation, Multiple Channels<\/h2>\n    <p class=\"caption\">\n      This is the simplest way to explain the strategy: three different user experiences, one trusted EP knowledge and decision layer underneath.\n    <\/p>\n\n    <svg viewBox=\"0 0 1100 610\" role=\"img\" aria-labelledby=\"business-title business-desc\">\n      <title id=\"business-title\">JayAI multichannel business strategy diagram<\/title>\n      <desc id=\"business-desc\">Website chat, phone voice, and ticket drafting all reuse a shared JayAI backend made of trusted EP knowledge, routing logic, and quality feedback.<\/desc>\n      <defs>\n        <filter id=\"softShadow\" x=\"-20%\" y=\"-20%\" width=\"140%\" height=\"140%\">\n          <feDropShadow dx=\"0\" dy=\"10\" stdDeviation=\"12\" flood-color=\"#16324f\" flood-opacity=\"0.12\"\/>\n        <\/filter>\n        <marker id=\"arrowBlue\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"8\" markerHeight=\"8\" orient=\"auto-start-reverse\">\n          <path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"#075db8\"\/>\n        <\/marker>\n      <\/defs>\n\n      <rect x=\"20\" y=\"20\" width=\"1060\" height=\"570\" rx=\"28\" fill=\"#f7fbff\" stroke=\"#d8e5f2\"\/>\n\n      <text x=\"550\" y=\"64\" text-anchor=\"middle\" class=\"label\">User-facing channels<\/text>\n\n      <g filter=\"url(#softShadow)\">\n        <rect x=\"70\" y=\"90\" width=\"285\" height=\"170\" rx=\"24\" fill=\"#ffffff\" stroke=\"#bfd5eb\"\/>\n        <circle cx=\"112\" cy=\"132\" r=\"23\" fill=\"#eaf5ff\" stroke=\"#83b6e8\"\/>\n        <path d=\"M100 122 h24 a6 6 0 0 1 6 6 v8 a6 6 0 0 1 -6 6 h-8 l-10 7 v-7 h-6 a6 6 0 0 1 -6 -6 v-8 a6 6 0 0 1 6 -6 z\" fill=\"none\" stroke=\"#075db8\" stroke-width=\"3\" stroke-linejoin=\"round\"\/>\n        <circle cx=\"105\" cy=\"132\" r=\"1.8\" fill=\"#075db8\"\/>\n        <circle cx=\"112\" cy=\"132\" r=\"1.8\" fill=\"#075db8\"\/>\n        <circle cx=\"119\" cy=\"132\" r=\"1.8\" fill=\"#075db8\"\/>\n        <text x=\"145\" y=\"126\" class=\"box-title-small\">AI Chat Assistant<\/text>\n        <text x=\"145\" y=\"150\" class=\"box-text\">Visitors on ep.jhu.edu ask<\/text>\n        <text x=\"145\" y=\"170\" class=\"box-text\">questions inside the site.<\/text>\n        <rect x=\"96\" y=\"206\" width=\"232\" height=\"34\" rx=\"17\" fill=\"#eaf5ff\"\/>\n        <text x=\"212\" y=\"228\" text-anchor=\"middle\" class=\"box-text-dark\">ep.jhu.edu \/ JayAI<\/text>\n      <\/g>\n\n      <g filter=\"url(#softShadow)\">\n        <rect x=\"408\" y=\"90\" width=\"285\" height=\"170\" rx=\"24\" fill=\"#ffffff\" stroke=\"#bfd5eb\"\/>\n        <circle cx=\"450\" cy=\"132\" r=\"23\" fill=\"#e8f7f0\" stroke=\"#79c6a6\"\/>\n        <path d=\"M439 121 c2 14 10 22 24 24 l5 -7 -8 -5 -4 4 c-5 -2 -9 -6 -11 -11 l4 -4 -5 -8 z\" fill=\"none\" stroke=\"#16855d\" stroke-width=\"3\" stroke-linejoin=\"round\" stroke-linecap=\"round\"\/>\n        <text x=\"483\" y=\"126\" class=\"box-title-small\">AI Voice Assistant<\/text>\n        <text x=\"483\" y=\"150\" class=\"box-text\">Calls to (410) 516-2300 get<\/text>\n        <text x=\"483\" y=\"170\" class=\"box-text\">answers, routing, or handoff.<\/text>\n        <rect x=\"434\" y=\"206\" width=\"232\" height=\"34\" rx=\"17\" fill=\"#e8f7f0\"\/>\n        <text x=\"550\" y=\"228\" text-anchor=\"middle\" class=\"box-text-dark\">410-516-2300 \/ voice<\/text>\n      <\/g>\n\n      <g filter=\"url(#softShadow)\">\n        <rect x=\"746\" y=\"90\" width=\"285\" height=\"170\" rx=\"24\" fill=\"#ffffff\" stroke=\"#bfd5eb\"\/>\n        <circle cx=\"788\" cy=\"132\" r=\"23\" fill=\"#fff5df\" stroke=\"#e6b961\"\/>\n        <rect x=\"774\" y=\"122\" width=\"28\" height=\"21\" rx=\"4\" fill=\"none\" stroke=\"#c98518\" stroke-width=\"3\"\/>\n        <path d=\"M776 125 l12 10 12 -10\" fill=\"none\" stroke=\"#c98518\" stroke-width=\"3\" stroke-linejoin=\"round\" stroke-linecap=\"round\"\/>\n        <text x=\"821\" y=\"126\" class=\"box-title-small\">AI Email\/Ticket Assistant<\/text>\n        <text x=\"821\" y=\"150\" class=\"box-text\">Email to jhep@jhu.edu becomes<\/text>\n        <text x=\"821\" y=\"170\" class=\"box-text\">a ticket draft staff can review.<\/text>\n        <rect x=\"772\" y=\"206\" width=\"232\" height=\"34\" rx=\"17\" fill=\"#fff5df\"\/>\n        <text x=\"888\" y=\"228\" text-anchor=\"middle\" class=\"box-text-dark\">jhep@jhu.edu \/ ticketing<\/text>\n      <\/g>\n\n      <path d=\"M 212 270 C 250 330, 330 350, 408 374\" stroke=\"#075db8\" stroke-width=\"4\" fill=\"none\" marker-end=\"url(#arrowBlue)\"\/>\n      <path d=\"M 550 270 L 550 360\" stroke=\"#075db8\" stroke-width=\"4\" fill=\"none\" marker-end=\"url(#arrowBlue)\"\/>\n      <path d=\"M 888 270 C 850 330, 770 350, 692 374\" stroke=\"#075db8\" stroke-width=\"4\" fill=\"none\" marker-end=\"url(#arrowBlue)\"\/>\n\n      <g filter=\"url(#softShadow)\">\n        <rect x=\"275\" y=\"360\" width=\"550\" height=\"170\" rx=\"30\" fill=\"#08315f\"\/>\n        <text x=\"550\" y=\"405\" text-anchor=\"middle\" font-size=\"24\" font-weight=\"800\" fill=\"#ffffff\">Shared JayAI Backend<\/text>\n        <text x=\"550\" y=\"436\" text-anchor=\"middle\" font-size=\"15\" font-weight=\"600\" fill=\"#cfe6ff\">trusted knowledge, retrieval, routing, and tools.<\/text>\n        <g>\n          <rect x=\"320\" y=\"466\" width=\"146\" height=\"34\" rx=\"17\" fill=\"#0b76d1\"\/>\n          <text x=\"393\" y=\"488\" text-anchor=\"middle\" class=\"pill-text\">EP data<\/text>\n          <rect x=\"482\" y=\"466\" width=\"146\" height=\"34\" rx=\"17\" fill=\"#16855d\"\/>\n          <text x=\"555\" y=\"488\" text-anchor=\"middle\" class=\"pill-text\">official content<\/text>\n          <rect x=\"644\" y=\"466\" width=\"146\" height=\"34\" rx=\"17\" fill=\"#c98518\"\/>\n          <text x=\"717\" y=\"488\" text-anchor=\"middle\" class=\"pill-text\">routing logic<\/text>\n        <\/g>\n      <\/g>\n\n      <text x=\"550\" y=\"570\" text-anchor=\"middle\" class=\"box-text-dark\">The value is not three separate bots. It is one governed AI capability reused across the channels people already use.<\/text>\n    <\/svg>\n\n    <p class=\"takeaway\">\n      <strong>Plain-language takeaway:<\/strong> Build the trusted backend once, then expose it through chat, phone, and support workflows with channel-specific safeguards.\n    <\/p>\n  <\/section>\n\n  <section class=\"diagram-card\" aria-labelledby=\"infra-diagram-title\">\n    <h2 id=\"infra-diagram-title\">Infrastructure View: Shared Backend With Channel-Specific Interfaces<\/h2>\n    <p class=\"caption\">\n      This version is more technical but still high level: each channel has its own interface and orchestration layer, but they all reuse the same JayAI data, retrieval, answer rules, and model access path.\n    <\/p>\n\n    <svg viewBox=\"0 0 1100 760\" role=\"img\" aria-labelledby=\"infra-title infra-desc\">\n      <title id=\"infra-title\">JayAI multichannel infrastructure architecture<\/title>\n      <desc id=\"infra-desc\">Three channel interfaces connect through channel orchestration to a shared JayAI Worker backend, D1 data, AI Search, AI Gateway, and a quality feedback loop.<\/desc>\n      <defs>\n        <filter id=\"infraShadow\" x=\"-20%\" y=\"-20%\" width=\"140%\" height=\"140%\">\n          <feDropShadow dx=\"0\" dy=\"8\" stdDeviation=\"10\" flood-color=\"#16324f\" flood-opacity=\"0.11\"\/>\n        <\/filter>\n        <marker id=\"arrowGray\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\">\n          <path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"#6d8298\"\/>\n        <\/marker>\n        <marker id=\"arrowGreen\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\">\n          <path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"#16855d\"\/>\n        <\/marker>\n      <\/defs>\n\n      <rect x=\"20\" y=\"20\" width=\"1060\" height=\"720\" rx=\"28\" fill=\"#ffffff\" stroke=\"#d8e5f2\"\/>\n\n      <text x=\"88\" y=\"70\" class=\"label\">1. Channels<\/text>\n      <text x=\"418\" y=\"70\" class=\"label\">2. Channel orchestration<\/text>\n      <text x=\"734\" y=\"70\" class=\"label\">3. Shared JayAI core<\/text>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"65\" y=\"100\" width=\"245\" height=\"92\" rx=\"20\" fill=\"#eaf5ff\" stroke=\"#91bfe9\"\/>\n        <text x=\"90\" y=\"132\" class=\"box-title-small\">Website chat<\/text>\n        <text x=\"90\" y=\"156\" class=\"box-text\">ep.jhu.edu visitors<\/text>\n        <text x=\"90\" y=\"176\" class=\"box-text\">Embedded JayAI widget<\/text>\n      <\/g>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"65\" y=\"225\" width=\"245\" height=\"92\" rx=\"20\" fill=\"#e8f7f0\" stroke=\"#8ccdaf\"\/>\n        <text x=\"90\" y=\"257\" class=\"box-title-small\">Phone \/ voice<\/text>\n        <text x=\"90\" y=\"281\" class=\"box-text\">(410) 516-2300 calls<\/text>\n        <text x=\"90\" y=\"301\" class=\"box-text\">Realtime voice + routing<\/text>\n      <\/g>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"65\" y=\"350\" width=\"245\" height=\"92\" rx=\"20\" fill=\"#fff5df\" stroke=\"#e7bf72\"\/>\n        <text x=\"90\" y=\"382\" class=\"box-title-small\">Email \/ ticket<\/text>\n        <text x=\"90\" y=\"406\" class=\"box-text\">jhep@jhu.edu emails<\/text>\n        <text x=\"90\" y=\"426\" class=\"box-text\">Ticketing system drafts<\/text>\n      <\/g>\n\n      <path d=\"M310 146 H382\" stroke=\"#6d8298\" stroke-width=\"3\" fill=\"none\" marker-end=\"url(#arrowGray)\"\/>\n      <path d=\"M310 271 H382\" stroke=\"#6d8298\" stroke-width=\"3\" fill=\"none\" marker-end=\"url(#arrowGray)\"\/>\n      <path d=\"M310 396 H382\" stroke=\"#6d8298\" stroke-width=\"3\" fill=\"none\" marker-end=\"url(#arrowGray)\"\/>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"385\" y=\"100\" width=\"270\" height=\"92\" rx=\"20\" fill=\"#ffffff\" stroke=\"#cddbea\"\/>\n        <text x=\"410\" y=\"132\" class=\"box-title-small\">Chat runtime<\/text>\n        <text x=\"410\" y=\"156\" class=\"box-text\">Cloudflare Pages + Worker<\/text>\n        <text x=\"410\" y=\"176\" class=\"box-text\">Agents SDK session state<\/text>\n      <\/g>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"385\" y=\"225\" width=\"270\" height=\"92\" rx=\"20\" fill=\"#ffffff\" stroke=\"#cddbea\"\/>\n        <text x=\"410\" y=\"257\" class=\"box-title-small\">Voice runtime<\/text>\n        <text x=\"410\" y=\"281\" class=\"box-text\">OpenAI Realtime SIP<\/text>\n        <text x=\"410\" y=\"301\" class=\"box-text\">Cloudflare Worker + Durable Object<\/text>\n      <\/g>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"385\" y=\"350\" width=\"270\" height=\"92\" rx=\"20\" fill=\"#ffffff\" stroke=\"#cddbea\"\/>\n        <text x=\"410\" y=\"382\" class=\"box-title-small\">Support runtime<\/text>\n        <text x=\"410\" y=\"406\" class=\"box-text\">Ticketing webhook + Queue<\/text>\n        <text x=\"410\" y=\"426\" class=\"box-text\">Draft run stored for staff review<\/text>\n      <\/g>\n\n      <path d=\"M655 146 C705 146, 690 214, 735 232\" stroke=\"#6d8298\" stroke-width=\"3\" fill=\"none\" marker-end=\"url(#arrowGray)\"\/>\n      <path d=\"M655 271 H735\" stroke=\"#16855d\" stroke-width=\"4\" fill=\"none\" marker-end=\"url(#arrowGreen)\"\/>\n      <path d=\"M655 396 C705 396, 690 332, 735 314\" stroke=\"#6d8298\" stroke-width=\"3\" fill=\"none\" marker-end=\"url(#arrowGray)\"\/>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"735\" y=\"205\" width=\"300\" height=\"150\" rx=\"24\" fill=\"#08315f\"\/>\n        <text x=\"885\" y=\"246\" text-anchor=\"middle\" font-size=\"21\" font-weight=\"800\" fill=\"#ffffff\">JayAI Worker Backend<\/text>\n        <text x=\"885\" y=\"276\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"600\" fill=\"#cfe6ff\">shared answer logic + tool orchestration<\/text>\n        <text x=\"885\" y=\"304\" text-anchor=\"middle\" font-size=\"13\" fill=\"#cfe6ff\">channel APIs for chat, voice, and support<\/text>\n        <text x=\"885\" y=\"328\" text-anchor=\"middle\" font-size=\"13\" fill=\"#cfe6ff\">protected access and service boundaries<\/text>\n      <\/g>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"120\" y=\"500\" width=\"190\" height=\"92\" rx=\"20\" fill=\"#f7fbff\" stroke=\"#cddbea\"\/>\n        <text x=\"145\" y=\"532\" class=\"box-title-small\">Structured data<\/text>\n        <text x=\"145\" y=\"556\" class=\"box-text\">D1: programs, courses,<\/text>\n        <text x=\"145\" y=\"576\" class=\"box-text\">people, fast facts, history<\/text>\n      <\/g>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"340\" y=\"500\" width=\"190\" height=\"92\" rx=\"20\" fill=\"#f7fbff\" stroke=\"#cddbea\"\/>\n        <text x=\"365\" y=\"532\" class=\"box-title-small\">Official content<\/text>\n        <text x=\"365\" y=\"556\" class=\"box-text\">AI Search over EP<\/text>\n        <text x=\"365\" y=\"576\" class=\"box-text\">website\/source corpus<\/text>\n      <\/g>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"560\" y=\"500\" width=\"190\" height=\"92\" rx=\"20\" fill=\"#f7fbff\" stroke=\"#cddbea\"\/>\n        <text x=\"585\" y=\"532\" class=\"box-title-small\">Rules + tools<\/text>\n        <text x=\"585\" y=\"556\" class=\"box-text\">Deterministic routing,<\/text>\n        <text x=\"585\" y=\"576\" class=\"box-text\">guardrails, handoff logic<\/text>\n      <\/g>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"780\" y=\"500\" width=\"190\" height=\"92\" rx=\"20\" fill=\"#f7fbff\" stroke=\"#cddbea\"\/>\n        <text x=\"805\" y=\"532\" class=\"box-title-small\">Model layer<\/text>\n        <text x=\"805\" y=\"556\" class=\"box-text\">OpenAI via Cloudflare<\/text>\n        <text x=\"805\" y=\"576\" class=\"box-text\">AI Gateway<\/text>\n      <\/g>\n\n      <path d=\"M805 355 C730 475, 315 470, 215 500\" stroke=\"#6d8298\" stroke-width=\"3\" fill=\"none\" marker-end=\"url(#arrowGray)\"\/>\n      <path d=\"M855 355 C805 440, 490 440, 435 500\" stroke=\"#6d8298\" stroke-width=\"3\" fill=\"none\" marker-end=\"url(#arrowGray)\"\/>\n      <path d=\"M910 355 C865 440, 700 440, 655 500\" stroke=\"#6d8298\" stroke-width=\"3\" fill=\"none\" marker-end=\"url(#arrowGray)\"\/>\n      <path d=\"M955 355 C945 430, 905 450, 875 500\" stroke=\"#6d8298\" stroke-width=\"3\" fill=\"none\" marker-end=\"url(#arrowGray)\"\/>\n\n      <g filter=\"url(#infraShadow)\">\n        <rect x=\"60\" y=\"646\" width=\"980\" height=\"58\" rx=\"22\" fill=\"#f0f7ff\" stroke=\"#b9d6f2\"\/>\n        <text x=\"550\" y=\"681\" text-anchor=\"middle\" font-size=\"12.3\" font-weight=\"700\" fill=\"#24364a\">Logging, quality checks, transcript\/draft review, and human feedback improve the shared layer for every channel.<\/text>\n      <\/g>\n\n      <path d=\"M920 646 C1040 600, 1060 440, 1010 356\" stroke=\"#16855d\" stroke-width=\"3\" fill=\"none\" stroke-dasharray=\"8 8\" marker-end=\"url(#arrowGreen)\"\/>\n    <\/svg>\n\n    <p class=\"takeaway\">\n      <strong>Technical takeaway:<\/strong> the channel code stays separate, but the knowledge layer is shared. That keeps answers consistent while allowing each channel to have its own UX, safety rules, routing behavior, and human review model. The latency budget of each channel turned out to be the most consequential design constraint. Voice was hardest by far since a caller expects an answer in seconds, which leaves no room to query many sources, run heavier reasoning models, or revise a draft before speaking. Chat sits in the middle. It has to feel responsive, but there&#8217;s space for retrieval and lighter reasoning. Email and ticketing are the most forgiving where you have minutes or hours of working time, and the system can use reasoning models, chain more tools, pull from more data, and produce a draft before staff review.<br \/><br \/>\nThe bigger takeaway is that user expectations of speed shape both answer quality and the architecture underneath. The faster the channel, the harder to integrate depth, sourcing, and reasoning, and the more those constraints ripple through every layer of the system.\n    <\/p>\n  <\/section>\n<\/div>\n\n  <section class=\"article-section\">\n    <h2>What this means for labor<\/h2>\n    <p>\n      The goal is to reduce repetitive intake, help users get to the right answer faster, and give staff better starting points for review, escalation, and advising.\n    <\/p>\n    <p>\n      When the shared knowledge layer improves, every channel can benefit. That creates a better service loop where user questions reveal gaps, quality checks identify weak spots, and staff feedback improves the underlying system over time. But by building in careful engineering harnessing, you can monitor the user logs in addition to staff feedback every 24 hours and have the system iterate, test, and push enhancements. \n    <\/p>\n  <\/section>\n\n  <section class=\"article-section\">\n    <h2>What other teams can reuse<\/h2>\n    <p>\n      The reusable lesson is the pattern, not the interface. Start with real user questions, identify trusted information sources, separate exact-answer workflows from interpretive guidance workflows, and keep human review in the loop where judgment matters.\n    <\/p>\n    <ol>\n      <li>Start with the questions people actually ask.<\/li>\n      <li>Identify the trusted sources of truth.<\/li>\n      <li>Separate exact-answer workflows from interpretive guidance workflows.<\/li>\n      <li>Keep human review in the loop where judgment matters.<\/li>\n      <li>Assign clear ownership for content, rules, escalation paths, and quality review.<\/li>\n      <li>Measure usage, gaps, handoffs, and draft quality from day one.<\/li>\n    <\/ol>\n  <\/section>\n<\/article>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Launched in April, JayAI began as a website chat assistant for Johns Hopkins Engineering for Professionals. Since then, we&#8217;ve extended the same backend to an AI voice assistant on the&nbsp;<a href=\"https:\/\/engineering.jhu.edu\/cmts\/from-chatbot-to-multichannel-ai-infrastructure\/\">&hellip;<\/a><\/p>\n","protected":false},"author":7,"featured_media":7981,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[384],"tags":[388],"class_list":["post-7933","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology","tag-artificial-intelligence","odd"],"acf":[],"_links":{"self":[{"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/posts\/7933","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/comments?post=7933"}],"version-history":[{"count":10,"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/posts\/7933\/revisions"}],"predecessor-version":[{"id":7978,"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/posts\/7933\/revisions\/7978"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/media\/7981"}],"wp:attachment":[{"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/media?parent=7933"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/categories?post=7933"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/engineering.jhu.edu\/cmts\/wp-json\/wp\/v2\/tags?post=7933"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}