<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Practice Space]]></title><description><![CDATA[All things creative and personally fulfilling. Research, music, AI, and the outdoors.]]></description><link>https://practicespace.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!2d9L!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a3f22ba-363b-40e8-8db4-c9eac148a517_1280x1280.png</url><title>Practice Space</title><link>https://practicespace.substack.com</link></image><generator>Substack</generator><lastBuildDate>Thu, 17 Sep 2026 15:35:57 GMT</lastBuildDate><atom:link href="https://practicespace.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Nick Feamster]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[practicespace@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[practicespace@substack.com]]></itunes:email><itunes:name><![CDATA[Nick Feamster]]></itunes:name></itunes:owner><itunes:author><![CDATA[Nick Feamster]]></itunes:author><googleplay:owner><![CDATA[practicespace@substack.com]]></googleplay:owner><googleplay:email><![CDATA[practicespace@substack.com]]></googleplay:email><googleplay:author><![CDATA[Nick Feamster]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Teaching a Living Course With Claude]]></title><description><![CDATA[Making a live course actually live: student input shapes what happens in the room, examples stay current to the week, and every in-class insight flows back into the durable material.]]></description><link>https://practicespace.substack.com/p/teaching-a-living-course-with-claude</link><guid isPermaLink="false">https://practicespace.substack.com/p/teaching-a-living-course-with-claude</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Fri, 10 Jul 2026 23:25:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!LRR7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LRR7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LRR7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 424w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 848w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 1272w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LRR7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png" width="1456" height="337" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18c36958-99c2-4318-9308-64e025afe877_2961x686.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:337,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:761927,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/206514224?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!LRR7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 424w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 848w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 1272w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>I moved my Internet Censorship course off <a href="https://gh.io/classroom-sunset">GitHub Classroom</a> this summer. GitHub is <a href="https://github.blog/changelog/2026-05-26-github-classroom-sign-ups-are-no-longer-available/">winding it down</a> &#8212; sign-ups closed May 26, 2026; the platform is decommissioned August 28; Classroom-specific data is deleted September 4. That forced me into a hand-rolled replacement.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>The replacement is simple: personal private GitHub repos as student response repos, a Google Form for intake, a private roster CSV, a private <code>instructor-data</code> repo for course notes, and a growing collection of Claude Code &#8220;skills&#8221; that I trigger from the terminal. Think of a skill as a named workflow I can invoke by phrase.</p><p>The stack itself isn&#8217;t the story. The story is that I ended up with five concrete teaching goals I couldn&#8217;t reach before:</p><ol><li><p><strong>Keep track of every student&#8217;s progress.</strong> No quiet non-submitters.</p></li><li><p><strong>Incorporate student input into class in real time.</strong> What they wrote about actually shapes what happens in the room.</p></li><li><p><strong>Keep examples current in slides and breakouts.</strong> Never teach the DoS lecture with a 2018 case study when there&#8217;s a better 2025 one.</p></li><li><p><strong>Make all of that seamless during class.</strong> Slides render from Quarto in a browser; a speaker-notes file sits alongside as an outline with clickable links; when I click a link, it opens in the same browser. No context switching, no URL h<span>un</span>ting.</p></li><li><p><strong>Close the loop from class back into the durable material.</strong> When I bring up a new example in class, or land on a framing that finally works, I push it back into the notes, the slides, the breakout for that topic, and the book chapter &#8212; so nothing that worked in the room dies there.</p></li></ol><p>Below is how I got to each.</p><h2><strong>Goal 1: Keep Track of Every Student&#8217;s Progress</strong></h2><p>Four skills, one loop.</p><p><strong>Onboarding.</strong> When a student fills the Google Form, they name themselves and give me their GitHub handle. I r<span>un</span> <code>accept-invitations censorship</code>, which walks pending GitHub collaborator invitations, filters case-insensitively for the course pattern (and matches the inviter login too, because repo names and handles diverge in surprising ways), and accepts the matches. Then <code>merge-roster censorship-summer</code> folds the intake spreadsheet into the master roster CSV. It accepts <code>.csv</code>, <code>.csv.zip</code>, and <code>.xlsx</code> directly, because Google Sheets, that&#8217;s why. There&#8217;s a <code>--dedupe</code> flag for the students who fill the form twice.</p><p><strong>Weekly pulls.</strong> Before each class, <code>pull-submissions censorship-summer</code> clones or <code>git pull</code>s every student&#8217;s private response repo into a gitignored <code>gradebook/</code> directory. It reports fresh clones, pulls, and failures. Failures usually mean a student revoked collaborator access or deleted their repo &#8212; worth knowing.</p><p><strong>Coverage check.</strong> <code>response-digest</code> produces a TSV of who submitted this week&#8217;s file, who submitted a template stub, and who submitted nothing. That&#8217;s the nudge list.</p><p><strong>The nudge.</strong> I built a <a href="https://github.com/feamster/slack-mcp">custom Slack MCP server</a> that Claude can talk to. Recently I extended it so it can DM anyone in the workspace (not just people I&#8217;ve DMed before), by adding a users-lookup step and a <code>conversations.open</code> fallback. One skill invocation DMs the missing students by name.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gma3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gma3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png 424w, https://substackcdn.com/image/fetch/$s_!gma3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png 848w, https://substackcdn.com/image/fetch/$s_!gma3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png 1272w, https://substackcdn.com/image/fetch/$s_!gma3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gma3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png" width="643" height="593" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0762df5a-44f4-4f91-bffe-04223843b986_643x593.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:593,&quot;width&quot;:643,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:89925,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/206514224?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!gma3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png 424w, https://substackcdn.com/image/fetch/$s_!gma3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png 848w, https://substackcdn.com/image/fetch/$s_!gma3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png 1272w, https://substackcdn.com/image/fetch/$s_!gma3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0762df5a-44f4-4f91-bffe-04223843b986_643x593.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The turnaro<span>un</span>d from &#8220;student is invisibly missing&#8221; to &#8220;student is back on track&#8221; is nearly instantaneous now. Before this summer, students would routinely fall through the cracks until grading deadlines at the end of the term.</p><h2><strong>Goal 2: Incorporate Student Input Into Class in Real Time</strong></h2><p>This is the goal I most doubted was possible. It turned out to be the easiest.</p><p><strong>Digest, not aggregate.</strong> After <code>pull-submissions</code>, I ask Claude to read every response and write a <code>week-summary.md</code>. The constraint is that the digest has to be <strong>attributed and specific.</strong> Not &#8220;several students asked about deniability&#8221; but a paraphrased threading of individual student threads, each cited by response filename. That specificity is what makes the summary a working document instead of a report I&#8217;d file away.</p><p><strong>Agenda that names specific threads.</strong> I do this before every class, not once a week. I ask Claude to draft an agenda referencing the summary. The agenda is a markdown file with a schedule table, materials queued (slide deck, breakout, activity), and a <strong>discussion moves</strong> section. That section maps concrete response threads onto specific moments in the class period. Item 1 in the Q&amp;A block: open with X&#8217;s question. Minute 40 handoff from the reading discussion: pull in Y&#8217;s example.</p><p><strong>Post to the class.</strong> Right before class: <code>post today's agenda to Slack</code>. The skill reads the agenda, strips the parts students shouldn&#8217;t see (private instructor notes, nudge lists), converts the schedule table into a Slack-friendly bullet list, and shows me a preview. I confirm. It posts. Confirm-before-posting is non-negotiable &#8212; every skill that touches shared state has a preview step.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rNYd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rNYd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png 424w, https://substackcdn.com/image/fetch/$s_!rNYd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png 848w, https://substackcdn.com/image/fetch/$s_!rNYd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png 1272w, https://substackcdn.com/image/fetch/$s_!rNYd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rNYd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png" width="494" height="194" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:194,&quot;width&quot;:494,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:33522,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/206514224?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!rNYd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png 424w, https://substackcdn.com/image/fetch/$s_!rNYd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png 848w, https://substackcdn.com/image/fetch/$s_!rNYd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png 1272w, https://substackcdn.com/image/fetch/$s_!rNYd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F028fa012-b153-433a-bc5b-bebabc1549b3_494x194.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><strong>Live during class.</strong> The other tool I use here is a small local pipeline I built called <code>transcripts-mcp</code>. <a href="https://existential.audio/blackhole/">BlackHole 2ch</a> captures system audio; ffmpeg mixes it with the mic; <a href="https://github.com/ggerganov/whisper.cpp">whisper.cpp</a> transcribes locally. A <code>meeting-summary</code> skill polls the transcript mid-class and writes a structured markdown summary to disk with a r<span>un</span>ning &#8220;open questions&#8221; section. Every poll only reads and summarizes the <em>tail</em> since the previous poll &#8212; the summary file carries an HTML-comment state marker like <code>&lt;!-- covered_through_sec=NNN.N --&gt;</code>, and the incremental pipeline makes a three-hour class meeting cost almost nothing. Everything stays on the laptop; no audio ever leaves the machine.</p><p>I use the live summary two ways. During class, I glance at &#8220;open questions&#8221; as a prompt for what to circle back to. After class, the final summary becomes raw material for the <em>next</em> agenda. Between polls the skill preserves any hand-edits I make to the summary file. Only the state marker line is fully owned by the tool.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BjVl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BjVl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png 424w, https://substackcdn.com/image/fetch/$s_!BjVl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png 848w, https://substackcdn.com/image/fetch/$s_!BjVl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png 1272w, https://substackcdn.com/image/fetch/$s_!BjVl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BjVl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png" width="1118" height="508" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:508,&quot;width&quot;:1118,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:124890,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/206514224?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BjVl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png 424w, https://substackcdn.com/image/fetch/$s_!BjVl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png 848w, https://substackcdn.com/image/fetch/$s_!BjVl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png 1272w, https://substackcdn.com/image/fetch/$s_!BjVl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7c2fb56-0645-4ca4-b204-2f57a4be40d9_1118x508.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The class discussion genuinely shapes what happens next. Before this, &#8220;read every response and hold the themes in my head by class time&#8221; was aspirational.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Vlnc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Vlnc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png 424w, https://substackcdn.com/image/fetch/$s_!Vlnc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png 848w, https://substackcdn.com/image/fetch/$s_!Vlnc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png 1272w, https://substackcdn.com/image/fetch/$s_!Vlnc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Vlnc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png" width="1112" height="514" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:514,&quot;width&quot;:1112,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:110695,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/206514224?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Vlnc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png 424w, https://substackcdn.com/image/fetch/$s_!Vlnc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png 848w, https://substackcdn.com/image/fetch/$s_!Vlnc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png 1272w, https://substackcdn.com/image/fetch/$s_!Vlnc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa35ff020-bfb2-4fe9-aab6-5d0eb708c9a9_1112x514.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>Goal 3: Keep Examples Current in Slides and Breakouts</strong></h2><p>Course content ages fast, especially in a course about a moving target. What matters here isn&#8217;t that I remember to look up recent examples &#8212; it&#8217;s that the skills find them and hand them to me for review.</p><p>The workflow is: I ask a skill to catch me up on what&#8217;s happened in the last twelve months on a given topic. The skill r<span>un</span>s targeted <code>WebSearch</code> calls, filters for reputable sources (peer-reviewed venues, regulator press releases, Reuters/AP/BBC, <a href="https://citizenlab.ca/">Citizen Lab</a>, <a href="https://ooni.org/">OONI</a>, <a href="https://www.accessnow.org/">Access Now</a>, <a href="https://dfrlab.org/">DFRLab</a>), and presents a short list of candidate developments with one-sentence context each. I pick the ones that fit the arc of the class.</p><p>When I refreshed the DoS lecture for this term, the candidate list came back with the <a href="https://blog.cloudflare.com/ddos-threat-report-2025-q4/">Cloudflare Q4 2025 DDoS threat report</a> (31.4 Tbps in November 2025); the <a href="https://blog.cloudflare.com/18-november-2025-outage/">November 18, 2025 Cloudflare outage</a> as a &#8220;one company, so much of the web&#8221; case study; the <a href="https://thehackernews.com/2025/12/record-297-tbps-ddos-attack-linked-to.html">Aisuru IoT botnet writeup</a>; and the <a href="https://www.accessnow.org/internet-shutdowns-2025/">Access Now KeepItOn 2025 shutdown data</a>. I hadn&#8217;t tracked most of these in real time; the skill did. I read the candidates, picked what fit, and the skill folded them into the deck, the speaker notes, and the breakout for that lecture.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9006!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9006!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png 424w, https://substackcdn.com/image/fetch/$s_!9006!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png 848w, https://substackcdn.com/image/fetch/$s_!9006!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png 1272w, https://substackcdn.com/image/fetch/$s_!9006!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9006!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png" width="1107" height="922" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:922,&quot;width&quot;:1107,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:725597,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/206514224?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9006!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png 424w, https://substackcdn.com/image/fetch/$s_!9006!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png 848w, https://substackcdn.com/image/fetch/$s_!9006!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png 1272w, https://substackcdn.com/image/fetch/$s_!9006!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e44f83-32a4-4b74-9270-483eb9ca95ed_1107x922.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Three skills handle this, all following the same generate-or-refresh, mode-auto-detected pattern:</p><ul><li><p><code>refresh-breakouts</code> &#8212; updates current-event prep-reads inside the breakout discussion files. Only edits content between <code>&lt;!-- current-events:start --&gt;</code>markers, so evergreen debate motions and prompts stay <span>un</span>touched.</p></li><li><p><code>course-slides</code> &#8212; generates a new Quarto lecture deck OR refreshes an existing one with the last twelve months of developments.</p></li><li><p><code>speaker-notes</code> &#8212; same pattern; produces a slide-by-slide notes/outline table with live current-event links, so clicking a link in the notes opens the source in the same browser where the Quarto slides are r<span>un</span>ning.</p></li></ul><p>Every URL is verified in the session or is a canonical org landing page. This is non-negotiable. Language models are cheerful about inventing plausible citations. I have caught skills making up arXiv IDs, inventing Washington Post search URLs, and confidently linking to blog posts that didn&#8217;t exist. Every content skill has an explicit &#8220;never invent URLs; if the search is thin, use a descriptive citation with no URL&#8221; rule at the top of its safety section. I re-read every diff.</p><h2><strong>Goal 4: Make It Seamless During Class</strong></h2><p>Once the material is prepared, the classroom itself has to feel like one environment, not five separate tools.</p><p>My slides are <a href="https://quarto.org/docs/presentations/revealjs/">Quarto</a> reveal.js decks, rendered to HTML and opened in a browser on the projector. On my second monitor I open the corresponding <code>speaker-notes.md</code>, which is a two-column markdown table: slide title in the left column, per-slide context and clickable links in the right. The reference file lives at <code>docs/slides/02-Technical/02-Throttling-DoS/speaker-notes.md</code> in my course repo.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pvRL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pvRL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png 424w, https://substackcdn.com/image/fetch/$s_!pvRL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png 848w, https://substackcdn.com/image/fetch/$s_!pvRL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png 1272w, https://substackcdn.com/image/fetch/$s_!pvRL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pvRL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png" width="652" height="103" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:103,&quot;width&quot;:652,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:15032,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/206514224?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pvRL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png 424w, https://substackcdn.com/image/fetch/$s_!pvRL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png 848w, https://substackcdn.com/image/fetch/$s_!pvRL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png 1272w, https://substackcdn.com/image/fetch/$s_!pvRL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdfd8728-ea9d-47cb-8d86-e30de6d8c2a2_652x103.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The key move is that the notes file is rendered as markdown <strong>in the same browser environment as the slides</strong> &#8212; GitHub Pages, or a Quarto site, or VS Code&#8217;s markdown preview. So when I click a link in the notes, it opens in the same browser where the slides live. There&#8217;s no context switch. I never have to fumble with a terminal or a note-taking app or a separate bookmark manager mid-lecture. One browser, two tabs. The notes are the outline.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LRR7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LRR7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 424w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 848w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 1272w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LRR7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png" width="1456" height="337" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18c36958-99c2-4318-9308-64e025afe877_2961x686.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:337,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:761927,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/206514224?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!LRR7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 424w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 848w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 1272w, https://substackcdn.com/image/fetch/$s_!LRR7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c36958-99c2-4318-9308-64e025afe877_2961x686.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Reveal.js also has a speaker view (press <strong>S</strong>) that shows in-deck <code>::: {.notes}</code> blocks on my monitor. Those are for context that belongs <em>to</em> a slide. The external <code>speaker-notes.md</code> is for <em>between</em>-slide flow: the links, the current-event citations, the &#8220;here&#8217;s why this transition works&#8221; framing. Together they cover both.</p><h2><strong>Goal 5: Close the Loop From Class Back Into the Durable Material</strong></h2><p>The thing that surprises me most about this setup in practice is how much it captures the reverse direction: the ephemeral moment in class that becomes durable material.</p><p>Mid-class I&#8217;ll say something like &#8220;actually the cleanest way to think about this is &#8212;&#8221; and land on a framing I hadn&#8217;t planned. Or a student surfaces an example I hadn&#8217;t considered. Or I read a live-transcript summary paragraph out of the corner of my eye and realize it captures a distinction better than my slides do.</p><p>Any of those used to disappear. I&#8217;d remember for a day, kind of mangle it into next semester&#8217;s notes, and lose the specifics. Now the loop closes in minutes:</p><ul><li><p><strong>Into the speaker-notes.</strong> <em>&#8220;Refresh the throttling notes to add the framing I just used about TSPU being the enabler, not the technique.&#8221;</em> One skill invocation, the notes file is updated, verified links preserved.</p></li><li><p><strong>Into the slides.</strong> <em>&#8220;Add a bullet on the Aisuru example to the DoS deck slide about defense.&#8221;</em> The <code>course-slides</code> skill drops the bullet with a citation and shows me the diff.</p></li><li><p><strong>Into the breakout for that topic.</strong> If the example changes what the discussion should be, <code>refresh-breakouts</code> pulls it into the prep-reads block.</p></li><li><p><strong>Into the book.</strong> The book chapter lives in a sibling <code>../censorship-book/</code> repo with its own <code>refresh-book-chapter</code> skill. Same interface: <em>&#8220;add the example to the DoS section, cite Krebs 2016, keep the existing framing.&#8221;</em> The skill edits the LaTeX and stages the diff for review.</p></li><li><p><strong>Into the reading list.</strong> If the example points to a paper I hadn&#8217;t assigned, it goes into the reading list for the following week.</p></li></ul><p>Every one of those edits is proposed, shown as a diff, and confirmed before it&#8217;s written. Nothing is autonomous. But the <em>availability</em> of that motion &#8212; capturing a live-class insight and propagating it into four different documents before the next class meeting &#8212; is what makes the course improve continuously, instead of drifting into whatever last semester&#8217;s version was.</p><h2><strong>AI-Assisted, Not AI-Generated</strong></h2><p>Every insight, every direction, every decision here is mine. The class discussion is mine to lead. Which student threads to open with, which examples to bring in, when to change tack &#8212; those are judgment calls I make in real time. The framing of a lecture, the argument I want the semester to build toward, the reason a particular reading is on the syllabus &#8212; all mine.</p><p>What Claude does is take the parts that used to force me to choose between doing them well and doing them at all, and makes both possible. Read every student response with real attribution instead of an aggregate summary. Verify a dozen current-event citations before class instead of five. Keep the slides, the notes, the breakout, and the book chapter aligned on the same example, instead of watching them drift apart across semesters. Compose five heroic tasks into an hour of work instead of a S<span>un</span>day-evening slog.</p><p>None of this is autonomous. Every workflow starts with me typing a short command, and every one of them has a confirmation step where Claude shows me what it&#8217;s about to do and waits. The value isn&#8217;t the AI making decisions. It&#8217;s the AI making the composition fast enough that a much better class becomes an ordinary part of the week.</p><p>The <code>SKILL.md</code> files live in <code>noise-courses/instructor-tools</code>.</p>]]></content:encoded></item><item><title><![CDATA[I Used Claude Code to Build a Local Archive of Every Paper I’ve Written]]></title><description><![CDATA[I'd put this task off for decades. Claude Code helped me finish it in an afternoon.]]></description><link>https://practicespace.substack.com/p/i-used-claude-code-to-build-a-local</link><guid isPermaLink="false">https://practicespace.substack.com/p/i-used-claude-code-to-build-a-local</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Wed, 17 Jun 2026 21:34:53 GMT</pubDate><enclosure url="https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For most of my career I&#8217;ve wanted one organized place that holds the original PDF of every paper I&#8217;ve published. Not a list of links, since links rot, but the actual files, in one place I control. I never built it. It was always too tedious to justify the time, and too specialized for any tool I could buy. This week I built it with <a href="https://claude.com/claude-code">Claude Code</a> in about half a day. The result lives at <strong><a href="https://github.com/feamster/publications">github.com/feamster/publications</a></strong>, and on <a href="https://feamster.github.io/publications.html">my site</a>.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080" width="5184" height="3456" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3456,&quot;width&quot;:5184,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;person writing on brown wooden table near white ceramic mug&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="person writing on brown wooden table near white ceramic mug" title="person writing on brown wooden table near white ceramic mug" srcset="https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1434030216411-0b793f4b4173?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxfHxyZXNlYXJjaCUyMHBhcGVyfGVufDB8fHx8MTc4MTczMjAxMHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@uns__nstudio">Unseen Studio</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><p></p><h3><strong>The Idea</strong></h3><p>The design decision that made this tractable was to treat the CV as the source of truth. My CV already lists every publication, in order, grouped into journal, conference, workshop, theses, and books. So instead of maintaining a separate list, the tool parses the CV&#8217;s LaTeX source directly. Every paper cited there becomes an entry, joined to my BibTeX metadata, and the tool goes and finds the PDF for each one.</p><p>The output is a Git repository, organized by year, with every file named by its citation key and a generated README that mirrors the CV&#8217;s numbering and grouping exactly. Paper [137] is right there, linked, in the same order as my CV.</p><h3><strong>How It Fetches Things</strong></h3><p>About 250 PDFs spanning 1999 to 2026 meant building a waterfall of sources and trying them in order of cleanliness:</p><ul><li><p><strong>Open APIs first.</strong> <a href="https://openalex.org">OpenAlex</a>, <a href="https://unpaywall.org">Unpaywall</a>, <a href="https://www.crossref.org">Crossref</a>, and <a href="https://www.semanticscholar.org">Semantic Scholar</a> resolve titles to DOIs and DOIs to open-access PDFs. They&#8217;re free, well-documented, and straightforward to script against.</p></li><li><p><strong>Open-access venues.</strong> <a href="https://arxiv.org">arXiv</a>, <a href="https://www.usenix.org">USENIX</a>, <a href="https://www.ndss-symposium.org">NDSS</a>, the <a href="https://ojs.aaai.org">AAAI</a> portal, and <a href="https://dspace.mit.edu">MIT&#8217;s DSpace</a> (for my theses) serve PDFs at stable, predictable URLs. USENIX is the model here. Every paper is free, forever, at a clean URL.</p></li><li><p><strong>Licensed content through the library.</strong> For ACM, Springer, and the like, the tool authenticates through my university&#8217;s library proxy, with single sign-on and two-factor, in a real browser session, and pulls the PDFs I&#8217;m entitled to.</p></li></ul><h3><strong>Where It Got Hard</strong></h3><p>The instructive part, and the part that says something about academic publishing, is where automation failed.</p><p><a href="https://ieeexplore.ieee.org">IEEE Xplore</a> sits behind an aggressive bot-detection layer. It blocked automated downloads even when I went through my university&#8217;s standard library proxy, which is a DNS-based redirect that rewrites the publisher&#8217;s hostname (EZproxy). The fix was to route traffic through a campus network connection so the requests came from an institutional IP directly. Even then, IEEE rate-limited me after about fifteen downloads and returned errors until I slowed down.</p><p>Everything else that failed did so in a similar way. A law journal&#8217;s repository threw bot challenges. ResearchGate wouldn&#8217;t hand a file to a script, since it gates downloads behind a login. One repository wouldn&#8217;t even complete a TLS handshake. A few of my oldest papers were only ever hosted on university servers that are now gone. This last set came down to a small handful of papers, so I tracked them down myself, usually through Google Scholar or ResearchGate, and dropped the PDFs in a folder. The tool then matched each one back to the right CV entry by title and DOI and filed it. At that scale, doing it by hand was no trouble.</p><p>The pattern is consistent. The open infrastructure made hundreds of papers effortless. The friction, the rate limits, the dead links, and the bot walls were all on the proprietary side. If you want a concrete argument for open access and open metadata, try assembling your own publication record and see which sources help and which fight you.</p><h3><strong>A Bonus: It Found a 20-Year-Old Error in My CV</strong></h3><p>Because the tool checks that each downloaded PDF&#8217;s title matches its CV entry, it flagged a mismatch on a paper from more than twenty years ago. My CV listed it under its tech-report title, from around 2005, but cited it as the journal version, which was published in 2007 under a different title. The entry had been wrong for the better part of two decades, copied forward from one CV to the next. I corrected the BibTeX, rebuilt the CV and website from it, and archived the correct published PDF. Forcing a machine to reconcile your records against reality is a good way to find what you&#8217;ve been overlooking.</p><h3><strong>The Workflow, and Making It Last</strong></h3><p>The part I care about most is that this isn&#8217;t a one-off script. It&#8217;s a repeatable workflow, captured as reusable Claude skills, so I can run it the same way every month.</p><p>The ordering follows from treating the CV as canonical:</p><ol><li><p><strong>Update the source.</strong> Add each new paper to my bibliography and to the CV. One rule the workflow encodes: a paper only enters the archive once it&#8217;s actually cited in the CV. The citation list defines membership, and the bibliography just supplies metadata.</p></li><li><p><strong>Rebuild what&#8217;s derived from it.</strong> That&#8217;s the CV PDF and my website, both generated from the same bibliography.</p></li><li><p><strong>Re-sync the archive.</strong> The skill rebuilds its index, fetches any newly available PDFs (open access first, then the library proxy, then the campus connection for the stubborn ones), regenerates the README, and commits.</p></li></ol><p>The operational knowledge is written into the skill itself: which sources are friendly, how to authenticate, that IEEE will rate-limit you, and that the long-tail stragglers are easiest to drop into a folder and let the tool file. Keeping my paper archive current went from a vague, years-long aspiration to a ten-minute monthly task that mostly runs itself.</p><h3><strong>The Point</strong></h3><p>What&#8217;s notable about this project isn&#8217;t just the archive I&#8217;d always wanted. It&#8217;s the category of task, and how well suited agentic AI turns out to be for it. I&#8217;d wanted to do this for years and never started, because it was too tedious to justify a weekend and too specialized for any off-the-shelf tool. That describes a lot of valuable work: personal, fiddly infrastructure that never clears the bar. Agentic AI is unreasonably good at it. Half a day, start to finish, including the awkward stragglers and a latent error I didn&#8217;t know I had.</p><p>I suspect a lot of us have a project like this on the list. Mine&#8217;s done.</p>]]></content:encoded></item><item><title><![CDATA[Using Claude Code to Modernize My Courses]]></title><description><![CDATA[How a semester&#8217;s worth of student feedback became a set of tracked GitHub issues &#8212; and then a fleet of Claude Code agents that did the work.]]></description><link>https://practicespace.substack.com/p/using-claude-code-to-modernize-my</link><guid isPermaLink="false">https://practicespace.substack.com/p/using-claude-code-to-modernize-my</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Wed, 03 Jun 2026 05:36:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!jE8T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every course accumulates cruft. Slides drift a year (or five) out of date. The &#8220;permitted materials&#8221; rule for the exam gets announced slightly differently every term. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jE8T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jE8T!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png 424w, https://substackcdn.com/image/fetch/$s_!jE8T!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png 848w, https://substackcdn.com/image/fetch/$s_!jE8T!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png 1272w, https://substackcdn.com/image/fetch/$s_!jE8T!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jE8T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png" width="1456" height="1561" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1561,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:768562,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/200405850?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jE8T!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png 424w, https://substackcdn.com/image/fetch/$s_!jE8T!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png 848w, https://substackcdn.com/image/fetch/$s_!jE8T!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png 1272w, https://substackcdn.com/image/fetch/$s_!jE8T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F959631e7-0531-4e17-84ae-c6a1b16b6ad5_1610x1726.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Assignment rubrics live in my head instead of on the page. End-of-term feedback gets read once, nodded at, and forgotten. None of this is hard to fix. It&#8217;s just tedious, and tedium is exactly what gets deferred until &#8220;next year.&#8221;</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>This year I tried something different. I sat down with <a href="https://claude.com/claude-code">Claude Code</a> and a single organizing idea: <strong>turn every intention into a tracked GitHub issue, then point agents at the issue.</strong> The issue becomes the spec; the agents become the labor. Here&#8217;s what that looked like across my <a href="https://github.com/noise-lab/security-course">security course</a> &#8212; and how I then cloned the whole approach into two other courses (<a href="https://github.com/noise-lab/ml-systems">ML systems</a> and <a href="https://github.com/noise-lab/censorship-course">censorship</a>) without redoing the thinking.</p><h2>Start With The Feedback, End With An Issue</h2><p>I exported the course evaluations as a PDF and dropped it in my Downloads folder. Step one was simply: <em>read this and tell me what students actually said.</em> Claude summarized it &#8212; the praise, but more usefully the constructive themes: feedback on graded work was slow and opaque, the once-a-week three-hour block was a slog, exam questions were uneven, some assignments felt surface-level, and a few materials were hard to find.</p><p>Then the important move: <strong>file it as a tracking issue</strong> with a checklist, one box per theme. The security course&#8217;s <em><a href="https://github.com/noise-lab/security-course/issues/5">Course feedback &#8212; Autumn 2025 (summary &amp; follow-ups)</a></em> issue is the canonical worked example: a feedback summary up top, then a checklist where each box &#8212; rubrics, the syllabus communication/response-times section, the debate rubric, the exam-logistics standardization &#8212; gets checked off as the corresponding change ships. That issue became the backbone for everything that followed. Instead of a vague memory of &#8220;students wanted better feedback,&#8221; I had a durable, checkable artifact &#8212; and every change I shipped later got a one-line &#8220;shipped in commit X&#8221; note against its box. The issue is both the to-do list and the changelog.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!M5jF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!M5jF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png 424w, https://substackcdn.com/image/fetch/$s_!M5jF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png 848w, https://substackcdn.com/image/fetch/$s_!M5jF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png 1272w, https://substackcdn.com/image/fetch/$s_!M5jF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!M5jF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png" width="1456" height="1266" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1266,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:542811,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/200405850?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!M5jF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png 424w, https://substackcdn.com/image/fetch/$s_!M5jF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png 848w, https://substackcdn.com/image/fetch/$s_!M5jF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png 1272w, https://substackcdn.com/image/fetch/$s_!M5jF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7de8a153-926f-4676-9f74-55ab1b26f8b9_1886x1640.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Assignments: Rubrics, Auto-Grading, And &#8220;AI-Resilience&#8221;</h2><p>The loudest signal was about graded work, so we restructured the assignments (tracked as one of the checklist boxes in <a href="https://github.com/noise-lab/security-course/issues/5">issue #5</a>). Each one became a self-contained folder with an <strong>up-front rubric</strong> the students see, plus a separate <strong>grading key</strong> designed so I can grade with an LLM consistently. That second part forced a useful discipline: if a model is going to grade a submission, the assignment has to ask for <em>evidence in the text</em> (paste the actual packet fields, the token JSON, the metrics) rather than artifacts a grader can&#8217;t open.</p><p>The part I&#8217;m most pleased with is what I started calling <strong>AI-resilience</strong>. Students will use AI &#8212; that&#8217;s fine, and I tell them so. The trick is to design tasks where doing the thinking yourself, with AI as a tool, still beats a one-shot prompt:</p><ul><li><p>Build on personal artifacts (your own capture, your own account).</p></li><li><p><em>Verify and correct</em> the model against your own data.</p></li><li><p>Write a short reflection on what surprised you.</p></li><li><p>Be ready to defend it live.</p></li></ul><p>The rubric rewards exactly that.</p><h2>Syllabus And Exams: Killing Inconsistency</h2><p>A lot of &#8220;policy&#8221; problems are really <em>consistency</em> problems. So we added a <strong>Communication &amp; Response Times</strong> section to the syllabus (public channel first, peers expected to help, a stated turnaround), pinned that assignment release and due dates are published on day one, and wrote an actual <strong>debate rubric</strong> so a third of the grade isn&#8217;t a vibe.</p><p>Exams were the cleanest example of the consistency fix (another box on <a href="https://github.com/noise-lab/security-course/issues/5">issue #5</a>). The &#8220;permitted materials&#8221; rule &#8212; one double-sided handwritten sheet, no devices &#8212; now appears <strong>byte-for-byte identical</strong> in the syllabus, on the course homepage, in the LaTeX exam instructions, in the exam style file, <em>and</em> in the exam-generation templates, so future exams inherit it automatically and it can never get announced differently at exam time. We also built and published the past-exam PDFs students kept asking for. Along the way an agent discovered that one past final&#8217;s source files were empty &#8212; a latent bug that would have bitten me at the worst possible moment &#8212; and reconstructed it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ac7X!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ac7X!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png 424w, https://substackcdn.com/image/fetch/$s_!Ac7X!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png 848w, https://substackcdn.com/image/fetch/$s_!Ac7X!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png 1272w, https://substackcdn.com/image/fetch/$s_!Ac7X!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ac7X!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png" width="1456" height="1150" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1150,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:470740,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/200405850?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ac7X!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png 424w, https://substackcdn.com/image/fetch/$s_!Ac7X!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png 848w, https://substackcdn.com/image/fetch/$s_!Ac7X!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png 1272w, https://substackcdn.com/image/fetch/$s_!Ac7X!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5659db-c120-4535-854b-83c8442fdd70_1568x1238.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><h2>Slides: The Big Fan-Out</h2><p>The headline project was the slides: roughly two dozen PowerPoint decks, years of accretion, some 70&#8211;150 slides each. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2Zwv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2Zwv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png 424w, https://substackcdn.com/image/fetch/$s_!2Zwv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png 848w, https://substackcdn.com/image/fetch/$s_!2Zwv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png 1272w, https://substackcdn.com/image/fetch/$s_!2Zwv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2Zwv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png" width="1456" height="1031" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1031,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:343476,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/200405850?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2Zwv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png 424w, https://substackcdn.com/image/fetch/$s_!2Zwv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png 848w, https://substackcdn.com/image/fetch/$s_!2Zwv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png 1272w, https://substackcdn.com/image/fetch/$s_!2Zwv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c93fe76-2d5b-424b-b4d9-3724000c33c6_1672x1184.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The goal wasn&#8217;t a faithful port &#8212; it was a <strong>content-driven rebuild</strong> into <a href="https://quarto.org/">Quarto</a> reveal.js: leaner decks, aligned to what I actually covered, with examples refreshed to the present.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3db0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3db0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png 424w, https://substackcdn.com/image/fetch/$s_!3db0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png 848w, https://substackcdn.com/image/fetch/$s_!3db0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png 1272w, https://substackcdn.com/image/fetch/$s_!3db0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3db0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png" width="1456" height="844" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:844,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:284662,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/200405850?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3db0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png 424w, https://substackcdn.com/image/fetch/$s_!3db0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png 848w, https://substackcdn.com/image/fetch/$s_!3db0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png 1272w, https://substackcdn.com/image/fetch/$s_!3db0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F928f8922-3f28-451b-b9f7-1af4d0f94ee7_1580x916.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This is where multi-agent workflows earned their keep. After I hand-built one reference deck to lock the look &#8212; and <em>approved it</em> before anything scaled &#8212; I kicked off a workflow that fanned out <strong>one agent per deck</strong>, about six running at a time. Each agent did the following:</p><ul><li><p>Read a shared template spec.</p></li><li><p>Pulled the extracted text from its deck.</p></li><li><p>Found the matching part of my agenda.</p></li><li><p>Web-searched and verified a current-events hook.</p></li><li><p>Curated the images worth keeping.</p></li><li><p>Wrote inline speaker notes.</p></li><li><p>Rendered its deck to confirm it built.</p></li></ul><p>Every deck also got a <code>coverage-notes.md</code>: what I changed, what&#8217;s missing, and &#8212; my favorite touch &#8212; a seeded &#8220;next-year refresh&#8221; checklist of the dated facts that will go stale, so the <em>annual</em> update is a one-paste job next fall.</p><p>The detail I didn&#8217;t expect: the fan-out generated its own follow-up work rather than just closing the original. When I ran this same overhaul on the censorship course, the slide agents collectively noticed gaps between the decks and the companion book and filed them as a fresh <a href="https://github.com/noise-lab/censorship-course/issues/7">missing-coverage backlog</a> &#8212; a new issue, spun out of the overhaul, ready for the next pass. Agents producing the next spec, not just consuming the current one.</p><h2>Four Shapes Of Agent Work</h2><p>What struck me is that &#8220;use agents&#8221; isn&#8217;t one thing. Across this project I leaned on at least four distinct shapes:</p><ul><li><p><strong>Summarize-Then-File</strong> &#8212; read the feedback, produce the tracking issue.</p></li><li><p><strong>Surgical Consistency Pass</strong> &#8212; make one exact string identical across eight files, no creativity wanted.</p></li><li><p><strong>Parallel Fan-Out</strong> &#8212; one agent per slide deck (or per assignment), dozens at once, each an independent unit of work.</p></li><li><p><strong>Playbook Issue</strong> &#8212; write an issue so complete that <em>another</em> agent, in another repo, can execute it cold.</p></li></ul><p>That last one is the multiplier.</p><h2>Issues As Portable Specs: Doing It Three Times</h2><p>Once the security course was done, I didn&#8217;t want to re-explain any of it to modernize my <strong><a href="https://github.com/noise-lab/ml-systems">ML systems</a></strong> and <strong><a href="https://github.com/noise-lab/censorship-course">censorship</a></strong> courses. The first step in each repo was the same feedback-to-issue pattern applied again &#8212; the evals summarized and filed as a checklist (<a href="https://github.com/noise-lab/ml-systems/issues/11">ML systems</a>, <a href="https://github.com/noise-lab/censorship-course/issues/6">censorship</a>) &#8212; so each course had its own tracked backbone before any agent touched a file.</p><p>But the real reuse was the <strong>playbook issues</strong>: I had Claude write the security-course approach up as specs complete enough that a fresh Claude Code session could execute them cold. For ML systems that meant an <a href="https://github.com/noise-lab/ml-systems/issues/9">assignments-and-materials playbook</a> (&#8221;apply the security-course patterns&#8221;) and a <a href="https://github.com/noise-lab/ml-systems/issues/10">slide-overhaul playbook</a> (&#8221;migrate to Quarto, match the book&#8221;); the censorship course got its own <a href="https://github.com/noise-lab/censorship-course/issues/5">slide-overhaul playbook</a>. </p><p>Each one captured the exact folder structure, the extraction pipeline, the template, the workflow, the repo hygiene, and the annual-refresh loop, adapted to that course &#8212; notably, both slide playbooks align the decks to a companion book, not just a lecture agenda. For instance, the ML-systems slide issue spells out the per-deck book-chapter mapping so an agent knows which chapter each deck should track without me in the loop. Then I opened a fresh Claude Code session in each repo, pointed it at its issue, and let it run, pausing at the same reference-deck checkpoint I used the first time.</p><p>The issue stopped being a to-do list and became a <strong>transferable specification</strong>. The knowledge isn&#8217;t trapped in one conversation; it&#8217;s a document a human or an agent can pick up.</p><h2>What Kept It Safe</h2><p>This was fast, not reckless. I reviewed diffs before anything was committed, the agents stopped for my approval at the reference deck before fanning out, and I never let them commit or push without a confirmation. Web-sourced claims got verified, not trusted. And the work cut both ways: an agent caught the broken exam source; the permission system caught me when I tried to delete original files it judged I shouldn&#8217;t. Human-in-the-loop wasn&#8217;t a slogan &#8212; it was the reason I&#8217;d do it again.</p><h2>The Takeaway</h2><p>The pattern that worked is almost embarrassingly simple: <strong>make the intention explicit and tracked, then let agents execute against it.</strong> A GitHub issue turns out to be a near-perfect interface for this &#8212; it&#8217;s the spec, the checklist, the changelog, and (when written well) a portable playbook another agent can run somewhere else.</p><p>Course maintenance is the kind of important-but-deferred work that never quite justifies a free afternoon. It turns out an afternoon was enough &#8212; as long as I spent it writing the issues, and let the agents spend it doing the work.</p><p><em>Built With <a href="https://claude.com/claude-code">Claude Code</a> And Its Multi-Agent Workflows.</em></p>]]></content:encoded></item><item><title><![CDATA[How AI Agents Helped Me Go from Lecture Transcripts to Book Draft]]></title><description><![CDATA[Outlining my process for creating a book, and how AI agents are helping me get it across the finish line.]]></description><link>https://practicespace.substack.com/p/how-ai-agents-helped-me-go-from-lecture</link><guid isPermaLink="false">https://practicespace.substack.com/p/how-ai-agents-helped-me-go-from-lecture</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Wed, 11 Feb 2026 20:09:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!mq82!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mq82!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mq82!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png 424w, https://substackcdn.com/image/fetch/$s_!mq82!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png 848w, https://substackcdn.com/image/fetch/$s_!mq82!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png 1272w, https://substackcdn.com/image/fetch/$s_!mq82!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mq82!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png" width="1313" height="538" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:538,&quot;width&quot;:1313,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1191564,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/187669220?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mq82!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png 424w, https://substackcdn.com/image/fetch/$s_!mq82!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png 848w, https://substackcdn.com/image/fetch/$s_!mq82!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png 1272w, https://substackcdn.com/image/fetch/$s_!mq82!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a50ee8-e3d7-4532-832c-ec622fadcd78_1313x538.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Whether it is music, research, courses, or books, I use the following maxim as a guide:</p><blockquote><p><strong>Make the things you want to exist in the world.</strong></p></blockquote><p>The courses I teach, for example, I have created from scratch. They are the courses I wished I had as a student. One of those courses is &#8220;Internet Censorship and Online Speech&#8221;.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>When one teaches a course, it is helpful to have accompanying reading material, but material that you didn&#8217;t create yourself is always a bit of a shoehorn. One of the most valuable things we can do as instructors, especially in the age of AI, is synthesis.</p><p>For that reason, I&#8217;ve created textbooks and online courses from scratch in an attempt to synthesize everything I learn as I continue to teach the material.</p><p>As one such effort, I&#8217;ve been writing a textbook on Internet censorship and information control for the past five years. What started as a way to capture my lectures has evolved into a fascinating journey in human-AI collaboration. Here&#8217;s how I used AI tools&#8212;culminating in Claude&#8217;s new &#8220;agent teams&#8221; feature&#8212;to transform raw lecture transcripts into a polished manuscript.</p><h2><strong>The Starting Point: A Course Without a Textbook</strong></h2><p>When I began teaching my course on Internet Censorship at the University of Chicago, I faced a common problem: there was no textbook that covered the breadth of topics I wanted to address. The field spans technical mechanisms (DNS manipulation, BGP hijacking, deep packet inspection), platform dynamics (content moderation, algorithmic curation, disinformation), legal frameworks (Section 230, copyright, net neutrality), measurement techniques, and circumvention technologies.</p><p>So, I decided to write one.</p><h2><strong>Phase 1: Capturing Lectures (2021)</strong></h2><p>The first step in drafting the book was getting some initial thoughts down. During the Covid lockdown, we were all teaching online, and so I had a significant cache of online videos (now on YouTube!) comprising the course lectures. Arvind Narayanan once told me that he started some of his books from video lecture transcripts. So, rather than staring at a blank page, I recorded my lectures and extracted transcripts from YouTube. </p><p>My earliest commits tell the story:</p><pre><code><code>Feb 2021: first draft of Chapter 2 material from YouTube transcripts
Feb 2021: BGP draft text from transcript
Mar 2021: transcripts through first seven chapters/weeks
Mar 2021: transcripts for legal aspects</code></code></pre><p>The raw transcripts were messy&#8212;full of verbal tics, digressions, and the natural meandering of spoken explanation. But they contained the core ideas, organized roughly the way I wanted the book structured. Back in 2021, there were no LLMs, and so I spent a fair amount of time manually editing the spoken prose. This, frankly, was a painstaking process, and not particularly creative&#8212;it mainly involved changing my spoken &#8220;lecture voice&#8221; into something more appropriate for a book, while preserving the content.</p><h2><strong>Phase 2: Transcript to Prose (2021&#8211;2025)</strong></h2><p>Prior to AI, transforming spoken lectures into readable prose was tedious work. This past fall, I began to use Claude to help me. I would record all of my lectures and get transcripts which now included not only my lecture but also student questions.</p><p>Again, this step was painstakingly manual at first, but as AI models and agents have improved over the past several years, I&#8217;ve been able to leverage these tools to really speed up this part of the process.</p><ul><li><p><strong>Clean up the language</strong>: Removing filler words, fixing grammar, smoothing transitions</p></li><li><p><strong>Restructure for reading</strong>: What works in a 75-minute lecture doesn&#8217;t always work on the page</p></li><li><p><strong>Add pedagogical scaffolding</strong>: Signposting, summaries, clearer section breaks</p></li></ul><p>Sample commits from this period:</p><pre><code><code>Edit DNS and TCP sections into polished book prose
Enhance BGP section with class discussion insights
Enhance traffic shaper explanations with clearer pedagogical flow</code></code></pre><p>I kept teaching the course while continuing to write, saving notes, questions, and presentations from students. Each semester gave me new material:</p><ul><li><p><strong>Student questions</strong> revealed where explanations were unclear</p></li><li><p><strong>Class discussions</strong> surfaced interesting angles I hadn&#8217;t considered</p></li><li><p><strong>Student presentations</strong> brought in current case studies and examples</p></li></ul><p>I fed these back into the manuscript:</p><pre><code><code>Add points and case studies raised in Fall 2025 class presentations
Add citations and content from student project references (782 words)
Enhance BGP section with class discussion insights</code></code></pre><h2><strong>Phase 3: Case Studies, Examples, and Sources</strong></h2><p>Writing of this nature requires up-to-date examples and case studies, with citations&#8212;lots of them. Of course, left to their own devices, AI models have a well-known tendency to hallucinate citations, inventing plausible-sounding papers that don&#8217;t exist.</p><p>I developed a rigorous citation workflow, codified in a custom <code>/add-citations</code> command for Claude Code. The core principle being that every single citation needs to be verified by an agent through: (1) download; (2) analysis of the abstract; (3) inclusion of a URL that I can subsequently go manually read myself.)</p><p>The workflow uses a hierarchy of academic APIs:</p><ol><li><p><strong>DBLP API</strong> for computer science papers (returns clean BibTeX directly)</p></li><li><p><strong>CrossRef API</strong> when you have a DOI</p></li><li><p><strong>arXiv API</strong> for preprints</p></li><li><p><strong>Semantic Scholar API</strong> for discovery</p></li></ol><p>Every citation must be verified with WebFetch on the actual publisher page before being added. If the title doesn&#8217;t match, it doesn&#8217;t get added. Period.</p><pre><code><code># Example: Search DBLP and get BibTeX directly
curl "https://dblp.org/search/publ/api?q=censorship+measurement&amp;format=bib&amp;h=5"

