Retrieval is critical in AI agents. To do any task correctly, AI agents needs to be able to retrieve all the information that is relevant to the task from its memory.Enterprise AI agents need context graphs to do this. This post discusses – why AI agents need decision traceshow context graphs capture themhow context graphs can be used by AI agentswhat are the quantifiable improvementsAn agent failure caseIt’s the last week of the quarter. A renewal agent is working a $480k account. The customer wants 20% off or they walk. The agent’s policy caps renewals at 10%.Now what?A human doing that task will use their experience instead of the policy document. Didn’t we do this exact thing with Globex last quarter? It was a similar story. Big Fortune 500 logo, threatening to churn, and someone signed off on 18% because there’d been three SEV-1 outages on their account that month. While Finance grumbled, they approved it anyway. The risk was worth taking on a $300k account. It worked and Globex renewed shortly after.This reasoning chain that makes the decision is not written down anywhere your agent can read.Salesforce will happily tell your agent that the Globex discount was 18%. It will not tell it that the number was an exception, who approved it, what justified it, or that a nearly identical situation is sitting in the agent’s queue right now. The what is spread across six systems of record. The why lives in three people’s heads and a Slack thread that already rolled off retention.So your agent does one of two things. It does the dumb-but-compliant thing, caps at 10%, and you lose the account. Or it escalates to a human, who spends forty minutes doing Slack archaeology to reconstruct a decision the company already made once. Either way, the organization failed to realize the benefit of adopting an AI agent.This is the gap. We have gotten extremely good at recording what changed, i.e. the parts, prices, suppliers, statuses, approvals. We systematically throw away why it changed. And “why” turns out to be the one thing your agents need most and have least.This is the gap people have started calling a context graph. Foundation Capital called it a trillion-dollar opportunity, which is the kind of phrase that usually sends people reaching for the back button. Stick around anyway. The term is new and a little overloaded, but it points at something real. If you ship or use agents, you will end up employing a context graph soon.Flat contextThe bad way to give your AI agents context is to just give them all the data, records, documents, rules and policies in a flat context window. Dump the invoice, PO, vendor record, contract, policy document into the context. Then watch the agent fail. Why?1. Context rotWhen the agent asks itself “can I pay invoice #842?” To answer, it has to hop – which PO does this invoice reference? does that PO still have budget? was the delivery received? is the vendor on payment hold? does $12,400 cross the approval threshold? what do the contract’s payment terms say? is the policy doc accurate and up-to-date? are there undocumented nuances related to this invoice payment currently living on Slack messages and Zoom call transcripts?Flat retrieval tries to hand this massive amount of information to the LLM model in a pile of disconnected chunks. Some invoice text here, some PO text there, some language from random docs and slack channels, all given as a flat wall of text.
“Can I pay invoice #842?”
Inbox
A
Acme Billingbilling@acme.com · Tue 09:14
Invoice #842 — $12,400.00 due
Hi, attaching this month’s invoice. Terms per contract.
📎 invoice_842.pdf · 84 KB
SAPPurchase Order · ME23N
PO Number7731
VendorAcme Corporation Ltd
Net Amount12,400.00
Budget left3,600.00
Goods receiptPosted · 12 Mar
StatusOpen
W policy_v4.docx
AP Approval Policy
▸ Invoices ≥ $10,000 need manager sign-off
# ap-ops
DDana 10:21Acme always pays end of quarter — don’t chase them.
WWes 10:22noted 👍 leaving #842 as-is
▦ payment_hold.csv
A · VendorB · On hold
1Acme Corporation LtdNo
2Globex LLCYes
3InitechNo
PDF contract_acme.pdf
Payment terms: NET-60
● REC Renewal call · transcript 14:02
Sales Gave Acme Net-60 this renewal.
AP lead Paid late twice… but it’s a $40k account. Approved.
.cgf, .cgf *{ box-sizing:border-box; }
.cgf{
–paper:#F5F6F8; –line:#E3E7ED; –ink:#0E1626; –tx:#1B2536;
font-family:-apple-system,BlinkMacSystemFont,”Segoe UI”,Roboto,system-ui,sans-serif;
color:var(–tx); background:var(–paper); border:1px solid var(–line);
border-radius:16px; padding:20px 20px 22px; max-width:760px; margin:24px auto;
box-shadow:0 1px 2px rgba(16,22,38,.04),0 12px 30px -18px rgba(16,22,38,.22);
-webkit-font-smoothing:antialiased;
}
.cgf-title{ margin:0 0 14px; font-size:22px; font-weight:700; letter-spacing:-.01em; color:var(–tx); }
.cgf-board{ position:relative; aspect-ratio:7/6; background:
radial-gradient(120% 90% at 50% -10%, #18233c 0%, #0E1626 60%);
border-radius:13px; overflow:hidden; }
/* generic document window */
.cgf-doc{ position:absolute; transform:rotate(var(–rot)); transform-origin:center;
background:#fff; border:1px solid #e6e8ec; border-radius:9px; overflow:hidden;
box-shadow:0 14px 28px -12px rgba(0,0,0,.55), 0 2px 6px rgba(0,0,0,.3);
font-size:11px; line-height:1.4; color:#1f2937; transition:transform .25s ease, box-shadow .25s ease; }
.cgf-doc:hover{ transform:rotate(0deg) scale(1.03); box-shadow:0 22px 40px -14px rgba(0,0,0,.6); z-index:9; }
.cgf-bar{ display:flex; align-items:center; gap:7px; padding:6px 9px; font-size:10px; font-weight:600;
color:#fff; background:#3a4153; }
.cgf-doc .page{ padding:9px 11px; }
.cgf-doc .ln{ display:block; height:5px; border-radius:3px; background:#e3e6ea; margin:5px 0; }
.ln.w90{width:90%}.ln.w85{width:85%}.ln.w80{width:80%}.ln.w70{width:70%}.ln.w60{width:60%}.ln.w55{width:55%}.ln.w50{width:50%}.ln.w45{width:45%}
.badge{ display:inline-grid; place-items:center; width:16px; height:16px; border-radius:3px; color:#fff; font-size:8px; font-weight:800; }
/* mac dots */
.dot{ width:8px;height:8px;border-radius:50%;display:inline-block; }
.dot.r{background:#ff5f57}.dot.y{background:#febc2e}.dot.g{background:#28c840}
/* EMAIL */
.email-bar{ background:#eef0f3; color:#5a6473; }
.email-head{ display:flex; gap:8px; align-items:center; padding:9px 11px 6px; }
.avatar{ width:26px;height:26px;border-radius:50%; background:#7c4dff; color:#fff;
display:grid;place-items:center;font-weight:700;font-size:12px; }
.em-from{ font-weight:700; } .em-meta{ color:#8a93a2; font-size:9.5px; }
.em-subj{ padding:0 11px; font-weight:700; font-size:11.5px; }
.em-body{ padding:4px 11px 8px; color:#5b6471; }
.attach{ margin:0 11px 10px; padding:5px 8px; background:#f3f5f8; border:1px solid #e6e9ee;
border-radius:6px; color:#3b4250; font-weight:600; font-size:10px; display:inline-block; }
/* SAP */
.sap-bar{ background:linear-gradient(180deg,#1d4f86,#163d68); }
.sap-mark{ background:#f0ab00; color:#0a2a4a; font-weight:800; font-size:9px; padding:1px 5px; border-radius:3px; letter-spacing:.04em; }
.sap-body{ padding:7px 11px 10px; }
.sap-body .f{ display:flex; justify-content:space-between; gap:10px; padding:4px 0; border-bottom:1px solid #f0f1f4; }
.sap-body .f:last-child{ border-bottom:0; }
.sap-body label{ color:#8a93a2; } .sap-body b{ font-weight:600; }
.sap-body b.ok{ color:#188038; }
.pill{ font-size:9px;font-weight:700;padding:1px 7px;border-radius:99px; }
.pill.open{ background:#e6f0fb;color:#1d4f86; }
/* WORD */
.word-bar{ background:#fff; color:#2b579a; border-bottom:1px solid #eef0f3; }
.badge.w{ background:#2b579a; }
.w-h{ font-weight:800; font-size:12px; color:#2b579a; margin-bottom:6px; }
.w-rule{ margin:6px 0; padding:6px 8px; background:#eef4ff; border-left:3px solid #2b579a; border-radius:4px;
color:#27364d; font-weight:600; }
/* SLACK */
.cgf-doc.slack{ display:flex; }
.slack-side{ width:34px; background:#3F0E40; display:flex; flex-direction:column; align-items:center; gap:7px; padding-top:9px; }
.slack-side i{ width:18px;height:18px;border-radius:6px; background:rgba(255,255,255,.22); }
.slack-side i:first-child{ background:#fff; }
.slack-main{ flex:1; }
.slack-head{ padding:7px 10px; font-weight:800; border-bottom:1px solid #eef0f3; color:#1d1c1d; }
.msg{ display:flex; gap:7px; padding:6px 10px; }
.sq{ width:22px;height:22px;border-radius:5px;color:#fff;display:grid;place-items:center;font-weight:700;font-size:10px;flex-shrink:0; }
.m-h{ margin:0 0 1px; font-weight:800; color:#1d1c1d; } .m-h span{ font-weight:500; color:#9aa0a6; font-size:9px; margin-left:4px; }
.msg p{ margin:0; color:#3b4046; }
/* SHEET */
.sheet-bar{ background:#188038; }
.badge.s{ background:rgba(255,255,255,.25); }
.grid{ width:100%; border-collapse:collapse; font-size:10px; }
.grid td{ border:1px solid #e6e9ee; padding:4px 7px; }
.grid .h td{ background:#f1f3f5; color:#7a828e; font-weight:700; font-size:9px; }
.grid .rn{ width:18px; text-align:center; background:#f7f8fa; color:#9aa0a6; }
.grid .no{ color:#188038; font-weight:700; } .grid .yes{ color:#d93025; font-weight:700; }
.grid tr:nth-child(2) td{ background:#fff7e6; }
/* PDF */
.pdf-bar{ background:#fff; color:#b3271e; border-bottom:1px solid #eef0f3; }
.badge.p{ background:#d93025; width:auto; padding:0 4px; }
.pdf-hl{ margin:6px 0; padding:5px 8px; background:#fff3cd; border-radius:4px; color:#5b4a00; font-weight:600; }
.pdf-hl b{ color:#7a3c00; }
/* ZOOM */
.zoom-bar{ background:#0b1f3a; }
.rec{ color:#ff5b5b; font-weight:800; font-size:9px; }
.zoom-body{ padding:8px 11px; }
.z-line{ margin:5px 0; color:#3b4250; }
.spk{ display:inline-block; min-width:42px; font-weight:800; color:#0b1f3a; font-size:9.5px;
background:#eaf1fb; padding:1px 6px; border-radius:4px; margin-right:6px; }
/* scan beam */
.cgf-scan{ position:absolute; left:0; right:0; top:0; height:34%; pointer-events:none;
background:linear-gradient(180deg, transparent, rgba(91,168,255,.16) 50%, transparent);
mix-blend-mode:screen; animation:cgfScan 5.5s ease-in-out infinite; }
@keyframes cgfScan{ 0%{transform:translateY(-40%)} 50%{transform:translateY(230%)} 100%{transform:translateY(-40%)} }
@media (max-width:600px){
.cgf-board{ aspect-ratio:auto; height:auto; padding:14px; display:flex; flex-direction:column; gap:12px; }
.cgf-doc{ position:static !important; transform:none !important; width:auto !important;
box-shadow:0 8px 18px -10px rgba(0,0,0,.5); }
.cgf-doc:hover{ transform:none !important; }
.cgf-scan{ display:none; }
}
@media (prefers-reduced-motion:reduce){ .cgf *{ animation:none !important; } }
The model, in its inference run, is forced to re-derive every one of those connections from scratch on each turn. Flattening business data into loose text destroys exactly the structure it needs.And as context size becomes large, LLM models fail in their tasks. They fail to follow instructions, drop rules randomly, misunderstand the relation between two pieces of information far apart, ignore middle-of-context data, apply rules and constraints out of order. Surge AI documents this in their instruction-following benchmark. The best frontier model solves <41% of such complex tasks.2. Lack of decision tracesAI Agents are bound to run into the same ambiguity humans resolve every day with learned judgment and organizational memory. But the inputs that form these judgements and organizational memory aren’t stored in a flat context window.Tribal knowledge. “We always give healthcare companies an extra 10% because their procurement cycles are brutal.” That’s not in the CRM. It’s tribal knowledge passed down through onboarding and side conversations.Past decisions. “We structured a similar deal for X last year where they split payments into installments, so we should offer this similar account Y the same terms.” No system links the two deals to convey why Y’s contract was drafted this way.Context across systems of record. The account manager sees usage sliding in the product dashboard, an unpaid invoice in NetSuite, and a cold one-line reply on the renewal thread, then flags customer as “churn risk” in the CRM. This reasoning happened in their head. The context just says “churn risk”.Manual approvals. A VP approves a discount on a Zoom call or in a Slack DM. The opportunity record shows the final price. It doesn’t show who approved the deviation or why this one-time exception was made.In a flat context window, the reasoning connecting data to decisions/actions isn’t treated as data in the first place. Every developer has hit the same wall in their own codebase. Why did we pick this queue over that one in 2019? Why is there a sleep(200) in the retry path that breaks everything when you remove it? It was obvious to whoever wrote it, and it’s gone now. Remember Architecture Decision Records? We invented them to fix exactly this. But most ADR folders die at three entries, because writing them is friction and nobody reads them later.That is the real shape of the problem. Companies are good at storing what happened. They are bad at storing why, because the why is unstructured, it spans systems, and until recently nothing could read it back even if you saved it.Both failures, the flattened web and the missing why, have the same fix.So what is a context graph?Two ideas, and neither is exotic.First, store every link once. Treat the things your business cares about as nodes: invoices, POs, vendors, contracts, policies, people. Treat the relationships as edges: this invoice references that PO, that PO is fulfilled by this receipt, this vendor signed that contract. Now the agent doesn’t rebuild the web each turn. It walks it. It pulls the small slice a decision touches and leaves the other ten thousand records out of the window. Context rot goes away, because the window stays small and on-point.
“Can I pay invoice #842?”
‹
trace
›
.cgg, .cgg *{ box-sizing:border-box; }
.cgg{
–paper:#F5F6F8; –line:#E3E7ED; –ink:#0E1626; –ink2:#16223A; –tx:#1B2536;
–dtx:#E9EEF6; –dmut:#8A99B0; –blue:#5BA8FF; –blue-d:#2E5C9E;
–amber:#F2B441; –green:#43D496; –edge:rgba(120,150,190,.30);
font-family:-apple-system,BlinkMacSystemFont,”Segoe UI”,Roboto,system-ui,sans-serif;
color:var(–tx); background:var(–paper); border:1px solid var(–line);
border-radius:16px; padding:20px 20px 20px; max-width:760px; margin:24px auto;
box-shadow:0 1px 2px rgba(16,22,38,.04),0 12px 30px -18px rgba(16,22,38,.22);
-webkit-font-smoothing:antialiased;
}
.cgg-title{ margin:0 0 14px; font-size:22px; font-weight:700; letter-spacing:-.01em; color:var(–tx); }
.cgg-board{ position:relative; background:var(–ink); border-radius:13px; overflow:hidden; aspect-ratio:900/720; }
.cgg-board svg{ width:100%; height:100%; display:block; }
.cgg-bottom{ position:absolute; left:0; right:0; bottom:0; z-index:2; padding:18px 16px 14px;
background:linear-gradient(180deg, transparent, rgba(8,12,22,.92) 42%); pointer-events:none; }
.cgg-status{ font-size:13px; line-height:1.45; color:var(–dmut); min-height:36px; }
.cgg-status b{ color:var(–dtx); }
.cgg-status .q{ color:#7fc0ff; font-weight:600; }
.cgg-status .ok{ color:var(–green); font-weight:600; }
.cgg-status .flag{ color:var(–amber); font-weight:600; }
.cgg-nav{ display:flex; align-items:center; gap:8px; margin-top:11px; pointer-events:auto; }
.cgg-arrow{ width:38px; height:32px; display:grid; place-items:center; cursor:pointer;
border:1px solid rgba(255,255,255,.18); background:#d3d3d3;
border-radius:8px; font-size:17px; line-height:1; transition:all .15s ease; }
.cgg-count{ font:600 11px/1 ui-monospace,Menlo,Consolas,monospace; color:var(–dmut);
letter-spacing:.04em; min-width:52px; text-align:center; }
.cgg .edge{ stroke:var(–edge); stroke-width:1.6; fill:none; transition:stroke .3s ease,stroke-width .3s ease; }
.cgg .edge.hot{ stroke:var(–blue); stroke-width:2.6; }
.cgg .elabel{ fill:var(–dmut); font:500 10px ui-monospace,Menlo,monospace; transition:fill .3s ease; }
.cgg .elabel.hot{ fill:var(–blue); }
.cgg .elbg{ fill:var(–ink); }
.cgg .node rect{ fill:var(–ink2); stroke:rgba(255,255,255,.10); stroke-width:1; transition:all .3s ease; }
.cgg .node .n-title{ fill:var(–dtx); font:600 13px -apple-system,system-ui,sans-serif; }
.cgg .node .n-sub{ fill:var(–dmut); font:500 10.5px ui-monospace,Menlo,monospace; }
.cgg .node.hub rect{ fill:#1C2C4C; stroke:rgba(91,168,255,.5); }
.cgg .node.hot rect{ fill:#1E3158; stroke:var(–blue); }
.cgg .node.hot .n-title{ fill:#fff; }
.cgg .dim{ opacity:.15; }
.cgg .verdict{ font:600 10px ui-monospace,Menlo,monospace; }
.cgg .vchip{ opacity:0; transition:opacity .3s ease; }
.cgg .vchip.show{ opacity:1; }
@media (max-width:560px){
.cgg{ padding:16px 13px; } .cgg-title{ font-size:19px; }
.cgg .node .n-title{ font-size:14px; } .cgg .node .n-sub{ font-size:11.5px; } .cgg .elabel{ font-size:11px; }
.cgg-status{ font-size:12px; }
}
@media (prefers-reduced-motion:reduce){ .cgg *{ transition:none !important; animation:none !important; } }
(function(){
var root=document.getElementById(‘cgg’); if(!root) return;
var SVGNS=’http://www.w3.org/2000/svg’;
var nodes={
inv: {x:430,y:300,w:160,h:64, title:’Invoice #842′, sub:’$12,400.00′, kind:’hub’},
po: {x:430,y:120,w:150,h:58, title:’PO-7731′, sub:’open’},
bud: {x:150,y:90, w:140,h:58, title:’Budget’, sub:’$3,600 left’},
grn: {x:120,y:300,w:150,h:58, title:’Delivery’, sub:’GRN · 12 Mar’},
ven: {x:690,y:300,w:160,h:58, title:’Acme Corp Ltd’, sub:’vendor’, kind:’ven’},
hold: {x:760,y:130,w:150,h:58, title:’Payment status’,sub:’not on hold’},
con: {x:700,y:480,w:160,h:58, title:’Contract’, sub:’Net-60′},
rule: {x:430,y:490,w:170,h:58, title:’Approval rule’, sub:’≥ $10k → sign-off’},
gl: {x:170,y:480,w:150,h:58, title:’GL account’, sub:’5200 · COGS’}
};
var edges=[
{id:’e1′,a:’inv’, b:’po’, l:’references’},
{id:’e2′,a:’po’, b:’bud’, l:’has budget’},
{id:’e3′,a:’po’, b:’grn’, l:’fulfilled by’},
{id:’e4′,a:’inv’, b:’ven’, l:’billed by’},
{id:’e5′,a:’ven’, b:’hold’,l:’status’},
{id:’e6′,a:’ven’, b:’con’, l:’terms’},
{id:’e7′,a:’inv’, b:’rule’,l:’amount → check’},
{id:’e8′,a:’inv’, b:’gl’, l:’posts to’}
];
var hops=[
{q:’Which PO does this invoice reference?’, e:[‘e1’], n:[‘inv’,’po’], node:’po’, v:’PO-7731 ✓’, vk:’ok’, cap:’Invoice → PO.’},
{q:’Does that PO still have budget?’, e:[‘e2’], n:[‘po’,’bud’], node:’bud’, v:’$3,600 ✓’, vk:’ok’, cap:’PO → Budget.’},
{q:’Was the delivery received?’, e:[‘e3’], n:[‘po’,’grn’], node:’grn’, v:’received ✓’, vk:’ok’, cap:’PO → Delivery receipt.’},
{q:’Is the vendor on payment hold?’, e:[‘e4′,’e5’], n:[‘inv’,’ven’,’hold’], node:’hold’, v:’not on hold ✓’, vk:’ok’, cap:’Invoice → Vendor → Status.’},
{q:’Does $12,400 cross the approval threshold?’, e:[‘e7’], n:[‘inv’,’rule’], node:’rule’, v:’≥ $10k ⚑’, vk:’flag’, cap:’Crosses the line so the agent escalates instead of guessing.’},
{q:’What do the contract’s payment terms say?’, e:[‘e6’], n:[‘ven’,’con’], node:’con’, v:’Net-60 · 47d ✓’, vk:’ok’, cap:’Vendor → Contract → Net-60.’}
];
var LAST=hops.length-1, SUMMARY=hops.length; // 6
var svg=document.getElementById(‘cgg-svg’);
var status=document.getElementById(‘cgg-status’);
var prev=document.getElementById(‘cgg-prev’);
var next=document.getElementById(‘cgg-next’);
var count=document.getElementById(‘cgg-count’);
function cx(n){return nodes[n].x;} function cy(n){return nodes[n].y;}
function el(t,a){var e=document.createElementNS(SVGNS,t); for(var k in a)e.setAttribute(k,a[k]); return e;}
var edgeEls={}, elabEls={}, nodeEls={};
edges.forEach(function(e){
var p=el(‘line’,{class:’edge’,x1:cx(e.a),y1:cy(e.a),x2:cx(e.b),y2:cy(e.b)});
svg.appendChild(p); edgeEls[e.id]=p;
});
edges.forEach(function(e){
var mx=(cx(e.a)+cx(e.b))/2, my=(cy(e.a)+cy(e.b))/2;
var bg=el(‘rect’,{class:’elbg’,rx:3}); svg.appendChild(bg);
var tx=el(‘text’,{class:’elabel’,x:mx,y:my+3,’text-anchor’:’middle’}); tx.textContent=e.l; svg.appendChild(tx);
bg.setAttribute(‘x’,mx-(e.l.length*3.0+5)); bg.setAttribute(‘y’,my-8);
bg.setAttribute(‘width’,e.l.length*6.0+10); bg.setAttribute(‘height’,15);
elabEls[e.id]={t:tx,bg:bg};
});
for(var id in nodes){ (function(id){
var n=nodes[id];
var g=el(‘g’,{class:’node’+(n.kind===’hub’?’ hub’:”)}); g.dataset.id=id;
var rect=el(‘rect’,{x:n.x-n.w/2,y:n.y-n.h/2,width:n.w,height:n.h,rx:11});
var t1=el(‘text’,{class:’n-title’,x:n.x,y:n.y-2,’text-anchor’:’middle’}); t1.textContent=n.title;
var t2=el(‘text’,{class:’n-sub’,x:n.x,y:n.y+15,’text-anchor’:’middle’}); t2.textContent=n.sub;
g.appendChild(rect); g.appendChild(t1); g.appendChild(t2);
var vg=el(‘g’,{class:’vchip’});
var vbg=el(‘rect’,{x:n.x,y:n.y-n.h/2-13,width:60,height:18,rx:9,fill:’#16223A’,stroke:’rgba(255,255,255,.12)’});
var vt=el(‘text’,{class:’verdict’,x:n.x,y:n.y-n.h/2-1,’text-anchor’:’middle’,fill:’#43D496′});
vg.appendChild(vbg); vg.appendChild(vt); g.appendChild(vg);
svg.appendChild(g);
nodeEls[id]={g:g,vchip:vg,vbg:vbg,vt:vt};
})(id); }
function clearHot(){
for(var k in edgeEls){edgeEls[k].classList.remove(‘hot’); elabEls[k].t.classList.remove(‘hot’);}
for(var k in nodeEls){nodeEls[k].g.classList.remove(‘hot’);}
}
function setChip(h){
var nv=nodeEls[h.node], nd=nodes[h.node];
nv.vt.textContent=h.v;
nv.vt.setAttribute(‘fill’, h.vk===’flag’?’#F2B441′:’#43D496′);
nv.vbg.setAttribute(‘stroke’, h.vk===’flag’?’rgba(242,180,65,.5)’:’rgba(67,212,150,.4)’);
nv.vchip.classList.add(‘show’);
var tw=nv.vt.getComputedTextLength?nv.vt.getComputedTextLength():h.v.length*6.2;
var bw=tw+18, bx=Math.min(nd.x+nd.w/2-12, 900-bw-6), by=nd.y-nd.h/2-13;
nv.vbg.setAttribute(‘x’,bx); nv.vbg.setAttribute(‘y’,by); nv.vbg.setAttribute(‘width’,bw);
nv.vt.setAttribute(‘x’,bx+bw/2); nv.vt.setAttribute(‘y’,by+13);
}
var step=-1;
function render(s){
clearHot();
hops.forEach(function(h){ nodeEls[h.node].vchip.classList.remove(‘show’); });
if(s-1){ step–; render(step); } });
next.addEventListener(‘click’,function(){ if(step

