{"id":13991,"date":"2026-08-25T09:57:33","date_gmt":"2026-08-25T09:57:33","guid":{"rendered":"https:\/\/www.xgrid.co\/resources\/?post_type=success-stories&#038;p=13991"},"modified":"2026-09-01T08:03:06","modified_gmt":"2026-09-01T08:03:06","slug":"multi-agent-system-observability-temporal","status":"publish","type":"success-stories","link":"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/","title":{"rendered":"Multi-Agent System Observability with Temporal: How We Cut Cost 65% and Latency 70%"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"13991\" class=\"elementor elementor-13991\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a085f3a e-con-full e-flex e-con e-parent\" data-id=\"a085f3a\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-22c3a77 elementor-widget elementor-widget-html\" data-id=\"22c3a77\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\r\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap\" rel=\"stylesheet\">\r\n\r\n<style>\r\n\/* \u2550\u2550 1. DESIGN TOKENS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n:root{\r\n  \/* \u2014 Brand colors \u2014 *\/\r\n  --paper:      #FFFFFF;   \/* page background            *\/\r\n  --paper-2:    #F5F6F8;   \/* alternating section wash   *\/\r\n  --paper-3:    #EEF0F4;   \/* insets \/ code surfaces     *\/\r\n  --ink:        #0A0E1A;   \/* primary text + dark panels *\/\r\n  --ink-2:      #3A4356;   \/* secondary text             *\/\r\n  --ink-3:      #6B7488;   \/* muted \/ captions \/ mono    *\/\r\n  --line:       #E3E6EC;   \/* hairlines & borders        *\/\r\n  --line-2:     #D2D7E0;   \/* stronger dividers          *\/\r\n\r\n  --brand:      #6f63de;   \/* Xgrid accent \u2014 \"agentic\/active\"  *\/\r\n  --brand-link:  #6f63de;   \/* accent for text\/hover on light   *\/\r\n  --brand-ink:  #6f63de; \r\n  --brand-tint: #EDF1FF;   \/* light accent wash                *\/\r\n  --ok:         #17805B;   \/* success\/\"validated\" ONLY         *\/\r\n  --ok-tint:    #E7F3EC;\r\n\r\n  --on-dark:    #EDEFF5;   \/* body text on --ink panels  *\/\r\n  --on-dark-2:  #9AA2B6;   \/* muted text on --ink panels *\/\r\n\r\n  \/* \u2014 Type families \u2014 *\/\r\n  --font-display: 'Bower-Bold' !important;;\r\n  --font-body:    \"Inter\", system-ui, sans-serif;\r\n  --font-mono:    \"JetBrains Mono\", ui-monospace, monospace;\r\n\r\n  \/* \u2014 Type scale (fluid) \u2014 *\/\r\n  --fs-mono:   0.75rem;   \/* 12px eyebrows \/ captions \/ labels *\/\r\n  --fs-small:  0.875rem;  \/* 14px                              *\/\r\n  --fs-body:   1.0625rem; \/* 17px body                         *\/\r\n  --fs-lead:   1.1875rem; \/* 19px lead paragraphs              *\/\r\n  --fs-h4:     1.0625rem; \/* 17px                              *\/\r\n  --fs-h3:     clamp(1.15rem, 1rem + 0.7vw, 1.375rem);\r\n  --fs-h2:     clamp(1.6rem, 1.25rem + 1.7vw, 2.25rem);\r\n  --fs-h1:     clamp(2.1rem, 1.4rem + 3.4vw, 3.5rem);\r\n  --fs-stat:   clamp(2.4rem, 1.6rem + 3.6vw, 3.75rem);\r\n\r\n  \/* \u2014 Spacing scale (8px base) \u2014 *\/\r\n  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px;\r\n  --s6:32px; --s7:48px; --s8:64px; --s9:80px; --s10:96px; --s11:120px;\r\n\r\n  \/* \u2014 Layout \u2014 *\/\r\n  --container: 1160px;   \/* full page width  *\/\r\n  --measure:   680px;    \/* prose reading width *\/\r\n  --radius:    14px;\r\n  --radius-sm: 9px;\r\n  --section-y: clamp(56px, 4vw + 40px, 104px);\r\n\r\n  --shadow-sm: 0 1px 2px rgba(10,14,26,.05), 0 1px 1px rgba(10,14,26,.04);\r\n  --shadow-md: 0 12px 34px -14px rgba(10,14,26,.18);\r\n}\r\n\r\n\/* \u2550\u2550 1b. BRAND DISPLAY FONT \u2014 Bower \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n@font-face{font-family:\"Bower\";font-style:normal;font-weight:500;font-display:swap;\r\n  src:local(\"Bower Medium\"),url(\"fonts\/Bower-Medium.woff2\") format(\"woff2\"),url(\"fonts\/Bower-Medium.woff\") format(\"woff\")}\r\n@font-face{font-family:\"Bower\";font-style:normal;font-weight:600;font-display:swap;\r\n  src:local(\"Bower SemiBold\"),url(\"fonts\/Bower-SemiBold.woff2\") format(\"woff2\"),url(\"fonts\/Bower-SemiBold.woff\") format(\"woff\")}\r\n@font-face{font-family:\"Bower\";font-style:normal;font-weight:700;font-display:swap;\r\n  src:local(\"Bower Bold\"),url(\"fonts\/Bower-Bold.woff2\") format(\"woff2\"),url(\"fonts\/Bower-Bold.woff\") format(\"woff\")}\r\n\r\n\/* \u2550\u2550 2. RESET & BASE (Zero Horizontal Overflow) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n*,*::before,*::after{box-sizing:border-box}\r\n\r\nimg{max-width:100%;height:auto;display:block}\r\na{color:var(--brand-ink);text-decoration:none}\r\nh1,h2,h3,h4{margin:0;font-family:var(--font-display);line-height:1.16;\r\n  letter-spacing:-.02em;font-weight:600;color:var(--ink);word-break:break-word}\r\np{margin:0}\r\n::selection{background:var(--brand);color:#fff}\r\n:focus-visible{outline:2.5px solid var(--brand);outline-offset:3px;border-radius:3px}\r\n\r\n\/* \u2550\u2550 3. LAYOUT PRIMITIVES \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n\r\n.section{padding-block:var(--section-y);width:100%;overflow:hidden}\r\n.section--wash{background:var(--paper-2);border-block:1px solid var(--line)}\r\n.section--ink{background:var(--ink);color:var(--on-dark)}\r\n.section--ink h1,.section--ink h2,.section--ink h3,.section--ink h4{color:#fff}\r\n.measure{max-width:var(--measure)}\r\n.stack{display:flex;flex-direction:column;gap:var(--s4);min-width:0;max-width:100%}\r\n\r\n\/* \u2550\u2550 3b. TWO-COLUMN SPLIT GRIDS (Bounded minmax tracks prevent overflow) \u2550\u2550\u2550\u2550 *\/\r\n.two-col,\r\n.two-col--wide-left,\r\n.two-col--wide-right,\r\n.two-col--spine,\r\n.exec-cols {\r\n  display: grid;\r\n  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\r\n  gap: clamp(24px, 3.5vw, 48px);\r\n  align-items: start;\r\n  width: 100%;\r\n  max-width: 100%;\r\n  min-width: 0;\r\n}\r\n.two-col--wide-left {\r\n  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);\r\n}\r\n.two-col--wide-right {\r\n  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);\r\n}\r\n.two-col--spine {\r\n  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);\r\n}\r\n.exec-cols {\r\n  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);\r\n}\r\n\r\n.two-col > *,\r\n.two-col--wide-left > *,\r\n.two-col--wide-right > *,\r\n.two-col--spine > *,\r\n.exec-cols > * {\r\n  min-width: 0;\r\n  max-width: 100%;\r\n  overflow-wrap: break-word;\r\n}\r\n\r\n@media(max-width:960px){\r\n  .two-col,\r\n  .two-col--wide-left,\r\n  .two-col--wide-right,\r\n  .two-col--spine,\r\n  .exec-cols {\r\n    grid-template-columns: minmax(0, 1fr)!important;\r\n    gap: var(--s6)!important;\r\n  }\r\n}\r\n\r\n\/* \u2550\u2550 4. SYSTEM CHROME \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.eyebrow{font-family:var(--font-mono);font-size:var(--fs-mono);font-weight:500;\r\n  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);\r\n  display:inline-flex;align-items:center;gap:.6em;margin:0}\r\n.eyebrow .tick{width:16px;height:1px;background:var(--line-2);flex:none}\r\n.section--ink .eyebrow{color:var(--on-dark-2)}\r\n.eyebrow--brand{color:var(--brand-ink)}\r\n\r\n.slug{font-family:var(--font-mono);font-size:var(--fs-small);color:var(--ink-3);\r\n  letter-spacing:.02em;word-break:break-all}\r\n\r\n.sec-head{display:flex;flex-direction:column;gap:var(--s4);margin-bottom:var(--s7);min-width:0}\r\n.sec-head h2{font-size:var(--fs-h2)}\r\n.sec-head .lead{font-size:var(--fs-lead);color:var(--ink-2);max-width:var(--measure)}\r\n.section--ink .sec-head .lead{color:var(--on-dark)}\r\n\r\n\/* \u2550\u2550 5. BUTTONS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.btn{--_bg:var(--brand);--_fg:#fff;--_bd:var(--brand);\r\n  display:inline-flex;align-items:center;justify-content:center;gap:.55em;\r\n  font-family:var(--font-body);font-size:var(--fs-small);font-weight:600;\r\n  letter-spacing:.01em;line-height:1;padding:.85em 1.35em;border-radius:999px;\r\n  background:var(--_bg);color:var(--_fg);border:1.5px solid var(--_bd);\r\n  cursor:pointer;transition:transform .15s ease,box-shadow .2s ease,\r\n  background .2s ease,color .2s ease;text-align:center}\r\n.btn:hover{transform:translateY(-1px);box-shadow:0 8px 20px -8px rgba(42,91,255,.55)}\r\n.btn svg{width:15px;height:15px;flex:none}\r\n.btn--ghost{--_bg:transparent;--_fg:var(--ink);--_bd:var(--line-2)}\r\n.btn--ghost:hover{--_bd:var(--ink);box-shadow:none}\r\n.section--ink .btn--ghost{--_fg:#fff;--_bd:rgba(255,255,255,.28)}\r\n.section--ink .btn--ghost:hover{--_bd:#fff}\r\n.btn--lg{font-size:var(--fs-body);padding:1.05em 1.7em}\r\n.link-arrow{font-family:var(--font-body);font-weight:600;font-size:var(--fs-small);\r\n  color:var(--brand-ink);display:inline-flex;align-items:center;gap:.4em}\r\n.link-arrow svg{width:14px;height:14px;transition:transform .18s ease}\r\n.link-arrow:hover svg{transform:translateX(3px)}\r\n\r\n@media (max-width: 767px) {\r\n    .cta {\r\n        display: block;\r\n    }\r\n\r\n    .cta__actions {\r\n        margin-top: 20px;\r\n    }\r\n}\r\n\r\n\/* \u2550\u2550 7. HERO \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.hero{padding-block:clamp(56px,6vw,108px) 0}\r\n.hero__eyebrows{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s5);\r\n  align-items:center;margin-bottom:var(--s6)}\r\n.pill{font-family:var(--font-mono);font-size:var(--fs-mono);font-weight:500;\r\n  letter-spacing:.08em;text-transform:uppercase;color:var(--brand-ink);\r\n  background:var(--brand-tint);border:1px solid #DCE4FF;\r\n  padding:.4em .8em;border-radius:999px}\r\n.hero h1{font-size:var(--fs-h1);margin-block:0 var(--s6);     max-width: 850px;\r\n  font-weight:600;line-height:1.16}\r\n.hero__dek{font-size:var(--fs-lead);color:var(--ink-2); max-width: 850px;\r\n  line-height:1.55;}\r\n.hero__cta{display:flex;flex-wrap:wrap;gap:var(--s4);margin-top:var(--s7)}\r\n\r\n\/* Meta rail \u2014 4-up mono fact strip *\/\r\n.metarail{display:grid;grid-template-columns:repeat(4,1fr);\r\n  border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;\r\n  margin-top:var(--s8);background:var(--paper)}\r\n.metarail__cell{padding:var(--s5) var(--s5);border-right:1px solid var(--line)}\r\n.metarail__cell:last-child{border-right:0}\r\n.metarail__k{font-family:var(--font-mono);font-size:var(--fs-mono);\r\n  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);\r\n  display:block;margin-bottom:var(--s2)}\r\n.metarail__v{font-family:var(--font-display);font-weight:600;font-size:1.0625rem;\r\n  color:var(--ink);letter-spacing:-.01em;line-height:1.25}\r\n@media(max-width:760px){.metarail{grid-template-columns:1fr 1fr}\r\n  .metarail__cell{border-bottom:1px solid var(--line)}\r\n  .metarail__cell:nth-child(2n){border-right:0}\r\n  .metarail__cell:nth-last-child(-n+2){border-bottom:0}}\r\n@media(max-width:440px){.metarail{grid-template-columns:1fr}\r\n  .metarail__cell{border-right:0}\r\n  .metarail__cell:not(:last-child){border-bottom:1px solid var(--line)}}\r\n\r\n\/* \u2550\u2550 8. FIGURE \/ DIAGRAM FRAME \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.fig{margin:0;width:100%;max-width:100%}\r\n.fig__frame{position:relative;border:1px solid var(--line);border-radius:var(--radius);\r\n  background:\r\n    linear-gradient(0deg,transparent 23px,var(--line) 24px) 0 0\/24px 24px,\r\n    linear-gradient(90deg,transparent 23px,var(--line) 24px) 0 0\/24px 24px,\r\n    var(--paper-2);\r\n  background-blend-mode:normal;overflow:hidden;}\r\n.fig__frame[data-ph]:not(:has(img))::after{content:attr(data-ph);position:absolute;inset:0;\r\n  display:flex;align-items:center;justify-content:center;text-align:center;\r\n  font-family:var(--font-mono);font-size:var(--fs-small);color:var(--ink-3);\r\n  letter-spacing:.04em;padding:var(--s5)}\r\n.fig__frame img{position:relative;z-index:1;width:100%;height:auto;display:block;\r\n  object-fit:contain;background:var(--paper)}\r\n.fig__frame img:not([src]),.fig__frame img[src=\"\"]{display:none}\r\n.fig__cap{font-family:var(--font-mono);font-size:var(--fs-mono);\r\n  letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);\r\n  margin-top:var(--s3);align-items:center;gap:.6em;line-height:1.4}\r\n.fig__cap b{color:var(--brand-ink);font-weight:600}\r\n\r\n\/* \u2550\u2550 9. STAT CARDS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.statgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s4)}\r\n.stat{border:1px solid var(--line);border-radius:var(--radius);\r\n  padding:var(--s6) var(--s5);background:var(--paper)}\r\n.section--ink .stat{background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.12)}\r\n.stat__n{font-family:var(--font-display);font-weight:700;font-size:var(--fs-stat);\r\n  letter-spacing:-.03em;line-height:1;color:var(--brand);display:block}\r\n.section--ink .stat__n{color:#7DA0FF}\r\n.stat__n small{font-size:.42em;font-weight:600;color:var(--ink-3);letter-spacing:0}\r\n.section--ink .stat__n small{color:var(--on-dark-2)}\r\n.stat__l{margin-top:var(--s3);font-size:var(--fs-small);color:var(--ink-2);\r\n  line-height:1.4}\r\n.section--ink .stat__l{color:var(--on-dark)}\r\n@media(max-width:820px){.statgrid{grid-template-columns:1fr 1fr}}\r\n@media(max-width:460px){.statgrid{grid-template-columns:1fr}}\r\n\r\n\/* \u2550\u2550 10. NUMBERED LIST \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.numlist{list-style:none;margin:0;padding:0;display:grid;gap:var(--s3)}\r\n.numlist li{display:grid;grid-template-columns:auto 1fr;gap:var(--s4);\r\n  align-items:start;padding:var(--s4) 0;border-top:1px solid var(--line);\r\n  color:var(--ink-2);font-size:var(--fs-body)}\r\n.section--ink .numlist li{border-color:rgba(255,255,255,.12);color:var(--on-dark)}\r\n.numlist li:last-child{border-bottom:1px solid var(--line)}\r\n.section--ink .numlist li:last-child{border-color:rgba(255,255,255,.12)}\r\n.numlist .idx{font-family:var(--font-mono);font-size:var(--fs-small);\r\n  font-weight:500;color:var(--brand);padding-top:.15em}\r\n\r\n\/* \u2550\u2550 11. CALLOUT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.callout{border-left:3px solid var(--brand);background:var(--brand-tint);\r\n  border-radius:0 var(--radius-sm) var(--radius-sm) 0;padding:var(--s5) var(--s6);\r\n  font-size:var(--fs-body);color:var(--ink);margin-top:var(--s4);\r\n  box-sizing:border-box;max-width:100%}\r\n.callout b{color:var(--brand-ink)}\r\n.section--ink .callout{background:rgba(42,91,255,.15);border-left-color:#7DA0FF;color:var(--on-dark)}\r\n.section--ink .callout b{color:#A9C2FF}\r\n\r\n\/* \u2550\u2550 12. CODE BLOCK \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.code{background:var(--ink);border-radius:var(--radius);overflow:hidden;\r\n  margin-top:var(--s4);width:100%;max-width:100%;box-sizing:border-box;\r\n  border:1px solid rgba(255,255,255,.1)}\r\n.code__bar{display:flex;align-items:center;gap:.55em;padding:.7em 1em;\r\n  border-bottom:1px solid rgba(255,255,255,.1)}\r\n.code__dot{width:9px;height:9px;border-radius:50%;background:rgba(255,255,255,.2)}\r\n.code__name{font-family:var(--font-mono);font-size:var(--fs-mono);\r\n  color:var(--on-dark-2);letter-spacing:.04em;margin-left:.4em}\r\n.code pre{margin:0;padding:var(--s5);overflow-x:auto;width:100%;max-width:100%;\r\n  box-sizing:border-box;font-family:var(--font-mono);font-size:.8125rem;line-height:1.7;\r\n  color:var(--on-dark);-webkit-overflow-scrolling:touch;white-space:pre}\r\n.code .c-key{color:#7DA0FF}\r\n.code .c-com{color:var(--on-dark-2)}\r\n.code .c-str{color:#7EE787}\r\n\r\n\/* \u2550\u2550 13. TABLES \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.tbl-wrap{border:1px solid var(--line);border-radius:var(--radius);overflow-x:auto;\r\n  -webkit-overflow-scrolling:touch;margin-block:var(--s3);background:var(--paper);\r\n  width:100%;max-width:100%;box-sizing:border-box}\r\ntable.tbl{width:100%;border-collapse:collapse;font-size:var(--fs-small);min-width:340px}\r\ntable.tbl th{font-family:var(--font-mono);font-size:var(--fs-mono);\r\n  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);\r\n  text-align:left;font-weight:600;padding:var(--s4) var(--s5);\r\n  background:var(--paper-2);border-bottom:1px solid var(--line)}\r\ntable.tbl td{padding:var(--s4) var(--s5);border-bottom:1px solid var(--line);\r\n  color:var(--ink-2);vertical-align:top;line-height:1.55}\r\ntable.tbl tr:last-child td{border-bottom:0}\r\ntable.tbl td:first-child{font-weight:600;color:var(--ink)}\r\n\r\n\/* \u2550\u2550 14. BEFORE \u2192 AFTER \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.baa{display:grid;grid-template-columns:1fr auto 1fr;align-items:stretch;\r\n  gap:var(--s4);border:1px solid var(--line);border-radius:var(--radius);\r\n  padding:var(--s6);background:var(--paper);height:100%;box-sizing:border-box;max-width:100%}\r\n.baa__side{display:flex;flex-direction:column;gap:var(--s3)}\r\n.baa__tag{font-family:var(--font-mono);font-size:var(--fs-mono);\r\n  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}\r\n.baa__val{font-family:var(--font-display);font-weight:600;\r\n  font-size:clamp(1.4rem,1rem+1.6vw,2rem);letter-spacing:-.02em;line-height:1.1}\r\n.baa--before .baa__val{color:var(--ink-2)}\r\n.baa--after .baa__val{color:var(--brand)}\r\n.baa__arrow{display:grid;place-items:center;color:var(--line-2)}\r\n.baa__arrow svg{width:34px;height:34px}\r\n@media(max-width:640px){.baa{grid-template-columns:1fr}\r\n  .baa__arrow{transform:rotate(90deg);justify-self:start}}\r\n\r\n\/* \u2550\u2550 15. FAQ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.faq{border-top:1px solid var(--line);}\r\n.faq details{border-bottom:1px solid var(--line)}\r\n.faq summary{list-style:none;cursor:pointer;padding:var(--s5) 0;\r\n  display:flex;align-items:center;justify-content:space-between;gap:var(--s5);\r\n  font-family:var(--font-display);font-weight:600;font-size:var(--fs-h4);\r\n  color:var(--ink)}\r\n.faq summary::-webkit-details-marker{display:none}\r\n.faq summary .plus{width:22px;height:22px;position:relative;flex:none;\r\n  transition:transform .2s ease}\r\n.faq summary .plus::before,.faq summary .plus::after{content:\"\";position:absolute;\r\n  background:var(--brand);border-radius:2px}\r\n.faq summary .plus::before{inset:10px 0;height:2px}\r\n.faq summary .plus::after{inset:0 10px;width:2px;transition:opacity .2s ease}\r\n.faq details[open] summary .plus{transform:rotate(180deg)}\r\n.faq details[open] summary .plus::after{opacity:0}\r\n.faq__a{padding:0 0 var(--s5);color:var(--ink-2);font-size:var(--fs-body);line-height:1.65}\r\n\r\n\/* \u2550\u2550 16. CTA BAND \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.cta{display:grid;grid-template-columns:1.2fr auto;gap:var(--s7);align-items:center}\r\n.cta h2{font-size:var(--fs-h2);max-width:24ch}\r\n.cta p{color:var(--on-dark);margin-top:var(--s4);max-width:52ch;font-size:var(--fs-lead)}\r\n.cta__actions{display:flex;flex-direction:column;gap:var(--s3);align-items:stretch}\r\n@media(max-width:820px){.cta{grid-template-columns:1fr}\r\n  .cta__actions{flex-direction:row;flex-wrap:wrap}}\r\n\r\n\r\n\r\n\/* \u2550\u2550 18. MOTION \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.reveal{opacity:0;transform:translateY(14px);\r\n  transition:opacity .6s ease,transform .6s ease}\r\n.reveal.in{opacity:1;transform:none}\r\n@media(prefers-reduced-motion:reduce){\r\n  *{animation:none!important;transition:none!important;scroll-behavior:auto!important}\r\n  .reveal{opacity:1;transform:none}\r\n}\r\n<\/style>\r\n\r\n\r\n<!-- \u2550\u2550\u2550 SITE NAV \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n\r\n<main>\r\n\r\n<!-- \u2550\u2550\u2550 HERO \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"hero section\">\r\n  <div class=\"container\">\r\n    <div class=\"hero__eyebrows\">\r\n      <span class=\"pill\">Case Study \/\/ Multi-Agent Systems<\/span>\r\n      <span class=\"slug\">temporal \/ multi-agent-observability<\/span>\r\n    <\/div>\r\n\r\n    <h1>Multi-Agent System Observability with Temporal: How We Cut Cost 65% and Latency 70%<\/h1>\r\n\r\n    <p class=\"hero__dek\">How durable execution turned a \u201cslow model\u201d mystery into a readable multi-agent timeline \u2014 and why usage budgets and a thinner tool API changed the unit economics.<\/p>\r\n\r\n    <div class=\"hero__cta\">\r\n      <a class=\"btn btn--lg\" href=\"#cta\">Book a free workflow review\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\"><path d=\"M5 12h14M13 6l6 6-6 6\"\/><\/svg>\r\n      <\/a>\r\n      <a class=\"btn btn--ghost btn--lg\" href=\"#summary\">Read the summary<\/a>\r\n    <\/div>\r\n\r\n    <div class=\"metarail\">\r\n      <div class=\"metarail__cell\"><span class=\"metarail__k\">Architecture<\/span><span class=\"metarail__v\">Orchestrator \u00b7 Worker \u00b7 Reviewer<\/span><\/div>\r\n      <div class=\"metarail__cell\"><span class=\"metarail__k\">Runtime<\/span><span class=\"metarail__v\">Temporal + Pydantic AI<\/span><\/div>\r\n      <div class=\"metarail__cell\"><span class=\"metarail__k\">Failure Signal<\/span><span class=\"metarail__v\">~50 model turns \u00b7 0 reviewer runs<\/span><\/div>\r\n      <div class=\"metarail__cell\"><span class=\"metarail__k\">Outcome<\/span><span class=\"metarail__v\">~65% lower cost \u00b7 ~70% lower latency<\/span><\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 HERO FIGURE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section\" style=\"padding-top:var(--s7)\">\r\n  <div class=\"container\">\r\n    <figure class=\"fig reveal\">\r\n      <div class=\"fig__frame\" data-ph=\"Diagram slot \u00b7 16:8 \u00b7 Temporal as the single multi-agent observability spine across orchestrator, worker, tools, and reviewer\"><\/div>\r\n      <!-- <figcaption class=\"fig__cap\"><b>Fig. 01<\/b> \u2014 the multi-agent execution timeline across orchestrator, worker, tools, and reviewer<\/figcaption>-->\r\n    <\/figure>\r\n  <\/div>\r\n<\/section> \r\n\r\n<!-- \u2550\u2550\u2550 EXECUTIVE SUMMARY & WHAT WE LEARNED \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section section--ink\" id=\"summary\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow\"><span class=\"tick\"><\/span>Executive Summary<\/p>\r\n      <h2>What We Learned<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"exec-cols\">\r\n      <div class=\"stack\">\r\n        <p>Happy-path runs finished in under a minute. A long tail burned tokens for several minutes and sometimes died with an opaque workflow error. Dashboards said workers were healthy. The model vendor said we were spending money. Neither answered the only question that mattered:<\/p>\r\n        <p style=\"font-size:1.15rem;font-weight:600;color:#fff\">How many model turns did this run take \u2014 and which agent was still talking?<\/p>\r\n        <p>This is the story of re-engineering a <a href=\"https:\/\/www.xgrid.co\/resources\/agentic-ai-orchestration-temporal\/\">multi-agent recommendation system<\/a> so that cost policy lives in the orchestrator, trivial helpers are not agent tools, and Temporal is the single observability spine across worker, tools, and reviewer.<\/p>\r\n        <p>After that re-engineering, on the same shape of traffic:<\/p>\r\n        <ul style=\"margin:0;padding-left:1.2em;display:grid;gap:var(--s2);color:var(--on-dark)\">\r\n          <li>~65% lower cost per successful result<\/li>\r\n          <li>~70% lower time to yield a result<\/li>\r\n          <li>Failures that explain themselves instead of vanishing into \u201cthe model was slow\u201d<\/li>\r\n        <\/ul>\r\n        <p style=\"font-size:var(--fs-small);color:var(--on-dark-2);font-style:italic\">No product names. No customer data. Just the architecture.<\/p>\r\n      <\/div>\r\n\r\n      <div>\r\n        <p class=\"eyebrow\" style=\"margin-bottom:var(--s5)\"><span class=\"tick\"><\/span>Key Learnings<\/p>\r\n        <ol class=\"numlist\">\r\n          <li><span class=\"idx\">01<\/span><span><b>The problem:<\/b> A worker agent was repeatedly making model requests and calling a trivial deterministic tool, driving up cost and latency.<\/span><\/li>\r\n          <li><span class=\"idx\">02<\/span><span><b>What exposed it:<\/b> Temporal gave us a per-run history across the orchestrator, worker, tools, and reviewer.<\/span><\/li>\r\n          <li><span class=\"idx\">03<\/span><span><b>What we changed:<\/b> We introduced per-agent usage budgets and removed deterministic helpers from the agent tool surface.<\/span><\/li>\r\n          <li><span class=\"idx\">04<\/span><span><b>The result:<\/b> ~65% lower cost and ~70% lower latency per successful result.<\/span><\/li>\r\n        <\/ol>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- Headline metrics -->\r\n    <div class=\"statgrid\" style=\"margin-top:var(--s8)\">\r\n      <div class=\"stat\"><span class=\"stat__n\">~65%<\/span><span class=\"stat__l\">Lower cost per successful result<\/span><\/div>\r\n      <div class=\"stat\"><span class=\"stat__n\">~70%<\/span><span class=\"stat__l\">Lower latency to result<\/span><\/div>\r\n      <div class=\"stat\"><span class=\"stat__n\">~50<\/span><span class=\"stat__l\">Model requests in a pathological worker run<\/span><\/div>\r\n      <div class=\"stat\"><span class=\"stat__n\">0<\/span><span class=\"stat__l\">Reviewer activities in that run<\/span><\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 THE SYSTEM WAS NEVER A SINGLE PROMPT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>Scaling Challenges<\/p>\r\n      <h2>Why Multi-Agent Systems Hide Cost and Latency<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"two-col\">\r\n      <div class=\"stack\">\r\n        <p class=\"lead\" style=\"color:var(--ink-2)\">We don\u2019t run a chatbot. We run a pipeline of agents with a job: gather structured facts, recommend a version, and defend that recommendation under review.<\/p>\r\n        <ol class=\"numlist\">\r\n          <li><span class=\"idx\">01<\/span><span><b>Orchestrator:<\/b> cache, round policy, when to stop<\/span><\/li>\r\n          <li><span class=\"idx\">02<\/span><span><b>Worker agent:<\/b> plans, calls tools, emits structured output<\/span><\/li>\r\n          <li><span class=\"idx\">03<\/span><span><b>Reviewer agent:<\/b> scores consistency and phrasing; can send the worker back<\/span><\/li>\r\n        <\/ol>\r\n      <\/div>\r\n      <div class=\"stack\">\r\n        <p>Around that sit knowledge APIs, release metadata, deterministic helpers, retries, and timeouts.<\/p>\r\n        <div class=\"callout\">\r\n          <b>Where cost hides:<\/b> That design is powerful. In a multi-agent system, waste is rarely one slow HTTP call. It is dozens of invisible turns that never reach the reviewer the architecture promised.\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 WHY LOGS WEREN'T ENOUGH (TABLE 1) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section section--wash\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>Observability Gap<\/p>\r\n      <h2>Why logs weren\u2019t enough<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"two-col--wide-left\">\r\n      <div>\r\n        <p class=\"lead\" style=\"color:var(--ink-2);margin-bottom:var(--s4)\">When a run stretched, every layer had a partial story:<\/p>\r\n        <div class=\"tbl-wrap\">\r\n          <table class=\"tbl\">\r\n            <thead>\r\n              <tr>\r\n                <th>Layer<\/th>\r\n                <th>What it showed<\/th>\r\n                <th>What it hid<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody>\r\n              <tr>\r\n                <td>App logs<\/td>\r\n                <td>Agent started, a tool returned<\/td>\r\n                <td>How many model turns, in what order<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>Model provider<\/td>\r\n                <td>Aggregate token spend<\/td>\r\n                <td>Which agent, which loop, which tool<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>Reviewer<\/td>\r\n                <td>Sometimes nothing<\/td>\r\n                <td>Whether the worker was still exploring or stuck<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>Intuition<\/td>\r\n                <td>\u201cThe model is slow\u201d<\/td>\r\n                <td>Whether we had an architectural leak<\/td>\r\n              <\/tr>\r\n            <\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"stack\">\r\n        <p>Failure mode here can take the form of the worker consuming the entire request budget, preventing the reviewer from starting and leaving the orchestrator with only a late exception.<\/p>\r\n        <div class=\"callout\">\r\n          <b>Core requirement:<\/b> We needed one timeline that spanned <b>orchestrator \u2192 worker \u2192 tools \u2192 reviewer<\/b>.\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 TEMPORAL AS THE OBSERVABILITY SPINE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>The Runtime Foundation<\/p>\r\n      <h2>Temporal as the observability spine<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"two-col--spine\">\r\n      <div class=\"stack\">\r\n        <p class=\"lead\" style=\"color:var(--ink-2)\">We re-engineered the runtime around Temporal, making workflow orchestration a first-class part of the system:<\/p>\r\n        <ul style=\"margin:0;padding-left:1.2em;display:grid;gap:var(--s2);color:var(--ink-2)\">\r\n          <li><b>The orchestrator<\/b> is the workflow<\/li>\r\n          <li><b>The worker<\/b> is a durable pydantic-ai TemporalAgent<\/li>\r\n          <li><b>The reviewer<\/b> is its own activity<\/li>\r\n          <li><b>Every model request and tool call<\/b> is a Temporal activity<\/li>\r\n        <\/ul>\r\n        <p>Exporting one workflow\u2019s event history answered questions logs never could:<\/p>\r\n        <ul style=\"margin:0;padding-left:1.2em;display:grid;gap:var(--s2);color:var(--ink-2)\">\r\n          <li>How many worker model turns?<\/li>\r\n          <li>Which tools, how often, with what arguments?<\/li>\r\n          <li>Did the reviewer ever run?<\/li>\r\n          <li>Where did wall-clock time actually go?<\/li>\r\n        <\/ul>\r\n        <div class=\"callout\">\r\n          Temporal did not replace metrics or billing. It gave us <a href=\"https:\/\/www.xgrid.co\/resources\/temporal-observability-in-production-guide\/\"><b>causal, per-run observability<\/b><\/a> for a multi-agent graph.\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div>\r\n        <p style=\"font-size:var(--fs-small);color:var(--ink-3);font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;margin-bottom:var(--s2)\">Unified execution tree<\/p>\r\n        <div class=\"code\" style=\"margin-top:0\">\r\n          <div class=\"code__bar\"><span class=\"code__dot\"><\/span><span class=\"code__dot\"><\/span><span class=\"code__dot\"><\/span><span class=\"code__name\">workflow-spine<\/span><\/div>\r\n<pre><span class=\"c-key\">Workflow<\/span> (orchestrator)\r\n\u251c\u2500\u2500 load context \/ cache\r\n\u251c\u2500\u2500 <span class=\"c-key\">Worker agent run<\/span>\r\n\u2502   \u251c\u2500\u2500 model_request              <span class=\"c-com\">\u2190 activity<\/span>\r\n\u2502   \u251c\u2500\u2500 tool: knowledge check      <span class=\"c-com\">\u2190 activity<\/span>\r\n\u2502   \u251c\u2500\u2500 tool: releases             <span class=\"c-com\">\u2190 activity<\/span>\r\n\u2502   \u251c\u2500\u2500 tool: deterministic logic  <span class=\"c-com\">\u2190 activity<\/span>\r\n\u2502   \u2514\u2500\u2500 model_request \u2192 output     <span class=\"c-com\">\u2190 activity<\/span>\r\n\u251c\u2500\u2500 <span class=\"c-key\">Reviewer agent turn<\/span>            <span class=\"c-com\">\u2190 activity<\/span>\r\n\u251c\u2500\u2500 (optional) worker revision\r\n\u2514\u2500\u2500 cache \/ complete<\/pre>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 WHAT TEMPORAL WORKFLOW HISTORY REVEALED (TABLE 2) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section section--wash\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>History Evidence<\/p>\r\n      <h2>What Temporal workflow history revealed<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"two-col--wide-left\">\r\n      <div>\r\n        <p class=\"lead\" style=\"color:var(--ink-2);margin-bottom:var(--s4)\">A healthy run was a short play: a handful of worker model turns, purposeful tools, then reviewer consensus. A pathological run looked like a different system:<\/p>\r\n        <div class=\"tbl-wrap\">\r\n          <table class=\"tbl\">\r\n            <thead>\r\n              <tr>\r\n                <th>Signal in history<\/th>\r\n                <th>Meaning<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody>\r\n              <tr>\r\n                <td>~50 model_request activities<\/td>\r\n                <td>Worker hit pydantic-ai\u2019s default request_limit<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>Same trivial helper ~46 times, same arguments<\/td>\r\n                <td>Worker never moved to final structured output<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>Zero reviewer activities<\/td>\r\n                <td>The multi-agent path collapsed to a solo looping agent<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>~87% of wall time in model activities<\/td>\r\n                <td>Cost and latency were the same bug<\/td>\r\n              <\/tr>\r\n            <\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div class=\"stack\">\r\n        <p>The terminal message was blunt:<\/p>\r\n        <div class=\"code\" style=\"margin-top:0\">\r\n          <div class=\"code__bar\"><span class=\"code__dot\"><\/span><span class=\"code__dot\"><\/span><span class=\"code__dot\"><\/span><span class=\"code__name\">terminal-error<\/span><\/div>\r\n<pre><span class=\"c-key\">The next request would exceed the request_limit of 50<\/span><\/pre>\r\n        <\/div>\r\n        <p>That is pydantic-ai\u2019s default ceiling on model requests per agent.run() \u2014 a safety net, not a product SLA we had chosen. In a multi-agent design it is catastrophic: you pay for the loop and you never get the quality gate.<\/p>\r\n        <p>One model activity in that run lasted more than two minutes. Context grew from tens of kilobytes toward hundreds. We were not waiting on a database. We were buying turns for a button the model should not have had.<\/p>\r\n        <div class=\"callout\">\r\n          <b>If the reviewer never appears in history, you do not have a multi-agent system that run. You have a solo agent with aspirations.<\/b>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 RE-ENGINEERING 1: PER-AGENT BUDGETS (TABLE 3) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>Re-Engineering 1<\/p>\r\n      <h2>Per-agent budgets as part of the contract<\/h2>\r\n      <p class=\"lead\">Multi-agent systems need per-agent budgets the way services need rate limits.<\/p>\r\n    <\/div>\r\n\r\n    <div class=\"two-col--wide-left\">\r\n      <div class=\"stack\">\r\n        <p>Healthy histories used on the order of six worker model turns. Pathological runs used fifty. We encoded that evidence in pydantic-ai UsageLimits on every run() \u2014 the boundary of one agent turn inside the orchestrator.<\/p>\r\n        <p><b>Important:<\/b> apply limits directly to run(). Constructor-level limits on Agent(...) can be silently ineffective and create a subtle footgun.<\/p>\r\n\r\n        <div class=\"code\">\r\n          <div class=\"code__bar\"><span class=\"code__dot\"><\/span><span class=\"code__dot\"><\/span><span class=\"code__dot\"><\/span><span class=\"code__name\">limits_enforcement.py<\/span><\/div>\r\n<pre><span class=\"c-key\">from<\/span> pydantic_ai.exceptions <span class=\"c-key\">import<\/span> UsageLimitExceeded\r\n<span class=\"c-key\">from<\/span> pydantic_ai.usage <span class=\"c-key\">import<\/span> UsageLimits\r\n<span class=\"c-key\">from<\/span> temporalio.exceptions <span class=\"c-key\">import<\/span> ApplicationError\r\n\r\n<span class=\"c-com\"># Derived from healthy histories (~6 turns)<\/span>\r\nWORKER_LIMITS = UsageLimits(\r\n    request_limit=15,\r\n    tool_calls_limit=20,\r\n)\r\n\r\nREVIEWER_LIMITS = UsageLimits(\r\n    request_limit=5,    <span class=\"c-com\"># scoring turn<\/span>\r\n    tool_calls_limit=0, <span class=\"c-com\"># tool-free<\/span>\r\n)\r\n\r\n<span class=\"c-key\">async def<\/span> run_worker_agent(prompt, *, deps, ...):\r\n    <span class=\"c-key\">try<\/span>:\r\n        <span class=\"c-key\">return await<\/span> worker_agent.run(\r\n            prompt,\r\n            deps=deps,\r\n            usage_limits=WORKER_LIMITS,  <span class=\"c-com\"># must be here<\/span>\r\n        )\r\n    <span class=\"c-key\">except<\/span> UsageLimitExceeded <span class=\"c-key\">as<\/span> exc:\r\n        <span class=\"c-key\">raise<\/span> ApplicationError(\r\n            str(exc),\r\n            type=<span class=\"c-str\">\"WorkerLimitExceeded\"<\/span>,\r\n            non_retryable=<span class=\"c-key\">True<\/span>,  <span class=\"c-com\"># fail fast<\/span>\r\n        ) <span class=\"c-key\">from<\/span> exc<\/pre>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div class=\"stack\">\r\n        <p style=\"font-weight:600\">Why both limits?<\/p>\r\n        <div class=\"tbl-wrap\" style=\"margin-top:0\">\r\n          <table class=\"tbl\">\r\n            <thead>\r\n              <tr>\r\n                <th>Limit<\/th>\r\n                <th>What it guards<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody>\r\n              <tr>\r\n                <td>request_limit<\/td>\r\n                <td>Infinite model turns \u2014 exactly the failure we saw<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>tool_calls_limit<\/td>\r\n                <td>Tool thrash even while the model keeps \u201cplanning\u201d<\/td>\r\n              <\/tr>\r\n            <\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n\r\n        <p>In Temporal terms, exceeding the limit fails the agent run before another expensive model_request activity is scheduled. That is the difference between a four-minute autopsy and a fail-fast.<\/p>\r\n\r\n        <div class=\"code\">\r\n          <div class=\"code__bar\"><span class=\"code__dot\"><\/span><span class=\"code__dot\"><\/span><span class=\"code__dot\"><\/span><span class=\"code__name\">orchestrator_boundary.py<\/span><\/div>\r\n<pre><span class=\"c-com\"># Does not enforce the way teams expect<\/span>\r\nAgent(..., usage_limits=UsageLimits(request_limit=15))\r\n\r\n<span class=\"c-com\"># Enforces at the orchestrator boundary<\/span>\r\n<span class=\"c-key\">await<\/span> agent.run(..., usage_limits=UsageLimits(request_limit=15))<\/pre>\r\n        <\/div>\r\n        <div class=\"callout\">\r\n          The orchestrator now owns policy: how expensive one worker turn may be. The model no longer owns the wallet by accident.\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 RE-ENGINEERING 2: THE TOOL CATALOG IS A PUBLIC API \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section section--wash\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>Re-Engineering 2<\/p>\r\n      <h2>The tool catalog is a public API<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"two-col--wide-left\">\r\n      <div class=\"stack\">\r\n        <p class=\"lead\" style=\"color:var(--ink-2)\">The looping call was not a knowledge lookup. It was string hygiene \u2014 strip a leading v from a version \u2014 exposed as a first-class tool.<\/p>\r\n        <p>In a Temporal + pydantic-ai world, every tool call is an activity. Every accidental press is durable, billed, and visible\u2026 after you have already paid.<\/p>\r\n        <p>We re-drew the boundary:<\/p>\r\n\r\n        <div class=\"code\">\r\n          <div class=\"code__bar\"><span class=\"code__dot\"><\/span><span class=\"code__dot\"><\/span><span class=\"code__dot\"><\/span><span class=\"code__name\">deterministic_tools.py<\/span><\/div>\r\n<pre><span class=\"c-key\">def<\/span> compute_deterministic_verdict(\r\n    ctx,\r\n    current_version: str,\r\n    releases: list[dict],\r\n    is_eol: bool,\r\n    is_incompatible: bool,\r\n    no_compatible_version_available: bool = False,\r\n) -> dict:\r\n    current = normalize_version(current_version)  <span class=\"c-com\"># local, free<\/span>\r\n    <span class=\"c-com\"># \u2026pure verdict math\u2026<\/span>\r\n    <span class=\"c-key\">return<\/span> {\r\n        <span class=\"c-str\">\"upgrade_recommended\"<\/span>: ...,\r\n        <span class=\"c-str\">\"recommended_version\"<\/span>: ...,\r\n    }\r\n\r\n<span class=\"c-com\"># Agent tools: retrieval and policy \u2014 not string hygiene<\/span>\r\ntools = [compute_deterministic_verdict, ...]<\/pre>\r\n        <\/div>\r\n\r\n\r\n    \r\n      <\/div>\r\n\r\n      <div class=\"stack\">\r\n                <p>The system prompt had told the model it must call the normalizer. Prompt and tool surface had been collaborating on the loop. We removed both.<\/p>\r\n    <div class=\"callout\">\r\n          <b>Rule we now use:<\/b><br><br>\r\n          \u2022 If a function has no I\/O and no policy beyond string hygiene, it is not a tool.<br><br>\r\n          \u2022 Tools are for side effects, retrieval, and decisions that need an audit trail.<br><br>\r\n          \u2022 Hygiene belongs in deterministic code.\r\n        <\/div>\r\n        <figure class=\"fig\">\r\n          <div class=\"fig__frame\" style=\"background:var(--paper);padding:var(--s3);display:flex;align-items:center;justify-content:center\">\r\n            <img decoding=\"async\" src=\"https:\/\/www.xgrid.co\/resources\/wp-content\/uploads\/2026\/08\/image2-1.png\" alt=\"Re-Engineering 2: The Tool Catalog is a Public API\" loading=\"lazy\" style=\"border-radius:var(--radius-sm);max-height:480px\" \/>\r\n          <\/div>\r\n          <figcaption class=\"fig__cap\"><b>Fig. 02<\/b> \u2014 Tool Boundary: Deterministic Local Code vs. Durable Temporal Activity<\/figcaption>\r\n        <\/figure>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 WHY USAGE LIMITS AND TOOL DESIGN WORK TOGETHER \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>Synthesis<\/p>\r\n      <h2>Why usage limits and tool design work together<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"two-col--wide-left\">\r\n      <div class=\"stack\">\r\n        <p class=\"lead\" style=\"color:var(--ink-2)\">Either change helps. Together they close the failure mode.<\/p>\r\n        <p>Temporal records every remaining model and tool activity, turning the next anomaly into a concrete history diff that can be investigated immediately.<\/p>\r\n        <p>An optional extra \u2014 a per-run dedupe on remaining tools that rejects identical (name, args) \u2014 is belt and suspenders. Removing the bad tool removed the fuse we measured.<\/p>\r\n        <div class=\"callout\">\r\n          <b>Closed loop:<\/b> Removing bad tools prevents the spark, while strict limits guarantee runaway loops fail fast.\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div class=\"stack\">\r\n        <figure class=\"fig\">\r\n          <div class=\"fig__frame\" style=\"background:var(--paper);padding:var(--s3);display:flex;align-items:center;justify-content:center\">\r\n            <img decoding=\"async\" src=\"https:\/\/www.xgrid.co\/resources\/wp-content\/uploads\/2026\/08\/image3.png\" alt=\"Why Usage Limits and Tool Design Work Together\" loading=\"lazy\" style=\"border-radius:var(--radius-sm);max-height:480px\" \/>\r\n          <\/div>\r\n          <figcaption class=\"fig__cap\"><b>Fig. 03<\/b> \u2014 Combined Guardrails: Orchestrator Usage Limits &amp; Refined Tool Surface<\/figcaption>\r\n        <\/figure>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 THE MULTI-AGENT PATH, STILL ONE TIMELINE (TABLE 4) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section section--wash\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>Operational Clarity<\/p>\r\n      <h2>The multi-agent path, still one timeline<\/h2>\r\n    <\/div>\r\n <div class=\"stack\" style=\"margin-bottom: 40px;\">\r\n        <figure class=\"fig\">\r\n          <div class=\"fig__frame\" style=\"background:var(--paper);padding:var(--s3);display:flex;align-items:center;justify-content:center\">\r\n            <img decoding=\"async\" src=\"https:\/\/www.xgrid.co\/resources\/wp-content\/uploads\/2026\/08\/image1-1.png\" alt=\"The Multi-Agent Path, Still One Timeline\" loading=\"lazy\" style=\"border-radius:var(--radius-sm);max-height:480px\" \/>\r\n          <\/div>\r\n          <figcaption class=\"fig__cap\"><b>Fig. 04<\/b> \u2014 Single-Timeline Observability across Orchestrator, Worker, and Reviewer<\/figcaption>\r\n        <\/figure>\r\n      <\/div>\r\n    <div class=\"\">\r\n      <div class=\"stack\">\r\n        <p class=\"lead\" style=\"color:var(--ink-2)\">On-call does not ask \u201cwhich microservice log?\u201d They open one workflow and read worker vs reviewer as chapters in the same book.<\/p>\r\n        \r\n        <div class=\"tbl-wrap\" style=\"margin-top:0\">\r\n          <table class=\"tbl\">\r\n            <thead>\r\n              <tr>\r\n                <th>Question<\/th>\r\n                <th>Answered from history<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody>\r\n              <tr>\r\n                <td>Is the worker looping?<\/td>\r\n                <td>Count of model_request \/ repeated tool names<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>Is the multi-agent path intact?<\/td>\r\n                <td>Reviewer activities after the worker<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>Where is latency?<\/td>\r\n                <td>Activity durations by type<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>Are we paying for quality or waste?<\/td>\r\n                <td>Turns before structured output vs after review<\/td>\r\n              <\/tr>\r\n            <\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n\r\n        <div class=\"callout\">\r\n          <b>Single Timeline Advantage:<\/b> Having orchestrator, worker, tools, and reviewer in one causal trace eliminates cross-system log correlation during incidents.\r\n        <\/div>\r\n      <\/div>\r\n\r\n     \r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 WHAT THE RE-ENGINEERING DELIVERED (TABLE 5) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>Outcomes<\/p>\r\n      <h2>What the re-engineering delivered<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"\">\r\n      <div>\r\n        <p class=\"lead\" style=\"color:var(--ink-2);margin-bottom:var(--s4)\">Happy paths were already fine. Averages moved because we changed the shape of the system under stress \u2014 which is where multi-agent cost lives.<\/p>\r\n        <div class=\"tbl-wrap\">\r\n          <table class=\"tbl\">\r\n            <thead>\r\n              <tr>\r\n                <th>Outcome<\/th>\r\n                <th>What changed underneath<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody>\r\n              <tr>\r\n                <td>~65% cost reduction<\/td>\r\n                <td>Worker budgets and a thinner tool API collapsed long-tail token burn<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>~70% latency reduction<\/td>\r\n                <td>Loops fail fast; the reviewer stays on the critical path<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>Clearer operations<\/td>\r\n                <td>Orchestrator, worker, and reviewer share one timeline<\/td>\r\n              <\/tr>\r\n              <tr>\r\n                <td>Safer iteration<\/td>\r\n                <td>Next anomaly is evidence, not folklore<\/td>\r\n              <\/tr>\r\n            <\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n      <\/div>\r\n\r\n     <!---- <div class=\"baa\">\r\n        <div class=\"baa__side baa--before\">\r\n          <span class=\"baa__tag\">Before \u2014 unbudgeted<\/span>\r\n          <span class=\"baa__val\">~50 turns \u00b7 0 reviews<\/span>\r\n          <p style=\"font-size:var(--fs-small);color:var(--ink-3)\">4+ minute long-tail runs, runaway token spend, model loops hiding behind \"the model was slow\".<\/p>\r\n        <\/div>\r\n        <div class=\"baa__arrow\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><path d=\"M5 12h14M13 6l6 6-6 6\"\/><\/svg><\/div>\r\n        <div class=\"baa__side baa--after\">\r\n          <span class=\"baa__tag\">After \u2014 bounded<\/span>\r\n          <span class=\"baa__val\">~65% cost \u2193 \u00b7 ~70% lat \u2193<\/span>\r\n          <p style=\"font-size:var(--fs-small);color:var(--ink-3)\">Enforced 15-turn limits, local deterministic helpers, guaranteed reviewer execution, causal single timeline.<\/p>\r\n        <\/div>\r\n      <\/div> -->\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 PRINCIPLES WE WOULD TAKE TO THE NEXT BUILD \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section section--wash\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>Best Practices<\/p>\r\n      <h2>Principles we would take to the next multi-agent build<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"two-col\">\r\n      <ol class=\"numlist\">\r\n        <li><span class=\"idx\">01<\/span><span><b>Orchestrator on Temporal, agents as durable units.<\/b> Observability comes for free when turns are activities.<\/span><\/li>\r\n        <li><span class=\"idx\">02<\/span><span><b>Per-agent UsageLimits on every run().<\/b> Budgets are part of the multi-agent contract.<\/span><\/li>\r\n        <li><span class=\"idx\">03<\/span><span><b>Tool catalogs are public APIs.<\/b> Keep I\/O and policy; push pure helpers into deterministic code.<\/span><\/li>\r\n        <li><span class=\"idx\">04<\/span><span><b>Measure healthy turn counts from history, then set limits.<\/b> Ours was closer to six worker turns, not fifty.<\/span><\/li>\r\n        <li><span class=\"idx\">05<\/span><span><b>If the reviewer never appears in history, the architecture did not run.<\/b> You paid for a solo loop.<\/span><\/li>\r\n      <\/ol>\r\n\r\n      <div class=\"stack\">\r\n        <div class=\"callout\" style=\"margin-top:0\">\r\n          <b>Rule of Thumb:<\/b><br><br>\r\n          If your model turn count is near a framework default you never explicitly selected, your agents are likely spending budget in unmonitored loops.\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 THE TAKEAWAY: OBSERVABILITY BEFORE OPTIMIZATION \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section section--ink\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow\"><span class=\"tick\"><\/span>Closing Takeaway<\/p>\r\n      <h2>The Takeaway: Observability Before Optimization<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"two-col\">\r\n      <div class=\"stack\">\r\n        <p>We re-engineered a multi-agent system to achieve better economics through architecture:<\/p>\r\n        <ul style=\"margin:0;padding-left:1.2em;display:grid;gap:var(--s2);color:var(--on-dark)\">\r\n          <li>the orchestrator owns cost policy,<\/li>\r\n          <li>the worker cannot thrash on trivial tools,<\/li>\r\n          <li>the reviewer remains on the path,<\/li>\r\n          <li>and Temporal makes the whole graph readable in one place.<\/li>\r\n        <\/ul>\r\n        <p style=\"font-size:1.15rem;font-weight:600;color:#fff;margin-top:var(--s3)\">The 65% cost and 70% latency numbers are the business result. The lasting win is simpler: multi-agent complexity, with single-timeline observability.<\/p>\r\n      <\/div>\r\n\r\n      <div>\r\n        <div class=\"callout\" style=\"margin-top:0\">\r\n          <b>Production Diagnostic:<\/b><br><br>\r\n          If you are shipping agents in production, export one of your worst Temporal histories and count the model_request activities. If the number is near a framework default you never chose, you have already found the leak.\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 FAQS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section\">\r\n  <div class=\"container\">\r\n    <div class=\"sec-head\">\r\n      <p class=\"eyebrow eyebrow--brand\"><span class=\"tick\"><\/span>FAQ<\/p>\r\n      <h2>Frequently asked questions<\/h2>\r\n    <\/div>\r\n\r\n    <div class=\"faq\">\r\n      <details open>\r\n        <summary>How do you reduce cost in a multi-agent AI system?<span class=\"plus\"><\/span><\/summary>\r\n        <div class=\"faq__a\">Set explicit budgets for model requests and tool calls, then inspect agent histories to identify loops and unnecessary model-mediated work.<\/div>\r\n      <\/details>\r\n      <details>\r\n        <summary>Why are multi-agent systems expensive?<span class=\"plus\"><\/span><\/summary>\r\n        <div class=\"faq__a\">Costs can compound when worker agents make repeated model calls, repeatedly invoke tools, or fail to hand control to downstream agents such as reviewers.<\/div>\r\n      <\/details>\r\n      <details>\r\n        <summary>How does Temporal help with AI agent observability?<span class=\"plus\"><\/span><\/summary>\r\n        <div class=\"faq__a\">Temporal can provide a durable execution history across workflow steps, model requests, tool calls, and agent boundaries, making individual runs easier to reconstruct.<\/div>\r\n      <\/details>\r\n      <details>\r\n        <summary>What should count as an AI agent tool?<span class=\"plus\"><\/span><\/summary>\r\n        <div class=\"faq__a\">Tools should generally represent retrieval, side effects, or auditable policy decisions. Pure deterministic transformations are often better handled directly in application code.<\/div>\r\n      <\/details>\r\n      <details>\r\n        <summary>How do Pydantic AI UsageLimits prevent runaway agents?<span class=\"plus\"><\/span><\/summary>\r\n        <div class=\"faq__a\">request_limit bounds model requests and tool_calls_limit bounds successful tool executions during a run, providing explicit runtime guardrails.<\/div>\r\n      <\/details>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<!-- \u2550\u2550\u2550 CTA BAND \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<section class=\"section section--ink\" id=\"cta\">\r\n  <div class=\"container\">\r\n    <div class=\"cta\">\r\n      <div>\r\n        <p class=\"eyebrow\"><span class=\"tick\"><\/span>Work with Xgrid<\/p>\r\n        <h2 style=\"margin-top:var(--s4)\">Want a second set of eyes on what your Temporal histories are telling you?<\/h2>\r\n        <p>If you want a second set of eyes on what your Temporal histories are telling you, <a href=\"https:\/\/www.xgrid.co\/temporal-services\/\">Xgrid<\/a> helps teams review production workflows for reliability, cost, and orchestration issues.<\/p>\r\n      <\/div>\r\n      <div class=\"cta__actions\">\r\n        <div style=\"background:var(--paper);border-radius:var(--radius);padding:clamp(20px,3vw,32px);box-shadow:var(--shadow-md);width:440px;max-width:100%\">\r\n         <h3 style=\"color:black; text-align: center; margin-bottom:20px;\">Share Your Details<\/h3><div id=\"hubspot-form\"><\/div>\r\n\r\n<script charset=\"utf-8\" type=\"text\/javascript\" src=\"\/\/js.hsforms.net\/forms\/embed\/v2.js\"><\/script>\r\n\r\n<script>\r\nhbspt.forms.create({\r\n    portalId: \"4404057\",\r\n    formId: \"b69dbfe2-6504-4a7e-9e2a-31dbdd2fe5e0\",\r\n    region: \"na2\",\r\n    target: \"#hubspot-form\"\r\n});\r\n<\/script>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/section>\r\n\r\n<\/main>\r\n\r\n\r\n\r\n<script>\r\n\/* Scroll reveal *\/\r\n(function(){\r\n  var els=document.querySelectorAll('.reveal');\r\n  if(!('IntersectionObserver' in window)){els.forEach(function(e){e.classList.add('in')});return;}\r\n  var io=new IntersectionObserver(function(en){\r\n    en.forEach(function(x){if(x.isIntersecting){x.target.classList.add('in');io.unobserve(x.target);}});\r\n  },{threshold:.12});\r\n  els.forEach(function(e){io.observe(e);});\r\n})();\r\n\r\n\/* Mobile nav toggle *\/\r\n(function(){\r\n  var b=document.getElementById('navBurger'),p=document.getElementById('navPanel');\r\n  if(!b||!p)return;\r\n  b.addEventListener('click',function(){\r\n    var open=p.classList.toggle('open');\r\n    b.setAttribute('aria-expanded',open?'true':'false');\r\n  });\r\n  p.addEventListener('click',function(e){ if(e.target.tagName==='A'){p.classList.remove('open');b.setAttribute('aria-expanded','false');} });\r\n})();\r\n<\/script>\r\n\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"featured_media":14050,"template":"","tags":[],"success-story-category":[460,459,255],"class_list":["post-13991","success-stories","type-success-stories","status-publish","has-post-thumbnail","hentry","success-story-category-agentic-ai","success-story-category-multi-agent-systems","success-story-category-temporal"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Multi-Agent System Observability: 65% Lower Cost with Temporal<\/title>\n<meta name=\"description\" content=\"See how Temporal workflow history exposed costly multi-agent loops, helping cut cost by 65% and latency by 70% through better observability and guardrails.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Multi-Agent System Observability: 65% Lower Cost with Temporal\" \/>\n<meta property=\"og:description\" content=\"See how Temporal workflow history exposed costly multi-agent loops, helping cut cost by 65% and latency by 70% through better observability and guardrails.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/\" \/>\n<meta property=\"og:site_name\" content=\"Xgrid.co\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-01T08:03:06+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.xgrid.co\/resources\/wp-content\/uploads\/2026\/08\/listing-images-4.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1048\" \/>\n\t<meta property=\"og:image:height\" content=\"568\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/success-stories\\\/multi-agent-system-observability-temporal\\\/\",\"url\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/success-stories\\\/multi-agent-system-observability-temporal\\\/\",\"name\":\"Multi-Agent System Observability: 65% Lower Cost with Temporal\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/success-stories\\\/multi-agent-system-observability-temporal\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/success-stories\\\/multi-agent-system-observability-temporal\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/listing-images-4.webp\",\"datePublished\":\"2026-08-25T09:57:33+00:00\",\"dateModified\":\"2026-09-01T08:03:06+00:00\",\"description\":\"See how Temporal workflow history exposed costly multi-agent loops, helping cut cost by 65% and latency by 70% through better observability and guardrails.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/success-stories\\\/multi-agent-system-observability-temporal\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/success-stories\\\/multi-agent-system-observability-temporal\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/success-stories\\\/multi-agent-system-observability-temporal\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/listing-images-4.webp\",\"contentUrl\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/listing-images-4.webp\",\"width\":1048,\"height\":568,\"caption\":\"Multi-Agent System Observability with Temporal: How We Cut Cost 65% and Latency 70%\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/success-stories\\\/multi-agent-system-observability-temporal\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Multi-Agent System Observability with Temporal: How We Cut Cost 65% and Latency 70%\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/#website\",\"url\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/\",\"name\":\"Xgrid.co\",\"description\":\"Learn, Design, Develop, and Engage with Xgrid\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.xgrid.co\\\/resources\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Multi-Agent System Observability: 65% Lower Cost with Temporal","description":"See how Temporal workflow history exposed costly multi-agent loops, helping cut cost by 65% and latency by 70% through better observability and guardrails.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/","og_locale":"en_US","og_type":"article","og_title":"Multi-Agent System Observability: 65% Lower Cost with Temporal","og_description":"See how Temporal workflow history exposed costly multi-agent loops, helping cut cost by 65% and latency by 70% through better observability and guardrails.","og_url":"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/","og_site_name":"Xgrid.co","article_modified_time":"2026-09-01T08:03:06+00:00","og_image":[{"width":1048,"height":568,"url":"https:\/\/www.xgrid.co\/resources\/wp-content\/uploads\/2026\/08\/listing-images-4.webp","type":"image\/webp"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/","url":"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/","name":"Multi-Agent System Observability: 65% Lower Cost with Temporal","isPartOf":{"@id":"https:\/\/www.xgrid.co\/resources\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/#primaryimage"},"image":{"@id":"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/#primaryimage"},"thumbnailUrl":"https:\/\/www.xgrid.co\/resources\/wp-content\/uploads\/2026\/08\/listing-images-4.webp","datePublished":"2026-08-25T09:57:33+00:00","dateModified":"2026-09-01T08:03:06+00:00","description":"See how Temporal workflow history exposed costly multi-agent loops, helping cut cost by 65% and latency by 70% through better observability and guardrails.","breadcrumb":{"@id":"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/#primaryimage","url":"https:\/\/www.xgrid.co\/resources\/wp-content\/uploads\/2026\/08\/listing-images-4.webp","contentUrl":"https:\/\/www.xgrid.co\/resources\/wp-content\/uploads\/2026\/08\/listing-images-4.webp","width":1048,"height":568,"caption":"Multi-Agent System Observability with Temporal: How We Cut Cost 65% and Latency 70%"},{"@type":"BreadcrumbList","@id":"https:\/\/www.xgrid.co\/resources\/success-stories\/multi-agent-system-observability-temporal\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.xgrid.co\/resources\/"},{"@type":"ListItem","position":2,"name":"Multi-Agent System Observability with Temporal: How We Cut Cost 65% and Latency 70%"}]},{"@type":"WebSite","@id":"https:\/\/www.xgrid.co\/resources\/#website","url":"https:\/\/www.xgrid.co\/resources\/","name":"Xgrid.co","description":"Learn, Design, Develop, and Engage with Xgrid","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.xgrid.co\/resources\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/www.xgrid.co\/resources\/wp-json\/wp\/v2\/success-stories\/13991","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xgrid.co\/resources\/wp-json\/wp\/v2\/success-stories"}],"about":[{"href":"https:\/\/www.xgrid.co\/resources\/wp-json\/wp\/v2\/types\/success-stories"}],"version-history":[{"count":53,"href":"https:\/\/www.xgrid.co\/resources\/wp-json\/wp\/v2\/success-stories\/13991\/revisions"}],"predecessor-version":[{"id":14068,"href":"https:\/\/www.xgrid.co\/resources\/wp-json\/wp\/v2\/success-stories\/13991\/revisions\/14068"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.xgrid.co\/resources\/wp-json\/wp\/v2\/media\/14050"}],"wp:attachment":[{"href":"https:\/\/www.xgrid.co\/resources\/wp-json\/wp\/v2\/media?parent=13991"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xgrid.co\/resources\/wp-json\/wp\/v2\/tags?post=13991"},{"taxonomy":"success-story-category","embeddable":true,"href":"https:\/\/www.xgrid.co\/resources\/wp-json\/wp\/v2\/success-story-category?post=13991"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}