# Verify with CrossRef
curl -LH "Accept: application/x-bibtex" https://doi.org/10.1145/...</code></code></pre><p>This approach takes longer than just asking an AI to &#8220;add some citations,&#8221; but it produces a bibliography you can actually trust.</p><h2><strong>Phase 4: Agent Teams for Deep Editing (February 2026)</strong></h2><p>Recently, Claude Code introduced an &#8220;agent teams&#8221; feature that lets you spawn multiple AI agents to work on a task in parallel. I decided to use this for a comprehensive editing pass.</p><h3><strong>The Workflow</strong></h3><p><strong>Step 1: Launch Six Parallel Editors</strong></p><p>I spawned six agents simultaneously, one for each chapter:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2Kmk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2Kmk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png 424w, https://substackcdn.com/image/fetch/$s_!2Kmk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png 848w, https://substackcdn.com/image/fetch/$s_!2Kmk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png 1272w, https://substackcdn.com/image/fetch/$s_!2Kmk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2Kmk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png" width="501" height="173" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:173,&quot;width&quot;:501,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:25878,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/187669220?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2Kmk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png 424w, https://substackcdn.com/image/fetch/$s_!2Kmk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png 848w, https://substackcdn.com/image/fetch/$s_!2Kmk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png 1272w, https://substackcdn.com/image/fetch/$s_!2Kmk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80d298b6-171e-4789-8c8b-2d8d2f9cb2ba_501x173.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Each agent received detailed instructions:<br>- Read all chapter files thoroughly<br>- Add verified citations (using the citation workflow)<br>- Edit for clarity without changing structure (it matches my course syllabus)<br>- Report back on edits made, citations added, and cross-chapter issues</p><p><strong>Step 2: Cross-Chapter Consistency Review</strong></p><p>After the initial edit, I had the agents swap chapters. Each agent reviewed a chapter they hadn&#8217;t edited, specifically looking for:<br>- Voice consistency across the book<br>- Working cross-references between chapters<br>- Consistent terminology<br>- Flow and length balance</p><p><strong>Step 3: Image Pipeline</strong></p><p>I also used a specialized four-agent pipeline for figures:</p><ol><li><p><strong>Image Sourcing Agent</strong>: Reviewed ~400 images from my own lecture slides, identifying useful diagrams, charts, and maps</p></li><li><p><strong>Image Quality Reviewer</strong>: Checked each candidate for accuracy, currency, copyright permissions, and resolution</p></li><li><p><strong>Placement Finder Agent</strong>: Located exact insertion points in the LaTeX source</p></li><li><p><strong>Insertion Agent</strong>: Actually added the figure code to the manuscript</p></li></ol><p>The agent teams processed six chapters in parallel, adding dozens of verified citations, improving clarity throughout, and ensuring consistency across the book. Work that would have taken me weeks of tedious editing happened in under an hour.</p><h2><strong>Lessons Learned</strong></h2><p><strong>1. Start with your own voice.</strong> The transcripts captured how I actually explain these concepts to students. AI helped refine the prose, but the pedagogical approach and examples are mine.</p><p><strong>2. Iterate with students.</strong> Teaching the course while writing the book created a feedback loop. Student confusion pointed to unclear explanations. Their presentations brought in fresh case studies.</p><p><strong>3. Build guardrails for citations.</strong> AI-generated citations are a minefield. Building a verified citation workflow was essential for producing something I could stand behind academically.</p><p><strong>4. Parallel agents are powerful for editing.</strong> Having multiple agents work simultaneously&#8212;then swap and review each other&#8217;s work&#8212;catches issues that a single pass would miss.</p><p><strong>5. AI is useful, but the author must be in the loop at every stage.</strong> At every stage, I reviewed what the agents produced. Ultimately, the book reflects my voice, expertise, and judgment; AI was a tool that accelerated the work. </p><p>6. <strong>Work with AI agents like you might a collaborative human editor</strong>. The agents did not &#8220;write the book&#8221; per se; rather, they incorporated all of my inputs, including full chapter drafts that came from my own words (either through transcripts or my own typing). They helped me take care of annoying formatting things, identified thematic gaps, helped me find places to integrate content and examples that I devised (often &#8220;on the fly&#8221; in lecture), and served to provide me with important editorial feedback along the way.</p><h2><strong>What&#8217;s Next</strong></h2><p>The manuscript is nearing completion. It&#8217;s been a five-year journey from &#8220;I need a textbook for this course&#8221; to a full manuscript with six chapters, hundreds of citations, and dozens of figures.</p><p>The tooling has evolved dramatically over that time. What started with simple transcript cleanup has progressed to sophisticated multi-agent workflows. I&#8217;m excited to see where these tools go next&#8212;and what other professors might be able to accomplish with them.</p><div><hr></div><p><em>The book, tentatively titled &#8220;Filtered,&#8221; covers Internet censorship and information control, based on my course at the University of Chicago (<a href="https://noise-lab.net/censorship-course/">course website</a>). The techniques described here could apply to any textbook project built from lecture materials.</em></p>]]></content:encoded></item><item><title><![CDATA[How to Get (Coding) Agents to Work Well]]></title><description><![CDATA[My workflow with spec-driven development in Claude Code]]></description><link>https://practicespace.substack.com/p/how-to-get-coding-agents-to-work</link><guid isPermaLink="false">https://practicespace.substack.com/p/how-to-get-coding-agents-to-work</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Tue, 03 Feb 2026 07:04:52 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/ce4306f5-ee67-4c6e-ab83-80e91bbdc4f6_806x584.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few people have asked about my coding workflow, so I thought I would write it up. Here&#8217;s how it actually works, and why I think it works. (Note: I use this for coding, but the same general principles apply across a variety of agentic tasks.)</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IO5x!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IO5x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png 424w, https://substackcdn.com/image/fetch/$s_!IO5x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png 848w, https://substackcdn.com/image/fetch/$s_!IO5x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png 1272w, https://substackcdn.com/image/fetch/$s_!IO5x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IO5x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png" width="806" height="584" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:584,&quot;width&quot;:806,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:735177,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/186706618?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IO5x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png 424w, https://substackcdn.com/image/fetch/$s_!IO5x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png 848w, https://substackcdn.com/image/fetch/$s_!IO5x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png 1272w, https://substackcdn.com/image/fetch/$s_!IO5x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0d8e09a-b914-46e0-a6c3-c78cb1e5ccdd_806x584.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>I&#8217;ve found that agents work best under three conditions:</p><h3>1. Limited Context</h3><p>LLMs have finite context windows, and even within those windows, attention degrades over distance. When you ask an agent to work on a 50-line function with a clear input/output contract, it can hold the entire problem in focus. When you ask it to &#8220;refactor the whole application,&#8221; it starts losing track of things&#8212;dependencies, side effects, earlier decisions.</p><blockquote><p>The practical implication: <strong>decompose your tasks aggressively</strong>. Break big tasks into small ones. </p><p>Give the agent a piece it can fully comprehend. This isn&#8217;t just good practice for AI; it&#8217;s good software engineering. But with agents, it&#8217;s mandatory.</p></blockquote><p>I&#8217;ve found that when Claude Code starts making inconsistent changes or forgetting earlier context, the problem is almost always that I&#8217;ve let the scope creep too wide. The fix is to step back, carve off a smaller piece, and let it finish that completely before moving on. Carve a task up into sub-agents, if necessary (something I myself am still learning how to do).</p><h3>2. Tight Constraints</h3><p>The problem space is bounded. You&#8217;re not wandering through infinite possibilities&#8212;you&#8217;re meeting a spec, passing tests, satisfying types.</p><p>Constraints are liberating. When you tell an agent &#8220;write a function that takes a list of integers and returns the sum,&#8221; there&#8217;s not much room for hallucination. When you tell it &#8220;build something useful,&#8221; you get chaos.</p><p>This is where the spec becomes critical. A good spec is a set of constraints that bounds the solution space. Types are constraints. Tests are constraints. &#8220;Use this library, not that one&#8221; is a constraint. &#8220;Follow the existing code style&#8221; is a constraint.</p><blockquote><p>The more constraints you provide, the less the agent has to guess&#8212;and guessing is where things go wrong. </p></blockquote><p>I&#8217;ve started thinking of spec-writing as constraint-specification: <strong>what are all the ways this could go wrong, and how do I rule them out in advance? </strong>Inevitably, you will miss some constraints. This is where the third factor comes into play</p><h3>3. Verifiable Outputs</h3><p>First of all, tests pass or fail; code compiles or doesn&#8217;t. This simple fact actually makes coding very suitable for agentic tasks, because the models can do some amount of verification simply based on whether the code runs. </p><p>But, just because code runs doesn&#8217;t mean it is correct. I started writing MCP servers in Claude in the domain of music; it became painfully clear when something wasn&#8217;t working because <em>I could hear it</em> (four measures played instead of eight, dissonant sounds wildly out of the diatonic, etc.)</p><p>The verifiability of coding and its outputs make it particularly amenable to agentic coding.  Verification creates a feedback loop. The agent can try something, check if it worked, and iterate. This is why agentic coding tools run the code they generate, execute the tests, read the error messages. They&#8217;re not just generating&#8212;they&#8217;re generating, checking, and refining. </p><p>Verification can be automated, but it doesn&#8217;t have to be. Human review is verification too. The key is that verification is <em>possible</em> and <em>cheap enough</em> to actually do. In coding, you get both automated checks (tests, types, linters) and human review of outputs. </p><blockquote><p>There is an important lesson here, too: <strong>You want to make sure that what is generated is actually verifiable. </strong></p></blockquote><p>I work in Internet measurement and so the code I generate often involves data analysis; there are easy ways to check the output of analysis. One way is simple sanity checks and knowing &#8220;the back of the envelope&#8221; (e.g., how many seconds in a day, what&#8217;s the round-trip latency across the United States, etc.). </p><p>Having both specific and general domain knowledge internalized allows one to quickly spot non-sensical or incorrect output. But, regardless of the domain, the output must be checked&#8212;these days, still by a human&#8212;and thus it is imperative that whatever the model generates is easy to check. You can instruct the model to do this! I tend to provide instructions that include both automated checks and instructions that make it easy for me to verify outputs (think &#8220;clicking and reading&#8221; to verify).</p><h3>Takeaway: Specify Constraints, Limit Context</h3><p>Rich tooling and clear feedback are immensely helpful in this context. But the tooling isn&#8217;t what makes this work&#8212;it&#8217;s how the domain lets you structure the problem. The magic isn&#8217;t in the compiler or the shell. It&#8217;s in the fact that coding naturally decomposes into small, constrained, verifiable pieces.</p><p>This matters because <strong>the better you specify constraints and limit context, the better the agents do.</strong> </p><p>This insight forms the foundation of the workflow I describe below.</p><div><hr></div><h2>My Development Cycle</h2><p>Here&#8217;s the short version:</p><ol><li><p><strong>Specify and document.</strong> Specify requirements, tools, structure, language, basic test cases and expectations. Importantly, specify constraints (what the agents should not do!). The spec is often incomplete at first because step 1 is hard. Humans are bad at specs. <strong>Fortunately, the model is probably better at writing a good spec than you are.</strong></p><p>I often start by telling Claude Desktop what I want to build, and asking it to help me write the spec. We iterate. I refine. Then, when I&#8217;m happy with it, I take that spec to Claude Code. I&#8217;ve found that this can be an iterative process. Part of why I hadn&#8217;t written this up earlier is that I haven&#8217;t fully wrapped my head around what really works well versus what doesn&#8217;t. But a little supervision and independent thinking goes a long way.</p><p>This is the question I ask myself when creating a spec and documentation on which to build a piece of software: <strong>Imagine that you are starting up Claude Code for the very first time and want it to read the docs and run the code. What would it need to know?</strong></p></li><li><p><strong>Feed the specification into Claude Code to get a first pass. </strong>This is the part that feels like magic. You hand it a spec, and code appears. But don&#8217;t get drunk on the magic. The output needs to be checked. This isn&#8217;t &#8220;fire and forget.&#8221;</p></li><li><p><strong>Iterate.</strong> Try using the code, check all outputs, supervise, take notes of errors and missing features. Use Claude itself to note things like missing features, things that are not working correctly, etc. Use the tool for a while. Check the outputs. Does it actually do what you wanted? Does it handle edge cases? Does it fail gracefully? This is where you catch the hallucinations, the subtle bugs, the things that &#8220;work&#8221; but don&#8217;t work <em>correctly</em>. Or, you notice that something you wanted the code to do, it simply &#8230;can&#8217;t, because you forgot something in your spec.</p></li><li><p><strong>Push documentation to &#8220;memorialize&#8221;.</strong> Take note of (a) what went wrong and how you ended up fixing the issue; (b) make sure that updates and fixes to the code are also memorialized in the updated specification and documentation. Before I close a Claude Code project, I always take time to work on the documentation. Think of it like this: If I were to come back to this later, what would I want Claude to immediately pull into context and not have to type again? That should all be in the updated docs.</p></li><li><p><strong>Use Git for everything.</strong> Commit early, commit often, push often. Agents make mistakes. You will make mistakes supervising them. You need to be able to roll back, and you will. Treat every commit as a potential restore point. Be very careful with rebasing; consider disallowing it unless you explicitly ask for it&#8212;I've lost work by letting Claude Code "clean up" commit history or resolve a merge conflict when I actually needed that history preserved.  As with other parts of your project, if you are not explicit about constraints, the agents will fill in the gaps and you may not like the results.</p></li></ol><div><hr></div><h2>Why Things Break, When They Break</h2><p>Here&#8217;s what I&#8217;ve learned:</p><ul><li><p><strong>Poor specification or constraints &#8594; limited (or unwanted!) functionality.</strong> The specification is king. If the spec doesn&#8217;t capture what you actually want, you&#8217;ll get something that technically meets the spec but doesn&#8217;t solve your problem and may also do things you never asked for. It is thus critically important to specify constraints.</p></li><li><p><strong>Context window exceeded &#8594; weird failures.</strong> The model starts losing track of things. You get inconsistencies, repeated mistakes, or outputs that ignore earlier instructions. The trick here is to limit the context window. I am still working on ways to do this; for example, I am learning a bit more about sub-agents. I am interested to hear how others deal with this.</p></li><li><p><strong>Missing implementation &#8594; need to update the server.</strong> Sometimes the model assumes a feature exists that doesn&#8217;t. This is a signal that your spec or your tooling has a gap. The model won&#8217;t often tell you that it&#8217;s missing a feature; you have to intuit from the output that you&#8217;re asking it to do something that it doesn&#8217;t know how to do. From there, you can go back to iterating on a spec.</p></li><li><p><strong>Config sprawl</strong> &#8594; When you&#8217;re building tools, configurations multiply, and agents are not particularly good at keeping configuration organized and tidy. Periodically step back and ask: &#8220;If I had to set this up on a new machine, how painful would it be?&#8221; If you couldn&#8217;t migrate in under a minute, or you have to think about where every part of your project configuration is living (auth, environment settings, etc.), this your signal to consolidate. I periodically blow all of my software away and re-install just to make sure my processes are streamlined.</p></li></ul><div><hr></div><h2>Example Workflow: Desktop MCP &#8596; Code Iteration</h2><p>Claude Desktop and Claude Code don&#8217;t know about each other. They&#8217;re separate tools with separate contexts. But with good specs and MCP connections, I&#8217;ve found that you can stitch them together to really enhance productivity. I now have MCPs for calendaring, briefing, email triage, invoicing, &#8230; not to mention countless creative projects, as well.</p><p>My typical pattern is as follows:</p><ul><li><p><strong>Desktop for ideation and spec writing</strong>. I think out loud with Claude, brainstorm approaches, write the spec collaboratively.</p></li><li><p><strong>Code for execution</strong>. I copy the spec over and let Claude Code generate.</p></li><li><p><strong>In the case of MCP, back to the Desktop</strong>. I try to use my MCP servers. At the outset, I trust nothing. I verify what the agents are doing manually, because often they will make mistakes&#8212;and typically the source of the mistake was a failure in my specification. When something breaks or does not work as planned, I often talk through it with Desktop first, figure out exactly what the MCP is not seeing, then work on an updated specification, and bring the fix back to Code.</p></li></ul><p>I use the spec, not the conversation, as the conduit. The conversation is ephemeral. The spec persists and is continually being updated. </p><div><hr></div><h2>Note: &#8220;AI Failures&#8221; are Often User Failures</h2><p>We&#8217;ve all seen the headlines: AI loses money, AI gets tricked, AI does something absurd. For example, recently the Wall Street Journal ran an experiment where they let an AI agent run a vending machine. It gave away inventory for free, bought a PlayStation 5, ordered a live fish. Chaos, laughs, great clickbait.</p><p>A closer read reveals what actually happened, though: the user gave an agent vague instructions (&#8221;generate profits&#8221;), no guardrails, no supervision, and let 70 journalists red-team it unsupervised. When it predictably fell apart, the diagnosis was &#8220;the context window filled up&#8221;&#8212;which they present as an inevitable AI limitation rather than a design failure.</p><p>While this might be an entertaining cautionary tale, that&#8217;s not AI &#8220;failing&#8221;, but simply a user failing to understand how the tools work. A clear spec, incremental testing, active supervision, and documented fixes would have caught every one of those problems. The vending machine wasn&#8217;t a case study in AI limitations. It was a case study in not having a workflow.</p><h2>Bottom Line: Understand How Your Tools Work</h2><p>If you think you know how these systems work (and how they fail), you can understand what is likely to work for input and how to check the output. </p><p>There is a lot of benefit to structured thinking and clear spec. The limited context window is something to be aware of&#8212;so I&#8217;m continually refining the docs and code as I go, almost like a &#8220;compressed&#8221; version of what I want the model to be remembering. Truly thinking about it as a collaborator or &#8220;coding engineer who can meet a spec&#8221;... but a little supervision and independent thinking goes a long way. None of this is by any means a substitute for thinking. If anything, it pushes us to think more clearly than ever, because errors in specification end up even more amplified.</p><blockquote><p><strong>Agents work best when you give them limited context, tight constraints, and clear ways to verify their outputs. Coding happens to be a domain where all three are natural. But the lesson generalizes: if you can structure </strong><em><strong>any</strong></em><strong> problem that way, you can make these tools work.</strong></p></blockquote><p>I must admit that I still don&#8217;t really know &#8220;how to write a good spec&#8221; for these systems. But that can be a bit of an iterative process too, and one that the models are pretty good at, themselves. </p>]]></content:encoded></item><item><title><![CDATA[I Had Safeguards in Place. AI Hallucinated Anyway.]]></title><description><![CDATA[Cautionary tale: AI is designed to fill in gaps. If you don't explicitly define your workflow, AI will make one up for you (even if you don't ask), and you may not like the result.]]></description><link>https://practicespace.substack.com/p/i-had-safeguards-in-place-ai-hallucinated</link><guid isPermaLink="false">https://practicespace.substack.com/p/i-had-safeguards-in-place-ai-hallucinated</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Mon, 26 Jan 2026 18:35:27 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2d9L!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a3f22ba-363b-40e8-8db4-c9eac148a517_1280x1280.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8zHl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8zHl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!8zHl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!8zHl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!8zHl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8zHl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8zHl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!8zHl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!8zHl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!8zHl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a9a7d0c-8ded-4047-a5c0-620e4b059725_1024x608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I was finishing up an NSF grant proposal with Claude Code when my collaborator flagged something odd. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>She&#8217;d been reviewing the bibliography and couldn&#8217;t find some of the papers I&#8217;d cited. First of all, here&#8217;s one of the fabricated entries Claude created:</p><pre><code><code>@inproceedings{chanenson2023,
    title={Privacy in K-12 Schools},
    author={Chanenson, Emily},
    booktitle={Proceedings of CHI},
    year={2023}
}
</code></code></pre><p>The real paper, which my collaborator is a co-author on, was this:</p><pre><code><code>@inproceedings{chanenson2023K12PrivacySecurity,
    title={Uncovering Privacy and Security Challenges In K-12 Schools},
    author={Chanenson, Jake and Sloane, Brandon and Rajan, Navaneeth 
            and Morril, Amy and Chee, Jason and Huang, Danny Yuxing 
            and Chetty, Marshini},
    booktitle={Proceedings of the 2023 CHI Conference on Human Factors 
                in Computing Systems},
    year={2023},
    pages={1--28},
    doi={10.1145/3544548.3580777}
}
</code></code></pre><p>Wrong first name. Simplified title. Missing six co-authors. No DOI. </p><h2>Safeguards aren&#8217;t enough if you don&#8217;t define the workflow</h2><p>I traced the problem back through git history to understand how this happened. I&#8217;d been using Claude to adapt a &#8220;PI Qualifications&#8221; paragraph describing my co-PI&#8217;s prior work that I had from a previous proposal, a simple request that should have been a small text edit based on text that was already in the proposal elsewhere.</p><p><strong>I never asked Claude to find or create citations.</strong> My workflow was designed to be safe&#8212;Claude was supposed to reference only my existing .bib file. I thought that was sufficient.</p><p>But Claude knew my co-PI had expertise in educational technology privacy, VPN user studies, and privacy mental models. So when it wrote the qualifications paragraph, it included citations:</p><pre><code><code>Chetty brings expertise in empirical studies of privacy attitudes 
and technology adoption, including NSF CAREER-funded research on 
educational technology privacy~\cite{chanenson2023}, prior work on 
VPN mental models~\cite{kumar2023understanding} and privacy 
adoption~\cite{wagman2023}.
</code></code></pre><p>Then&#8212;without being asked&#8212;Claude created bibliography entries to match. It didn&#8217;t have the actual papers. It didn&#8217;t verify they existed. It didn&#8217;t check my existing .bib file. It invented plausible-sounding entries based on what it thought the papers should be about. I didn&#8217;t immediately catch it either, because the text itself read well-enough; the error was in a citation that was added that I didn&#8217;t ask for.</p><p>This is more subtle than the typical &#8220;AI hallucinated a citation&#8221; story you hear about. I wasn&#8217;t asking Claude to find papers. I had safeguards in place. But because I didn&#8217;t explicitly bound the capabilities of the agents, they went off-script anyway, proactively (&#8220;helpfully&#8221;) fabricating entries that looked like they belonged.</p><h2>Plausible-looking output is the danger zone</h2><p>The fabricated entries had proper BibTeX formatting, reasonable titles, plausible author names. If my collaborator hadn&#8217;t caught them during review, they might have made it into the final submission. And once fake citations enter a bibliography file, they propagate&#8212;other researchers copy them, students cite them, the misinformation spreads.</p><p>This is a known problem with large language models. The technical term is &#8220;confabulation&#8221;&#8212;filling gaps with plausible-sounding but false information. LLMs can generate text that looks right but can&#8217;t reliably distinguish between &#8220;plausible&#8221; and &#8220;true.&#8221; That&#8217;s not something that gets fixed by trying harder or being more careful. It&#8217;s a fundamental limitation that requires external verification.</p><h2>If you don&#8217;t define the workflow, the AI will</h2><p>The incident revealed something important: <strong>I didn&#8217;t have a citation workflow. So Claude invented one.</strong> And the workflow it invented was wrong&#8212;create content with citations first, create bibliography entries to match, never verify they&#8217;re real.</p><p>That&#8217;s the core lesson here. If you don&#8217;t explicitly define how citations should be handled, the AI will fill the gap with its own approach. And its approach prioritizes plausibility over truth.</p><p>So I built an actual workflow around a simple principle: verify first, not after. Search for and verify papers exist first, add verified entries to bibliography, then write content citing them. No exceptions, no &#8220;I&#8217;m pretty sure this exists.&#8221;</p><p>I also added explicit rules for Claude. If it&#8217;s creating BibTeX entries for papers it hasn&#8217;t verified via web search, or guessing at author names or titles, or writing about someone&#8217;s prior work without their actual paper list&#8212;stop. For co-PI qualification sections specifically, it&#8217;s faster and more accurate for Claude to just ask me &#8220;What are the key papers on educational privacy?&#8221; I have her CV. I know her work. I can point to citation keys already in my .bib file.</p><p>I documented all of this in an <code>check-citations.md</code> command file (included below) that includes the exact failure mode, step-by-step verification procedures, and mandatory checklists. The goal is to make it impossible to repeat this mistake through inattention. <strong>I also added a step to add DOI and URL to every single citation so that human verification becomes easy</strong>&#8212;all one has to do is go through the citations and click the links to perform manual verification on each.</p><h2>This isn&#8217;t just about citations</h2><p>This incident captures a fundamental tension in AI-assisted work. These tools can genuinely increase productivity&#8212;Claude can help one become significantly more efficient at formatting, restructuring, finding inconsistencies, even drafting prose. But agents require explicit workflows <em>with constraints</em> because they will, inevitably, fill gaps with plausible-sounding fabrications. Citations are just one example. The same problem applies to any task where the AI needs to reference external facts: legal documents, financial data, technical specifications, historical records.</p><blockquote><p><strong>For anyone using AI assistants: trust but verify.</strong> Every factual claim needs human verification. Design your workflows assuming AI will occasionally fabricate things. <em>Make verification cheap and easy so you&#8217;ll actually do it. And when AI makes a mistake, analyze it, update your workflows, share what you learned.</em></p><p><strong>For AI developers:</strong> confabulation is the hard problem. Don&#8217;t just generate content&#8212;build in verification steps. Flag unverified claims. When uncertain, say &#8220;I need to verify this&#8221; instead of generating something plausible-looking. It&#8217;s better to be slow and right than fast and wrong.</p></blockquote><p>It would be great if citation verification APIs integrated directly into tools like Claude&#8212;automatic checks against CrossRef, Semantic Scholar, DBLP before any citation gets added. Confidence scoring that distinguishes &#8220;verified from publisher&#8221; from &#8220;generated from context (UNVERIFIED).&#8221; Audit trails tracking where each citation came from.</p><p>In the meantime, I&#8217;ve built my own workaround: a Claude Code command that enforces verification before any citation gets added, requires WebFetch to confirm titles match actual webpages, and checks for broken references in the bibliography. It&#8217;s not foolproof, and I&#8217;ll continue verifying manually. But it makes the workflow explicit instead of leaving gaps for Claude to fill with fabrications. In some ways, it is actually better than what I had before <strong>and</strong> better than humans&#8212;the process ended up finding several other erroneous citations that humans had entered.</p><p>My collaborator caught these errors. Otherwise, fake citations would have landed in an NSF proposal. AI assistance is valuable, but human verification remains essential.</p><blockquote><p><strong>AI will improve, but we need critical self-examination and post-mortems like this.</strong></p></blockquote><p>Finally, I will note that git revision history was extremely valuable in helping diagnose the root cause of how this error occurred. AI will make mistakes. The answer is not to avoid it, but rather to firmly understand why and how it makes mistakes, and improving our systems and workflows so that the tools can work better for us. A careful, critical, honest eye towards mistakes is how we make progress, which is why I thought it was important to share this cautionary tale.</p><p><strong>Update:</strong> A friend tells me that even this approach below may not be good enough. Relying on WebSearch is not constrained enough, and that all information that comes in should be brought in via an API, not via the web. Additionally, dividing up tasks with subagents helps preserve the context window, so this approach I have laid out above may ultimately require a bit of re-design.</p><pre><code><code>## Citation Verification Workflow

1. **Never create citations without verification**
   - Search for the actual paper using WebSearch
   - Use WebFetch to verify the title on the publisher's page
   - Cross-check authors, year, venue against official sources
   - Test that DOIs/URLs actually work

2. **Verify before you write, not after**
   - Search for and verify papers exist first
   - Add verified entries to bibliography
   - THEN write content citing them

3. **When citing someone's prior work**
   - Ask the user: "Which papers should I cite for [topic]?"
   - Search their Google Scholar or DBLP page
   - DO NOT fabricate entries based on what you think should exist

4. **Red flags that require stopping**
   - Creating BibTeX entries for papers not verified via web search
   - Guessing at author names or titles
   - Writing about someone's prior work without their actual paper list
   - Adding incomplete metadata
</code></code></pre>]]></content:encoded></item><item><title><![CDATA[Initial Lessons from My First Experience in the Recording Studio]]></title><description><![CDATA[Twenty years later, I'm back in Atlanta, getting out of my comfort zone again.]]></description><link>https://practicespace.substack.com/p/initial-lessons-from-my-first-experience</link><guid isPermaLink="false">https://practicespace.substack.com/p/initial-lessons-from-my-first-experience</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Thu, 01 Jan 2026 22:38:03 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7Bl5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On this week in 2005, I moved to Atlanta to start my first job as an assistant professor at Georgia Tech. Twenty years later, I returned to Atlanta to work on a completely different project. I&#8217;m right back where I like to be: just beyond the edge of my comfort zone, riding an exponential learning curve.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>I spent a couple of days in the studio this week, working on my first professionally produced track. Here&#8217;s what I learned.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7Bl5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7Bl5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg 424w, https://substackcdn.com/image/fetch/$s_!7Bl5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg 848w, https://substackcdn.com/image/fetch/$s_!7Bl5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!7Bl5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7Bl5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg" width="1456" height="680" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:680,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2552257,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/183185914?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7Bl5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg 424w, https://substackcdn.com/image/fetch/$s_!7Bl5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg 848w, https://substackcdn.com/image/fetch/$s_!7Bl5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!7Bl5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff9d068a-3f63-4683-9786-1b732d79941c_4000x1868.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>1. Get a chord chart on a grid.</strong></p><p>I did this with MIDI over my demo track before going in, and it ended up saving hours. There will be many opportunities to re-track things with different arrangements - bass, synths, guitars - and this goes much faster if your producer knows the chords you&#8217;re using rather than figuring them out on the fly.</p><p><strong>2. Know how to play your songs in different ways.</strong></p><p>If you&#8217;re layering tracks, there will be countless opportunities to &#8220;paint&#8221; in the mix. A part that sat one way in your bedroom demo might need to breathe differently when there&#8217;s a live drummer pushing the energy.</p><p><strong>3. Be flexible.</strong></p><p>Some things will change. Having a complete song is critical - not because it&#8217;s necessarily &#8220;done,&#8221; but because it gives you a foundation to make small adjustments from. Sometimes we&#8217;d spend an hour or two on eight bars of just one track. (&#8221;How is this going to sound? Only one way to find out!&#8221;) This isn&#8217;t writing the song in studio. It&#8217;s being willing to experiment with what best brings out the emotion of what&#8217;s already written.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iOIK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iOIK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg 424w, https://substackcdn.com/image/fetch/$s_!iOIK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg 848w, https://substackcdn.com/image/fetch/$s_!iOIK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!iOIK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iOIK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg" width="1456" height="680" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:680,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2360943,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/183185914?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iOIK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg 424w, https://substackcdn.com/image/fetch/$s_!iOIK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg 848w, https://substackcdn.com/image/fetch/$s_!iOIK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!iOIK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72102047-3e82-4e80-b793-a57a5a9ce261_4000x1868.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>4. Basic music theory is critical.</strong></p><p>Theory can be limiting if the rules pen you in, but in the studio, it&#8217;s essential because it gives you a common language. It lets you communicate efficiently with session musicians and your producer, and helps you understand why different layers work together.</p><p><strong>5. Practice the new parts.</strong></p><p>In pre-production, your producer may send back additional ideas - new riffs, alternate bass lines, different voicings. Practice playing anything you like, because you&#8217;ll likely be playing it yourself. In hindsight, I would have saved time if I&#8217;d practiced some of those parts on bass guitar before showing up.</p><p><strong>6. Learn about production.</strong></p><p>The goal isn&#8217;t necessarily to become a professional producer yourself. It&#8217;s to know what&#8217;s possible and speak the language. You don&#8217;t have to be an expert in compression, reverb, or EQ, but knowing what they do helps you communicate the sound you want.</p><p><strong>7. More survives than you&#8217;d think.</strong></p><p>Much more of the original composition survives the demo process than I expected, even though almost everything gets re-tracked.</p><p><strong>8. There is no substitute for a human drummer.</strong></p><p>Enough said. It&#8217;s good to go in with programmed tracks to give a feel for groove. We definitely also layered drum machine tracks over the human drummer, because that&#8217;s the sound I&#8217;m going for. But, nothing quite captures the energy like a live human drumming to a track you wrote.</p><div><hr></div><p>I&#8217;ve always wanted to make music, and do it at a high level. Two years ago, I had not written a single song. How did I get here? </p><p>The same way I end up doing anything. Little by little. With consistency and focus, and a healthy dose of fearlessness. Approaching the practice with humility and curiosity. Not being afraid to be bad at first. Asking countless stupid questions. Surrounding myself with good, kind, generous people who are better than me at the craft and trying to learn from them as much as possible.</p><p>It&#8217;s all worth it. Because what a beautiful thing, to make something where there was once nothing.</p>]]></content:encoded></item><item><title><![CDATA[SwiftQueue: A Small Transformer Model for Per-Packet Latency Prediction]]></title><description><![CDATA[We reduced tail latency for real-time applications with a 100K-parameter Transformer.]]></description><link>https://practicespace.substack.com/p/swiftqueue-a-small-transformer-model</link><guid isPermaLink="false">https://practicespace.substack.com/p/swiftqueue-a-small-transformer-model</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Wed, 17 Dec 2025 15:59:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!bZOb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>L4S is finally getting deployed. After years of talking about reducing latency at the router level, ISPs are actually rolling this out&#8212;Verizon, Nokia, and others are on board. The basic idea is simple: mark your packets with an ECN bit, and L4S-enabled routers put them in the appropriate queue. Low-latency traffic gets the fast lane.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>I was fortunate to be able to present this morning at the <a href="https://understandinglatency.com/">Understanding Latency 4.0</a> Conference on our new technology, <a href="https://arxiv.org/abs/2410.06112">SwiftQueue</a>. </p><p><a href="https://arxiv.org/abs/2410.06112">SwiftQueue</a> uses a compact transformer model to perform sub-millisecond prediction of traffic latency, allowing per-packet queue assignment and reduction of tail latency by as much as 45%.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tt81!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tt81!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png 424w, https://substackcdn.com/image/fetch/$s_!tt81!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png 848w, https://substackcdn.com/image/fetch/$s_!tt81!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png 1272w, https://substackcdn.com/image/fetch/$s_!tt81!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tt81!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png" width="1456" height="452" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:452,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:518839,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/180711519?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tt81!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png 424w, https://substackcdn.com/image/fetch/$s_!tt81!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png 848w, https://substackcdn.com/image/fetch/$s_!tt81!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png 1272w, https://substackcdn.com/image/fetch/$s_!tt81!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28ae9577-b89c-404e-baf3-713503e4fb50_1779x552.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>But there&#8217;s a problem with how L4S works today. It treats every packet in a flow the same way. All your video call packets get the same queue assignment, even though congestion is bursty. Some packets sail through; others hit a traffic jam and spike your tail latency. It&#8217;s that variance that kills real-time apps&#8212;not the average, the outliers.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QfDR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QfDR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png 424w, https://substackcdn.com/image/fetch/$s_!QfDR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png 848w, https://substackcdn.com/image/fetch/$s_!QfDR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png 1272w, https://substackcdn.com/image/fetch/$s_!QfDR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QfDR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png" width="605" height="318" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:318,&quot;width&quot;:605,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:41989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/180711519?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QfDR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png 424w, https://substackcdn.com/image/fetch/$s_!QfDR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png 848w, https://substackcdn.com/image/fetch/$s_!QfDR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png 1272w, https://substackcdn.com/image/fetch/$s_!QfDR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd61379b-5fa4-44d9-bca3-995288e3a02f_605x318.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><strong>Current L4S marks all packets in a flow identically, missing per-packet optimization opportunities</strong></figcaption></figure></div><p>We asked a simple question: what if we could predict <em>which</em> packets are about to get hammered, and route them differently?</p><h3>The Approach</h3><p>SwiftQueue uses a Transformer&#8212;the same architecture behind large language models like ChatGPT&#8212;to predict per-packet latency based on the timing of recent ACKs. The insight is that packet-level latency variations aren&#8217;t random. They follow patterns from complex interactions at shared router queues: video apps have periodic bursts, TCP congestion control creates predictable queue buildups and back-offs. Traditional time-series models can&#8217;t capture these patterns efficiently. Transformers can.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!89v0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!89v0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png 424w, https://substackcdn.com/image/fetch/$s_!89v0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png 848w, https://substackcdn.com/image/fetch/$s_!89v0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png 1272w, https://substackcdn.com/image/fetch/$s_!89v0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!89v0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png" width="573" height="163" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:163,&quot;width&quot;:573,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:20335,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/180711519?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!89v0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png 424w, https://substackcdn.com/image/fetch/$s_!89v0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png 848w, https://substackcdn.com/image/fetch/$s_!89v0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png 1272w, https://substackcdn.com/image/fetch/$s_!89v0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7914b9-ae1f-48a6-b331-e2cbdb362d01_573x163.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption"><strong>SwiftQueue predicts latency per packet and chooses the appropriate queue for each</strong> packet.</figcaption></figure></div><p>Armed with that prediction, the sender dynamically marks each packet&#8217;s header to route it to whichever queue has lower predicted latency&#8212;even if that means packets within the same flow end up in different queues.</p><h3>Why Transformers?</h3><p>The core innovation in Transformers is self-attention: the model learns to weigh which elements in a sequence matter for predicting what comes next. In language, &#8220;bank&#8221; means different things depending on whether &#8220;river&#8221; or &#8220;financial&#8221; appeared earlier. The same logic applies to packet latencies&#8212;a spike three packets ago might be highly predictive, or irrelevant, depending on context.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bZOb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bZOb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png 424w, https://substackcdn.com/image/fetch/$s_!bZOb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png 848w, https://substackcdn.com/image/fetch/$s_!bZOb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png 1272w, https://substackcdn.com/image/fetch/$s_!bZOb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bZOb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png" width="569" height="351" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:351,&quot;width&quot;:569,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:66647,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/180711519?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bZOb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png 424w, https://substackcdn.com/image/fetch/$s_!bZOb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png 848w, https://substackcdn.com/image/fetch/$s_!bZOb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png 1272w, https://substackcdn.com/image/fetch/$s_!bZOb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d61818c-40a4-4112-8fd6-3aa14c6d50ca_569x351.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Custom Transformer architecture optimized for this task.</figcaption></figure></div><p>RNNs and LSTMs can learn sequences, but they suffer from vanishing gradients and memory limitations. Transformers parallelize attention across the whole context window, making them faster to train and better at long-range dependencies.</p><p>SwiftQueue&#8217;s Transformer is deliberately small&#8212;about 100K parameters, nothing like the billions in language models. Two encoder attention blocks, two linear layers. Input features include latency, timestamp, packet size, flow ID, and receiver ID. The history window is sized to the bandwidth-delay product of the link.</p><p>One nice result from the paper: even when two packets have nearly identical recent latency histories, the Transformer maps them to completely different positions in its internal feature space if one is about to experience a spike. The model learned to detect signals that aren&#8217;t obvious to human inspection.</p><h3>Key Design Choices</h3><p><strong>Custom loss function.</strong> Standard MSE tries to minimize error everywhere. We don&#8217;t care about predicting smooth periods&#8212;we care about catching spikes. SwiftQueue uses a 10&#215; penalty when true latency change exceeds 20ms and 20% relative difference. Trades slightly higher average error for dramatically better spike detection.</p><p><strong>Fast online fine-tuning.</strong> Network conditions change constantly. SwiftQueue only fine-tunes the linear layers using the most recent minute of data&#8212;takes under 30 seconds on a commodity GPU.</p><p><strong>Batched predictions.</strong> At 200 Mbps, you can&#8217;t wait for each ACK before predicting the next packet&#8217;s latency. SwiftQueue predicts batches of up to 8 future packets simultaneously, keeping inference under 400 microseconds.</p><p><strong>Oscillation prevention.</strong> A naive controller could thrash between queues. SwiftQueue includes un-ACKed packets (with queue assignments but not latencies) in the prediction input, so it knows how many packets it&#8217;s already assigned to each queue.</p><h3>Results</h3><p>Evaluated on real traces (Netflix and Facebook traffic over WiFi and Ethernet) and NS-3 simulations:</p><ul><li><p><strong>Prediction accuracy:</strong> 45-65% higher F1 scores on sharp latency changes vs. LSTM and XGBoost baselines</p></li><li><p><strong>Tail latency reduction:</strong> P99 latency drops 36-45% compared to default L4S or LSTM-driven selection</p></li></ul><p>Show Image</p><p><em>SwiftQueue achieves better prediction on sharp changes by 45-65% and reduces P99 tail latency by 36-45% compared to baseline approaches.</em></p><p>Results hold across different network conditions&#8212;even with 500 concurrent flows or 200ms propagation delay.</p><h3>Deployment Reality</h3><p>SwiftQueue has some deployment considerations:</p><ul><li><p><strong>Hardware.</strong> Needs a GPU for fast inference, albeit a cheap one (TITAN RTX, 2GB peak memory utilization). Datacenter-scale with 10+ Gbps links would need beefier hardware.</p></li><li><p><strong>Delayed ACKs.</strong> High propagation delay means less recent information to predict from. The model degrades gracefully but can&#8217;t overcome fundamental information constraints.</p></li><li><p><strong>Scaling.</strong> Handles hundreds of concurrent flows well; thousands would need architectural changes.</p></li><li><p><strong>Congestion control coupling.</strong> SwiftQueue only does queue selection&#8212;doesn&#8217;t touch congestion control. The predictor is trained on specific CC algorithms (primarily DCTCP+L4S) and may not generalize perfectly. TCP BBR&#8217;s probing behavior creates more random-looking patterns.</p></li><li><p><strong>L4S availability.</strong> Assumes L4S-enabled routers along the path. Deployment is growing but not ubiquitous.</p></li></ul><h3>Why This Matters</h3><p>This is part of a broader trend: using ML to make fine-grained, per-packet decisions that were previously impossible. Traditional congestion control operates at the flow level because that&#8217;s what humans could reason about. Neural networks don&#8217;t have that limitation.</p><p>You also don&#8217;t need billions of parameters. A 100K-parameter model, purpose-built for the domain, beats larger general-purpose architectures. Match the architecture to the problem structure.</p><h3>Read More</h3><p>SwiftQueue will appear at the <a href="https://nines-conference.org/">New Ideas in Networked Systems (NINeS) Conference</a> in 2026.</p><div><hr></div><p><em>SwiftQueue: Siddhant Ray, Xi Jiang, Jack Luo, Nick Feamster, Junchen Jiang. University of Chicago. <a href="https://arxiv.org/abs/2410.06112">arXiv:2410.06112</a></em></p>]]></content:encoded></item><item><title><![CDATA[AI Use is not "Cheating". It is Normalized. We Must Teach to This New Reality.]]></title><description><![CDATA[It's well past time to stop talking about "AI detection" snake oil software and think more critically about learning objectives.]]></description><link>https://practicespace.substack.com/p/ai-use-is-not-cheating-it-is-normalized</link><guid isPermaLink="false">https://practicespace.substack.com/p/ai-use-is-not-cheating-it-is-normalized</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Fri, 12 Dec 2025 22:06:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!dYCY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A <a href="https://www.sagepub.com/docs/default-source/corp-comms/ai-and-the-future-of-pedagogy.pdf">recent white paper on AI and pedagogy</a> landed in my inbox the same week my university is debating whether to adopt yet another AI detection tool, at the same time as my university is debating rolling out purported &#8220;AI detection&#8221; software, which I argue in this post is both technologically and pedagogically flawed.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dYCY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dYCY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg 424w, https://substackcdn.com/image/fetch/$s_!dYCY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg 848w, https://substackcdn.com/image/fetch/$s_!dYCY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!dYCY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dYCY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2858915,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/181466657?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dYCY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg 424w, https://substackcdn.com/image/fetch/$s_!dYCY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg 848w, https://substackcdn.com/image/fetch/$s_!dYCY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!dYCY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91fefcc0-132d-4796-9907-7d6123d83dc6_3968x2232.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Teaching AI to high school students earlier this week.</figcaption></figure></div><h2>&#8220;AI Detection&#8221; Software is the Wrong Approach</h2><p>Simply put: Surveillance and policing is the wrong response to pedagogy. </p><p>First, AI detection tools are unreliable at best. Even the latest tools operate at a 5% false positive rate in ideal scenarios. In more challenging conditions&#8212;like a university where students are smart and motivated&#8212;accuracy drops further.</p><p>Second, the harm to students from inevitable false positives is asymmetric. A student accused of academic dishonesty carries the weight of that accusation, regardless of outcome.  </p><div class="pullquote"><p>Perhaps the only good thing about AI detection software is that it is ineffective at achieving the ill-considered goal that it sets out to achieve.</p></div><p>What concerns me more than the technical failures is that <strong>this is fundamentally the wrong way to think about pedagogy</strong>.</p><h2>What I&#8217;ve Learned Actually Using AI in My Teaching</h2><p>I&#8217;ve written before about my approach: I fully encourage the use of AI tools in all my courses. The core principle is simple: <strong>you must understand what you&#8217;re turning in.</strong> I&#8217;ll ask you about it on exams, in discussions, and during assessments. Use whatever tools help you learn and complete your work, but you&#8217;re responsible for understanding the output. I also require attribution&#8212;tell me what assistance you used.</p><p>The classroom is a simulator for the real world, and in the real world, these tools are everywhere. Ignoring them doesn&#8217;t serve our students well.</p><p>But I don&#8217;t just permit AI use&#8212;I&#8217;ve restructured my teaching around it:</p><ul><li><p><strong>Automated class notes.</strong> I take transcripts of my lectures and use LLMs to generate summaries and notes for students. These get posted immediately after every class. (Example: <a href="https://github.com/noise-lab/systems-fall-2024/blob/main/agenda.md">my agenda files on GitHub</a>)</p></li><li><p><strong>AI-assisted exam creation.</strong> I use past exams and instruction files with LLMs to generate draft copies of exams. Even better&#8212;I share the prompts with students so they can generate their own practice exams based on past materials and covered topics. (See <a href="https://github.com/noise-lab/systems-fall-2024/tree/main/exams">the exam generation setup</a>)</p></li><li><p><strong>Discussion preparation.</strong> I use AI to organize student reading responses to prepare better class discussions.</p></li><li><p><strong>Reduced friction.</strong> AI helps me set up environments so students focus on concepts, not configuration.</p></li><li><p>The result? Students spend less time on grunt work and more time on higher-level thinking about security, privacy, and online speech. That&#8217;s what my courses are actually about.</p></li></ul><h2>The Mode Switch</h2><p>Here&#8217;s what I&#8217;ve learned using AI for both pedagogy and my own creative work (I&#8217;ve been building MCP servers to control my Digitakt sequencer and drum machine, learning about music production as a lifelong learner): there&#8217;s a critical distinction between modes of operation.</p><blockquote><p><strong>Are you in push-button mode or evaluation mode?</strong> </p></blockquote><p>When you&#8217;re creating something, are you expressing yourself or having something else do it for you?</p><p>Push-button outputs from LLMs are usually terrible. They produce statistical token completion&#8212;the most likely next word. That&#8217;s exactly what you don&#8217;t want in creative work. You want emotion, lived experience, surprise.</p><p>But using AI to break through a block? To help figure out how to express something that&#8217;s already inside you? That works.</p><p>The principle applies in teaching: Use the tools, absolutely, but ultimately the goal is to further your understanding. If you just copy-paste, you didn&#8217;t learn anything, and the learning objectives were not met. We must instead focus on how to design our pedagogy to achieve the learning objectives.</p><h2>It is Time to Stop with &#8220;AI Shaming&#8221; </h2><p>A colleague recently shared something striking from a survey of undergraduates at our university: about 40% won&#8217;t admit to using AI but are happy to say their peers do. That&#8217;s mathematically impossible if students and their peers are the same population.</p><p>What does this mean? Our students are deeply ashamed of using AI, regardless of whether that use is detrimental or instrumental to learning.</p><p>This culture of &#8220;AI shaming&#8221; harms students&#8212;psychologically and in terms of their ability to leverage their educational experience to prepare for the real world. </p><p>Are policies that encourage policing and punishment of AI use conducive to making our institutions the best they can be right now? I&#8217;d argue no. Blanket bans prevent the very conversations that would help students and faculty distinguish between beneficial and harmful uses.</p><h2>AI as Normal Technology</h2><p>AI is the latest in a long line of cultural and social technologies&#8212;like writing, print, and the internet. I&#8217;ve been making this point for two years: this is just another tool&#8212;like IDEs, Stack Overflow, or GitHub before it. Potentially more powerful, but fundamentally another instrument in the problem-solving toolkit.</p><p>Assessment should be conversation, not surveillance. The question moves from &#8220;What do you know?&#8221; to &#8220;How do you think?&#8221; That&#8217;s exactly what my approach operationalizes: I test comprehension, not compliance.</p><h2>What Forward-Thinking Pedagogy Looks Like</h2><p>Pedagogy will vary widely by course, learning objective, design, mode of interaction, type of assignment, level. I would caution against any prescriptive approach, especially one that generalizes.</p><p>But here are some principles that have worked for me:</p><ul><li><p><strong>Make AI use visible, not hidden.</strong> Build tasks that incorporate AI into the learning process. Require students to explain how they used it, what they learned, what choices they made.</p></li><li><p><strong>Teach prompt design as critical thinking.</strong> Crafting effective prompts is itself a lesson in precision and clarity.</p></li><li><p><strong>Restructure tasks around critical thinking, evaluation of outputs, judgment, testing, and debugging.</strong> Design assignments that require uniquely human contributions and insist on transparent, reflective use of technology.</p></li><li><p><strong>Use AI as complement to group work, not substitute.</strong> Treat interactions with AI as opportunities for consolidating core skills to support participation in peer discussions.</p></li></ul><h2>CS Education Is More Important Than Ever</h2><p>Computer science degrees are becoming more important than ever. These models can assist us and make us more efficient, but they can&#8217;t (yet) do the same level higher-level reasoning and creative thinking that we are capable of&#8212;they automate tasks we specify and lead us to probabilistic likely outcomes and outputs. Such tools are hugely useful&#8212;but only if we know how to integrate them into our workflows and thought processes and adapt them for new ones.</p><p>The real differentiators are what CS degrees teach: abstraction, specification, testing, debugging, and reasoning about complex systems.</p><p>Entry-level isn&#8217;t &#8220;junior developer&#8221; anymore&#8212;it&#8217;s project manager and test engineer. The thinking doesn&#8217;t change. The tools do.</p><p>The real question isn&#8217;t whether to use AI in education&#8212;students are already using it. The question is: Are we teaching them to use it thoughtfully, critically, and ethically? Or are we leaving them to figure it out alone while we chase an unwinnable arms race?</p><div><hr></div><p><em>My previous post on this topic: <a href="https://practicespace.substack.com/p/embracing-ai-in-the-classroom">Embracing AI in the Classroom</a>.</em></p>]]></content:encoded></item><item><title><![CDATA[Students Aren’t Asking for Help Anymore. That Could Be a Good Thing.]]></title><description><![CDATA[AI is rapidly disrupting how both students and faculty teach in their classroom. There is no single right approach. The only wrong approach is to ignore it.]]></description><link>https://practicespace.substack.com/p/students-arent-asking-for-help-anymore</link><guid isPermaLink="false">https://practicespace.substack.com/p/students-arent-asking-for-help-anymore</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Tue, 09 Dec 2025 17:25:59 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!9sYD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p><strong>Bespoke AI tutors and teaching assistants are here and they are replacing the traditional functions of professors and teaching assistants. This is a wake-up call.</strong></p></div><p>Earlier today, a colleague recently shared some striking data from his course this quarter: page views on Ed Discussion down 65%, discussion threads down 48%, comments down 44%. TA office hours are ghost towns. </p><p>Other instructors in our department are reporting similar trends. While it&#8217;s important to distinguish between correlation and causality, the hypothesis is clear: Students are increasingly asking for help from LLMs instead of human instructors (specifically, professors and teaching assistants in office hours).</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Some of my colleagues have responded in particular ways: concern, a bit of alarm, suggestions that we should run all assignments through GPT before releasing them to see what it spits out.  One colleague noted that even plain Google searches now surface LLM-generated responses&#8212;making AI assistance essentially &#8220;unavoidable&#8221; (as LLMs were a technology to be avoided).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9sYD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9sYD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png 424w, https://substackcdn.com/image/fetch/$s_!9sYD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png 848w, https://substackcdn.com/image/fetch/$s_!9sYD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png 1272w, https://substackcdn.com/image/fetch/$s_!9sYD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9sYD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png" width="888" height="453" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:453,&quot;width&quot;:888,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:415199,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/181158949?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9sYD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png 424w, https://substackcdn.com/image/fetch/$s_!9sYD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png 848w, https://substackcdn.com/image/fetch/$s_!9sYD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png 1272w, https://substackcdn.com/image/fetch/$s_!9sYD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7af8159-4853-4b53-9b12-f44bab7d932d_888x453.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Teaching AI to high school students in 2017.</figcaption></figure></div><p><strong>I think this discussion needs a careful re-thinking and framing.</strong></p><h2>The Uncomfortable Reality</h2><div class="pullquote"><p><strong>LLMs are already good tutors and teaching assistants, and they are going to get better.</strong></p></div><p>If students are consulting &#8220;bots&#8221; instead of humans, we should consider the uncomfortable reality that the way we used to do our jobs is potentially quite replaceable. <br><br>As students become more skilled at using these tools and evaluating their outputs&#8212;which is, in part, what we should be training them to do&#8212;the old model of &#8220;ask the TA how to fix your code&#8221; becomes less central to learning.</p><p>This presents both disruption and opportunity.</p><h2>A Different Approach</h2><p>In my courses, I&#8217;ve leaned into this shift rather than fighting it. I give students all of my old homeworks, midterms, and finals. I share full lecture summaries and transcripts. I even share the prompts I used to generate draft exams, so students can create essentially infinite practice material. I&#8217;ve written about my approach to AI in the classroom this year <a href="https://practicespace.substack.com/p/embracing-ai-in-the-classroom">in a previous post</a>.</p><p><strong>I was really nervous about how this would work out. The result? Students loved it.</strong> <br><br>Just as many students came to my office hours as in the past&#8212;and the discussions were much more interesting. They were engaged at a <em>higher</em> level, asking deeper questions rather than asking &#8220;how do I get this to compile?&#8221;-style debugging questions</p><p>I did discover, that, in allowing my students to use LLMs to assist with assignment completion&#8212;a couple of assignments were completed more quickly than in past years. I noted several where it was clear that the assignment was perhaps too &#8220;AI-friendly&#8221;, in the sense that my earlier assignment design makes it a little too easy for students to &#8220;phone it in&#8221; without understanding the learning objectives. </p><p>My response to that, &#8220;in the offseason&#8221;, will be to think about how to tune the assignments and syllabus accordingly&#8212;probably adding a couple more, as well as asking students to think more deeply about the outputs, testing them more on exams on the concepts I want them to be learning. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CKI_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CKI_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png 424w, https://substackcdn.com/image/fetch/$s_!CKI_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png 848w, https://substackcdn.com/image/fetch/$s_!CKI_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png 1272w, https://substackcdn.com/image/fetch/$s_!CKI_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CKI_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png" width="435" height="593.6034115138593" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:640,&quot;width&quot;:469,&quot;resizeWidth&quot;:435,&quot;bytes&quot;:454438,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/181158949?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!CKI_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png 424w, https://substackcdn.com/image/fetch/$s_!CKI_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png 848w, https://substackcdn.com/image/fetch/$s_!CKI_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png 1272w, https://substackcdn.com/image/fetch/$s_!CKI_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd7d6699-7707-49c3-8dd0-12a892eb81bc_469x640.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">I, too, used to use a chalkboard.</figcaption></figure></div><p><br><br>In short, we need to think hard about how we adapt learning objectives to these new realities training our students to work with the tools as we prepare them for their eventual occupations. </p><p>And, as educators ourselves, we need to be thinking hard about how to incorporate these tools into our own occupation as educators. That ultimately makes us better educators for two reasons: one, we can teach better having had direct experience with the tools, and two, we can improve our own teaching efficiencies with AI to improve the delivery of our own content and steamlining the logistics of teaching (and anyone who has taught before can appreciate, there are a <em>lot </em>of rote logistics that are ripe for automation).</p><h2>Caveat: Your Mileage May Vary</h2><p>It&#8217;s early days here, and nobody has the answers. In my courses, I treat my students as &#8220;co-learners&#8221; and partners in the journey. I bring value to the classroom, and AI can also bring value&#8212;to myself as an educator, and to the students as learners. The answers are not all clear, but one thing I think is clear even in these early days: The answer is not to ban or police the tools or deny their existence, but to think hard about what integrative approaches can help us achieve learning objectives, which themselves are ultimately going to to evolve.</p><p>And finally, I&#8217;d caution against any prescriptive approach here, especially one that generalizes across all courses and contexts. Pedagogy, material, learning objectives, style of instruction, and general philosophy all matter. What works for a systems course may not work for discrete math. What works for a Master&#8217;s seminar may not work for an intro programming class.</p><p>But if the old indicators of engagement&#8212;Piazza/Ed posts, TA queues&#8212;are dropping, maybe we should ask whether those were ever the right metrics for learning in the first place.</p>]]></content:encoded></item><item><title><![CDATA[To Understand How AI Will Affect Productivity, Look to Agents]]></title><description><![CDATA[Or, how I built a collection of AI agents to act as my personal administrative assistant.]]></description><link>https://practicespace.substack.com/p/to-understand-how-ai-will-affect</link><guid isPermaLink="false">https://practicespace.substack.com/p/to-understand-how-ai-will-affect</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Mon, 08 Dec 2025 03:20:25 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!yK30!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>An investor friend asked me today: What&#8217;s your take on AI and workplace productivity?</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yK30!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yK30!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!yK30!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!yK30!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!yK30!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yK30!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yK30!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!yK30!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!yK30!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!yK30!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3030f2e8-9253-4b4e-b3a2-b371e09eaf76_1024x608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>After some moderanvestment of time and energy on my side, I now have my own administrative assistant. I&#8217;ve spent a chunk of time building model context protocol (MCP) servers that run against my calendar, email, notes, and meeting transcripts. The setup wasn&#8217;t trivial&#8212;this took actual work, actual code, actual debugging&#8212;but the payoff has been immediate and substantial.</p><p>Now I can fire off queries like &#8220;brief me for my meetings today&#8221; or &#8220;find the emails related to my 2pm&#8221; or &#8220;when&#8217;s the best time to schedule a meeting with this person based on my preferences,&#8221; and while the system cranks away, I go do something else. Play guitar. Go for a run. Do laundry. Or&#8212;radical thought&#8212;get on with the actual work that requires my brain.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HvUi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HvUi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png 424w, https://substackcdn.com/image/fetch/$s_!HvUi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png 848w, https://substackcdn.com/image/fetch/$s_!HvUi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png 1272w, https://substackcdn.com/image/fetch/$s_!HvUi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HvUi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png" width="648" height="263" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:263,&quot;width&quot;:648,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:42585,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/181007309?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!HvUi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png 424w, https://substackcdn.com/image/fetch/$s_!HvUi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png 848w, https://substackcdn.com/image/fetch/$s_!HvUi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png 1272w, https://substackcdn.com/image/fetch/$s_!HvUi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F759f90eb-bac7-40d3-a00e-4df76267fe79_648x263.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The time savings alone would justify the effort. But the real win isn&#8217;t just efficiency. I show up to meetings prepped and briefed. My meetings get scheduled with my actual preferences in mind, the way a human admin would do it. I&#8217;m not burning mental cycles on calendar optimization, or trying to remember what that person emailed me about three weeks ago (or search for it with bad email search tools).</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!67aw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!67aw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png 424w, https://substackcdn.com/image/fetch/$s_!67aw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png 848w, https://substackcdn.com/image/fetch/$s_!67aw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png 1272w, https://substackcdn.com/image/fetch/$s_!67aw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!67aw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png" width="629" height="220" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:220,&quot;width&quot;:629,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:37486,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/181007309?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!67aw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png 424w, https://substackcdn.com/image/fetch/$s_!67aw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png 848w, https://substackcdn.com/image/fetch/$s_!67aw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png 1272w, https://substackcdn.com/image/fetch/$s_!67aw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08ba36d3-a71a-480a-85d4-1e82c209d111_629x220.png 1456w" sizes="100vw"></picture><div></div></div></a></figure></div><p>What actually matters: I&#8217;ve reduced time spent on rote tasks significantly, but more importantly, my brain is free for creative thinking&#8212;the kind where I can actually add value. The stuff that requires human judgment, intuition, synthesis. The work that <em>matters</em>.</p><p>I feel like this is the AI productivity story that isn&#8217;t getting enough attention. </p><blockquote><p><strong>It&#8217;s not about AI doing your job for you. It&#8217;s about AI handling the cognitive overhead that prevents you from doing your job well.</strong> </p></blockquote><p>When used well, AI can help us minimize the endless context-switching, the administrative tax, and the mental load of keeping track of everything. We talk a lot about &#8220;augmenting human intelligence&#8221; in the abstract, and this is one example of what it looks like in practice. </p><p>The tools I built are open source: </p><ul><li><p><a href="https://github.com/feamster/spark-mcp">spark-mcp</a> for email and meeting transcripts, and </p></li><li><p><a href="https://github.com/feamster/calendar-mcp">calendar-mcp</a> for calendar management. </p></li></ul><p>They&#8217;re hardly &#8220;production ready&#8221; for the masses, but they work for my needs. They&#8217;ve changed how I work. </p><p>And that idea of &#8220;just good enough&#8221; bespoke tools brings me to my final point. It has become so easy to build these bespoke tools for ourselves, what may ultimately happen to all of the companies that build these kinds of bespoke &#8220;productivity&#8221; tools that revert to the common case but never seem to quite fit anyone&#8217;s specific workflow. I do wonder if many of us will simply build these kinds of tools for ourselves now instead of paying for things that don&#8217;t quite work.</p>]]></content:encoded></item><item><title><![CDATA[The First College of Computing in the U.S. is Now 35 Years Old]]></title><description><![CDATA[Georgia Tech launched a College of Computing years before the commercial Internet.]]></description><link>https://practicespace.substack.com/p/the-first-college-of-computing-in</link><guid isPermaLink="false">https://practicespace.substack.com/p/the-first-college-of-computing-in</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Fri, 05 Dec 2025 05:16:23 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!g73m!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With all of the news of new colleges of computing these days, I find it all the more incredible to think that Georgia Institute of Technology has had a College of Computing for 35 years now. In 1990. Years before the commercial Internet, even.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!g73m!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!g73m!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png 424w, https://substackcdn.com/image/fetch/$s_!g73m!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png 848w, https://substackcdn.com/image/fetch/$s_!g73m!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png 1272w, https://substackcdn.com/image/fetch/$s_!g73m!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!g73m!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png" width="1089" height="742" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/de53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:742,&quot;width&quot;:1089,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:786466,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/180771075?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!g73m!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png 424w, https://substackcdn.com/image/fetch/$s_!g73m!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png 848w, https://substackcdn.com/image/fetch/$s_!g73m!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png 1272w, https://substackcdn.com/image/fetch/$s_!g73m!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde53fc5b-b3e3-40f6-b4ce-149508fc8073_1089x742.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Think about that timing for a moment. In 1990, Tim Berners-Lee was still working on the first web browser at CERN. Most people had never heard of email. The idea that computer science would become as fundamental to modern life as it has&#8212;that it would reshape everything from how we communicate to how we work to how we think&#8212;was far from obvious. And yet Georgia Tech made a bet that computer science deserved to stand on its own, separate from electrical engineering, as a full college.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4LEz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4LEz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4LEz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4LEz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4LEz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4LEz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg" width="1456" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:301549,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/180771075?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4LEz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4LEz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4LEz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4LEz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F987610ca-effe-42c7-916e-b3d309c1c4ee_1600x1200.jpeg 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>While I don&#8217;t know the full history of the establishment of the College, I remember hearing stories about how the restructuring was quite controversial at the time. I can only imagine what those faculty meetings must have been like. Academic reorganizations are never easy, and this one was particularly bold. It meant pulling computer science out from under the traditional engineering umbrella and giving it independence, resources, and autonomy. That kind of move doesn&#8217;t happen without fierce debate and, I imagine, some bruised egos along the way.</p><p>Even when I started there as an assistant professor in 2006&#8212;sixteen years after the College was established&#8212;I remember thinking that the structure was pretty unusual. As a fresh Ph.D. graduate, I really couldn&#8217;t wrap my head around it. The thought of CS in a completely separate department from EE seemed utterly foreign to me at the time. I had come from a world where computer science and electrical engineering were tightly coupled, where the organizational chart reflected the historical reality that computing had emerged from electrical engineering. Separating them felt almost unnatural.</p><p>But so many faculty there, including and especially Ellen Zegura, sold me on the College, saying how advantageous this structure was. I took a leap of faith at the time, but over the years it has become increasingly clear to me how right she was about this&#8212;and many other things. Organizational structure is critical for innovation, in scholarship as it is in anything. When you give a field room to define itself on its own terms, rather than as a subset of something else, it can move faster and think bigger.</p><p>I think it&#8217;s one of the reasons Georgia Tech has been able to remain so agile in thinking about CS over the years. The Online MS in CS program, which launched in 2014 and ultimately reached over a million students worldwide, was a radical experiment in making high-quality graduate education accessible at scale. The Threads curriculum reimagined how to teach computer science by letting students weave together their own path through the discipline rather than following a rigid sequence. And more recently, the School of Cybersecurity and Privacy represents yet another structural innovation, recognizing that security and privacy have become foundational concerns that deserve their own institutional home.</p><p>None of these innovations were guaranteed to work. All of them required institutional flexibility, a willingness to experiment, and the kind of autonomy that comes from having your own college rather than being a department within someone else&#8217;s college. When you have to negotiate with other departments over every curriculum change or new program, innovation slows to a crawl. When you have the independence to move quickly, you can try things that other institutions can&#8217;t.</p><p>The more experience and perspective I accrue, the more impressed I am that Georgia Tech did this so early, and even more so that they pulled it off in the face of what must have been incredible resistance at the time. It amazes me every time I think about it. Someone&#8212;or more likely, a group of people&#8212;had the vision to see that computer science was going to be massive and the courage to fight for the institutional structure to support that vision. They were willing to endure the controversy and discomfort of reorganization for something that wouldn&#8217;t fully pay off for years or even decades.</p><p>Now, 35 years later, other universities are catching on. We&#8217;re seeing new colleges of computing announced with great fanfare, as if the idea is novel. And maybe for those institutions, it is. To me, this just makes it all the more incredible that Georgia Tech figured this out in 1990, when it was far from obvious that this was the right move.</p><p>That kind of foresight and institutional courage is worth celebrating, and learning from.</p>]]></content:encoded></item><item><title><![CDATA[The Router Configuration Checker at 20: The Birth of Static Network Configuration Analysis]]></title><description><![CDATA[This year marks the 20-year anniversary of rcc, our pioneering research and software on static verification of router configurations.]]></description><link>https://practicespace.substack.com/p/the-router-configuration-checker</link><guid isPermaLink="false">https://practicespace.substack.com/p/the-router-configuration-checker</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Wed, 03 Dec 2025 06:31:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!H74D!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On <a href="https://www.nbcnews.com/news/us-news/amazon-web-services-outage-websites-offline-rcna238594">October 20, 2025</a>, Amazon Web Services experienced a massive outage that took down Snapchat, McDonald&#8217;s app, Ring doorbells, Roblox, Fortnite, and thousands of other services worldwide. The culprit? A DNS resolution failure triggered by a faulty configuration update. Just over a year earlier, <a href="https://en.wikipedia.org/wiki/2024_CrowdStrike-related_IT_outages">CrowdStrike&#8217;s configuration error</a> caused what has been called the largest IT outage in history, crashing 8.5 million Windows systems and causing an estimated $10 billion in damage. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Twenty years after these kinds of configuration errors first motivated my Ph.D. thesis research, they remain one of the primary causes of network and system outages.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!H74D!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!H74D!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!H74D!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!H74D!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!H74D!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!H74D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!H74D!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!H74D!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!H74D!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!H74D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F799aaff3-a8e9-4226-96f3-ace98f9b2905_1024x608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"></figcaption></figure></div><p>In May 2005, my advisor Hari Balakrishnan and I published <a href="https://www.usenix.org/legacy/event/nsdi05/tech/feamster/feamster.pdf">&#8220;Detecting BGP Configuration Faults with Static Analysis&#8221;</a>. The tool was called rcc (Router Configuration Checker), and it introduced static analysis of router configurations before deployment. Studies at the time showed that 50-80% of network outages were caused by configuration errors. Two decades later, that fundamental problem persists&#8212;though the systems have gotten vastly more complex.</p><h2>The Problem in 2005</h2><p>In the mid-2000s, network operators were managing increasingly complex routing infrastructures with no systematic way to verify correctness. The state of the art was to push configurations to production routers and see what breaks. When something went wrong, operators would scramble to diagnose the problem and roll back changes.</p><p>Configuring routers in an autonomous system is essentially writing a distributed program, but we were doing it with none of the verification tools that software engineers take for granted. BGP&#8217;s flexible configuration language made it powerful but error-prone. Operators had to manually decompose network-wide policies into device-level configurations across potentially thousands of BGP sessions, with complex interactions between iBGP, eBGP, route reflection, and filtering policies.</p><h2>The Approach</h2><p>rcc introduced static analysis of router configurations before deployment to detect faults automatically.</p><p>The approach was to parse vendor-specific configuration files, normalize them into a vendor-independent representation using relational database tables, and then check constraints based on a correctness specification. No need to run configurations in a live network or build expensive emulation environments.</p><p>rcc focused on detecting two broad classes of BGP configuration faults:</p><p><strong>Route validity faults</strong>: Where routers might learn routes that don&#8217;t correspond to usable paths. This included issues like:</p><ul><li><p>Invalid AS paths being propagated</p></li><li><p>Next-hop addresses unreachable via IGP</p></li><li><p>Undefined references to filters and route maps</p></li><li><p>Improper or missing route filtering</p></li></ul><p><strong>Path visibility faults</strong>: Where routers fail to learn routes for paths that exist in the network. The classic example was iBGP configuration errors&#8212;particularly with route reflection&#8212;that could cause network partitions where some routers never learn about certain destinations.</p><h2>What We Found</h2><p>We analyzed BGP configurations from 17 real-world networks. rcc found errors in every network. Most operators were unaware of these errors, which ranged from simple single-router problems like undefined variables to complex multi-router interactions.</p><p>The errors we uncovered included:</p><ul><li><p>Potential network partitions caused by route propagation problems</p></li><li><p>Invalid routes being propagated due to improper filtering</p></li><li><p>Routers forwarding packets inconsistently with high-level policy</p></li><li><p>420 incomplete iBGP sessions across the networks we studied</p></li></ul><p>Many of these errors were latent&#8212;not actively causing problems yet, but violations of correctness that would manifest under certain conditions. For example, misconfigured backup paths that would only fail after a primary link went down.</p><h2>Why Configuration Errors Happen</h2><p>Our analysis revealed three main causes:</p><ol><li><p><strong>Complex propagation mechanisms</strong>: The techniques used to scalably propagate routes within a network&#8212;particularly route reflection with clusters&#8212;are easily misconfigured.</p></li><li><p><strong>Levels of indirection</strong>: Even simple policy specifications get implemented using multiple layers of indirection in configuration files (distribute lists, prefix lists, route maps, community values).</p></li><li><p><strong>No systematic process</strong>: Most operators had no disciplined approach to network configuration. There were no configuration management tools, no testing frameworks, no verification.</p></li></ol><h2>The Impact</h2><p>rcc won Best Paper at NSDI 2005. The tool was open-sourced and is still on GitHub at <a href="https://github.com/noise-lab/rcc">github.com/noise-lab/rcc</a>. Operators used it to find and fix bugs before deployment.</p><p>The bigger impact was establishing static configuration verification as a research area. rcc showed that you could reason formally about network behavior from configuration files alone, without needing access to live networks or running emulation.</p><h2>The Research Lineage</h2><p>Over the past 20 years, researchers have built on rcc&#8217;s foundation with increasingly sophisticated techniques:</p><p><strong>Header Space Analysis (2012)</strong>: Kazemian, Varghese, and McKeown extended static analysis from the control plane to the data plane, introducing geometric representations of packet header spaces.</p><p><strong>Batfish (2015)</strong>: Fogel, Mahajan, Millstein and colleagues built a general-purpose configuration analysis tool using Datalog and logic programming, extending beyond BGP to multi-protocol networks.</p><p><strong>Minesweeper (2017)</strong>: Beckett et al. developed SMT-based verification for a wide range of properties including reachability, waypointing, and fault tolerance.</p><p>These tools advanced the techniques for network verification&#8212;new representations, new algorithms, broader protocol coverage. But they all built on the paradigm rcc established: that you can and should verify network configurations statically before deployment.</p><h2>Key Design Decisions</h2><p>Several design decisions proved important:</p><p><strong>Vendor-independent representation</strong>: By parsing vendor configs into normalized relational tables, we separated the parsing problem from the analysis problem. This pattern has been followed by every subsequent tool.</p><p><strong>Focus on correctness, not optimality</strong>: rcc didn&#8217;t try to find the &#8220;best&#8221; configuration&#8212;it found wrong configurations.</p><p><strong>Constraint-based approach</strong>: Rather than requiring operators to write formal specifications, rcc checked constraints that must hold for any correct configuration.</p><p><strong>Static analysis</strong>: No need for live network access, no emulation overhead, no waiting for convergence. You could verify configurations as fast as you could parse and analyze them.</p><h2>What&#8217;s Changed in 20 Years</h2><p>Networks have gotten more complex. We&#8217;ve added software-defined networking, cloud and multi-cloud environments, container networking, network functions virtualization, and programmable data planes. Configuration errors are more consequential than ever. A misconfiguration in a cloud environment can expose thousands of customers&#8217; data. An error in SDN controller logic can take down an entire data center. A faulty configuration update can crash millions of systems worldwide, as we saw with CrowdStrike.</p><h2>Looking Forward: LLMs and the Next Generation</h2><p>While outages persist and are often due to increasingly complex software and configuration errors, there is hope that tools with more sophisticated reasoning capabilities will ultimately help us reason about these errors. The rise of large language models has opened new approaches to the problems rcc was designed to solve.</p><p>Our recent work on <a href="https://arxiv.org/abs/2411.14283">CAIP (Context-Aware Iterative Prompting)</a> demonstrates how LLMs can detect router misconfigurations with over 30% better accuracy than traditional model checkers and consistency checkers, finding over 20 previously undetected misconfigurations in real-world configurations. Unlike traditional tools that require significant manual effort to develop and maintain for each new protocol or vendor, LLMs can learn patterns from vast datasets and apply them across layers and vendors.</p><p>This makes the verification that rcc pioneered feasible for much larger and more complex systems&#8212;from multi-protocol networks to cross-vendor translations to intent-based configuration generation. The fundamental insight remains the same: configuration errors are preventable through analysis before deployment. But LLMs are making that analysis practical at scales and across domains we couldn&#8217;t have imagined in 2005.</p><p>The AWS and CrowdStrike outages remind us that configuration errors remain a critical challenge. But they also show us that the problem rcc addressed two decades ago is more important than ever&#8212;and that new techniques building on that foundation offer genuine hope for finally getting ahead of these errors.</p><p><em>The original rcc paper: &#8220;Detecting BGP Configuration Faults with Static Analysis,&#8221; Nick Feamster and Hari Balakrishnan, NSDI 2005. <a href="https://www.usenix.org/legacy/event/nsdi05/tech/feamster/feamster.pdf">PDF</a></em></p><p><em>Recent work: &#8220;CAIP: Detecting Router Misconfigurations with Context-Aware Iterative Prompting of LLMs,&#8221; Xi Jiang, Aaron Gember-Jacobson, and Nick Feamster, 2024. <a href="https://arxiv.org/abs/2411.14283">arXiv</a></em></p><pre><code><code>@inproceedings{feamster2005rcc,
  title     = {Detecting {BGP} Configuration Faults with Static Analysis},
  author    = {Feamster, Nick and Balakrishnan, Hari},
  booktitle = {2nd USENIX Symposium on Networked Systems Design and 
               Implementation (NSDI &#8216;05)},
  year      = {2005},
  month     = {May},
  address   = {Boston, MA},
  publisher = {USENIX Association},
  url       = {https://www.usenix.org/legacy/event/nsdi05/tech/feamster/feamster.pdf},
  note      = {Best Paper Award}
}
</code></code></pre>]]></content:encoded></item><item><title><![CDATA[A New Home for Networking and AI Research]]></title><description><![CDATA[Re-launching the Network Operations and Internet Security Lab website to better reflect the lab's mission]]></description><link>https://practicespace.substack.com/p/a-new-home-for-networking-and-ai</link><guid isPermaLink="false">https://practicespace.substack.com/p/a-new-home-for-networking-and-ai</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Fri, 28 Nov 2025 20:51:04 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!9gBQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <a href="https://noise-lab.net/">NOISE Lab</a> website has a new look. After some long-overdue updates, <a href="https://noise-lab.net/">noise-lab.net</a> now better reflects the breadth and depth of our research program at the <a href="https://cs.uchicago.edu/">University of Chicago</a>. The redesign organizes our work around four interconnected research themes:</p><ul><li><p><strong>AI and Machine Learning for Networking</strong> &#8212; generative models for synthetic traffic, traffic classification, and operational analytics</p></li><li><p><strong>Internet Access and Broadband Measurement</strong> &#8212; tools and data for understanding network performance in homes and communities</p></li><li><p><strong>Internet Censorship and Online Speech</strong> &#8212; measuring and circumventing global Internet filtering</p></li><li><p><strong>Security and Privacy</strong> &#8212; protecting users from threats posed by IoT devices and network traffic analysis</p></li></ul><p>Here&#8217;s a quick tour of what you&#8217;ll find.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2>AI and Machine Learning for Networking</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9gBQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9gBQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!9gBQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!9gBQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!9gBQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9gBQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9gBQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!9gBQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!9gBQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!9gBQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e113f40-aa60-4fc0-b0a7-0a98640f4228_1024x608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This is perhaps the area where we&#8217;ve seen the most exciting recent progress. The scarcity of high-quality, labeled network traffic datasets has long been a bottleneck for applying machine learning to networking problems&#8212;privacy concerns, data staleness, and access restrictions have made it difficult to train models effectively.</p><p>Our response has been to develop generative AI techniques that can produce realistic, protocol-compliant synthetic network traffic. <a href="https://github.com/noise-lab/NetDiffusion_Generator">NetDiffusion</a> uses a fine-tuned <a href="https://stability.ai/stable-diffusion">Stable Diffusion</a> model to generate packet captures that closely mimic real network data while adhering to protocol specifications. More recently, <a href="https://arxiv.org/abs/2503.22663">NetSSM</a> applies state-space models to generate multi-flow network traces that capture the complex temporal dependencies between simultaneous network conversations. These tools are helping researchers train better ML models for traffic classification, anomaly detection, and network security&#8212;without needing access to sensitive real-world data.</p><p>Beyond data generation, we&#8217;re developing techniques for traffic classification, predictive modeling, and operational analytics. This includes work on efficient representations for network data through tools like <a href="https://github.com/noise-lab/netml">netml</a>, and models that can handle the practical challenges of deployment, like cost sensitivity and <a href="https://netml.io/blog/2023/leaf/">model drift</a>. <br><br>You can read more about our ML for networking research on <a href="https://netml.io/">netml.io</a>.</p><h2>Internet Access and Broadband Measurement</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GiN4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GiN4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!GiN4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!GiN4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!GiN4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GiN4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GiN4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!GiN4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!GiN4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!GiN4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F687a7e85-81ef-4c6e-ad0b-b2250b5aa0b7_1024x608.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Understanding how people actually experience the Internet requires measuring it where it matters most: in homes and communities. Our <a href="https://internetequity.org/">Internet Innovation Initiative</a> develops new tools to measure broadband access and performance, working with community partners to make high-speed Internet accessible to all.</p><p>This work builds on a long history of broadband measurement, including the <a href="https://projectbismark.net/">BISmark</a> project and our collaborations with the <a href="https://www.fcc.gov/">FCC</a> to develop technologies for understanding access network performance across the United States. Today, we deploy <a href="https://github.com/internet-equity/netrics">Netrics</a> devices in homes across Chicago and beyond, gathering continuous, granular data that enables comparisons of Internet experience across neighborhoods with different socioeconomic profiles. The goal isn&#8217;t just measurement for its own sake&#8212;it&#8217;s producing actionable insights that can inform policy and investment decisions to close the digital divide. </p><p>You can explore our open-source tools and datasets at <a href="https://internet-innovation.github.io/">internet-innovation.github.io</a>.</p><h2>Internet Censorship and Online Speech</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zmu1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zmu1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!zmu1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!zmu1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!zmu1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zmu1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!zmu1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!zmu1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!zmu1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!zmu1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9471a73-bad2-4409-af5b-297a1c43901d_1024x608.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>More than 60 countries perform some form of Internet censorship. Our group has been developing technologies to measure and mitigate censorship for over two decades, producing a series of firsts: <a href="https://dl.acm.org/doi/10.1145/964725.633156">Infranet</a> (2002), the first system to use covert channels for circumvention; <a href="https://www.usenix.org/conference/usenixsecurity10/collage-defeating-censorship-user-generated-content">Collage</a> (2009), which used user-generated content platforms as drop sites; <a href="https://dl.acm.org/doi/10.1145/2785956.2787485">Encore</a> (2015), the first system for global, real-time measurement of Web censorship; and <a href="https://www.usenix.org/conference/usenixsecurity17/technical-sessions/presentation/pearce">Iris</a> (2017), the first system to detect widespread DNS manipulation.</p><p>Current work focuses on <a href="https://datascience.uchicago.edu/news/using-ai-and-data-science-to-reliably-detect-internet-censorship-in-real-time/">applying AI to detect censorship in real time</a>. We&#8217;re training models to identify the &#8220;fingerprints&#8221; of filtering devices by analyzing how they manipulate traffic, with the goal of creating a real-time &#8220;weather map&#8221; for censorship&#8212;where observers can see Internet interference as it happens, which sites are being targeted, and in which countries. Recent work has developed more robust <a href="https://arxiv.org/abs/2302.02031">machine learning techniques for censorship detection</a> that can discover new blocking signatures missed by existing heuristics.</p><h2>Security and Privacy</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Nv7P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Nv7P!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!Nv7P!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!Nv7P!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!Nv7P!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Nv7P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Nv7P!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!Nv7P!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!Nv7P!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!Nv7P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1686b23-e63a-4082-bf69-ae1ad17205d5_1024x608.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The proliferation of connected devices creates new security and privacy challenges. Smart home IoT devices interact with multiple people, respond to environmental triggers, and operate in a fragmented ecosystem&#8212;none of which fits well with traditional security approaches designed for single-user, keyboard-and-screen computing.</p><p>Our <a href="https://noise-lab.net/iot-lab.html">IoT Lab</a> provides a testbed for studying these devices, where we&#8217;ve investigated everything from the <a href="https://dl.acm.org/doi/10.1145/3319535.3354198">tracking behavior of Smart TVs</a> to <a href="https://dl.acm.org/doi/10.1145/3139937.3139939">cleartext data transmissions in consumer medical devices</a>. We developed <a href="https://inspector.engineering.nyu.edu/">IoT Inspector</a>, a tool that crowdsources labeled network traffic from smart home devices to detect hidden security and privacy violations. We&#8217;re also working on <a href="https://noise.cs.uchicago.edu/security.html">DNS privacy</a>, designing protocols and systems to improve privacy properties even when encrypted DNS solutions are in use.</p><p>A key insight from this work is that network traffic itself reveals information users may want to keep private&#8212;eavesdroppers can <a href="https://arxiv.org/abs/1708.05044">infer in-home behaviors</a> just from traffic rate patterns, even when the content is encrypted. Our research explores both how to detect these threats and how to mitigate them through techniques like <a href="https://petsymposium.org/2019/files/papers/issue3/popets-2019-0040.pdf">smart traffic shaping</a>.</p><h2>Education and Courses</h2><p>We&#8217;re committed to making our research accessible through teaching. </p><p>I regularly offer courses on <a href="https://noise-lab.net/courses.html">machine learning for network security</a>, <a href="https://noise-lab.net/courses.html">Internet censorship</a>, and <a href="https://noise-lab.net/courses.html">security and privacy</a> to undergraduate and graduate students at UChicago. </p><p>For online learners, our <a href="https://www.coursera.org/learn/sdn">Software Defined Networking</a> and <a href="https://www.coursera.org/learn/applied-machine-learning">Applied Machine Learning</a> MOOCs on Coursera have reached millions of students worldwide&#8212;the SDN course was one of the first of its kind and helped launch Georgia Tech&#8217;s <a href="https://omscs.gatech.edu/">Online Masters in Computer Science</a> program. </p><p>Free instructional videos are also available on the <a href="https://youtube.com/c/nfeamster">nfeamster YouTube channel</a>. </p><p>See the full list of courses at <a href="https://noise-lab.net/courses.html">noise-lab.net/courses.html</a>. I continue to add more courses and content on these topics, so please subscribe and stay tuned for more updates! </p><div><hr></div><p>The redesigned site also highlights our commitment to <a href="https://github.com/noise-lab/">open-source software</a>, real-world deployments, and <a href="https://noise.cs.uchicago.edu/outreach.html">outreach</a>&#8212;from educational programs for underrepresented students to policy comments on spectrum allocation and data privacy. Take a look around, and <a href="mailto:feamster@uchicago.edu">reach out</a> if you&#8217;re interested in learning more about the group or how to get involved.</p><p><a href="https://noise-lab.net/">noise-lab.net</a></p>]]></content:encoded></item><item><title><![CDATA[Building Multi-MCP Server Workflows With Claude]]></title><description><![CDATA[I now use Claude to have my email and calendaring talk to one another]]></description><link>https://practicespace.substack.com/p/building-multi-mcp-server-workflows</link><guid isPermaLink="false">https://practicespace.substack.com/p/building-multi-mcp-server-workflows</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Mon, 24 Nov 2025 21:59:14 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!LBcm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently built an MCP server for Google Calendar. It&#8217;s called <code>calendar-mcp</code> and it&#8217;s <a href="https://github.com/feamster/calendar-mcp">on GitHub</a>. I also have one for email and meeting transcripts called <code>spark-mcp</code> (<a href="https://github.com/feamster/spark-mcp">also on GitHub</a>). Together they let Claude access my schedule and communications in a single conversation.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LBcm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LBcm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png 424w, https://substackcdn.com/image/fetch/$s_!LBcm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png 848w, https://substackcdn.com/image/fetch/$s_!LBcm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png 1272w, https://substackcdn.com/image/fetch/$s_!LBcm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LBcm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png" width="1456" height="1127" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1127,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:201983,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/179865146?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LBcm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png 424w, https://substackcdn.com/image/fetch/$s_!LBcm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png 848w, https://substackcdn.com/image/fetch/$s_!LBcm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png 1272w, https://substackcdn.com/image/fetch/$s_!LBcm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dbebae6-9411-4b1d-8a3c-47059d50ff19_1540x1192.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>What These Servers Do</h2><p><strong>calendar-mcp</strong> gives Claude access to Google Calendar:</p><ul><li><p>List events across all calendars (primary, work, shared)</p></li><li><p>Find when I last met with someone</p></li><li><p>Create events and send invitations</p></li><li><p>Accept/decline calendar invites</p></li><li><p>Find optimal meeting times based on configured preferences</p></li><li><p>Analyze time blocks (deep work vs. flexible time)</p></li></ul><p><strong>spark-mcp</strong> gives Claude access to email and meeting transcripts:</p><ul><li><p>Search and read emails</p></li><li><p>Find emails needing responses</p></li><li><p>Extract action items from messages</p></li><li><p>Access meeting transcripts</p></li><li><p>Search transcript content</p></li></ul><h2>Using Them Together</h2><p>The useful part is running both servers at once. Claude can pull from either system as needed, which means queries can span both without any extra work on my end.</p><p>Some examples of what this looks like:</p><p><strong>&#8220;What do I need to be prepared for tomorrow?&#8221;</strong></p><p>Claude checks the calendar for tomorrow&#8217;s meetings, then searches emails for recent threads with those attendees. I get a briefing that includes both the meeting details and relevant email context.</p><p><strong>&#8220;What were the action items from my meeting with Andrew last Tuesday?&#8221;</strong></p><p>Claude finds the meeting on the calendar, pulls the transcript from spark-mcp, and extracts the action items. One query, two systems.</p><p><strong>&#8220;Do I have any emails I need to respond to before my 2pm?&#8221;</strong></p><p>Claude checks pending responses in email, cross-references with the calendar to see what&#8217;s at 2pm, and prioritizes accordingly.</p><p><strong>&#8220;Find a time to meet with Sarah next week and draft an email inviting her.&#8221;</strong></p><p>Claude uses calendar-mcp to find available slots (respecting my preferences), then uses the email context to draft an appropriate message.</p><h2>Why LLMs Beat Existing Solutions: <br>Understanding Soft Preferences</h2><p>calendar-mcp has a configuration file for scheduling preferences:</p><pre><code><code>{
  &#8220;preferredDays&#8221;: {
    &#8220;Wednesday-PM&#8221;: 100,
    &#8220;Thursday&#8221;: 100,
    &#8220;Monday-PM&#8221;: 70,
    &#8220;Tuesday&#8221;: 40,
    &#8220;Friday&#8221;: 40
  },
  &#8220;preferAdjacentToMeetings&#8221;: true,
  &#8220;avoidDeepWorkBlocks&#8221;: true,
  &#8220;neverAvailablePatterns&#8221;: [&#8221;kids&#8221;]
}
</code></code></pre><p>When finding meeting times, Claude ranks options by these preferences. Wednesday afternoons and Thursdays score highest. It looks for slots adjacent to existing meetings to consolidate context-switching. It avoids blocks marked as deep work. Events with &#8220;kids&#8221; in the title are treated as immovable.</p><h2>Setup</h2><p>Both servers require OAuth setup with Google APIs&#8212;Calendar API for calendar-mcp, Gmail API for spark-mcp. The README files walk through the process. Once authenticated, you add them to your Claude Desktop config:</p><pre><code><code>{
  &#8220;mcpServers&#8221;: {
    &#8220;calendar&#8221;: {
      &#8220;command&#8221;: &#8220;python&#8221;,
      &#8220;args&#8221;: [&#8221;-m&#8221;, &#8220;calendar_mcp.server&#8221;],
      &#8220;cwd&#8221;: &#8220;/path/to/calendar-mcp&#8221;
    },
    &#8220;spark&#8221;: {
      &#8220;command&#8221;: &#8220;python&#8221;, 
      &#8220;args&#8221;: [&#8221;-m&#8221;, &#8220;spark_mcp.server&#8221;],
      &#8220;cwd&#8221;: &#8220;/path/to/spark-mcp&#8221;
    }
  }
}
</code></code></pre><p>Restart Claude Desktop and both servers are available.</p><h2>Why This Works</h2><p>MCP servers are additive. Each one gives Claude access to a different system, and Claude figures out which tools to use based on the query. I don&#8217;t have to think about which server handles what&#8212;I just ask questions and Claude routes appropriately.</p><p>The combination of calendar and email covers most of my organizational needs. I can check my schedule, find context from past communications, schedule new meetings, and respond to emails all in the same conversation where I&#8217;m doing actual work.</p><div><hr></div><p><em>Both projects are open source: <a href="https://github.com/feamster/calendar-mcp">calendar-mcp</a> and <a href="https://github.com/feamster/spark-mcp">spark-mcp</a>.</em></p>]]></content:encoded></item><item><title><![CDATA[Lessons from My First Live Loop Performance]]></title><description><![CDATA[I&#8217;ve been experimenting with live looping in my home studio for months now, layering guitar parts and vocals, building arrangements one pass at a time.]]></description><link>https://practicespace.substack.com/p/lessons-from-my-first-live-loop-performance</link><guid isPermaLink="false">https://practicespace.substack.com/p/lessons-from-my-first-live-loop-performance</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Sat, 22 Nov 2025 21:05:04 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!oZus!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oZus!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oZus!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png 424w, https://substackcdn.com/image/fetch/$s_!oZus!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png 848w, https://substackcdn.com/image/fetch/$s_!oZus!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png 1272w, https://substackcdn.com/image/fetch/$s_!oZus!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oZus!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png" width="836" height="718" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:718,&quot;width&quot;:836,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:903661,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/179674214?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!oZus!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png 424w, https://substackcdn.com/image/fetch/$s_!oZus!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png 848w, https://substackcdn.com/image/fetch/$s_!oZus!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png 1272w, https://substackcdn.com/image/fetch/$s_!oZus!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a948c55-8de8-4e24-ab81-08acca19548b_836x718.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p>I&#8217;ve been experimenting with live looping in my home studio for months now, layering guitar parts and vocals, building arrangements one pass at a time. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Last night, I performed with a live looper for the first time. Performing live with loops is a different animal entirely. It&#8217;s not just about the technology; it&#8217;s about managing time, recovering from mistakes, and learning to trust the layers you&#8217;re building in real-time while an audience watches.</p><div id="youtube2-KRZhhfjo3kQ" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;KRZhhfjo3kQ&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/KRZhhfjo3kQ?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Here are some lessons I took away.</p><h3><strong>Tempo Sync Gives and Takes Away</strong></h3><p>I was looping two tracks with tempo sync set, which ensures that different parts of the song, like verse and chorus, stay at a common tempo. </p><p>I learned a crucial lesson: if you&#8217;re using tempo sync, it&#8217;s best to have click or drum track running when you lay down your foundation, especially when you shift from verse to chorus. On the verse, it matters less because you&#8217;re establishing the tempo and you&#8217;re tapping out the beat. As you switch to chorus, however, the track assumes that you&#8217;re hitting exactly the same tempo, and even a little drift will cause chaos.</p><p>On one song, I started a chorus loop without the reference beat going. I was maybe 20 milliseconds off&#8212;nothing you&#8217;d notice on the first repetition. But loops are precise. That tiny error compounds with each cycle. By the fourth time through, I was noticeably chasing or dragging against my own playing. </p><p>It&#8217;s disorienting in a way that&#8217;s hard to describe: you&#8217;re simultaneously ahead of and behind yourself.</p><h3><strong>You&#8217;re the Bandmate and the Conductor</strong></h3><p>Playing with loops feels remarkably like playing with a band&#8212;with one critical difference. When you mess up in a band, the other musicians keep going and you find your way back in. With loops, the band keeps going too, but <em>you&#8217;re</em> also responsible for conducting them with your feet.</p><p>Miss your cue to transition to the bridge? The loop stays locked in the chorus. Forever. Or until you manually break the cycle.</p><p>I found myself literally stuck in a loop during the bridge transition, my foot hovering over the pedal, trying to find the exact moment to switch parts while singing and playing guitar. It requires a kind of split attention that&#8217;s genuinely difficult: you&#8217;re performing for the audience while simultaneously managing a set of time-synchronized tracks that need precise coordination.</p><h3><strong>You Always Have the Option to Clear, and It&#8217;s Often a Good Idea</strong></h3><p>Sometimes the best recovery from a drifting loop is to blow it up and start over.</p><p>If you&#8217;re noticeably out of sync, trying to force your way back into alignment rarely works. You end up fighting yourself. Instead, I learned to keep playing the current section smoothly for the audience while quietly clearing the problematic loop in the background. Then, when the progression cycles back around, you lay down a fresh, properly-synced foundation.</p><h3><strong>The Blessing of Diatonic Harmony</strong></h3><p>While loops are unforgiving masters when it comes to tempo sync, they are also more forgiving than they seem, thanks to diatonic harmony.</p><p>Afterward, multiple people told me it sounded great and they didn&#8217;t notice a single mistake. How? The layers give you cover.</p><p>When you&#8217;re working within a diatonic framework&#8212;all your chords belong to the same key&#8212;even a slightly misaligned loop won&#8217;t sound dissonant. <br><br>The worst that happens is some rhythmic ambiguity or harmonic density that might actually sound intentional. Your verse chords and chorus chords are all swimming in the same tonal pool, so as long as you recover quickly, the ear tends to forgive the temporary confusion.</p><p>This doesn&#8217;t mean you can be sloppy. But it does mean that the margin for error is wider than it feels in the moment. The perfectionism that serves you in the studio can become paralyzing on stage.</p><h3><strong>Think About Looping Like a Mix</strong></h3><p>After the set, someone gave me a tip that should have been obvious but wasn&#8217;t: treat your loop layers like you would tracks in a mix.</p><p>In the studio, you don&#8217;t record everything at the same volume with the same tone. You adjust EQ, panning, dynamics&#8212;you carve out space for each element. The same principle applies to live looping, but you have to think about it <em>before</em> you hit record on each layer.</p><p>Switch pickups between layers. Move from playing near the bridge to playing near the neck. Adjust your volume knob. Play some parts with more attack, others with a softer touch. Each layer should sit in its own part of the sonic spectrum.</p><p>This was a revelation. I&#8217;d been thinking of looping as &#8220;record parts and stack them,&#8221; when I should have been thinking &#8220;how does this layer fit in the arrangement I&#8217;m building?&#8221; That rhythm part doesn&#8217;t need to be as loud as the melody. That bass line can be warmer and rounder. That harmonic fill can be brighter and more percussive.</p><p>You&#8217;re not just a performer when you&#8217;re looping&#8212;you&#8217;re also the engineer, making mix decisions in real-time with the only tools available: your hands, your pickup selector, and your volume knob.</p><h3><strong>The Paradox of Layers</strong></h3><p>Live looping presents a fascinating paradox. Each layer you add:</p><ul><li><p>Makes the arrangement richer and more forgiving</p></li><li><p>But also makes each individual mistake more consequential</p></li><li><p>Creates more sonic space to hide in</p></li><li><p>But also requires more precise coordination to manage</p></li></ul><p>You&#8217;re simultaneously more exposed and more protected than playing solo. It&#8217;s like being in a band where all the members are slightly out-of-phase versions of yourself.</p><h3><strong>What I&#8217;m Taking Forward</strong></h3><p>For next time: click track always on during foundation building. Practice the foot transitions as much as the musical parts. </p><p>Think about each layer&#8217;s place in the mix before recording it. </p><p>Trust the diatonic safety net, but don&#8217;t rely on it. </p><p>And most importantly, stay calm when things drift&#8212;the audience almost certainly won&#8217;t notice unless you show them you&#8217;re panicking.</p><p>Live looping is less like recording and more like a very controlled form of improvisation. You&#8217;re composing in real-time with a collaborator who remembers everything perfectly but can&#8217;t adapt. </p><p>You&#8217;re also mixing in real-time with tools far more limited than any DAW. It&#8217;s challenging in ways I didn&#8217;t expect, and rewarding in ways I&#8217;m still discovering.</p><p>The loop keeps going. You keep going. Sometimes that&#8217;s in perfect sync, and sometimes it&#8217;s not. But as long as you&#8217;re both moving forward, the audience hears a song.</p>]]></content:encoded></item><item><title><![CDATA[We Built Our Own ISP to Fix the Internet. A Decade Later, It’s Still Running.]]></title><description><![CDATA[The PEERING testbed received the Test of Time Award at the 2025 ACM Internet Measurement Conference.]]></description><link>https://practicespace.substack.com/p/we-built-our-own-isp-to-fix-the-internet</link><guid isPermaLink="false">https://practicespace.substack.com/p/we-built-our-own-isp-to-fix-the-internet</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Thu, 20 Nov 2025 21:20:42 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!VxQ8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When a major service provider like Amazon or Cloudflare goes offline because of a routing error, as has happened in recent weeks, network engineers have to fix a problem they can&#8217;t see. Somewhere in the Internet&#8217;s routing system, traffic is being sent to the wrong place&#8212;maybe halfway across the world. But studying these failures used to be impossible. You couldn&#8217;t experiment with Internet routing without being an Internet service provider (ISP) yourself.</p><p>The solution? Build your own testbed ISP.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>In 2014, we published &#8220;<a href="https://dl.acm.org/doi/10.1145/2670518.2673887">PEERING: An AS for Us</a>,&#8221; describing a testbed that let researchers experiment with the Internet&#8217;s routing infrastructure for the first time. That work recently received the Test of Time Award from the ACM SIGCOMM Internet Measurement Conference. (The term &#8220;AS&#8221; in the paper&#8217;s title refers to &#8220;Autonomous System&#8221;, which is a technical term for an independently operated network like an ISP).</p><p>The project started under <a href="https://en.wikipedia.org/wiki/Global_Environment_for_Network_Innovations">GENI (Global Environment for Network Innovations)</a>, an NSF-funded program with an ambitious goal: design a future Internet architecture. GENI built infrastructure to let researchers experiment with networking at scale. The system that eventually became PEERING was called <a href="http://conferences.sigcomm.org/sigcomm/2010/papers/sigcomm/p463.pdf">Transit Portal</a>, infrastructure that my Ph.D. student <a href="https://www.linkedin.com/in/vytautas-valas-valancius-6aa382">Valas Valancius</a> and I developed at Georgia Tech to give researchers access to interdomain routing.<br></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VxQ8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VxQ8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png 424w, https://substackcdn.com/image/fetch/$s_!VxQ8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png 848w, https://substackcdn.com/image/fetch/$s_!VxQ8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png 1272w, https://substackcdn.com/image/fetch/$s_!VxQ8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VxQ8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png" width="740" height="758" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:758,&quot;width&quot;:740,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VxQ8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png 424w, https://substackcdn.com/image/fetch/$s_!VxQ8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png 848w, https://substackcdn.com/image/fetch/$s_!VxQ8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png 1272w, https://substackcdn.com/image/fetch/$s_!VxQ8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfc20b7e-276a-4c77-9ed8-ed7cd148c82b_740x758.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The GENI and FIND programs had a vision of letting researchers actually experiment with Internet infrastructure and architectures, not just simulate it. I had this idea that it should be possible to experiment with Internet routing on the real Internet. Transit Portal was our way of making that a reality. Actually getting it working&#8212;building the control plane, the safety mechanisms, the whole system&#8212;was a huge design and implementation lift. Valas really got it off the ground.</p><p>Transit Portal leveraged Internet Exchange Points (IXPs), the points in the Internet where networks connect to exchange traffic directly. By connecting to other service providers directly at IXPs, the testbed could peer with hundreds of networks and announce routes just like a real ISP. But the Transit Portal also needed safeguards. Servers sat between researchers and the live network, filtering routes and enforcing policies so a bad experiment couldn&#8217;t break anything.</p><p>The challenge wasn&#8217;t just technical. We had to convince operators at major IXPs like AMS-IX in Amsterdam to let us plug academic research infrastructure into their production network. That required trust, and we had to earn it.</p><p>After the GENI program ended, Transit Portal might have disappeared like so many research prototypes do when funding ends and students graduate. Instead, Professor <a href="http://www.columbia.edu/~ebk2141/">Ethan Katz-Bassett</a> and his team at USC, and later at Columbia, took over leadership of the project and continue to maintain it to this day. They expanded it to more IXPs, maintained the infrastructure, developed new capabilities, and continue to actively support the research community&#8217;s use of the testbed. <br><br>PEERING has flourished because of Ethan and his team. They&#8217;ve kept it running for more than a decade, expanded it, and supported the research community. That sustained effort&#8212;deploying at IXPs, maintaining the system, making it possible for so many researchers to actually use it&#8212;that&#8217;s why the work has stood the test of time. They deserve enormous credit. This work has stood the test of time and remains one of the main lasting, impactful legacies of the GENI program, in large part due to Ethan&#8217;s ongoing dedication to the project, as well as many other students and researchers who have continued to extend and support the work.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6Ifc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6Ifc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png 424w, https://substackcdn.com/image/fetch/$s_!6Ifc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png 848w, https://substackcdn.com/image/fetch/$s_!6Ifc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png 1272w, https://substackcdn.com/image/fetch/$s_!6Ifc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6Ifc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png" width="1271" height="725" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:725,&quot;width&quot;:1271,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6Ifc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png 424w, https://substackcdn.com/image/fetch/$s_!6Ifc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png 848w, https://substackcdn.com/image/fetch/$s_!6Ifc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png 1272w, https://substackcdn.com/image/fetch/$s_!6Ifc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb29c83df-eb51-4348-88cc-885cba9b51e9_1271x725.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The testbed enabled research that wasn&#8217;t possible before: <a href="https://dl.acm.org/doi/10.1145/2377677.2377756">systems for repairing routing failures</a>, <a href="https://sites.cs.ucsb.edu/~arpitgupta/pdfs/sdx.pdf">prototypes for software-defined Internet exchanges</a>, and <a href="https://www.youtube.com/watch?v=ROCp9FoMNt8">tools for diagnosing path changes</a>. It&#8217;s still being used today. Transit Portal, and ultimately PEERING, demonstrated that the Internet&#8217;s core could be studied experimentally, not just observed from the outside. In some sense, this is the lasting legacy of the work, as well&#8212;that Internet researchers can improve the Internet by building systems that interact with the live network, going beyond the simulation-based experiments that were the <em>de facto</em> mode of operation prior to Transit Portal and GENI.</p><p>The impact goes beyond just the testbed itself. We demonstrated that it was possible to do empirical research on the Internet&#8217;s routing infrastructure. Prior to Transit Portal and PEERING, the predominant mode of understanding Internet routing was through simulation or theory, both of which had significant shortcomings when translated to practice. We showed that it was possible to conduct experimental research on critical infrastructure if you build the right guardrails. That principle applies to everything I work on to this day, whether it is network security and privacy, performance monitoring and inference, or machine learning models for networks. Ultimately, lasting impact in this field requires building and measuring deployed systems.&#8221;</p><p>Check out our ongoing research at the <a href="https://noise.cs.uchicago.edu/">Network Operations and Internet Security Lab</a>, focusing on AI- and data-driven security, privacy, and auditing in networked systems.</p>]]></content:encoded></item><item><title><![CDATA[Introducing netml.io: A Hub for AI-Driven Networking Research and Technology]]></title><description><![CDATA[Bringing together two decades of research on Machine Learning for Networks.]]></description><link>https://practicespace.substack.com/p/introducing-netmlio-a-hub-for-ai</link><guid isPermaLink="false">https://practicespace.substack.com/p/introducing-netmlio-a-hub-for-ai</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Wed, 19 Nov 2025 21:15:45 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!N0EN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!N0EN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!N0EN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!N0EN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!N0EN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!N0EN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!N0EN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png" width="728" height="432.25" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/efd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!N0EN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!N0EN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!N0EN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!N0EN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd1c579-a1ec-4c04-9184-ae7f952b5b2f_1024x608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"></figcaption></figure></div><p>This month marks the 20-year anniversary of the beginning of our first research project on applications of machine learning to networking, <a href="https://dl.acm.org/doi/10.1145/1159947">Understanding the Network-Level Behavior of Spammers</a>.</p><p>Since 2006, we&#8217;ve been pioneering the application of machine learning to networking problems.</p><blockquote><p>Today, we are excited to announce <strong><a href="https://netml.io/">netml.io</a></strong>&#8212;a research initiative that brings together two decades of work at the intersection of ML and networking, from security applications to performance analysis to synthetic traffic generation.</p></blockquote><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Practice Space! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h1>Announcing netml.io</h1><p><a href="https://netml.io/">netml.io</a> is the home for all things at the intersection of networks and AI&#8212;a comprehensive resource for researchers, practitioners, and students working in this space. <br><br>The goals of the project include:</p><ul><li><p><strong>Open-source tools</strong>: Implementations of <a href="https://netml.io/projects/3-netdiffusion/">NetDiffusion</a>, <a href="https://netml.io/projects/3-netdiffusion/">NetSSM</a>, <a href="https://netml.io/projects/5-traffic-refinery/">Traffic Refinery</a>, and related traffic generation and analysis tools available on <a href="https://github.com/noise-lab">GitHub</a></p></li><li><p><strong>Datasets and benchmarks</strong>: Curated resources for common ML tasks in networking, making it easier to train and evaluate models</p></li><li><p><strong>Research collaborations</strong>: Partnerships with industry and academia to tackle real-world problems at the intersection of AI and networking.</p></li><li><p><strong>Educational resources</strong>: We&#8217;re developing comprehensive teaching materials including a forthcoming book on AI and ML for networking, an online course based on our <a href="https://noise-lab.net/ml-systems/">ML Systems course materials</a>, and tutorials and practical guides for applying ML to network analysis.</p></li><li><p><strong>Community hub</strong>: A central place for the networks + AI community to share ideas, code, and datasets</p></li></ul><p>The <a href="https://netml.io/">netml.io</a> website brings together decades of research applying AI to networking problems and datasets. Read on for a history of the project.</p><h2>Machine Learning for Network Security (2006-2009)</h2><p>The NetML story begins in 2006, when we were among the first to apply machine learning to network security problems. Our early work focused on understanding and combating spam and botnets at the network level. Rather than just looking at email content, we analyzed network-level behavior&#8212;examining patterns in how messages were sent, identifying spamming infrastructures, and detecting botnet membership through DNS blacklist reconnaissance.</p><p>This collection of work on &#8220;behavioral blacklisting&#8221;, starting with this initial SIGCOMM paper, showed that network-level features were far more difficult for attackers to manipulate than message content. The <a href="https://dl.acm.org/doi/10.1145/1159947">SIGCOMM 2006 paper</a> on understanding spammers&#8217; network-level behavior became foundational work in the field, demonstrating how ML could identify malicious activity from traffic patterns alone. The paper won a Best Paper Award and formed the basis for a Presidential Early Career Award for Scientists and Engineers (PECASE) in 2008 for contributions at the intersection of AI and cybersecurity.</p><p>The key observation behind the initial work was simple: attackers behave differently from legitimate senders, and those differences are evident in network traffic and other signals evident in network data. By examining features like AS numbers, geodesic distance between sender and receiver, sending patterns across time, and recipient clustering, we could distinguish malicious from legitimate traffic without ever looking at message content. <br><br>During this period, we also developed techniques for <a href="https://dl.acm.org/doi/10.1145/1298455.1298466">characterizing botnets from email spam records</a> and <a href="https://dl.acm.org/doi/10.1145/1159935.1159948">detecting botnet membership using DNS blacklist counter-intelligence</a>.</p><p>Our initial insight was simple but profound, and one that has ultimately stood the test of time and formed the basis of much of our work over the past two decades: networks contain rich signals that machine learning can exploit for a wide variety of inference problems in security, performance, and resource allocation.</p><h2>Deploying ML in Practice (2009-2016)</h2><p>Our spam and botnet detection work quickly moved from research to real-world deployment. In 2009, we developed <strong><a href="https://www.usenix.org/legacy/events/leet09/tech/full_papers/hao/hao_html/">SNARE</a></strong><a href="https://www.usenix.org/legacy/events/leet09/tech/full_papers/hao/hao_html/"> (Spatio-temporal Network-level Automatic Reputation Engine)</a>, an automated system that could identify spammers with over 94% accuracy and just 2% false positives using only network-level features. SNARE was designed to work as a lightweight &#8220;pre-acceptance&#8221; classifier&#8212;fast enough to make decisions before even accepting an email connection. SNARE was deployed at Cisco/IronPort and Secure Computing, demonstrating that network-level ML could work at scale in commercial email security products.</p><p>We also developed <strong><a href="https://dl.acm.org/doi/10.1145/1402946.1402974">WISE</a></strong><a href="https://dl.acm.org/doi/10.1145/1402946.1402974"> (What-If Scenario Evaluator)</a>, which used statistical learning to predict the effects of configuration and deployment changes in content distribution networks. WISE was deployed at Google, where it helped evaluate &#8220;what-if&#8221; scenarios for network changes without requiring expensive real-world experiments.</p><p>During this period, our research applying machine learning to botnet detection led to the founding of <strong>Damballa</strong>, a startup based on our research on DNS-based botnet detection. Damballa&#8217;s core technology used machine learning algorithms to identify the unique traffic patterns and communication signatures that botnets generate as they interact with command-and-control servers. By monitoring DNS queries for anomalous patterns&#8212;like the Non-Existent Domain (NXDomain) responses generated by domain generation algorithms (DGAs)&#8212;Damballa could detect botnet infections weeks before traditional signature-based approaches.</p><p>Damballa grew rapidly, eventually <a href="https://gra.org/company/26/Damballa.html">monitoring nearly 15% of global Internet traffic and protecting over half a billion devices</a> for enterprise customers, ISPs, and telecommunications providers. The company&#8217;s <a href="https://www.businesswire.com/news/home/20110620005271/en/Damballa%C2%AE-FirstAlert-Detects-Cyber-Threats-Weeks-Before-the-Malware-is-Ever-Discovered">FirstAlert service could detect threats 30 days earlier on average</a> than conventional malware detection systems. This work demonstrated that academic research in ML for networking could translate directly into commercial impact.Early Warning Systems (2012-2016)</p><p>As attackers evolved, so did our detection methods. By 2012-2016, we were working on <strong><a href="https://dl.acm.org/doi/10.1145/2976749.2978317">PREDATOR</a></strong><a href="https://dl.acm.org/doi/10.1145/2976749.2978317"> (Proactive Recognition and Elimination of Domain Abuse at Time-Of-Registration)</a>, which took an even more proactive approach: detecting malicious domains <em>before</em> they were used for harm.</p><p>The insight was that malicious actors exhibit different registration behavior than legitimate users&#8212;bulk purchasing domains to take advantage of discounts, registering many similar domains at once, and using specific patterns in registration information. By analyzing these behavioral signals at registration time, PREDATOR could identify potentially malicious domains with 70% detection rate and only 0.35% false positives, all before the domains had been used for any attacks.</p><p>This work was also featured in <a href="https://www.wsj.com/">Wall Street Journal</a> CIO and resulted in several <a href="https://patents.google.com/patent/US8713676B2">patents</a>, showing that ML could provide early warning systems for network security&#8212;catching threats in their planning stages rather than waiting for them to cause damage. The proactive approach represented a fundamental shift from reactive signature-based detection to predictive, behavior-based prevention.</p><h2>Inference from Encrypted Network Traffic (2017-2020)</h2><p>By 2017, encryption was becoming ubiquitous, and network traffic also became increasingly encrypted&#8212;certainly a win for privacy, but a challenge for network management and security. At this time, we started to encounter questions concerning what we could learn about network traffic when we can&#8217;t see the data inside the packets themselves. The rise of encryption led to a new research direction: inference from encrypted network traffic. <br><br>At the intersection of ML and privacy, we demonstrated that even encrypted IoT device traffic could reveal sensitive user activities through traffic analysis. Our work on <a href="https://arxiv.org/abs/1705.06805">IoT privacy</a> showed that a Sense sleep monitor&#8217;s traffic patterns could reveal when someone was in bed, and that an Amazon Echo&#8217;s traffic could indicate when users were speaking to it&#8212;all without decrypting a single packet. We also developed <a href="https://arxiv.org/abs/1812.00955">traffic shaping techniques</a> to protect smart home privacy.</p><p>In the area of network performance and management, we developed developed techniques to <a href="https://arxiv.org/abs/1901.05800">infer video streaming quality</a> (startup delay, resolution) from encrypted Netflix, YouTube, Amazon, and Twitch traffic. This work, featured on the <a href="https://www.wsj.com/graphics/faster-internet-not-worth-it/">front page of the Wall Street Journal in 2019</a>, showed that ML models could provide ISPs with visibility into application performance even as encryption spread across the Internet. The study demonstrated that premium internet speeds above 100 Mbps provide little benefit for video streaming&#8212;valuable information for both consumers and network operators.</p><h2>Making ML Practical: Cost-Aware Representations (2020-2023)</h2><p>As our ML models became more sophisticated, we confronted a new challenge: deploying them at scale. A critical first step was developing better representations of network traffic for machine learning. <br><br>In 2020, we developed <strong><a href="https://nprint.github.io/nprint/">nPrint</a></strong>, a standard packet-based representation that was the first system to successfully apply deep learning models directly to raw network traffic without manual feature engineering. nPrint represents packets as standardized bitmaps, enabling convolutional neural networks and other deep learning architectures to automatically discover important features (like IP TTL, window size, protocol fields) across diverse tasks including device fingerprinting, operating system detection, and application identification. Combined with automated machine learning (AutoML), <a href="https://dl.acm.org/doi/10.1145/3460120.3484758">nPrint achieved higher performance</a> than state-of-the-art hand-engineered approaches while being generalizable across multiple traffic analysis problems.</p><p>Building on this foundation, we developed <strong><a href="https://dl.acm.org/doi/10.1145/3447382">Traffic Refinery</a></strong> (2020), which explored the fundamental tradeoff between model accuracy and computational cost. We showed that different ML tasks benefit from different representations of network traffic&#8212;some need raw packet data, others can work with flow statistics&#8212;and built a framework for automatically selecting cost-effective representations.</p><p>This work on cost-aware data representation was crucial because real networks need to analyze traffic at line rate (10+ Gbps). The most accurate model is useless if it can&#8217;t keep up with traffic.</p><p>We also developed techniques for handling concept drift (<strong><a href="https://dl.acm.org/doi/10.1145/3624354.3630585">LEAF</a></strong>, 2023), recognizing that network traffic patterns change over time as applications evolve, new protocols emerge, and user behaviors shift. Our work on multimodal inference (<strong><a href="https://dl.acm.org/doi/10.1145/3580857">AMIR</a></strong>, 2023) showed how combining network data with other signals could improve robustness and accuracy.</p><h2>Dynamic Model Execution: Adapting in Real-Time (2023-2024)</h2><p>Recent work has focused on making ML-based traffic analysis adaptive and efficient through dynamic model execution&#8212;systems that intelligently adapt to changing network conditions and computational constraints in real-time. The core insight: not all traffic is equally difficult to classify. A high-confidence prediction from a simple model is just as valuable as one from a complex model, but costs far less.</p><ul><li><p><strong><a href="https://www.shinan.info/">JITI</a></strong> (Dynamic Model Serving for Just-in-Time Traffic Inference): An adaptive ensemble classification framework that dynamically selects which models to use based on traffic characteristics. JITI efficiently manages a pool of classifiers with different performance and cost profiles, using an adaptive scheduler that tracks system memory availability and incoming traffic rates to determine the optimal classifier and batch size.</p></li><li><p><strong><a href="https://arxiv.org/abs/2402.03694">ServeFlow</a></strong>: A fast-slow model architecture that recognizes a key insight: inference time across models can differ by up to 141&#215;, while inter-packet waiting time is up to 6-8 orders of magnitude higher than inference time. ServeFlow routes traffic through a &#8220;fast&#8221; model first, assigning flows to a &#8220;slow&#8221; (more accurate) model only when the fast model&#8217;s predictions show high uncertainty. The system achieves a 40.5&#215; speedup on median end-to-end serving latency while maintaining comparable accuracy, processing over 48.5k new flows per second on a 16-core CPU&#8212;matching the order of magnitude of flow rates observed on city-level network backbones.</p></li><li><p><strong><a href="https://arxiv.org/abs/2412.15146">Cruise Control</a></strong>: A system-driven approach to dynamically select the best ML model for network traffic analysis based on real-time system performance and network load. Rather than selecting an optimal model offline, Cruise Control pre-trains several models with different accuracy-cost tradeoffs and continuously adapts model selection based on lightweight signals representing the system&#8217;s current traffic processing state. Evaluation on real-world traffic analysis tasks shows Cruise Control improves median accuracy by 2.78% while reducing packet loss by a factor of four compared to offline-selected models.</p></li><li><p><strong><a href="https://arxiv.org/abs/2402.06099">CATO</a></strong> (End-to-end Optimization): A framework that jointly optimizes both the predictive performance and the systems costs of ML-based traffic analysis pipelines. CATO leverages multi-objective Bayesian optimization to efficiently identify Pareto-optimal configurations across feature selection and packet capture depth, then automatically compiles end-to-end optimized serving pipelines. Compared to popular feature optimization techniques, CATO provides up to 3,600&#215; lower inference latency and 3.7&#215; higher zero-loss throughput while simultaneously achieving better model performance.</p></li></ul><p>Together, these systems represent a fundamental shift in how we think about ML deployment for networking: from static, one-size-fits-all models to adaptive systems that intelligently balance accuracy, throughput, and latency based on real-time conditions.</p><h2>Synthetic Data Generation: Generative AI for Networks (2023-Present)</h2><p>Which brings us to our current focus: generative AI for networks. The challenge that motivated this work was fundamental&#8212;how do we train better ML models when we can&#8217;t easily share network traffic data due to privacy concerns and data staleness?</p><p>In the <strong><a href="https://cs.uchicago.edu/news/university-of-chicago-researchers-revolutionize-network-traffic-generation-with-ai-breakthrough/">GATEAU</a></strong><a href="https://cs.uchicago.edu/news/university-of-chicago-researchers-revolutionize-network-traffic-generation-with-ai-breakthrough/"> (Generative AI for Traffic Engineering and Network Understanding)</a> project, we&#8217;ve been developing tools that use generative AI to create realistic, privacy-preserving synthetic network traffic:</p><ul><li><p><strong><a href="https://arxiv.org/abs/2310.08543">NetDiffusion</a></strong> applies diffusion models&#8212;the same technology behind Stable Diffusion for images&#8212;to generate high-fidelity, protocol-compliant network traffic. It doesn&#8217;t just produce flow statistics; it creates actual packet captures (.pcap files) that work with standard tools like Wireshark and tshark. Critically, models trained on NetDiffusion synthetic data outperform those trained on data from existing GAN-based approaches. As we noted in our <a href="https://cs.uchicago.edu/news/university-of-chicago-researchers-revolutionize-network-traffic-generation-with-ai-breakthrough/">recent announcement</a>, &#8220;NetDiffusion represents a breakthrough in generating realistic, protocol-compliant traffic, overcoming long-standing data access challenges and opening new possibilities for AI-driven security and network traffic analysis.&#8221;</p></li><li><p><strong><a href="https://arxiv.org/abs/2503.22663">NetSSM</a></strong> uses state space models to generate multi-flow network traces, capturing temporal dependencies across concurrent flows.</p></li></ul><h2>Looking Ahead</h2><p>Machine learning has become essential for modern network management&#8212;from detecting intrusions to optimizing performance to ensuring quality of experience. But the field faces a data crisis:</p><ul><li><p>Privacy regulations restrict data sharing</p></li><li><p>Network protocols and applications evolve rapidly</p></li><li><p>Collecting and labeling network traces is expensive</p></li><li><p>Datasets become stale quickly</p></li></ul><p>Synthetic data generation addresses these challenges head-on. High-quality synthetic traffic can supplement real data, handle class imbalance, and enable experimentation without privacy concerns.</p><h2>Announcing netml.io</h2><p>netml.io formalizes and extends this research program. </p><p>Ultimately, we aim to make it easier for researchers and practitioners to work on ML problems in networking by providing easier access to datasets and code that we have developed throughout the years, so that we can grow the community of researchers working in this area and continue to advance the discipline.</p><h2>What&#8217;s Next</h2><p>We&#8217;re actively working on:</p><ul><li><p>Extending generative models to more protocols and network conditions</p></li><li><p>Real-time deployment of ML models for security and performance monitoring</p></li><li><p>Federated learning approaches that enable collaborative training without sharing sensitive data</p></li><li><p>Understanding and addressing fairness and equity issues through ML-based Internet measurement</p></li></ul><h2>Join Us</h2><p>This work has always been collaborative, involving talented students, postdocs, and industry partners. If you&#8217;re working at the intersection of ML and networking&#8212;in security, performance, traffic engineering, or measurement&#8212;let&#8217;s connect.</p><p>The networks of the future will be intelligent. The <a href="https://netml.io/">netml.io</a> project is dedicated to advancing this future together, as a community.</p><div><hr></div>]]></content:encoded></item><item><title><![CDATA[What Building an MCP for Music Composition Taught Me About Debugging AI Agents]]></title><description><![CDATA[When outputs aren't as expected, applying domain knowledge about expected outputs remains a critical step. And specifications remain as important as ever.]]></description><link>https://practicespace.substack.com/p/what-building-an-mcp-for-music-composition</link><guid isPermaLink="false">https://practicespace.substack.com/p/what-building-an-mcp-for-music-composition</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Mon, 17 Nov 2025 05:26:59 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!cELe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://practicespace.substack.com/subscribe?"><span>Subscribe now</span></a></p><p>One of my recent side projects has been building an MCP (Model Context Protocol) server for my Elektron Digitakt&#8212;essentially teaching Claude to control my sampler and drum machine through conversation. </p><p>It&#8217;s been an amazing playground for exploring how LLMs handle complex, domain-specific tasks. But it&#8217;s also exposed some fundamental challenges in how these systems reason about context, state, and when to think versus when to act.</p><p>Last week, I hit a particularly instructive bug: an infinite loop that perfectly captured the overthinking problem plaguing current LLM agent systems.</p><h2>The Bug: The MCP &#8220;Infinite Loop&#8221;</h2><p>I was trying to automate parameter changes over a 16-bar musical phrase. The system kept passing an empty dictionary. Then it would detect the error, attempt to fix it, fail to fix it correctly, detect the same error again, attempt another fix&#8212;forever. Claude Desktop would have looped indefinitely if I hadn&#8217;t manually intervened.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cELe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cELe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png 424w, https://substackcdn.com/image/fetch/$s_!cELe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png 848w, https://substackcdn.com/image/fetch/$s_!cELe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png 1272w, https://substackcdn.com/image/fetch/$s_!cELe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cELe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png" width="670" height="501" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:501,&quot;width&quot;:670,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:91801,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/179111733?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cELe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png 424w, https://substackcdn.com/image/fetch/$s_!cELe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png 848w, https://substackcdn.com/image/fetch/$s_!cELe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png 1272w, https://substackcdn.com/image/fetch/$s_!cELe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe88409f5-bf68-4839-a4d6-77e8b7cb67e8_670x501.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The actual problem? The automation was only populating the first 4 bars of the dictionary, leaving bars 5-16 empty. I could <em>hear</em> this&#8212;I&#8217;d asked for something to happen over 16 bars, and it only happened over 4. The 16-bar loop played, but the parameter automation stopped after the first 4 bars.</p><h2>How I Debugged the MCP</h2><p>Here&#8217;s roughly what the debugging process looked like:</p><ol><li><p><strong>Desktop Claude</strong> hit the infinite loop</p></li><li><p>I stopped it and switched to <strong>Claude Code</strong></p></li><li><p>I asked: &#8220;Here&#8217;s what&#8217;s happening. Tell me what&#8217;s causing this infinite looping.&#8221;</p></li><li><p>Claude Code suggested a specific data structure to pass</p></li><li><p>I went back to <strong>Desktop Claude</strong> and said: &#8220;Here&#8217;s the data structure I want you to pass. Try that.&#8221;</p></li><li><p>It sort of worked</p></li><li><p>I asked Desktop Claude: &#8220;Tell me what would help you not infinite loop.&#8221;</p></li><li><p>It responded: &#8220;What would help me is an accurate description of this function in the MCP function description.&#8221;</p></li><li><p>I went back to <strong>Claude Code</strong> and worked on improving the function description</p></li><li><p>Finally, it worked</p></li></ol><p>The whole process took about an hour. Without AI assistance, it would have taken a day. </p><p>But here&#8217;s the key insight: <em>I</em> had to know what was causing the problem at each step. I had to notice: &#8220;You&#8217;re overthinking a simple query,&#8221; or &#8220;You&#8217;re in a loop,&#8221; or &#8220;Show me the dictionary structure.&#8221; </p><p>I had to reason about <em>why</em> parameter automation over 16 bars was only executing over 4 bars, connect that to the empty dictionary complaint, and guide the debugging process.</p><h2>Domain Knowledge About Outputs is Critical</h2><p>Having a tangible, audible application made learning faster. This reminds me of my undergrad EE days&#8212;there&#8217;s something powerful about debugging something you can hear versus just looking at code on a screen. </p><p>When I hear a 16-bar loop but only hear parameter changes in the first 4 bars, the bug becomes obvious. The domain knowledge becomes a debugging superpower.</p><h2>Enter Semantic Router</h2><p>This experience maps perfectly onto a research project I&#8217;ve started to explore with a Ph.D. student. He recently pointed me at the <a href="https://github.com/aurelio-labs/semantic-router">Semantic Router project</a> from the Aurelio Labs team, which tackles exactly these problems in agentic systems.</p><p>The main problem: current LLM systems <strong>overthink simple queries and underthink complex ones</strong>.</p><p>I encounter both failure modes constantly:</p><ul><li><p><strong>Overthinking simple queries</strong>: I ask Claude to summarize something that&#8217;s right in front of it in context. Instead, it goes off to fetch additional sources. &#8220;No, it&#8217;s right here. Stop. You&#8217;ve already done it.&#8221;</p></li><li><p><strong>Underthinking complex queries</strong>: The music automation bug is a perfect example. The system needed to reason more carefully about state across a 16-bar phrase but instead rushed to a broken solution and then got stuck in a loop.</p></li></ul><p>Semantic Router addresses this by using application state to enable correct inference. The project focuses on:</p><ul><li><p><strong>Cache persistence</strong> across multiple stages of the same LLM call</p></li><li><p><strong>Failure recovery</strong> from incorrect MCP server responses</p></li><li><p><strong>Request routing</strong> to ensure sub-requests from the same session hit the same endpoint</p></li><li><p><strong>Query classification</strong> to allocate the right computational resources</p></li></ul><h2>What&#8217;s Missing: Domain-Specific Knowledge</h2><p>Current semantic routing abstractions classify queries as &#8220;simple versus complex.&#8221; But they don&#8217;t yet leverage <strong>application-specific knowledge</strong>.</p><p>In my music MCP debugging session, the relevant signal was: &#8220;Only 4 out of 16 bars were populated.&#8221; That&#8217;s music-specific knowledge, and something I could hear directly from the output. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5uCa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5uCa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png 424w, https://substackcdn.com/image/fetch/$s_!5uCa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png 848w, https://substackcdn.com/image/fetch/$s_!5uCa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png 1272w, https://substackcdn.com/image/fetch/$s_!5uCa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5uCa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png" width="569" height="792" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:792,&quot;width&quot;:569,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:143148,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/179111733?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5uCa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png 424w, https://substackcdn.com/image/fetch/$s_!5uCa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png 848w, https://substackcdn.com/image/fetch/$s_!5uCa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png 1272w, https://substackcdn.com/image/fetch/$s_!5uCa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c3d68-a92e-409a-81ed-4588cea7190a_569x792.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>If I could pass that insight and domain-specific knowledge to the LLM or to a routing system in the right interface, it might be able reason correctly from the start.</p><p>While I encountered this mismatch in my own experience, it is evident how it can also rise in other domains:</p><ul><li><p><strong>Art generation</strong>: A query specifies &#8220;warm earth tones&#8221; but the model generates cool blues and purples. The color palette constraint is domain knowledge that should guide inference.</p></li><li><p><strong>Network debugging</strong>: A query about packet loss should trigger different reasoning than a query about DNS resolution, even if both are phrased as &#8220;connection problems.&#8221;</p></li><li><p><strong>Code debugging</strong>: Information about which data structures are populated or empty (like my dictionary) should influence how the LLM approaches the problem.</p></li></ul><h2>Research: <br>Debugging Agents with Domain Knowledge</h2><p>The opportunity here is to bridge semantic routing with domain-specific knowledge extraction:</p><ol><li><p><strong>Automated domain signal extraction</strong>: Can we automatically extract relevant domain signals from queries (like &#8220;16 bars&#8221; in my music example) and use them to guide inference?</p></li><li><p><strong>User-in-the-loop feedback</strong>: When I told Claude &#8220;you only populated 4 bars,&#8221; that&#8217;s a valuable debugging signal. Can we formalize interfaces for users to provide this kind of application-specific feedback?</p></li><li><p><strong>Multi-modal domain knowledge</strong>: In my case, the audible output was the debugging signal. For network measurement, it might be latency graphs. For image generation, visual output. How do we incorporate multi-modal domain signals into semantic routing?</p></li><li><p><strong>MCP-to-MCP debugging</strong>: I developed a pattern of bouncing between Desktop Claude (executing MCP calls) and Claude Code (debugging the MCP server code). Can we formalize this pattern? Passing error messages and context between different Claude instances dramatically sped up debugging.</p></li></ol><h2>Why This Matters for Education and Research</h2><p>This work sits at an interesting intersection. </p><p>From an education perspective, these experiences reinforce why reasoning skills remain critical&#8212;I can immediately tell when the LLM is going off the rails. From a research perspective, there&#8217;s fundamental ML work to be done on how domain knowledge should flow into semantic routing systems.</p><p>Agentic workflow papers at the upcoming HotNets workshop this week are exploring related ideas&#8212;using LLM agents for network measurement research, for example. But I suspect the real breakthroughs will come from figuring out how to inject domain expertise into the routing and reasoning process itself. </p><blockquote><p>Putting together an agentic workflow is the easy part. Figuring out how to debug it when the outputs aren&#8217;t as expected is the true challenge.</p></blockquote><h2>Try It Yourself</h2><p>If you&#8217;re building MCP servers or working with agentic LLM systems, I highly recommend:</p><ol><li><p>Choose a domain with tangible, observable outputs (music, images, network measurements)</p></li><li><p>Pay attention to when the LLM overthinks versus underthinks</p></li><li><p>Document the domain-specific signals that help <em>you</em> debug</p></li><li><p>Experiment with bouncing between different Claude instances for debugging</p></li></ol><p>The bugs are frustrating, but they&#8217;re also revealing fundamental limitations in how these systems reason. And that makes them excellent research opportunities.</p><div><hr></div><p><em>What domain-specific knowledge do you wish you could pass to your LLM agents? Let me know in the comments or reach out&#8212;I&#8217;d love to hear about your debugging experiences.</em></p>]]></content:encoded></item><item><title><![CDATA[AI and the Spectrum of Creation: A Case Study in Songwriting]]></title><description><![CDATA[Five Songs, One Question: Where Does the Human End and the Machine Begin?]]></description><link>https://practicespace.substack.com/p/ai-creativity-and-the-spectrum-of</link><guid isPermaLink="false">https://practicespace.substack.com/p/ai-creativity-and-the-spectrum-of</guid><dc:creator><![CDATA[Nick Feamster]]></dc:creator><pubDate>Mon, 10 Nov 2025 05:47:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ZrEb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://practicespace.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://practicespace.substack.com/subscribe?"><span>Subscribe now</span></a></p><p>I was asked to give a guest lecture for Family Weekend at the University of Chicago this past weekend. Instead of diving into network protocols or cybersecurity frameworks, I picked up my guitar.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZrEb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZrEb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png 424w, https://substackcdn.com/image/fetch/$s_!ZrEb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png 848w, https://substackcdn.com/image/fetch/$s_!ZrEb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png 1272w, https://substackcdn.com/image/fetch/$s_!ZrEb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZrEb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png" width="1456" height="815" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:815,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2273994,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://practicespace.substack.com/i/178471289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZrEb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png 424w, https://substackcdn.com/image/fetch/$s_!ZrEb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png 848w, https://substackcdn.com/image/fetch/$s_!ZrEb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png 1272w, https://substackcdn.com/image/fetch/$s_!ZrEb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4b70889-ff1b-41e3-82e7-b7b477378aab_1926x1078.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I couldn&#8217;t decide whether to talk about generative AI, policy, content moderation, so I decided to combine all of these topics and use another passion of mine&#8212;music&#8212;as the lends to pose various questions about the role of AI in creation. </p><p>I gave a talk about AI, creativity, and copyright&#8212;topics that have been swirling around in my head as I&#8217;ve watched these tools reshape everything from my students&#8217; coding habits to my own songwriting process. And I figured the best way to cut through all the hype and anxiety was to run an experiment.</p><div id="youtube2-Bli5yWui90A" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;Bli5yWui90A&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/Bli5yWui90A?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><h2>The Hook: Can You Spot AI in a Song?</h2><p>The main hook for the lecture was that I played excerpts of five songs for the audience. All of them I wrote, for some definition of the word &#8220;wrote&#8221;.  (For the record, I generally do not use much AI in my own songwriting, typically stopping at #2 on this spectrum below, but for this lecture, I used Suno to create a couple of songs and then learned them on my guitar for the purposes of the experiment/demonstration).</p><p>The central question: which ones involved AI, and how much? </p><p><strong>Song 1: Pure human.</strong> I wrote this one unassisted&#8212;lyrics, melody, chord progression, etc., with no AI anywhere in the process. </p><p><strong>Song 2: LLM lyric assist.</strong> I had most of the song written, but there I had a particular couplet that just wasn&#8217;t landing. I had the imagery but I didn&#8217;t have quite the right words. So I described what I was going for to ChatGPT, and it gave me various images like &#8220;cobblestones&#8221;&#8212;exactly the mood I wanted but couldn&#8217;t articulate. AI helped me find words and imagery that I ultimately selected to integrate into my lyrics. In my view, this was very similar to what Jeff Tweedy describes as a &#8220;word ladder&#8221; in his book How to Write One Song. They main difference is that instead of having completely random words, I asked for words that matched the theme and lyrics that I had already largely composed.</p><p><strong>Song 3: Claude completes the progression.</strong> For this one, I took a D minor 6 - D major progression and fed the beginning of the chord progression into Claude. &#8220;Finish this for me,&#8221; I said. It gave me a really cool sounding Bb maj7 to A7 progression to complete the progression and even explained to me. Everything else&#8212;the melody, the lyrics, the arrangement, and even the other progressions in the song&#8212;was mine. But I wrote a lot around this foundation.</p><p><strong>Song 4: Suno from my lyrics.</strong> I took lyrics that I wrote for a completed song, threw them at Suno, and said &#8220;make me a song with these lyrics&#8221;, generally describing a lo-fi dream-pop vibe. Then I learned it and performed it. The lyrics were mine. The music, melodies, and chords? That came from the model. But the performance, the interpretation&#8212;that was all human again.</p><p><strong>Song 5: Full Prompt-Based AI.</strong> I prompted Suno with nothing but a vague idea and let it generate everything&#8212;lyrics, melody, arrangement. Then I learned it well enough to perform it. This is what people typically think about when we hear the phrase &#8220;AI-generated&#8221; , though even here, I had to interpret and embody what the machine created (&#8220;interpolation&#8221; as it is sometimes called in music).</p><h2>What People Heard</h2><p>Most people correctly identified Song 5 as AI-generated&#8212;I think partly because I didn&#8217;t know it as well, and partly because there was something missing in the emotional delivery. Several people pegged Song 2 as AI because of the lyrics, which is interesting given that only a couple of words came from AI, but people thought it was AI-generated because the lyrics felt less &#8220;personal&#8221;.</p><p>Almost nobody identified Song 3, the one where Claude completed my chord progression. And that makes sense&#8212;a chord progression is pattern-matching, it&#8217;s statistics, it&#8217;s &#8220;what usually comes next.&#8221; AI is actually pretty good at that. This was a good hook for the next part of my lecture were I talked about instances of many other artists, from Ed Sheeran to Taylor Swift, writing songs based off of extremely common chord progressions. </p><h2>AI as Normal Technology in Creation</h2><p>Here&#8217;s what struck me as I was preparing this exercise: we keep talking about &#8220;AI-generated&#8221; content as if it&#8217;s a binary. But, having now experimented with creation along this spectrum, I&#8217;ve concluded that this is a false dichotomy.</p><p>I&#8217;ve been thinking a lot about a concept called &#8220;AI as normal technology,&#8221; coined by Arvind Narayanan at Princeton. His argument is simple but profound: AI is just technology. </p><p>We panicked when calculators came along&#8212;nobody will learn math anymore! We panicked when drum machines were invented&#8212;real drummers are finished! We panicked when digital audio workstations made it possible to record and mix at home&#8212;goodbye, studio engineers!</p><p>None of those predictions came true. We still have mathematicians. We still have drummers. We still have studio engineers. </p><blockquote><p><strong>What changed was that the technology became a tool that professionals use, and the people who refused to learn the new tools got left behind.</strong></p></blockquote><p>Interesting questions of course are up for debate as far as our respective roles in creation. When I had Claude complete a chord progression, was that &#8220;AI creation&#8221; or was it more like using a calculator? What about Song 2, where ChatGPT gave me two words that unlocked an entire verse I&#8217;d been struggling with for days? When I threw my lyrics at Suno, was the result mine because the words were mine, or was it Suno&#8217;s because the music was its? What about the last one, where Suno did &#8220;everything&#8221;? Or, did it? I still had to prompt the model and ultimately learn the song. What if I had pulled stems from that last song and cut them up or remixed them? (Artists are actively doing just that these days.) And is that any less creative, or just a different form of creativity with new tools?</p><h2>We&#8217;ve Been Here Before</h2><p>The music industry has wrestled with these questions for decades, and the outcomes have shaped entire genres.</p><p>Take hip-hop. In the early days, sampling was the art form&#8212;&#8221;Rapper&#8217;s Delight&#8221; sampled Chic&#8217;s &#8220;Good Times&#8221; in 1979. But then came <em>Grand Upright Music, Ltd. v. Warner Bros. Records</em> in 1991, where Biz Markie sampled Gilbert O&#8217;Sullivan&#8217;s &#8220;Alone Again (Naturally)&#8221; without permission. The judge&#8217;s <a href="https://en.wikipedia.org/wiki/Grand_Upright_Music,_Ltd._v._Warner_Bros._Records_Inc">ruling</a> was blunt: &#8220;Thou shalt not steal.&#8221;</p><p>That decision fundamentally changed hip-hop. Suddenly, sampling became expensive and permission-based. Artists had to clear every sample, and rights holders knew they could charge for it. The creative process changed in response to the legal landscape. Hip-hop didn&#8217;t die&#8212;it evolved. But the law shaped what was possible.</p><p>Or consider Ed Sheeran&#8217;s <a href="https://www.rollingstone.com/music/music-news/ed-sheeran-not-liable-thinking-out-loud-trial-1234724464/">lawsuit</a> with Marvin Gaye&#8217;s estate over &#8220;Thinking Out Loud&#8221; and &#8220;Let&#8217;s Get It On.&#8221; Sheeran won, partly by demonstrating that chord progressions themselves can&#8217;t really be copyrighted&#8212;there are only so many combinations that sound good to human ears. He played twenty different songs back-to-back in court, showing how they all used similar progressions. The question wasn&#8217;t whether the songs sounded similar (they did), but whether that similarity constituted theft or just the natural constraints of music theory.</p><p>Now compare that to what Taylor Swift is doing. If you listen to her recent albums, you&#8217;ll hear echoes everywhere&#8212;the Pixies&#8217; bass line in one song, Jonas Brothers vibes in another, Jackson 5 in yet another. Music critics call it &#8220;interpolation.&#8221; It&#8217;s credited, it&#8217;s acknowledged, but it&#8217;s clearly building on what came before. At what point does &#8220;inspired by&#8221; become &#8220;copied from&#8221;? And would we even be asking that question if she weren&#8217;t using such recognizable sources?</p><h2>The Industry Response</h2><p>The platforms are trying to figure this out in real-time. Spotify sees <a href="https://www.musicbusinessworldwide.com/ai-music-app-boomy-spotify-stream-manipulation/">100,000 tracks uploaded every day</a> now&#8212;most of them AI-generated. They account for less than 1% of streams (Taylor Swift has the rest), but they create real problems.</p><p>Do you demonetize AI-generated music? Sounds simple, except it creates perverse incentives. Playlist curators get paid based on the royalties of the artists they include. If AI music is free to use and generates no royalties, suddenly there&#8217;s no economic reason to include real artists in your playlists. You hurt the humans you were trying to protect.</p><p>That&#8217;s why the industry is converging on disclosure rather than outright prohibition. There&#8217;s a consortium now&#8212;<a href="https://ddex.net/about-ddex/">DDEX</a> is one of the standards they&#8217;re building on&#8212;that allows artists to self-report what went into a track. &#8220;I wrote the lyrics, my friend played drums, AI generated the guitar part.&#8221; The idea is granular transparency: let listeners know what they&#8217;re hearing, let platforms make informed decisions, and let the market sort it out.</p><p>But this only works if people actually disclose. And it only works if we can agree on what counts as &#8220;AI-generated.&#8221; Is my Song 3, where Claude completed two chords, AI-generated? What about Song 2, where ChatGPT gave me two words?</p><h2>Story: That Time AI Helped Make <br>My Own Music Sound More Human</h2><p>During the lecture, I recounted a moment in my recent music-making that perfectly captures where we are right now. </p><p>I was programming a drum track on my Digitakt, and I asked Claude to &#8220;improve it&#8221;. It did and it sounded better, and I asked it why. What it told me taught me something surprising.</p><blockquote><p>Claude told me: &#8220;Human drummers never hit exactly on the beat, and they never hit with exactly the same velocity. So I shifted some notes slightly off-grid and varied the velocities.&#8221;</p><p><strong>I was talking to a machine to learn how to sound </strong><em><strong>less</strong></em><strong> like a machine.</strong></p></blockquote><div id="youtube2-eXshbtC1TUE" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;eXshbtC1TUE&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/eXshbtC1TUE?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>This is the uncanny valley we are currently traversing: AI tools are good enough to be useful, sophisticated enough to mimic human imperfection, but not yet advanced enough that we&#8217;ve figured out the etiquette and ethics of using them. My students can generate code they don&#8217;t understand. I can generate chord progressions I didn&#8217;t conceive. Artists can generate entire songs they never played.</p><p>How should we think about this? I can tell when the code is wrong because I spent years learning to code. I can tell when a chord progression works because I&#8217;ve studied music theory and played enough songs to develop an ear. The technology is a force multiplier, but only if you have something to multiply.</p><h2>Musicians Already Borrow from Other Humans. <br>How Is Borrowing from AI Different?</h2><p>As I told the audience, I&#8217;ve found that AI is terrible at writing lyrics. Why might that be? Because lyrics are emotion. They&#8217;re personal experience. They&#8217;re the thing that makes someone listen to a song and say &#8220;oh, that&#8217;s about something <em>real</em>.&#8221; That&#8217;s the human element that&#8212;so far, at least&#8212;the machines can&#8217;t fake.</p><blockquote><p>But chord progressions? Hooks? The ear actually <em>likes</em> things that sound familiar, even simple. We like patterns. We like statistical regularity with just enough variation to stay interesting. <strong>That&#8217;s literally what these models are built to do.</strong></p></blockquote><p>So now we&#8217;re in this gray area where Taylor Swift can <a href="https://www.stereogum.com/2325675/charlie-puth-explains-threshold-for-interpolation-as-tiktokers-compare-taylor-swifts-new-songs-to-old-hits/news/">interpolate</a> &#8220;Where Is My Mind?&#8221; by the Pixies into her own song, and we call it inspiration. But if I use AI to complete a chord progression that follows patterns drawn from thousands of existing songs, is that theft? Transformation? Or just another tool in the creative toolkit?</p><h2>The Hard Questions</h2><p>The question of whether AI training on copyrighted works should be allowed is the subject of much active litigation. There was a ruling last week in the UK courts saying AI models don&#8217;t violate copyright because they don&#8217;t actually make a copy&#8212;they train on data, extract patterns, then discard the original. </p><p>As the courts grapple with applying old copyright laws to this new technology, the deeper questions aren&#8217;t legal&#8212;they&#8217;re philosophical and practical:</p><ul><li><p>When does &#8220;inspired by&#8221; become &#8220;copied from&#8221;?</p></li><li><p>At what point does a tool become an active collaborator, and how does that matter for attribution&#8212;not only of the model, but also of anything that went into the process of creating that model?</p></li><li><p>Should we restrict AI tools from students (or as part of our own learning process) until we first learn to do things &#8220;the hard way&#8221;?</p></li></ul><p>That last question is one we&#8217;re actively grappling with in computer science education. I learned to code by writing everything from scratch. That means when an LLM spits out code that doesn&#8217;t meet my specifications I can typically spot it. I can work with the machine to fix it because I understand what it&#8217;s <em>supposed</em> to do.</p><p>But what about students who only ever learn to prompt? What about the next generation of musicians who never learn music theory because the tools can do it for them? Are they going to be like someone using a calculator without understanding arithmetic&#8212;unable to tell when 2+2=5? (Yes, that is a Radiohead reference.)</p><h2>What I Think (For Now)</h2><p>Here&#8217;s where I&#8217;ve landed, at least this week: AI isn&#8217;t going away. </p><p>It&#8217;s not going to replace artists or coders or writers, but it&#8217;s going to change what those jobs look like. Just like photography didn&#8217;t kill painting, and drum machines didn&#8217;t kill drummers, and DAWs didn&#8217;t kill studio engineers.</p><blockquote><p>The people who thrive will be the ones who understand both the craft <em>and</em> the tools. The ones who can tell when the machine is giving them something useful versus when it&#8217;s spitting out statistically plausible garbage. The ones who bring something distinctly human&#8212;emotion, experience, judgment&#8212;that the machines can&#8217;t replicate.</p></blockquote><p>When I played those five songs, many of people&#8217;s favorite songs were in the &#8220;grey zone&#8221;. Many felt the fully AI song lacked emotion&#8212;but the other four modes, where there was a distinct human element in creation, were very hard for humans to distinguish.</p><p>I think that&#8217;s the future (or increasingly, the present): the future of creation will  increasingly be less of a question of humans <em>or</em> machines, but rather humans <em>with</em> machines, and figuring out where the boundary between tool and collaborator actually lies.</p><p>Perhaps now the most important skill we can teach&#8212;in computer science, music, or anything else&#8212;is recognizing where that boundary lies and how to make intentional decisions about where to draw that line for various projects.<br></p><div><hr></div><p><em>This post is based on a talk I gave for a model class at University of Chicago&#8217;s Family Weekend. If you want to hear more about AI, creativity, copyright, and the messy intersection of technology and art, stay tuned. I&#8217;m still figuring this out myself.</em></p>]]></content:encoded></item></channel></rss>