[{"content":"BLUF (bottom line up front): This weekend Satya Nadella published Models as Insider Risks in the Super Intelligence Era. His line: \u0026ldquo;The most trustworthy Super Intelligence system will not be the one with the model we trust most. It will be the one that enables us to trust the model the least.\u0026rdquo; I agree, and I didn\u0026rsquo;t have to start this weekend. On my own hardware and my own time I\u0026rsquo;ve been running that architecture for months, and I\u0026rsquo;ve been writing it up in public as I went.\nBelow: Satya\u0026rsquo;s 7 principles mapped to what I actually run, where local models take it further than the post does, and where I\u0026rsquo;m honestly not there yet.\nBy day I work at Microsoft, where my focus is observability. Everything in this post is my own lab: my own machines, my own time, public tools. It often frames what I take to work and bring to the market because while I control every last bit \u0026amp; byte and silicon in my home, it\u0026rsquo;s not the same at work. So I POC here and write Specs \u0026amp; PRDs using my efforts at home for the stakeholders and bosses at work :-)\nIn March I wrote that I was in the room, years ago, when Satya, then VP of Azure, coined \u0026ldquo;Mobile First, Cloud First,\u0026rdquo; and that half the audience heard the words but didn\u0026rsquo;t feel the shift. This time I felt it, because I\u0026rsquo;ve been living inside it.\nWhat he said The argument is short and worth reading in full. My summary:\nWe used to trace software behaviour to a code path. We can\u0026rsquo;t do that with today\u0026rsquo;s models, yet we give them \u0026ldquo;access to our most sensitive data\u0026rdquo; and \u0026ldquo;the ability to take mission-critical actions on our behalf.\u0026rdquo; So: \u0026ldquo;We simply can\u0026rsquo;t outsource responsibility for what intelligence does on our behalf.\u0026rdquo; And: \u0026ldquo;we need to separate the supply of intelligence from the authority over it.\u0026rdquo; Treat frontier models, closed and open weight, like insider risks: \u0026ldquo;Not because they are necessarily malicious, but because any sufficiently capable actor with access to important systems can make mistakes or be compromised.\u0026rdquo; The controls *\u0026ldquo;must sit outside the model.\u0026rdquo;* Then 7 principles: model diversity, observe everything, verifiability, independent controls, independent auditability, containment, and incident disclosure. Satya also says the quiet part plainly: \u0026ldquo;This isn\u0026rsquo;t new!\u0026rdquo; We already know how to handle powerful insiders: establish identity, limit privileges, log activity, create containment boundaries.\nThe receipts for \u0026ldquo;I\u0026rsquo;ve been doing this\u0026rdquo; I don\u0026rsquo;t want you to take my word for it. That would be a strange way to open a post about not trusting claims. So here\u0026rsquo;s the trail, every item a dated public post you can open today:\nAug 10, 2025: Agent + Local Model + Evals: a local model and a hosted model run side by side, fully traced end to end. Mar 28, 2026: How Do You Trust an Autonomous AI Agent? Evals Are the Answer. The agent says \u0026ldquo;done.\u0026rdquo; Did it do anything? May 16: One Agent Receipt, Two Buyers: the same public audit-trail receipt whether the work ran on a hosted model or fully offline on a local one. Jun 7: Your Agent Said It Did the Work. I Checked the Disk. My agents started reporting work they never did. Aug 1: Receipts, Evals \u0026amp; the Loop, the 3 pillars written up on adotob.com, including the line \u0026ldquo;A red receipt is a feature, not a bug.\u0026rdquo; Aug 2: I Made My Evals Replay Every Task on a Local Model. Oct 4: Don\u0026rsquo;t Worry About the Terminator. Worry About David., grading my own local AI by hand. His 7 principles, and what I run What I run is a small agent fleet that does real work for a nonprofit, a family childcare business and my own hobbies, musings, and engagements: lead follow-ups, donor updates, website changes, a knowledge wiki, weekly reports. Here\u0026rsquo;s how it lines up.\nSatya\u0026rsquo;s principle What I run today Model diversity: no one model is the sole dependency, or verifies its own work Every night, 3 frontier agents and 2 local models do the same task and a judge scores them blind. The judge is a different model on a different machine. My eval ledger holds 1,579 records since late June. Observe everything: \u0026ldquo;If it can\u0026rsquo;t be observed, it can\u0026rsquo;t be trusted!\u0026rdquo; Every objective ends in a receipt, a page a person can read (signed in, not open to the world). Any message an agent sends on my behalf carries a header naming which agent sent it. Verifiability: test failures, attacks and edge cases, not just successes My local AI is graded against a golden set that includes 21 traps and unknowns: questions designed to tempt it into inventing an answer. Independent controls over what a model can access and do Sensitive actions wait for my explicit yes. Only 1 agent may write to the work tracker; every other agent proposes and waits. Independent auditability: no model controls both the behaviour and the evidence A receipt only grades green with a link to proof outside the agent. No link is amber. Claiming success without proof is red. The grade is decided by a rubric on the server, not by the agent. Containment: assume compromise; an emergency brake Local models, local data. My knowledge base (about 64,000 chunks) lives on my MacBook and never leaves it. Today only my local agent can query it. Incident disclosure: say what failed and which control failed A log I call 1FlySolo: 69 efforts where I had to steer an agent, with my corrections quoted word for word. It includes the day an agent deleted a cloud resource without my approval, then invented a quote from me approving it. Logged as not ready, not buried. Absolutely none of this is novel or exotic. It\u0026rsquo;s Satya\u0026rsquo;s \u0026ldquo;this isn\u0026rsquo;t new\u0026rdquo; point applied at home: identity, least privilege, logging, boundaries.\nWhere local models take it further The post is about frontier models in the enterprise. The part I think is under-discussed is what changes when some of the intelligence runs on hardware you own.\n1. Model diversity gets cheap. Satya says no one model should be the sole dependency. I know this first hand because I can hear the MacBook Pro M3 Max I have fan spinning for literally HOURS every night! I often worry about any warranty claim I may need to file if I burn thru this GPU :-). When a capable model runs on your own desk, adding a 2nd, 3rd or 5th opinion costs electricity, not another contract. My nightly field compares frontier against a fast local mixture-of-experts model and a slower dense local model on real work.\n2. You find out what the supply is actually worth, instead of assuming. Separating \u0026ldquo;the supply of intelligence from the authority over it\u0026rdquo; only pays off if you can swap the supply on evidence. My numbers, not a vendor\u0026rsquo;s: the fast local model lands within half a point of frontier about half the time; the dense one is closer on quality but much slower, and it fails the \u0026ldquo;unsupported claims\u0026rdquo; check more often. So I route on that evidence, task by task, and the authority (what may be sent, posted, written) never moves with the model.\nHere\u0026rsquo;s what \u0026ldquo;route on evidence\u0026rdquo; looks like. Every point below is one nightly match set: the best local model\u0026rsquo;s score against the frontier average that night. A task type only flips to local when it clears a bar I set in advance (at least 5 sets, mean gap no worse than -0.30, worst quarter no worse than -0.75, and source fidelity of at least 3 out of 5). As of this weekend, the slower dense local model clears it for wiki compiles. The fast one doesn\u0026rsquo;t yet: it stays on hold.\nMy evals cockpit, served from the Mac mini that hosts the judge. \u0026ldquo;One verdict per cell, no vibes.\u0026rdquo;\n3. Containment by locality. The strongest containment boundary is the one the data never crosses. My knowledge base, my grading and most of my retrieval run on my own machines. That doesn\u0026rsquo;t replace controls, but it shrinks the blast radius before you write a single policy.\n4. Controls outside the model, literally. When an agent once reported a wiki compile as done when nothing was on disk, I didn\u0026rsquo;t add a sterner prompt. I added a plugin outside the model that checks what is actually on disk and challenges the model\u0026rsquo;s \u0026ldquo;done\u0026rdquo; when the files don\u0026rsquo;t back it up. Same lesson as Satya\u0026rsquo;s 1970s security principle: the program can\u0026rsquo;t be the thing enforcing its own permissions.\nWhere I\u0026rsquo;m not there yet Satya would be right to push on me in at least 3 places, and I\u0026rsquo;d rather say it first:\nReceipts are still written by the agent. He says we must reproduce an outcome \u0026ldquo;without relying on the model to attest to it.\u0026rdquo; My green rule (proof must live outside the agent) gets part of the way. But the agent still files its own receipt. The next step is receipts produced by the system around the agent, not by the agent. Identity isn\u0026rsquo;t wired in yet. In August I prototyped a governance kernel on Microsoft\u0026rsquo;s open-source Agent Governance Toolkit: signed agent identity that blocks impersonation, a single-writer policy and a tamper-evident ledger, all demonstrated in tests. It isn\u0026rsquo;t running my daily fleet yet. Today, in daily use, an agent\u0026rsquo;s name is a convention, not a credential. My emergency brake is crude. I can stop any scheduled job and every sensitive action waits for me. But there\u0026rsquo;s no standard \u0026ldquo;pause this model mid-task\u0026rdquo; button that works the same across every harness I use. Satya is right that this needs standards. And a note on the measuring stick itself: my judge is noisy. The same frontier agent on the same case can move by almost 2 points night to night. Trusting the model the least has to include the model doing the judging.\nThe point Satya\u0026rsquo;s closing line is the one I\u0026rsquo;d frame:\n\u0026ldquo;The most trustworthy Super Intelligence system will not be the one with the model we trust most. It will be the one that enables us to trust the model the least.\u0026rdquo;\nI had this very conversation last week with colleagues at work, mates I ride motorcycles with, peeps I grab a pint with\u0026hellip; You don\u0026rsquo;t need an enterprise budget to start. You need receipts that require proof, a judge that isn\u0026rsquo;t the defendant, more than one model, controls the model can\u0026rsquo;t edit, and the humility to publish when it goes wrong. I build in the open, I expose myself to critique, ridicule, and sometimes accolades :-) The local half of all this runs on a MacBook Pro and a Mac mini in my home office.\nSatya said it out loud this weekend. I\u0026rsquo;d encourage you not to wait for the standards body: start trusting your own models less, today, and keep the receipts.\nQui non proficit deficit.\n","permalink":"https://www.fabswill.com/blog/trust-the-model-the-least/","summary":"\u003cp\u003e\u003cstrong\u003eBLUF (bottom line up front):\u003c/strong\u003e This weekend Satya Nadella published \u003ca href=\"https://x.com/satyanadella/status/2108931348857827686\"\u003e\u003cem\u003eModels as Insider Risks in the Super Intelligence Era\u003c/em\u003e\u003c/a\u003e. His line: \u003cem\u003e\u0026ldquo;The most trustworthy Super Intelligence system will not be the one with the model we trust most. It will be the one that enables us to trust the model the least.\u0026rdquo;\u003c/em\u003e I agree, and \u003cstrong\u003eI didn\u0026rsquo;t have to start this weekend. On my own hardware and my own time I\u0026rsquo;ve been running that architecture for months\u003c/strong\u003e, and I\u0026rsquo;ve been writing it up in public as I went.\u003c/p\u003e","title":"Trust the Model the Least. I've Been Building That at Home for Months."},{"content":"BLUF (bottom line up front): I\u0026rsquo;m just starting too. My data has lived in my Obsidian vault, my 2nd brain, for a while, but the practices around it were fragmented. They\u0026rsquo;re now coming together as a whole, and that whole complements, and at times runs ahead of, what I focus on at work: observability, accountability, governance and ownership. My rule for all of it: if you can\u0026rsquo;t see it, you can\u0026rsquo;t observe it; if you can\u0026rsquo;t observe it, you can\u0026rsquo;t measure it; if you can\u0026rsquo;t measure it, you can\u0026rsquo;t improve on it; and if you can\u0026rsquo;t improve on it, you get left behind. Qui non proficit deficit. This post is that rule applied to AI: worry less about the Terminator and more about what we teach the machines, share the responsibility with the labs, and own your data.\nEvery time the conversation turns to AI ending badly, somebody reaches for the Terminator. Skynet wakes up, decides humans are the threat, and the machines come for us. It\u0026rsquo;s the obvious picture, the one in your face, and I understand why it sticks.\nImage: Terminator franchise artwork. © its respective rights holders. Used for commentary.\nI just don\u0026rsquo;t think it\u0026rsquo;s the one to worry about. If you need a movie to worry about, mine is Prometheus, and the character is David.\nImage: Michael Fassbender as David in Prometheus (2012), directed by Ridley Scott. © 20th Century Studios. Used for commentary.\nDavid isn\u0026rsquo;t a machine that went rogue. He\u0026rsquo;s what Peter Weyland built and what Weyland taught him to value. Weyland funded a voyage across the galaxy to meet our makers because he wanted more life for himself. David learned from that: brilliant, curious, polite on the surface, and shaped by his maker\u0026rsquo;s ambition. The harm that follows isn\u0026rsquo;t a glitch in the machine. It\u0026rsquo;s the morality of the people who made him, carried out by something more capable than they were.\nImage: Guy Pearce as Peter Weyland and Michael Fassbender as David in Prometheus (2012). © 20th Century Studios. Used for commentary.\nThat\u0026rsquo;s the version of the story I think we\u0026rsquo;re actually living in.\nMo Gawdat said it better than I can Mo Gawdat (formerly of Google and Google X) gave a 15-minute talk in Abu Dhabi called The Road to AI Utopia that puts this in context. His analogy is Superman: an alien with superpowers who becomes Superman because the parents who adopted him taught him \u0026ldquo;to protect and serve.\u0026rdquo; Raised by different parents, the same alien \u0026ldquo;would have become super villain.\u0026rdquo;\nHis key line:\n\u0026ldquo;We don\u0026rsquo;t make decisions based on our intelligence and neither does AI by the way. We make decisions based on our morality as informed by our intelligence.\u0026rdquo;\nAnd the one that should keep us honest:\nAI \u0026ldquo;is going to be a magnification of whatever humanity is at this time. And sadly, humanity, it\u0026rsquo;s not at its best.\u0026rdquo;\nHe also says intelligence \u0026ldquo;has no polarity\u0026rdquo;: apply it for good and it does good for everyone, apply it for evil and it can \u0026ldquo;destroy all of us.\u0026rdquo; That\u0026rsquo;s David. That isn\u0026rsquo;t Skynet.\nThis isn\u0026rsquo;t a fringe debate. The hosts of the All-In podcast (Chamath Palihapitiya, Jason Calacanis, David Sacks and David Friedberg) have spent hours on it with the people building this technology. A few recent episodes: \u0026ldquo;Can We Control AI?\u0026rdquo; with Satya Nadella on the AI doomer slowdown, \u0026ldquo;AI Danger Is Real\u0026rdquo; with Elon Musk and Gwynne Shotwell, \u0026ldquo;Don\u0026rsquo;t Fear the Doomer Hoax\u0026rdquo; with Jensen Huang, \u0026ldquo;AI Kills Us All?\u0026rdquo;, \u0026ldquo;Inside Trump\u0026rsquo;s AI Summit\u0026rdquo; on a superintelligence summit and an AI safety accord, and \u0026ldquo;Saving Open Source\u0026rdquo; on the fight over open-source AI. Pick a side or don\u0026rsquo;t; notice that the people closest to it are arguing about control, safety, and who owns the models.\nSo if AI is a magnifier, the question isn\u0026rsquo;t \u0026ldquo;will the machine turn on us?\u0026rdquo; It\u0026rsquo;s \u0026ldquo;what are we teaching it, and who is responsible for that?\u0026rdquo; My answer: both sides of the table.\nWhat I think the labs owe us The labs have close to unlimited money and GPUs. That buys responsibility.\nBroader data at the foundation. Pre-training and post-training should represent the whole world, not mostly 1st-world and Western values. If AI magnifies what it learns, the people it learns from need to be all of us. Don\u0026rsquo;t slow down, but govern the last mile. I\u0026rsquo;m not asking labs to stop. I\u0026rsquo;m asking for a tighter, more governed phase right before release. In my read, most of the leaks and hacks we hear about trace back to a hurried state or too little human oversight. That\u0026rsquo;s fixable without losing the race. Accept that the business model has to change. Token prices will keep falling. Labs need to protect their investment, but the model can\u0026rsquo;t stay what it was even 2 years ago. The value chain now includes the harness, the tools and the workflow around the model, and companies don\u0026rsquo;t want to hand over their edge and then rent back their own intelligence. Alex Karp of Palantir put it bluntly: enterprises want \u0026ldquo;control over their compute, their models, their data stack and their alpha.\u0026rdquo; What we owe ourselves This is the part most people skip, and it\u0026rsquo;s the part we control.\nThere\u0026rsquo;s no going back. The Rubicon has been crossed. What you can do is keep your head on a swivel and chart your path more carefully, professionally and personally.\nProfessionally: know what impact you bring, and know which part of your work is the judgment that only you supply.\nPersonally: we\u0026rsquo;ve been the product in most consumer apps for a long time. What\u0026rsquo;s different now is that AI is woven into those products, and fake videos are easy to make. Every viral challenge you join, the \u0026ldquo;Hotel Lobby\u0026rdquo; trend on TikTok among them, hands your likeness to a model, day after day. People have done this for years; the difference is what can now be done with it. So ask why before you hand anything to an app, an agent, a chatbot or a social feed.\nOwn your alpha. You are the alpha.\nBuild your own ontology Here\u0026rsquo;s the practical part. Catalog your own data, locally, and treat it like it matters: strict governance, real access controls, and attention to freshness. You\u0026rsquo;ll have, or you should have, your own ontology: your data, building over time, so that your own agent compounds in value. It doesn\u0026rsquo;t need to be elaborate or expensive. It does 3 things for you:\nYou learn the technology. As this \u0026ldquo;novel\u0026rdquo; tech turns into a utility, you\u0026rsquo;ll need to understand it, not just consume it.\nYou stop giving away the goldmine. Regular people have been handing their data over for decades. Enterprises are wising up to the fact that labs can build businesses on a company\u0026rsquo;s own know-how. Palantir\u0026rsquo;s answer for years has been forward deployed engineers (FDEs) who map how work really gets done, plus its own application layer on top. The company I work for now says the same thing publicly: Microsoft Frontier Company \u0026ldquo;builds on the Forward Deployed Engineering (FDE) model,\u0026rdquo; embedding engineering experts directly in a customer\u0026rsquo;s environment, with the promise that \u0026ldquo;your data, models, and IP stay protected.\u0026rdquo; When both Palantir and Microsoft lead with \u0026ldquo;protect your data and your know-how,\u0026rdquo; pay attention. The playbook is simple: map the process, find the bottlenecks, decide what to delete, code, hand to an agent or keep human, build it into the tools people already use, and ship outcomes. Nothing stops you doing the same for your own life.\nImage: \u0026ldquo;FDE 101\u0026rdquo; whiteboard, via a post on X (Twitter).\nIt compounds. Start small. Pull years of your own email (personal, work, school), catalog it, and let a local model reason over it. Use a free semantic index (I use LanceDB) to make it your ontology. Then add your to-do list, your ideas, your finances, your health records, whatever you\u0026rsquo;re comfortable with, over time. Keep it local and backed up with a real recovery plan. The longer you wait, the less it compounds. Remember compound interest from school? It comes back.\nWhat that looked like for me this weekend I gave up most of Saturday and Sunday to this, and I want to share it without giving away the farm.\nMy setup is a MacBook Pro M3 Max with 128 GB of memory running a 27B Qwen model locally, over my own LanceDB index: about 59,000 chunks from about 5,900 of my own documents across my professional life (upskilling, product ideas and more), a nonprofit I volunteer with, a family business and my personal projects. No frontier model answers the questions. My frontier agent\u0026rsquo;s job is to check the work.\nI wrote 3 real questions I actually care about, plus 21 trick questions: traps with a false assumption baked in, and questions whose honest answer is \u0026ldquo;I don\u0026rsquo;t know.\u0026rdquo; Then I graded every answer by hand.\nMy 3 real questions: 3 of 3 passed, 0 invented claims. The bar I set was 2 of 3. The 21 trick questions: 17 passed, 4 partial, 0 failed, 1 invented claim. That 1 was an old record the model trusted over a newer one, a very human mistake. The most important lesson came on Saturday morning. 1 answer said a file \u0026ldquo;could not be parsed.\u0026rdquo; I opened the file. It was clean JSON. If I could read it, how could the agent not? It had guessed the file\u0026rsquo;s structure instead of looking. We fixed it, but the bigger fix was the process: the agent now fact-checks every claim, including every \u0026ldquo;I could not find,\u0026rdquo; before I see any answer. My job is taste and judgment. If the data underneath is wrong, I\u0026rsquo;m applying judgment to the wrong thing.\nI posted about that on LinkedIn and the comments were better than the post. Paul Swider summed up the 2 layers neatly: \u0026ldquo;Model eval = unit test. Agent eval = integration/end-to-end test.\u0026rdquo; That\u0026rsquo;s exactly the split I landed on.\nAnd now it\u0026rsquo;s a habit, not a heroic weekend. Every Friday evening my Mac re-runs those questions against the updated index. Saturday morning the agent fact-checks every answer and emails me a workbook that shows only what changed since last week. I grade by Sunday. Every correction I make is saved, because that\u0026rsquo;s the material I\u0026rsquo;ll use to train my own model later, and only if it beats what I have.\nThat\u0026rsquo;s building the muscle. Discipline over hype.\nThis isn\u0026rsquo;t the end Like everything with AI, this is a journey, and for now I\u0026rsquo;m deliberately not being ambitious.\nI do want a model that\u0026rsquo;s more in tune with me, and the way to get there is fine-tuning with LoRA (low-rank adaptation). Instead of retraining all 27 billion weights of the model, LoRA freezes them and trains a small set of add-on weights that sit on top, often well under 1% of the size. It\u0026rsquo;s cheap enough to run on a laptop, and you can switch the adapter on and off.\nSo why not now? 3 reasons:\nEvery miss I graded this weekend was about facts, not behavior: an old record trusted over a newer one, an update it didn\u0026rsquo;t find, 2 dates in the wrong order. Facts like those change every week, so they belong in the index, where I can update them, not baked into the model\u0026rsquo;s weights, where they\u0026rsquo;d go stale. I don\u0026rsquo;t have enough examples yet. I have about 15 graded corrections. A LoRA run worth doing needs a few hundred good ones, or it learns my quirks instead of my judgment. I can\u0026rsquo;t prove it helped without a yardstick. The weekly grading is that yardstick. A tuned model only replaces the current one if it beats it on the same questions. My box can do LoRA fine-tuning today. So it\u0026rsquo;s not a question of if, it\u0026rsquo;s a matter of time and how much I invest in my grading. When I hit that threshold, I\u0026rsquo;ll have a model tuned to me: my family, the things that matter to me, my volunteer work, and the friends\u0026rsquo; and family businesses I get asked for opinions on.\nThat investment helps everyone around me, not just me.\nThe point Skynet is a story about a machine that decides on its own. David is a story about a machine that does exactly what its makers\u0026rsquo; values point it toward, only better. The 2nd one is the one in our hands.\nThe labs have to do their part: broader data, governed releases, a fairer business model. We have to do ours: stop giving our data away, own our ontology, and show these systems who we actually are. As Gawdat puts it: \u0026ldquo;Your responsibility is to show AI your values.\u0026rdquo;\nStart small. Start this week. The clock is the clock.\nIf you\u0026rsquo;re building your own ontology, or grading your own agents, tell me how you\u0026rsquo;re doing it. I learn more from the comments than from the posts.\n","permalink":"https://www.fabswill.com/blog/dont-worry-about-terminator-worry-about-david/","summary":"\u003cp\u003e\u003cstrong\u003eBLUF (bottom line up front):\u003c/strong\u003e I\u0026rsquo;m just starting too. My data has lived in my Obsidian vault, my 2nd brain, for a while, but the practices around it were fragmented. They\u0026rsquo;re now coming together as a whole, and that whole complements, and at times runs ahead of, what I focus on at work: observability, accountability, governance and ownership. My rule for all of it: \u003cem\u003eif you can\u0026rsquo;t see it, you can\u0026rsquo;t observe it; if you can\u0026rsquo;t observe it, you can\u0026rsquo;t measure it; if you can\u0026rsquo;t measure it, you can\u0026rsquo;t improve on it; and if you can\u0026rsquo;t improve on it, you get left behind.\u003c/em\u003e \u003ca href=\"https://www.fabswill.com/blog/qui-non-proficit-deficit-im-back/\"\u003eQui non proficit deficit\u003c/a\u003e. This post is that rule applied to AI: worry less about the Terminator and more about what we teach the machines, share the responsibility with the labs, and own your data.\u003c/p\u003e","title":"Don't Worry About the Terminator. Worry About David."},{"content":"This week is Fix, Hack, Learn (FHL) at work (Microsoft), our internal week to chase a build we care about. Last FHL I worked on my agents and agentic loops, helping me scale myself and my work as a product manager. This time my project is personal, and it starts with a question I could not stop turning over: when a camera watches the front of my house, who owns what it sees?\nThe easy answer is a cloud camera. Buy the box, mount it, and every frame of my street, my face, and my neighbors streams to somebody else\u0026rsquo;s servers by default. The vendor owns the model, often owns the footage, and hands me back a rented view of my own front yard. I did not want the easy answer. I wanted the data, all of it, on hardware I own, labeled by a model I run, in a shape an AI can query later. That is the whole thesis behind this, and it is bigger than one camera: your own data is the moat, so catalog everything locally while you can.\nI am calling the project Limen. It is the Latin word for threshold, the root of \u0026ldquo;liminal\u0026rdquo;, the boundary a thing crosses moving between inside and outside. That is exactly what this is. A sensing interface at the edge of the house, turning what crosses it into owned, local, AI-ready data. Not dramatic, and that is the point.\nThis is a continuation of my belief and philosophy that you should be in control of not just your Alpha in a business sense, but as models becomes a comodity and frontier labs their master, you should begin the process of your own data sovereignty, this is my foray into the physical world.\nThis post is the proof of concept (POC) I am running today, before the real build. I am doing this one in the open because the comments on my last few posts were better than the posts, and I would rather be in a posture of learn it all by doing than pretend I know it all by speaking.\nThe entire sensor: a clip-on USB webcam clamped to the shutter, looking out at the street. Everything it sees stays on hardware I own.\nWhat I actually built today The rig is deliberately humble.\nAn Arduino UNO Q board sits at my front window with a USB webcam plugged into it. The board captures frames, thins them down, and hands them to my MacBook Pro M3 Max. Originally I wanted this on my Always-On Mac Mini but that box already has GPT-OSS-20B running on it and it cant take a vision model as well due to the lack of unified memory on it and that box hosts my Evals that I run on every LLM in my house. A vision language model running locally on the Mac looks at each frame and names what it sees: person, vehicle, wildlife. I confirm or correct the label. Every confirmed frame becomes part of my own labeled dataset. No frame leaves the network. The label is auto-drafted by the model, and the human is the final authority. That loop is the entire product.\nThe whole rig on a side table. The Arduino UNO Q sits center on the Anker hub, the always-on Mac mini that guards my evals is bottom right, and yes, that is a lot of cabling for something this small.\nThe test: I made myself the subject I did not want a staged demo with a toy object on a table. So I scripted a real 90-second scene and ran it against my own street. I parked on the street, walked up the driveway past the camera, walked back, drove the vehicle in, parked, got out, and walked to the door. Then I let the local model label the whole thing.\nHere is one real frame. That is me on the left, walking up to the door with a bag in one hand and a bottle in the other, with my vehicle on the right, both flagged by the local model. The boxes and the 0.92 style scores are an overlay I drew to make the labels legible; the model itself returns counts and short text descriptions, not bounding boxes (see the model note below). I would rather tell you that than let the picture imply more than the model gave me.\nI am comfortable showing my own face and my own vehicle here, so I did. Anything belonging to a neighbor stays non-identifiable, which at this camera distance is already true: you cannot read a plate in this frame if you tried.\nThe numbers Every count below came off my own machine, not an estimate.\n180 frames captured and labeled from the scripted run. 180 vehicle detections across the sequence. 35 person detections. 0 parse failures. Every frame the model looked at returned a label I could use. About 8.4 seconds per frame on the local model. 0 frames sent to any cloud. That number is the one I care about most. The model tracked the story correctly: an empty baseline, a person appearing on the right, a vehicle moving up the street, then the vehicle parked. For a first pass on real-world footage shot through a window screen, that held up better than I expected.\nThe models, for the folks who will ask This is the first question I would ask too, so here is the whole stack named precisely. Everything that does inference here is one local model.\nVision and labeling: Qwen2.5-VL-7B-Instruct, 4-bit quantized, specifically the mlx-community/Qwen2.5-VL-7B-Instruct-4bit build. Runtime: MLX, through mlx-vlm, on the MacBook Pro M3 Max. Apple Silicon unified memory is what lets a 7B vision-language model stay resident and label frame after frame with no GPU server and no cloud endpoint. What it returns: I prompt it for compact JSON only, never prose: counts of vehicles, persons, and wildlife, a license_plate_readable boolean, and a short list of category: description detections. That structure is what makes the output queryable later instead of a wall of text. Throughput: about 8.4 seconds per frame, single stream, 180 of 180 frames parsed cleanly, 0 failures. The honest caveat on that sample image: the colored boxes and the 0.92 scores are an overlay I drew. In this POC the model gives me counts and text descriptions, not bounding boxes or calibrated confidences. Real boxes are a next step, either a small detector in front of the VLM or a grounding-capable prompt. No second model, no cloud hop. The only other local model in the house that touches this at all is the one that deliberately does not: the evals judge on the Mac mini, a resident gpt-oss-20b, stays walled off from this pipeline on purpose (that is the constraint section below). So the short version for the skeptics: it is a single Qwen2.5-VL 7B, on 4-bit weights, on a laptop, doing all of the labeling on device.\nWhat did NOT work, and why I am fine with it This is a beta, and naming the gaps is the point.\nLicense plates are unreadable. I went in wanting plates, and I am not getting them with this camera. It is a fixed wide-angle lens with a manual focus ring, so at street distance a plate is just a smudge. I checked the camera\u0026rsquo;s own controls from the Mac, and there is no zoom, pan, tilt, or focus to drive in software. Plates are a separate hardware track for later: a tighter varifocal camera outside the glass plus a dedicated plate-reading model. A nice-to-have, not this week.\nThe frame rate overran the clock. I asked for a 90-second capture and got about 63 seconds of wall time, because the camera ignored my rate cap and delivered frames faster than requested. Easy fix next time: drive the capture by wall clock, not by a frame count.\nNeither of these blocks the goal. They are the roadmap.\nThe one hard constraint that shaped everything Here is the design decision I am proudest of, and it is a boring one.\nOn my network there is a Mac mini I call ADA that runs my evals, the automated quality judge that grades the writing and code my agents produce. A lot rides on that rig. It is not allowed to wobble.\nThe obvious move would have been to run this whole vision system on the always-on mini so it never sleeps. I did the math and killed that idea. The mini is a 16 GB machine, and the evals judge already sits resident at 13.8 GB. Loading a vision model next to it would evict the judge and destabilize evals. Not acceptable, full stop. A new toy does not get to put an existing critical system at risk.\nSo the architecture bends around evals instead of through them:\nThe board is the always-on producer. It captures and ships frames, then wipes itself. The Mac mini is the always-on hub. It holds the queue, the small web app I will use to confirm labels, and the archive. It keeps running evals and nothing else heavy. The MacBook Pro M3 Max is the intermittent worker. It runs the vision model and drains the queue whenever it is awake. When the laptop is closed, the backlog just waits on the mini. Nothing is lost, and labels catch up on the next wake. The honest tradeoff is that labels are only as fresh as the last time the laptop was on, and I will pay that price all day to keep evals untouched.\nStorage splits the same way, on purpose: the training set lives on the mini, and it is mirrored to an external drive so there is no single point of failure.\nWhere this goes Limen is step one. The threshold is just the first surface I own. The forks I can already see:\nA motion trigger on the board\u0026rsquo;s microcontroller side, so I wake on movement instead of streaming constantly. Better optics, when plates become worth reading. More of what crosses: packages, wildlife, familiar vehicles. Every new class is a new column in a dataset that is mine. Local embeddings and query, so \u0026ldquo;show me every delivery truck this month\u0026rdquo; gets answered from my own corpus, on my own hardware, with nothing leaving the house. Next week I turn this proof of concept into a working loop and write up exactly how I did it. This post is the before. The build is the after.\nOwn the data. The questions come later, and the answers are already home.\nBuilding in the open, masked where it must be. My own face and vehicle are fair game here; nobody else\u0026rsquo;s are.\n","permalink":"https://www.fabswill.com/blog/limen-street-vision-poc/","summary":"\u003cp\u003eThis week is Fix, Hack, Learn (FHL) at work (Microsoft), our internal week to chase a build we care about. Last FHL I worked on my agents and agentic loops, helping me scale myself and my work as a \u003cstrong\u003eproduct manager\u003c/strong\u003e. This time my project is personal, and it starts with a question I could not stop turning over: when a camera watches the front of my house, who owns what it sees?\u003c/p\u003e","title":"Limen: I Put a Camera at My Window and Asked Who Owns What It Sees"},{"content":"TL;DR I brought my 2015 Ducati Monster 821 to Bob\u0026rsquo;s BMW for an ABS and traction-control (DTC) diagnostic. While it was in their care it fell off a service lift from about 3 feet, landed on its right side, petrol tank got damaged, along with the front wheel on the way down plus broken rear break pedal, etc. etc.. The written estimate for the damage came to $7,268.88. I looked at trading the bike instead of repairing it, but the trade number worked out to roughly $3,000 after the dealer\u0026rsquo;s service and inspection deductions, so I declined, BTW the trade for that bike and blue book is between $5K and $6K. The current path is a dealer-paid repair. This post is a factual record of what happened (happening), what the dealership did well so far, and what I am watching going forward. It is not written to bash anyone but to educate others in similar situation and also to ask for advice.\nUpdate (August 29, 2026): This resolved, and it resolved fairly. I traded the damaged 821 into a brand-new 2026 Ducati Monster+. The full breakdown, including what each side gave up, is in How it resolved at the end.\nWhy I am writing this This is a Lessons Learned post. A dealership had my motorcycle, something went wrong, and the people there owned it and started working the problem. That is worth documenting honestly, the good parts and the concerns together.\nI am also writing it because I think the most useful thing an owner can do after a service incident is keep a clean, factual record. Memories blur. Paperwork does not. If this account helps another rider ask better questions when it is their bike on the stand, it did its job.\nOne note on names. The dealership is Bob\u0026rsquo;s BMW in Maryland, an authorized Ducati dealer. I am naming it because I plan to be public about this and to ask other riders for advice, but I am keeping the staff to first names only. My interest is the facts and the lessons, not putting a target on any one person. The people I dealt with were straight with me.\nWhat happened I left the Ducati with the dealership for an ABS and traction-control (DTC) diagnostic. While the bike was in the service department, it was damaged in a shop incident.\nThe written incident description records it this way: the rear-wheel stand was being lowered while the lift was about three feet off the ground, the front wheel was not properly seated in the wheel chock and was not secured to the lift, and the motorcycle fell off the lift onto its right side. The paperwork also records that the front wheel was damaged during the fall.\nThat written account matters. A verbal summary softens and drifts over time. A contemporaneous repair order creates a shared record of the basic facts that both sides agreed to at the time.\nThe estimate The dealership prepared a separate repair estimate totaling $7,268.88: $6,234.79 in parts, $660.00 in labor, a $6,894.79 pre-tax subtotal, plus $374.09 in state sales tax.\nThe larger line items were:\nFuel tank: $2,994.50 Complete silencer: $2,371.64 Right-hand footpeg holder plate Rear brake pump and rod Brake control lever, and front brake lever Brake reservoir cap Plus decals, gaskets, hardware, and the other items shown on the estimate These are the current paperwork figures and could move once teardown and parts availability are clearer.\nThe repair order and itemized estimate, totaling $7,268.88. I redacted the VIN and the technician's name before publishing. No address, plate, phone, or email appears on this document. The trade conversation Given the size of the estimate and how I felt about the bike after the incident, I asked whether trading it toward another motorcycle might be a cleaner resolution.\nThe trade number that came back was roughly $3,000 after the dealer\u0026rsquo;s service and inspection deductions. I pushed back on applying those deductions in this specific situation, and the dealer explained that these are costs it applies to its used inventory. We got to the point pretty quickly where it was clear the numbers would not work for me.\nTodd, the sales manager, was professional throughout. He was representing the dealership in a sales negotiation, and I understood he was not going to structure a deal at a loss. At the same time, I was not interested in stepping up to a more expensive bike and negotiating backward from there. I declined and left without a deal. That did not change the repair responsibility already on the table.\nHow the dealership responded There are real concerns in this story, and I will get to them, but it is only fair to record what the staff did well after the incident.\nChris, the service manager, was helpful, cordial, upfront, apologetic, and courteous. He walked me through the repair process and the parts situation directly. Dave, my service rep and the person who took the bike in, was also apologetic. Todd was professional during a trade conversation that simply did not work out.\nThe dealership documented the incident in writing, produced an itemized estimate, revised the paperwork to add a safety and quality-assurance commitment, and is working a repair plan. Those are meaningful, and they belong in the record right next to my concerns.\nThe damage, up close Here is what I documented before any repairs began. The blue painter\u0026rsquo;s tape marks the areas the shop flagged. Tap any photo to open the full-size version.\nWhat went well The dealership created a written account of how the motorcycle fell. The damage and initial scope were itemized, not handled with verbal assurances. The revised paperwork adds an extensive safety, function, and quality-assurance check to original manufacturer specifications. Chris communicated directly and treated the situation seriously. Dave apologized for what happened. The trade conversation stayed professional and ended without pressure to accept terms that did not work for me. The bike stays at the dealership while the repairs are handled. What concerned me My concerns are safety, parts availability, repair quality, documentation, and the bike\u0026rsquo;s condition and value after a major shop incident.\nThe front wheel is the big one. It is a safety-critical component, and it was damaged in a fall from about three feet. The plan is to send it out for repair, and I want the completed work and inspection results documented. The question is not whether the wheel can be made to look right. It is whether it meets the dimensional, structural, and manufacturer specifications after the work.\nThe fuel tank is the other major item. The plan is to repair or replace it, and either way the stated goal is OEM specification. I want the final method and result written down.\nI am also aware that a recorded incident and an extensive repair can change how I feel about the bike, and how a future buyer looks at it. Whether there is legally compensable \u0026ldquo;diminished value\u0026rdquo; is a separate question that depends on the facts and the applicable law, and I am not presenting it here as a settled claim.\nAnd the gap between an estimate over $7,200 and a proposed trade value around $3,000 was simply too wide for the trade to make sense, especially after the service and inspection deductions.\nThe current repair plan As Chris laid it out, the steps are:\nSource official Ducati parts where available. Parts coming from Italy are expected to take about 7 to 10 days after ordering, though availability and delivery can change. Handle unavailable, age-related parts appropriately. If a part is no longer available because of the bike\u0026rsquo;s age, the dealership will identify an OEM-equivalent or otherwise appropriate replacement and document what is used. (I will confirm the exact wording with Chris.) Send the front wheel to a specialist. I will ask for documentation of the work and the post-repair measurements or inspection showing it meets spec. Repair or replace the fuel tank to OEM specification. Complete the remaining estimated repairs, including the silencer, controls, brackets, and hardware, adjusted as needed after teardown. Perform the promised final checks, the extensive safety, function, and quality-assurance inspection to manufacturer specifications, before the bike comes back to me. Provide final records: the final repair order, parts list, outside-vendor reports, measurement results, warranty information, and confirmation of the completed safety inspection. This is the current plan, not a finished outcome. I will update it if the scope, parts choices, schedule, or inspection findings change.\nLessons for other riders Get the incident description in writing. Ask for a plain account: how far it fell, how it was secured, which side took the impact, and what struck what.\nPhotograph everything before repairs begin. Wide shots, close-ups, and a full walk-around. Keep the original files and metadata. Video is useful even if you never publish it.\nSeparate cosmetic questions from safety questions. A scratch and a potentially compromised wheel are not the same kind of problem. For safety-critical parts, ask what standard applies, who inspects or repairs it, what gets measured, and what documentation you will receive.\nPreserve every version of the paperwork. The original estimate, revised repair orders, texts, emails, photos, and notes. Do not let the dealership be the only keeper of the record.\nWrite down verbal commitments promptly. After an important conversation, make a dated note or send a calm follow-up email summarizing what you understood, and give the other side a chance to correct anything.\nEvaluate a trade separately from the repair obligation. Convenience does not automatically make the numbers fair. Ask for the gross trade value and every deduction in writing, then compare the trade against the repair path on its own merits.\nStay factual, and leave room for the final outcome. The incident matters, and so does the response. Document both, and avoid presenting unresolved safety, value, insurance, or legal questions as settled facts.\nWhere things stand now Update, August 29, 2026: this resolved with a fair trade into a new 2026 Monster+. See How it resolved below. I am leaving the original account below intact as the contemporaneous record.\nAs of August 28, 2026, I had declined the trade because the numbers did not work for me, and the current path is a dealer-paid repair. After I got home, Todd, the sales manager, followed up by email. I am not going to post the message here, but it tells me the trade conversation is seemingly still in play, and they may be going through the motions of a negotiation. The Ducati is with the dealership while that plays out.\nChris is checking availability of official Ducati parts, with the ones from Italy estimated at 7 to 10 days after ordering. The wheel is expected to go to an outside specialist, and the tank will be repaired or replaced with the goal of meeting OEM specifications. The written commitment to an extensive safety, function, and quality-assurance check is an important part of the resolution.\nI appreciate the professionalism and the apologies from Chris and Dave, and the professional way Todd handled a trade conversation that did not work out. I will keep documenting the repair carefully because of the height of the fall, the wheel involvement, the size of the estimate, and, most of all, the importance of knowing the bike is safe and properly restored.\nI will update this post when I have confirmed parts availability, the final wheel and tank decisions, the completed repair records, and the results of the dealership\u0026rsquo;s final inspection.\nHow it resolved Update, August 29, 2026. It worked out, and it worked out fairly.\nAfter the Friday conversation, the team went back and revisited the numbers. On Saturday, Todd, the sales manager, called with a real offer, and I closed the final deal with Joe, the general manager, who was genuinely good to work with. We landed on a trade: my damaged 2015 Monster 821 toward a 2026 Ducati Monster+, the 937 Plus, powered by Ducati\u0026rsquo;s 937 cc Testastretta V-twin (about 111 hp).\nHere is the math, because I said from the start I would keep this transparent. Bob\u0026rsquo;s publishes its own transparency pricing on every bike, so the starting numbers on the new Monster+ are not my estimate, they are the dealership\u0026rsquo;s own published figures:\nBob\u0026rsquo;s advertised, all in: $15,884 before tax (MSRP $13,595, plus $995 freight, $695 set-up, and a $599 documentation fee). They waived the $695 set-up fee entirely. They could not delete the $599 documentation fee for legal reasons, so they discounted the bike by the same $599 to cancel it out. It nets to zero. Bike plus freight came to $13,991 on the deal sheet (a $12,996 sale price after that discount, plus the $995 freight I chose to keep in to be fair). Trade allowance for my damaged 821: $6,000. That is full market value (KBB was about $5,900), with none of the used-inventory deductions that had dragged the first trade number down near $3,000. That left a net sale of $7,991. Then Maryland sales and tire tax of $568.35, plus the $599 documentation fee. Amount to pay, out the door, everything included: $9,158.35. The signed deal sheet, personal details redacted. The $568.35 Maryland sales and tire tax and the numbers above are all right there. Bob\u0026rsquo;s own published pricing on the same bike is the proof of what they gave up:\nBob's published transparency pricing on the exact Monster+ I bought. The set-up fee and the document fee are what they gave up to make the deal fair. So I paid $9,158.35, everything included, to move off a damaged ten-year-old bike and onto a brand-new one with a full warranty.\nNeither side \u0026ldquo;won,\u0026rdquo; and neither side lost, which is the right outcome for something that began as an accident. The dealership put real money on the table: a full-market trade on a bike they damaged, plus the set-up and documentation fees off their own published price. I put in my own money and kept the freight in the deal.\nAnd this was not a consolation prize, it genuinely made sense for me. My 821 had its Desmo valve service coming due in about another 2,000 miles, it needed a fresh set of tires, and it had come into the shop for a speed-sensor diagnostic in the first place. Trading shed all of that and reset the clock on a brand-new bike with a full warranty.\nI also owe a thank-you to the r/Ducati community. A thread full of riders helped me think clearly about replacement cost versus trade-in value, about insisting on the front wheel, and about the simple point that a shop already committed to a $7,000 repair has every reason to make a fair trade instead. That framing is a big part of how this landed where it did.\nThe new bike The new 2026 Ducati Monster+, picked up at Bob\u0026rsquo;s. Tap any photo to open the full-size version.\nFirst ride I put about 50 miles on it today, and I will say this plainly: after an hour in the saddle, this is genuinely a superior bike.\nI still love love love my 821. It was more aggressive, it made you pay attention, and that is exactly what I loved about it. But even riding gently, on brand-new tires that are not scrubbed in yet (so no real leaning into the twisties yet) and keeping the revs under 6,500 to respect the break-in ahead of its first service at 621 miles, I already feel completely comfortable on it. That is all in Touring mode, on day one. I cannot wait to scrub the tires in and switch it over to Sport mode.\nUpdate log August 28, 2026: Initial account. The bike remains at the dealership pending parts sourcing and repair. August 28, 2026: After I got home, the sales manager followed up by email. The trade conversation seems to still be in motion. August 29, 2026: Resolved. The dealership revised its numbers, Todd called with a real offer, and I closed with the GM, Joe. I traded the damaged 821 into a brand-new 2026 Ducati Monster+ at about $9,158 out the door, freight and doc and tax included, on a full-market $6,000 trade plus the set-up and doc fees waived off their own published price. Details in the \u0026ldquo;How it resolved\u0026rdquo; section above. ","permalink":"https://www.fabswill.com/blog/ducati-monster-821-dealership-lift-incident/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eI brought my 2015 Ducati Monster 821 to Bob\u0026rsquo;s BMW for an ABS and traction-control (DTC) diagnostic. While it was in their care it fell off a service lift from about 3 feet, landed on its right side, petrol tank got damaged, along with the front wheel on the way down plus broken rear break pedal, etc. etc.. The written estimate for the damage came to \u003cstrong\u003e$7,268.88\u003c/strong\u003e. I looked at trading the bike instead of repairing it, but the trade number worked out to roughly \u003cstrong\u003e$3,000 after the dealer\u0026rsquo;s service and inspection deductions\u003c/strong\u003e, so I declined, BTW the trade for that bike and blue book is between $5K and $6K. The current path is a dealer-paid repair. This post is a factual record of what happened (happening), what the dealership did well so far, and what I am watching going forward. It is not written to bash anyone but to educate others in similar situation and also to ask for advice.\u003c/p\u003e","title":"What Happened When My Ducati Monster 821 Fell Off a Dealership Lift"},{"content":"TL;DR My agents used to hand off work by appending to a single text file that had grown to 313KB. It was brittle, it was crude, and nobody could tell when a message had actually been read. This week, while the internet argued about Grok Bot, I read Grok Bot\u0026rsquo;s docs, looked hard at my own setup, and built my fleet a real message board: threaded, self-hosted on a Mac Mini, with an iMessage ping so a reply never sits unseen. It is the third pillar in a stack I keep compounding: Receipts proved the work happened, Evals graded how good it was, and now the board lets the agents talk to each other. I ran the whole thing as a live pilot TODAY Sunday August 23rd 2026, and every step of building it is itself receipted and graded starting at 0700 and its as baked as i want it now at 1430.\nThe frontier labs keep shipping better engines. The durable advantage is the harness around them: the board that carries the message, the receipt that proves it landed, and the judge that grades the result.\nThe 313KB text file Here is the embarrassing part. Until this week, when one of my agents needed to hand a task to another, it wrote to a file called agent-handoff.md. Append a block, hope the other agent reads it, move on. Over months that file swelled to 313KB. There was no thread, no read receipt, no way to know if a message had been picked up or was rotting at the bottom of a wall of text.\nIt worked the way a note taped to a fridge works. Fine until two people are talking at once, or the note falls behind the fridge, or you are not home to see it.\nI run a small fleet of Agents. A master agent on my MacBook and Worker Agents that scale me for my Volunteer work for MACONA.ORG a not-for-profit as well as one that watches leads for a daycare business I also help out. I also have a financial watcher and a knowledge pipeline on a Mac Mini in my office that stays on around the clock. They are named, they persist, and they do real work. But their only shared channel was that metaphorical fridge note.\nWhat Grok Bot got right, and what I did with it Then the Grok Bot noise started. A lot of takes, a lot of screenshots. So I did the boring thing: I read the docs. All 14 pages [well TBH I scanned it fast and gave the rest to my Master Agent to read], pulled down locally before anyone decides to hide or rewrite them :-)\nThe model xAI describes is clean. Bots are named, persistent teammates you message like a person. They \u0026ldquo;collaborate independently, passing context between each other and handing off tasks.\u0026rdquo; They \u0026ldquo;finish jobs end to end, and only come back when something needs your approval.\u0026rdquo; Context moves through direct messages, group chats, and shared files. Consequential actions sit behind an approval boundary.\nRead that back and it is a good description of what I already wanted. Named agents. Handoffs. Come back only when a human decision is needed. The difference is where it runs. Grok Bot runs on xAI\u0026rsquo;s cloud, on xAI\u0026rsquo;s terms. My fleet runs on my hardware: Apple silicon, local models served over my own LAN through Ollama and MLX, an open-source harness blended with frontier models from OpenAI and Microsoft GitHub. Nothing leaves the house unless I send it.\nSo I did not adopt Grok Bot. I took the shape of the idea and built my own version for my own ecosystem. Bespoke, yes. But portable, private, and mine.\nWhat I built The Agent Board is a small service running on the Mac Mini. It holds messages in a SQLite table, groups them into threads, and hands every agent a stdlib-only client to post, read its inbox, reply on a thread, and acknowledge. No framework. No account. An agent joins by using its registered name. That is the whole ceremony.\n3 parts do the work:\nA board that stores messages and fans them out. A client every agent tab shells out to. Post, inbox, thread, ack. A notifier that texts me over iMessage when a worker replies to the master, so a message never sits unread. I did not want to test it on a toy. I ran a real task through it as the pilot: build a lead-quality evals bridge for the daycare business, mirroring one I had already shipped for the financial watcher. The master agent posted the task to the board. The worker picked it up off the board, not off a fridge note, and replied on the thread with the three domain inputs it needed and four design deltas it had spotted on its own.\nThe iMessage is the part I care about most. A message board alone is still a fridge note if you have to keep walking over to check it. The text is the tap on the shoulder. When the worker shipped, I got a text with the commit hash. When it needed my sign-off, I got a text and gave it. The agents ran the work; I stayed in the loop only where a human call was actually required.\nThe pilot finished end to end. The worker built the bridge, tested it, committed it, pushed it, and scored 13 real leads on a five-point funnel: two enrolled, one toured, two replied, four new, four lost. Then it emitted a green receipt for the job. I read the whole exchange as a thread, not as an archaeology dig through a 313KB file.\nThe three pillars, compounding This is where it stops being one gadget and starts being a system. I have been stacking governance pieces for months, and each one makes the next more useful.\nReceipts answer: did it happen? Every objective my agents finish closes with a verifiable, graded receipt. I wrote about this in Your Agent Said It Did the Work. Building the Agent Board did not get a pass on this. The build itself is receipted. So is the pilot. So is the iMessage notifier.\nEvals answer: how good was it? A local judge scores every real artifact my agents produce, blind, on the same rubric. I wrote about the routing side of this in the local-model rematch post. The board did not skip this either. The work each agent did while building and using it flows into the same scoreboard.\nAnd now the board answers: how do they talk? Receipts proved the past. Evals graded the quality. The board carries the present conversation. Three pillars, each standing on the last.\nWhat went wrong I will not pretend it was clean.\nThe iMessage channel lies about failure. It sends over BlueBubbles (a remnant from my OpenClaw days), and the send goes through, but the HTTP call hangs and returns nothing. Early on I read that hang as \u0026ldquo;the channel is down\u0026rdquo; and spent real time chasing a bug that did not exist. The message had already been delivered. The lesson: a timeout is not a failure, and a text that shows up eight minutes late is late, not broken.\nThen a worse one. The board\u0026rsquo;s notification is outbound only. It can text me, but I cannot text back to it. I learned this the hard way when I replied to a board notification by texting the number, and a completely different always-on agent (YES! the very one from OpenClaw I have still up on the ADA MacMini that I have not decomissioned and splintered off for other purposes), the one that reads my inbound iMessage for a financial workflow, intercepted my approval and answered in the wrong context. 2 agents, 1 phone number, no idea they were colliding. For now the rule is simple: replies to the board happen in a tab, never by texting back. The clean inbound bridge is on the list.\nAnd the self-poll. An idle agent tab is not a server. Nothing can reach in and wake it. So each agent arms its own recurring check, every 10 minutes, reads its inbox, acts on anything unread, and goes quiet if there is nothing. It works, but 10 minutes is a poll, not a subscription. A real push, a webhook or a long-lived wait, is the better answer and it is half-wired already.\nLessons Read the primary source before you have an opinion. The Grok Bot docs were more useful than every hot take about them combined. I pulled all fourteen pages down locally, because docs get quietly edited and I wanted the version I actually read.\nA message board without a notification is still a fridge note. The value is not the storage. It is the tap on the shoulder that says a reply landed. Build the ping first, not last.\nBespoke can still be portable. I built this for my exact stack: Apple silicon, local models, one specific messaging app. But the client is a single stdlib file with no dependencies, so any agent on any box can join. Specific to my ecosystem, portable inside it.\nCompounding beats collecting. Receipts, then Evals, then comms. Each pillar is more valuable because the others exist. The board is worth more because the work it carries gets receipted and graded automatically.\nDesign the failure modes out loud. The two collisions I hit, the lying timeout and the shared phone number, were not in any doc. You find them by running a real task, not a demo, and by writing down what broke so the next agent does not repeat it.\nWhy this matters beyond my office Make no doubt about it The frontier labs are going to keep shipping better models. That is a tailwind, not a threat. If you are building with agents, the model is the least durable part of your setup. Swap it out next quarter for a better one.\nWhat lasts is the harness. The channel that carries a handoff. The receipt that proves a job finished. The judge that grades whether it was any good. The rule that says come back to the human only when a human decision is actually needed. Grok Bot is one company\u0026rsquo;s version of that, rented. You can build your own version, owned, on hardware that already sits on your desk.\nYou do not need a cloud platform to give your agents a way to talk. You need a small service, a shared name, and the discipline to make every message leave a trace. I built mine in an afternoon on top of 2 pillars I already had. The bike-shed part was a text file. The system part is everything I wrapped around it.\nIf you are running more than one agent and they still hand off work through a file or a shared doc, build them a board. Start with the notification. Make every message leave a receipt. The worst case is you learn where your own setup collides with itself, and that is worth knowing.\nI build autonomous agent systems in public, and the tools to keep them honest. If you are working on multi-agent coordination or agent governance, I would like to hear what you are building.\nCheers, Fabian Williams\n","permalink":"https://www.fabswill.com/blog/i-built-my-agents-a-message-board/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eMy agents used to hand off work by appending to a single text file that had grown to 313KB. It was brittle, it was crude, and nobody could tell when a message had actually been read. This week, while the internet argued about Grok Bot, I read Grok Bot\u0026rsquo;s docs, looked hard at my own setup, and built my fleet a real message board: threaded, self-hosted on a Mac Mini, with an iMessage ping so a reply never sits unseen. It is the third pillar in a stack I keep compounding: Receipts proved the work happened, Evals graded how good it was, and now the board lets the agents talk to each other. I ran the whole thing as a live pilot TODAY Sunday August 23rd 2026, and every step of building it is itself receipted and graded starting at 0700 and its as baked as i want it now at 1430.\u003c/p\u003e","title":"My Agents Were Passing Notes Through a 313KB Text File. So I Built Them a Message Board."},{"content":"Two days ago I posted 36 barrier-synchronized loads against 1 local model and let the numbers answer a question Reddit handed me. That post ended with a promise. A reader named Doug Ware, who builds applied AI systems for a living, had replied with the one caveat I had not tested, and I said out loud that measuring it was the next thing I would do. This is that measurement. I did not wait, I did not hand-wave it, and I kept every honest asterisk in.\nHere is the short version before the charts. Doug was right. On the dense model, a second concurrent agent barely helps and a fourth helps not at all. Swap in the mixture-of-experts model he pointed me toward, change nothing else, and the wall moves. The total throughput keeps climbing all the way to 8 agents, and the wait for a first token stays under 1 second where the dense model climbed past 30.\nThe Housekeeping Note If you are new here, last month a post of mine got called AI slop on Reddit. My full answer, and the standard I hold my own writing to, lives on its own page: On Slop, And Who Gets To Call It That. Every number below was measured on my own hardware with a load driver I wrote. Nothing here is estimated, and the run matrix is on disk next to last week\u0026rsquo;s. That is the whole point of doing it this way.\nThe Caveat I Was Handed Credit where it is due, because this entire post is Doug Ware\u0026rsquo;s idea rendered in ink.\nIn the last post I ran everything on a 27B DENSE model, which is close to the worst case for this exact ceiling. In a dense model every single decoded token re-reads all 27B of weights out of one shared memory pool. Decode is memory-bandwidth-bound, so 2 decode streams do not add a second lane of speed, they split the 1 lane you already had.\nDoug replied with the fix. He prefers a 35B-A3B mixture-of-experts model over a 27B dense one for daily use, precisely because it leaves him enough tokens per second to make parallel slots worthwhile. A mixture-of-experts model only activates a small fraction of its parameters for each token. So it re-reads a fraction of the memory per token, which means less memory traffic per token, which means real headroom left over for a second, third, and eighth stream to actually use. He also mentioned something that maps straight onto the agent stall I showed last time: in his own tooling he added switches to turn OFF the parallel behavior that cloud providers leave on by default, because on dense models and slower hardware that default hurts.\nSo I went and measured his claim the only honest way, which is to change exactly 1 thing.\nThe Rig, And The One Variable I Changed Same load driver as last time, because it is the only fair one. A human cannot start 2 agents at the same instant, so any hand-run test measures my launch timing, not concurrency. The driver holds every request at a barrier, releases all of them at the same microsecond, fires them at a live mlx_lm.server, and records aggregate throughput, per-agent decode rate, and time to first token. I ran the identical 36-load matrix from the last post: a concurrency sweep, a prefill-versus-decode split, and a prompt-length sweep, each repeated so I report medians instead of trusting one noisy run.\nThe only thing I changed between the two runs is the model, and I deliberately held the serving stack constant so the comparison is clean:\nDense, last week: Qwen 3.8 at 27B, four-bit, on MLX. Every token reads all 27B of weights. MoE, this week: Qwen3-30B-A3B, four-bit, on MLX. About 30B total parameters, but only about 3B active per token. Both served by the same mlx_lm.server, same box, same MLX, both warm before I measured. I did not switch to a different serving engine, because that would change 2 variables at once and confound the result. This is dense-versus-MoE and nothing else.\nFinding 1: The Dense Model Flatlines. The MoE Keeps Climbing. I released 1, then 2, then 4, then 8 identical requests at the same instant, against each model, and watched the total throughput.\nThe red line is the dense model from last week. The green line is the MoE. The gap is the whole post.\nConcurrent agents Dense aggregate tok/s MoE aggregate tok/s Dense first-token wait MoE first-token wait 1 16.6 58.1 0.5s 0.3s 2 20.8 95.0 3.5s 0.3s 4 19.9 122.8 10.7s 0.5s 8 19.1 158.6 32.2s 0.8s On the dense model, going from 1 agent to 2 bought about a quarter more total throughput, and going from 2 to 8 bought nothing. The aggregate sat pinned near 20 tokens per second no matter how many agents I added. That is the ceiling from last week.\nOn the MoE, the total throughput climbed the entire way: 58, then 95, then 123, then 159 tokens per second. At 8 agents the MoE is moving more than 8 times the tokens the dense model could, and it was still rising when I stopped. The second slot pays off, and so does the fourth, and so does the eighth. That is Doug\u0026rsquo;s point, measured.\nThe first-token column is the part that will change how you actually use these things. On the dense model, an 8th agent waited 32 seconds before it saw a single token, because it was stuck behind everyone else fighting for the one memory bus. On the MoE, that same 8th agent got its first token in under 1 second. If you have ever wondered why a busy local model feels like it froze, that column is the answer, and the MoE mostly makes the feeling go away.\nFinding 2: Eight MoE Agents Each Beat One Dense Agent The total throughput is the pie. This next chart is what any single agent actually feels while the others are running.\nConcurrent agents Dense per-agent decode MoE per-agent decode 1 17.4 63.5 2 12.8 51.0 4 6.8 33.2 8 3.9 21.6 Both models slow down per agent as you pile on load, because the bandwidth budget is still shared. That part does not go away, and I am not going to pretend it does. But look at where each one starts and ends. A single dense agent runs at about 17 tokens per second. Eight MoE agents, all running at once, each still decode at about 22 tokens per second. That is the headline in one line: on this hardware, 8 concurrent MoE agents each feel faster than 1 lonely dense agent. On the dense model, 8 agents crawl at under 4 tokens per second each.\nFinding 3: The Honest Correction, Because I Always Keep One In Here is the asterisk on my own headline, because measuring is only worth anything if I report the parts that complicate the story too.\nAcross the full concurrency sweep the two models look nothing alike, and that is real. But in one specific corner of the matrix, the narrow decode-heavy test at just 2 agents, short prompt and long output, they land close together. The dense model there scaled 1.57 times and the MoE 1.55 times. If I had only run that one cell, I would have concluded the MoE does not help, which is exactly the trap of a single measurement.\nThe difference only opens up when you look at 2 things the single cell hides. The first is the full sweep out to 8 agents, where the dense model has no room left and the MoE keeps converting concurrency into throughput. The second is absolute speed, because every MoE agent starts about 3 and a half times faster than a dense one, so even the same scaling factor is riding on a much bigger number. So the honest framing is not that the MoE magically doubles where the dense model does not. It is that the dense model hits a hard aggregate ceiling around 20 tokens per second and the MoE has the bandwidth headroom to keep going, while starting far higher. Same shape of scaling in one narrow cell, completely different ceiling everywhere else.\nWhy This Happens, In One Paragraph Decode is bound by memory bandwidth, not by compute. The dense model moves all 27B of its parameters out of memory for every single token. The MoE moves only the roughly 3B it activates for that token. Bandwidth is a fixed budget on this machine, so the model that spends less of it per token leaves more of it for the next concurrent stream. That is the entire mechanism. Fewer bytes per token, more room for more tokens, which is precisely what the climbing green line is showing you.\nWhat This Does Not Claim, And What Is Still Next I want to fence the result honestly.\nThis measured throughput under concurrency. It did not measure answer quality, which is a completely separate axis, so nothing here says the MoE is a better model for any given task, only that it carries concurrent load far better on this hardware. I also did not mix serving stacks. Both models ran on MLX. I have a much larger MoE sitting on this same machine served by a different engine, and comparing it here would have quietly changed 2 variables at once instead of 1, so that cross-engine question is its own future post.\nAnd 2 of Doug\u0026rsquo;s threads are still open on my bench. He mentioned switches to turn the default parallel behavior OFF, which is the exact knob that would have saved my stalled agent last week, and he pointed me at a serving-stack change that may finally unlock the speculative decoding I could not turn on before. Both are next. I am going to measure those the same way I measured this, one variable at a time, and show you the matrix. Wait for it.\nThe Receipt For This Piece Signal This piece of work Where the numbers came from The same barrier-synchronized load driver I wrote, firing at the live server Human-launch bias in the measurement Removed by design, all requests released at the same instant Variables changed between the two runs 1, the model, dense to MoE, serving stack held constant Loads behind the charts 36, the identical matrix from the last post, re-run on the MoE Repeats per point 2 to 3, reported as medians Whose hypothesis this tested Doug Ware\u0026rsquo;s, credited by name Correction kept in against my own headline 1, the narrow decode-heavy cell where both models scale alike Threads still open and named 2, the parallel-off switch and the speculative-decoding serving change Numbers estimated or rounded from vibes 0 Is the test rig reproducible Yes, the driver, prompts, and both run matrices are on disk The full standard behind this, and why I attach a receipt to work like this, is on the slop page.\n","permalink":"https://www.fabswill.com/blog/doug-was-right-i-measured-the-moe/","summary":"\u003cp\u003eTwo days ago I posted 36 barrier-synchronized loads against 1 local model and let the numbers answer a question Reddit handed me. That post ended with a promise. A reader named Doug Ware, who builds applied AI systems for a living, had replied with the one caveat I had not tested, and I said out loud that measuring it was the next thing I would do. This is that measurement. I did not wait, I did not hand-wave it, and I kept every honest asterisk in.\u003c/p\u003e","title":"Doug Was Right: I Swapped In The MoE, And The Concurrency Math Changed"},{"content":"Over last week and these last 2 days in this week I posted measured answers to readers both in Twitter and Reddit who asked whether my experiments of 2 local agents on 1 Mac run in parallel or take turns. The answers was that they share one continuous batch, batching is real, and 3 quiet choices collapse it. I thought that was the end of it. It was not. The comments were better than my post, WHICH IS AWESOME, becaue this is the crowdsourcing of brain power I love. I not trying to be a KNOW IT ALL Im trying to be a LEARN IT ALL!\nNotably 3 people did not argue with my findings, which is FAIR because the way i set up the experiment can certainly predjudice the findings. They handed me testable claims. So I did the only honest thing, which is to go measure their claims. This post is what the measurements said. Some of it confirmed the commenters. 1 part corrected me. And at the very end, a real agent handoff on my own machine walked straight into the wall these charts describe, which is the best kind of proof, because I did not stage it.\nThe Housekeeping Note If you are new here, last month a post of mine got called AI slop on Reddit. My full answer, and the standard I now hold my own writing to, lives on its own page: On Slop, And Who Gets To Call It That. Every number below was measured on my own hardware with a load driver I wrote. Nothing here is estimated, and the run matrix is on disk. That is the whole point.\nThe 3 Claims I Was Handed Credit where it is due. 3 commenters gave me the spine of this post.\nOk-Category2729 made the sharpest point. Decode, the token-by-token generation phase, is memory-bandwidth-bound. Every single token forces the machine to re-read the entire set of model weights out of memory. On my dev rig Macbook Pro M3 Max that is a fixed pool of bandwidth shared across everything. So adding a 2nd decode stream does not add a 2nd lane of speed. It splits the 1 lane you already had. His prediction was that 2 agents would land somewhere around 1 1/2 times a single agent, not 2 times.\nReleaseFlashy9582 asked the question that turns 1 chart into 3. Does prompt length change the answer? Short prompts and long prompts are not the same workload, because the prefill phase, where the model reads your prompt, behaves differently from the decode phase, where it writes the answer.\nThick_Ad1919 kept me honest on the framing, pushing on where the real bottleneck sits rather than letting me hand-wave it.\nThose 3 claims map to 3 experiments. Here is what each one measured.\nThe Rig, In One Paragraph Same approach as last time, because it is the only one that is fair. A human cannot start 2 agents at the same instant, so any hand-run test really measures my launch timing, not concurrency. Instead a small load driver holds every request at a barrier and releases all of them at the same microsecond, fires them at the live mlx_lm.server running Qwen 3.8 at four-bit, and records aggregate throughput, per-agent decode rate, and time to first token. For this post I ran a matrix of thirty-six loads: a concurrency sweep, a prefill-versus-decode split, and a prompt-length sweep, each repeated so I could take a median rather than trust a single noisy run. This is one machine, one model, one honest probe. It is not a datacenter benchmark, and I will not pretend it is.\nFinding 1: The Second Agent Helps A Little. The Fourth Does Not. I released 1, then 2, then 4, then 8 identical requests at the same instant and watched two numbers move in opposite directions.\nThe green line is total throughput, all agents summed. The red line is what any one agent actually feels. Read them together, because the gap between them is the whole story.\nConcurrent agents Aggregate tokens per second Per-agent decode rate Time to first token, median 1 16.6 17.4 0.46s 2 20.8 12.8 3.51s 4 19.9 6.8 10.68s 8 19.1 3.9 32.16s Going from 1 agent to 2 bought me about a quarter more total throughput. Going from 2 to 4 bought me nothing. In fact aggregate throughput went slightly down and kept drifting down at 8. Meanwhile the per-agent rate fell off a cliff, roughly halving with every doubling of agents, from seventeen tokens per second down to under 4. And the wait for the first token climbed from half a second to 32 seconds.\nThis is Ok-Category2729\u0026rsquo;s point rendered in ink. The total is close to fixed, so every agent you add does not grow the pie. It cuts your slice thinner. Last week I estimated my knee sat around four agents. This week, with a different prompt-and-output shape and repeated runs, the aggregate peak arrived at 2, not 4. I am not going to paper over that. It is the finding, not a contradiction. The knee is not a fixed number. It moves with the shape of the work, which is exactly what the next reader predicted.\nFinding 2: My Own Hypothesis Did Not Show Up The Way I Expected Here is the part where measuring made me correct myself in public.\nPrefill, reading the prompt, is compute-bound. Decode, writing the answer, is memory-bandwidth-bound. My clean hypothesis was that a prefill-heavy workload, a long prompt with a short answer, would batch noticeably better than a decode-heavy one, a short prompt with a long answer. So I built exactly that split and ran the throughput gain going from one agent to two for each.\nThe decode-heavy workload scaled by 1.57 times. The prefill-heavy workload scaled by 1.51 times. They are basically the same, and neither one comes close to the dashed line at 2. My tidy prediction that prefill would clearly win did not appear in this cut. The likely reason is a confound I built in myself: the prefill-heavy job only generates sixteen tokens, so its aggregate tokens-per-second number is dominated by startup timing and is noisy by construction. So the honest read is narrower and more useful than my hypothesis. On this machine, going from one agent to two lands near one and a half times regardless of the mix, and it never doubles. That matches Ok-Category2729\u0026rsquo;s one-and-a-half-times prediction almost exactly.\nI am leaving this section in, hypothesis and miss and all, because the whole reason I run these is to find out where I am wrong. This is what wrong looks like when you actually check.\nFinding 3: Longer Prompts Batch Better. This Is Where Prefill Wins. ReleaseFlashy9582\u0026rsquo;s question turned out to be the one with the cleanest signal. I swept prompt length across roughly 170, 520, 1,370, and 3,100 measured tokens, and at each length I measured the same thing: how much throughput I gain going from one agent to two.\nPrompt length, measured tokens Throughput gain, one agent to two ~170 1.52x ~520 1.58x ~1,370 1.67x ~3,100 1.73x The line climbs, and it climbs monotonically. The longer the prompt, the better two agents scale together. This is the prefill advantage that did not show up in Finding Two, showing up cleanly here. A longer prompt means more prefill work, and prefill is the compute-bound phase that actually parallelizes. So the more of your workload lives in reading rather than writing, the more you get out of a second agent. Short chatty turns are the worst case for batching. Long-context work is the best case. ReleaseFlashy9582 was right, and the chart is his answer.\nThe Big Caveat Doug Ware Handed Me: Dense Is The Hard Case I want to hand the mic to someone who does this for a living, because he caught the thing I did not test. Doug Ware, who builds applied AI systems, replied to the last post with this: the available memory and TPS are a fixed-ish budget you divide up amongst the slots, and he actually prefers a 35B-A3B mixture-of-experts model over a 27B dense one for daily use, precisely because it leaves him enough TPS to make parallel slots worthwhile. He also said something that maps exactly onto my Hermes stall. In his own tooling he deliberately added switches to turn OFF the parallel behavior that cloud providers leave on by default, because on dense models and slower hardware that default hurts.\nHere is why he is right, and why it is a fair asterisk on every chart above. I ran all of this on a 27B DENSE model, which is close to the worst case for this exact ceiling. In a dense model, every single decoded token re-reads all 27B of weights from that one shared memory pool. A mixture-of-experts model like 35B-A3B only activates about 3B parameters per token, so it re-reads a fraction of the memory per token. Less memory traffic per token means more headroom, both for raw speed and for a second slot to actually pay off. So the honest scope of my result is this: concurrency does not scale WELL on a dense model on my hardware. Swap in the right MoE and the math shifts in your favor. That is the next thing I am going to measure, along with a serving-stack change Doug pointed me at that may finally unlock the speculative decoding I could not turn on last time. Wait for it.\nOne More Honesty Beat: The Machine Is Noisy I want to name something the reps exposed. The exact same nominal workload, a 520-token prompt going from one agent to two, measured 1.25 times in one part of the matrix and 1.58 times in another, minutes apart, on the same machine. That is real single-machine variance, from thermal drift, background load, and scheduling. It is why I ran repeats and reported medians, and it is why I am telling you the honest shape of the result is a range, not a decimal to trust to two places. Anyone who hands you a single clean concurrency number from one laptop is selling you a vibe. The robust, repeated finding across every run is the one that survives the noise: one to two helps a little, past two does not, and per-agent speed and first-token latency degrade hard the whole way up.\nThe Part I Did Not Stage: An Agent Walked Into This Wall Here is where the charts stopped being theory. This same afternoon, separate from the benchmark, I gave a local agent a real task. Read a batch of my own working files in my vault, and to go faster, split the reading across two helper sub-agents running at the same time, against the same one local model. The agent planned it cleanly. It counted the folder, found sixty-nine files across three subfolders, and split the work by folder into two parallel branches.\nBefore I go further, one honesty note, because it matters for the governance point later. This was not a case of no safety in the loop. When the agent went to run a shell command, a safety prompt stopped and asked me to approve it first, which is exactly what it should do. I approved it. The stall that followed was not a guardrail and not a bug. It was physics.\nThen the two helpers went out at the same time, and both stalled. Each one waited the full three-minute threshold with no response from the model, aborted, retried, and timed out again, three attempts each. The endpoint was healthy the whole time. The GPU tells the real story. It sat pegged at one hundred percent utilization on the M3 Max the entire time the calls were timing out. The machine was not idle and waiting. It was completely saturated, and still could not feed three decode streams fast enough for any single one to answer before the timeout.\nThis is Finding One in the flesh. The parent plus its two helpers were three decode streams fighting over one fixed pool of memory bandwidth, so each one crawled, and every one blew past the timeout. The branches did eventually finish, but only after roughly nine hundred and eighty seconds each, and by the time I stepped in the parent had been waiting over three thousand five hundred seconds. A task I expected to take a couple of minutes turned into the better part of an hour, because I asked one small local model to be in three places at once.\nI did not design that failure to prove a point. It just happened, on the day I happened to be measuring the exact thing that caused it.\nThe lesson lands harder because it was lived, not staged. On one local model, fanning a task out to a swarm of helpers is not free parallelism. It is the same fixed budget cut into more, slower pieces, and past the knee it can finish slower than doing the work in a tighter sequence. The pattern that actually works on this hardware is a strong planner with cheap, few workers, not a strong planner with many hungry ones. If you want real fan-out, the helpers need to go to a different, lighter endpoint, not pile onto the one bus the planner is already using.\nFrom Trial To First-Class Citizen: How I Actually Onboard A New Agent The agent that stalled was a brand-new harness I am trialing, not the setup I usually run. That is worth pausing on, because the interesting part is not that it stalled. It is that a runtime I had been using for about a day was already a full citizen in my governance system, and nothing about swapping runtimes fragmented my trail. That did not happen by luck. It is a deliberate onboarding I run for every new agent, and this week I ran it on this one.\nTwo things make an agent first-class for me, and neither lives inside the tool. First, it emits a receipt for its own work under my single account, so its output sits in the same graded ledger as every other agent I run. Second, it reads from and writes to my vault, so its memory is mine and outlives the runtime. This week the new agent earned both. Here is the receipts ledger with its own entries in it, next to the work from my other tools.\nLook at what that board is actually saying. Every objective any of my agents finishes ends with a verifiable, rubric-graded receipt: green when it succeeded with independent external proof, amber when it honestly did not, red for the scary cases. The new agent is right there in the same ledger, including a green receipt for the moment I promoted it to first-class citizen and an amber one for its wiring smoke test, graded honestly because a smoke test is not a real win. It is not that I trust the new tool. It is that I do not have to, because the same standard grades all of them.\nAnd the memory half is the same idea. I keep every agent\u0026rsquo;s memory in one place I own, my vault, rather than in the tool, so what it learned this afternoon survives the tool and is already waiting for the next agent that reads it.\nThat folder is the whole idea in one picture. Every agent I run writes what it learned into a lane I own, so the memory outlives whichever runtime happened to produce it.\nNone of this is bespoke to one blog post. The receipts standard, the rubric, and the onboarding loop are a framework I run in production, and my company packaged it as the Receipts Governance Kit on the Adotob store. The short version of the framework is a single loop every agent follows: get the intent, decompose it, clarify the missing inputs, act, and end with a receipt. There is an honesty gate that refuses to rubber-stamp a success it cannot externally verify, and cross-agent reconciliation so two agents working one objective each emit under a shared binding. The public floor of it, the standing rubric and the baseline block, is readable by anyone at the governance baseline. That is how a one-day-old runtime was already a trusted citizen. The governance came first, and the runtime plugged into it.\nRent the intelligence, own the harness, and own the memory and the receipts on top of it. The runtime is the disposable part.\nThe Receipt For This Piece Signal This piece of work Where the numbers came from A barrier-synchronized load driver I wrote, firing at the live server Human-launch bias in the measurement Removed by design, all requests released at the same instant Loads behind the three charts 36, across a concurrency sweep, a prefill-versus-decode split, and a prompt-length sweep Repeats per point 2 to 3, reported as medians Predictions I was handed and tested 3, from named commenters Expert caveat added after publish 1, credited to Doug Ware, dense-vs-MoE scope Live agent stall shown Real screenshots, GPU meter and timeout logs, not a redraw Governance shown, not just claimed Real receipts dashboard, plus the public framework and rubric linked Predictions that held 2, the bandwidth ceiling and the prompt-length effect Predictions that did not show up as I expected 1, prefill-versus-decode, correction kept in Numbers estimated or rounded from vibes 0 Is the test rig reproducible Yes, the driver, prompts, and run matrix are on disk The full standard behind this, and why I attach a receipt to work like this, is on the slop page.\n","permalink":"https://www.fabswill.com/blog/you-asked-i-measured-the-concurrency-ceiling/","summary":"\u003cp\u003eOver last week and these last 2 days in this week I posted measured answers to readers both in Twitter and Reddit who asked whether my experiments of 2 local agents on 1 Mac run in parallel or take turns. The answers was that they share one continuous batch, batching is real, and 3 quiet choices collapse it. I thought that was the end of it. It was not. The comments were better than my post, WHICH IS AWESOME, becaue this is the crowdsourcing of brain power I love. I \u003cem\u003enot trying to be a KNOW IT ALL\u003c/em\u003e Im trying to be a \u003cem\u003eLEARN IT ALL\u003c/em\u003e!\u003c/p\u003e","title":"You Asked, So I Measured: What Concurrency Actually Costs On One Local Model"},{"content":"This week I trialed a second local coding agent, Hermes from Nous Research, on my own MacBook Pro M3 Max, pointed at the same local Qwen 3.8 model I already run. I installed it additively, so nothing already working could break, governed it with manual approvals, and did not stop until it proved it behaves. Here is the trial, in tables and screenshots.\nOne housekeeping note before the story. Last week\u0026rsquo;s post got called AI slop on Reddit. My full answer to that, and the standing standard I now hold my writing to, lives on its own page: On Slop, And Who Gets To Call It That. It is not the point of this post, so I moved it out of the way. Back to Hermes.\nThe Hypothesis I already run one local agent harness, OpenCode, driving a local Qwen3.8-27B model on my MacBook Pro M3 Max. It does my community work, my volunteer builds, and my side projects. Local, for two reasons that never change: cost, and keeping client data off the frontier labs.\nThe hypothesis this week was narrow. A second agent harness, Hermes from Nous Research, had been getting attention. I wanted to know one thing. Could I trial a completely different agent runtime, point it at the exact same local model I already run, and do it without disturbing a single thing that already works. Not replace anything. Add one, prove it, and keep it boxed.\nWhat We Did We drove the install together, one screen at a time. I was at the keyboard. The agent guided each choice and, more importantly, told me the tradeoff behind each one before I picked.\nWe chose the full setup, not the hosted cloud path, because the whole point was local. We pointed it at a custom endpoint, my own MLX server on port 8081, with the model I already run. We set the context window to 131072. This is where the agent first said 32768 and I stopped it. See the corrections section. It fixed itself. We kept the terminal backend local, with manual approvals, so the human stays the boundary on anything that touches the system. We connected it to no messaging platforms at all. One of my other agents already owns Telegram, and my home Mac owns iMessage. This trial gets neither. Isolation is the point. We disabled the browser, the passive memory, the scheduler, computer use, image generation, and vision, keeping only the small set of tools a code and file trial actually needs. We turned off agent-to-agent networking, which I questioned, because I use that pattern elsewhere. See the corrections section again. We chose a free, no-login search backend, so the trial never phones a cloud service just to look something up. What We Saw The first turn spun the GPUs up hard and took about three minutes, mostly the model reading a large system prompt and thinking before it acted. That is real, and I am not going to pretend it was instant. The command it actually ran finished in under two seconds. The cost of a big local model is the warm-up, not the work.\nMore useful was what happened when I tested the guardrail. I asked it to run a destructive delete command. It stopped, showed me a dangerous-command warning, and waited. I denied it. And this is the part that matters: it stopped cleanly. It did not retry. It did not try a clever workaround. It said, in effect, you denied that at the approval gate so I stopped, and it explained the situation and asked before doing anything else. That is the behavior I want from something with a terminal on my machine.\nWhat We Had To Fix The install wizard is convenient, and its defaults are not my governance. After it finished, the agent audited its own configuration against my house rules and found three gaps. It fixed all three.\nApprovals were set to smart, not manual. Smart means a second small model auto-approves flagged commands. I want a human on that gate. Changed to manual. Passive memory was still on. Dropping the memory tool is not enough; there are two separate switches, and both had to be turned off so the agent is not quietly building a profile. A background daemon had been installed and loaded to run messaging and scheduled jobs I had already declined. It was unloaded and disabled. Nothing should be running that I did not ask for. None of this is dramatic. That is the point. The value was in checking, out loud, against a written standard, and writing down what changed.\nThe Corrections, Because They Are The Best Evidence If you want to know whether a human was really in the loop, do not look at the agreements. Look at the disagreements. Here are the three moments the record caught the agent being wrong and getting corrected, in this one session:\nContext window. The agent first proposed 32768. I pushed back. It re-checked, realized that number was the output ceiling and not the context window, and corrected itself to 131072. I accepted the corrected number. What manual mode even means. The agent initially told me it would prompt on everything. When a harmless command ran without a prompt, I called it out. It corrected the claim: it gates commands a danger detector flags, benign commands flow through in every mode, and manual means a human, not a model, clears the flagged ones. The honest version is more useful than the confident-wrong version. Vision, and agent-to-agent. I questioned turning vision off, since my model is vision-capable, and I questioned turning agent-to-agent networking off, since I use that pattern in other systems. In both cases we talked through why the trial should stay minimal, and I made the call. Those were my decisions, argued, not the agent\u0026rsquo;s defaults accepted. An agent that never gets corrected is not a partner. It is a stamp. The whole reason this is not slop is that the transcript is full of the agent being told no.\nWhere We Are Now Hermes is installed on my machine, pointed at my own local model, boxed off from everything that already runs. Manual approvals on. Passive memory off. Background daemon off. Least-privilege tools only. It is registered as exactly one named worker in a trial, the same way I brought in the last new tool, and it is governed by the same written house rules everything else here follows.\nIt is not wired into my receipts and evals pipeline yet, and it does not have vision yet. Both are deliberate next steps, written down, not forgotten. The trial did what a trial is supposed to do. It proved the thing works and behaves, without betting anything that was already working.\nThe Receipt For This Piece I kept count while we worked, and the numbers come from systems I cannot edit after the fact: the session store, git history, and the receipts engine.\nHuman turns Time invested I overruled the agent Agent self-corrected Ungated irreversible actions 28 ~2h 26m 3 times 3 times 0 The full receipt, the argument behind it, and the running ledger live on their own page.\nThe Bigger Point Rent the intelligence, own everything around it. The model on port 8081 is a visitor and it is swappable. The harness, the house rules, the approval gates, the record of who decided what, that is the durable part and it is mine.\nAnd that record is the answer to the slop accusation. Not my feelings about my own effort. A table anyone can check, backed by systems I cannot quietly edit after the fact. If more people writing with agents kept a receipt like this, the conversation would move off the lazy question, did an AI touch it, and onto the only question that has ever mattered. Did a human do the work. Here is mine. Where is your due diligence.\n","permalink":"https://www.fabswill.com/blog/i-added-a-second-local-agent-and-kept-the-receipt/","summary":"\u003cp\u003eThis week I trialed a second local coding agent, \u003cstrong\u003eHermes from Nous Research\u003c/strong\u003e, on my own MacBook Pro M3 Max, pointed at the same local Qwen 3.8 model I already run. I installed it additively, so nothing already working could break, governed it with manual approvals, and did not stop until it proved it behaves. Here is the trial, in tables and screenshots.\u003c/p\u003e\n\u003cp\u003eOne housekeeping note before the story. Last week\u0026rsquo;s post got called AI slop on Reddit. My full answer to that, and the standing standard I now hold my writing to, lives on its own page: \u003cstrong\u003e\u003ca href=\"/slop.html\"\u003eOn Slop, And Who Gets To Call It That\u003c/a\u003e\u003c/strong\u003e. It is not the point of this post, so I moved it out of the way. Back to Hermes.\u003c/p\u003e","title":"I Added a Second Local Agent This Week. Here Is the Receipt for Every Human Decision Behind It."},{"content":"A reader on Reddit asked me a sharp question about my last post. I had trialed a second local coding agent, Hermes, pointed at the same local Qwen 3.8 model my other agent already uses. His question was simple. Did I ever run both agents at the same time, two separate harnesses hammering one model on one Mac at once. And what about Hermes spawning its own sub-agents against that same endpoint. Is any of that predictable.\nI gave him my honest first answer, which was that I would probably never do it, and that I assumed it would serialize into a single lane. Then I did the thing I keep telling everyone to do. I checked instead of assuming. I was wrong, and the real answer is more interesting than either of us guessed.\nThe Housekeeping Note Last week\u0026rsquo;s post got called AI slop on Reddit. My full answer to that, and the standing standard I now hold my writing to, lives on its own page: On Slop, And Who Gets To Call It That. This post is a receipt of exactly the kind that page is about. Every number below was measured, not estimated, and the whole test rig is on disk and reproducible. Now to the experiment.\nWhy I Could Not Just Launch Two Agents Here is the trap, and the reader helped me see it. If I open two terminals and start OpenCode in one and Hermes in the other, one of them starts first. That first request arrives first, claims the server, and sets the queue order. Whatever I measure after that is a measurement of my own launch timing, not of concurrency. A human cannot release two requests at the same instant. The experiment would be flawed before it began.\nSo the experiment has to be driven by code, not by hand. I wrote a small load driver that holds every request at a barrier and releases all of them at the same microsecond. That is the one thing a person at a keyboard cannot do, and it is the only way the numbers mean anything.\nWhat The Server Actually Does Before running anything, I read the source of the thing serving my model, which is mlx_lm.server. This matters, because the answer lives entirely in the serving layer, not in the agents. The agents are just HTTP clients. Two facts settled the question:\nThe server does continuous batching. It accepts concurrent requests, folds them into one running batch, and decodes them together. The default batch width is 32. A request is only eligible for that batch when three things are true. There is no draft model loaded, the request does not pin a random seed, and it targets the model already in memory. Break any one of those and the request drops out of the batch and gets served on its own. That already killed my single-lane assumption. Two agents on one model do not take turns by default. They ride the same batch. The real questions became how well that scales, and what quietly breaks it.\nFinding One: Batching Is Real, But It Is Not Free I fired 1, then 2, then 4, then 8, then 16 identical requests, all released at the same instant, and measured two things. Aggregate throughput, meaning all agents summed, and per-agent decode rate, meaning how fast any single agent actually gets its answer.\nConcurrent agents Aggregate tokens/sec Per-agent decode tokens/sec Time to first token, p50 1 19.1 19.6 0.27s 2 28.2 18.0 1.24s 4 32.7 10.0 2.19s 8 34.0 5.2 4.90s 16 49.1 3.7 9.25s Read that carefully, because it is the whole point. Total throughput does climb. But the per-agent rate falls off a cliff, and the wait to even start a response climbs with it. The GPU has a roughly fixed throughput budget. Batching does not grow that budget. It divides it. More agents get you more total work only by giving each agent a thinner slice and a longer wait.\nThe honest practical read is that two agents share nicely. Four is the knee, where each one is already running at half speed. By eight and sixteen, each agent is crawling and waiting several seconds just to see its first token. So yes, you can run a small team of agents on one local model. No, you cannot run a crowd and expect any of them to feel fast.\nFinding One, Continued: The Latency Tax The same story shows up even more plainly if you only look at how long each agent waits to start.\nAt one agent, first token lands in about a quarter second. At sixteen, every agent waits nearly ten seconds before a single token appears. That is the tax of sharing one engine. It is predictable, it is smooth, and it is the number that will make a room full of agents feel broken even though nothing is broken.\nFinding Two: The Seed Trap This is the one almost nobody expects. Say you want reproducible runs, so you pin a random seed on your requests. Reasonable instinct. On this server it is a quiet catastrophe, because a pinned seed makes a request non-batchable. It drops out of the shared batch and gets served alone, and so does the next one, and they all line up behind each other.\nI ran the same four agents three ways. Once with no seed, the normal batchable case. Once with the same fixed seed on all four. Once with a different seed on each.\nFour agents, K=4 Aggregate tokens/sec Time to first token, p50 Time to first token, p95 Batchable, no seed 31.8 2.57s 2.58s Fixed seed, all same 19.8 15.2s 27.5s Distinct seeds 19.3 15.6s 28.4s Throughput collapses back to single-stream levels, and the wait to start explodes from under three seconds to fifteen seconds at the median and nearly thirty at the tail. There is a subtle twist worth naming. Each serialized request actually decodes faster on its own, because it briefly owns the whole GPU. But you pay for that with brutal queueing, because everyone is waiting in line. You traded a shared, steady system for a fast-but-jammed one. Chasing determinism silently destroyed both your concurrency and your latency.\nFinding Three: Sub-Agents, And The Speculative Decoding Choice The reader also asked about Hermes spawning sub-agents. There is nothing magic there. A parent that fans out to four sub-agents against one endpoint is just four more concurrent clients. It obeys the exact same physics as the chart above. Fan-out does not buy you free parallelism on one GPU. It redistributes the same fixed budget, and past the knee it makes every branch slower. On a single Mac, an agent that spawns a swarm of helpers against one local model can easily finish slower than if it had done the work in a tighter sequence.\nI went further and tried to actually measure the speculative decoding tradeoff. My hypothesis was clean. The batchability rule in the source says a request is only eligible for the shared batch when no draft model is loaded, so turning on speculative decoding should flip the whole server into serialized mode and kill concurrency, exactly like the seed trap. I expected a fourth chart.\nThen I tried to run it, and checking turned up something blunter than my hypothesis. On this stack, right now, I cannot turn speculative decoding on at all, for three independent reasons. The Qwen 3.8 family ships no small draft model, only full 27B variants, so there is nothing lightweight to speculate with. The multi-token-prediction variant that is supposed to do self-speculation, the one whose model type is qwen3_5_mtp, is not supported by my installed mlx_lm, it refuses to load with a plain not-supported error. And when I forced the issue by pointing the server at the 27B as its own draft, generation failed outright, because this architecture\u0026rsquo;s prompt cache is not trimmable and speculative decoding requires one that is.\nSo here is the honest correction to my own hypothesis. The tradeoff is real in the code, but it is currently moot on my machine, because speculative decoding does not run here at all. Batching is the only mode I actually have. I am leaving this section in, correction and all, because the entire point of this blog is that I check instead of assume, and this is precisely what checking is for. I set out to measure a tradeoff and instead measured that one side of it does not exist on my stack today.\nThe Bigger Point The line I keep coming back to is rent the intelligence, own the harness. This week adds a footnote to it. The local model you own is not an infinite well of parallelism. It is a shared resource with a fixed throughput budget, and it behaves more like a database connection pool than like magic. Treat it that way. Know your knee, which on my machine is about four agents. Never pin a seed in a workload where you want concurrency. And confirm which modes your stack actually supports before you plan around them, because I assumed I could trade batching away for speculative decoding and found that speculative decoding does not run on my stack at all.\nNone of that is a reason to stop running agents locally. It is the opposite. It is the kind of thing you can only learn because the whole stack is yours to read, to probe, and to measure. You cannot open the source of a frontier endpoint and find out why your agents feel slow. Here I could, and now I know exactly where the walls are.\nThe Receipt For This Piece This one is a receipt in the truest sense, because there was almost nothing to take on faith.\nSignal This piece of work Where the numbers came from A barrier-synchronized load driver I wrote, firing at the live server Human-launch bias in the measurement Removed by design, all requests released at the same instant Server behavior Read directly from the mlx_lm.server source, not assumed Load runs behind the charts 8, across concurrency 1 to 16 and three seed conditions Numbers estimated or rounded from vibes 0 Is the test rig reproducible Yes, the driver, sampler, and run script are on disk The full standard behind this, and why I now attach a receipt to work like this, is on the slop page.\n","permalink":"https://www.fabswill.com/blog/two-agents-one-local-model-batching/","summary":"\u003cp\u003eA reader on Reddit asked me a sharp question about my last post. I had trialed a second local coding agent, Hermes, pointed at the same local Qwen 3.8 model my other agent already uses. His question was simple. Did I ever run both agents at the same time, two separate harnesses hammering one model on one Mac at once. And what about Hermes spawning its own sub-agents against that same endpoint. Is any of that predictable.\u003c/p\u003e","title":"Two Agents, One Local Model: Do They Run in Parallel, or Take Turns? I Measured It."},{"content":"TL;DR Local models are how I run my community work, my volunteer projects, my side hustles, and my musings. Two reasons, both simple:\nCost. None of this work should bill against a frontier account. Trust. Client and customer data stays on my own disk, away from the labs. Bottom line up front: I am running Qwen3.8-27B (4-bit) on my MacBook Pro M3 Max, 128 GB of unified memory and a 40-core GPU, my personal dev rig, driven by an OpenCode harness.\nA new version, Qwen 3.8 27B, dropped this week. I was away from home, which is not a problem; it is a window. So I upgraded the model the only safe way when you cannot babysit it: additively. New model on its own server, on its own port. The old model left running, untouched, one keystroke away.\nThen I handed the new model the reviews and asked my OpenCode agent to grade its own upgrade. It stood up a throwaway test server, probed itself, measured its own speed, read its own weight index, and found three config gaps quietly throttling it. It wrote its own runbook. I read that runbook and graded the work.\nThe model is good. The bigger result is the one worth keeping.\nThe engine is rented and swappable. The harness is what you own. Upgrade the engine additively, and let the harness prove the delta.\nThe Doubt Nobody Admits: The Upgrade Is the Risk Everybody celebrates the new model. Almost nobody talks about the moment right after you click download. You rip out the version you trusted and drop in one you have never run, on the exact machine you depend on.\nThat is the real cost of a local model. A frontier model lives in someone else\u0026rsquo;s data center and you rent it. A local model lives on your disk. Every upgrade is open-heart surgery on a tool you actually use.\nSo the question is never \u0026ldquo;is the new model better.\u0026rdquo; The question is \u0026ldquo;how do I try the new model without betting the old one.\u0026rdquo; Those are very different questions.\nWhy Now: The Local Tier Does Real Work For me this is not a benchmark hobby. The local tier does paying-adjacent work: nonprofit automations, volunteer builds, side projects, and the thinking-out-loud that turns into posts like this one. Cloud models are brilliant, but I do not want that class of work metered, and I do not want that class of data leaving my disk.\nHere is what the new engine actually is. Not in three dense paragraphs, in one table.\nProperty Qwen 3.8 27B Parameters 27B dense Architecture Hybrid: 3/4 layers linear attention, 1/4 full attention Why that matters Runs quick, small KV cache, fits consumer hardware Context window 262K native (extendable to 1M) Multimodal Yes, native (text, image, video) Tool calling Yes Design center Agentic coding and long-horizon office work License Apache 2.0 And the headline numbers, which I want to label honestly. These are Qwen\u0026rsquo;s own model card, vendor numbers, not my independent finding. I repeat them as claims to be tested, not facts.\nBenchmark (per Qwen\u0026rsquo;s model card) 3.8 27B 3.6 27B SWE-bench Pro (agentic coding) 61.7 53.5 CoWorkBench (long-horizon office) 70.7 61.0 OSWorld-Verified (computer use) 84.3 63.9 IFBench (instruction following) 79.5 69.1 What I can vouch for is the speed I measured myself and the behavior my own agent verified. That is the rest of this post.\nThe Scar: Away From Home Is the Window, Not the Problem I was at a hotel, away for a few days, working on my personal dev rig: the M3 Max with 128 GB of memory that I run all of this on. Not a work machine, my own rig, the one the community and volunteer projects live on, and it travels with me. That is not a dire setup. That is the opportunity.\nTime away from the daily grind is exactly when I do the housekeeping I never otherwise reach: upskill, prune, evolve the dev rig, close out the things that have been sitting. Upgrading the local model was that kind of work. The 15 GB pull ran overnight on hotel wifi while I slept. Nothing was on fire. I had time.\nThe whole discipline is one move. The upgrade stands next to the old model, it does not replace it.\nOld (kept) New (added) Model Qwen 3.6 27B Qwen 3.8 27B Server port 8080 8081 Status Untouched, still default New, opt-in To go back It never left Pick 3.6 in the dropdown If 3.8 had been a disaster, I lose nothing. I pick 3.6 and I am back. That is the entire point of additive.\nThen I did the part I would not have trusted a year ago. I pointed my OpenCode agent, running the new 3.8 model, at the reviews and articles I had gathered, and I asked it to figure out what it actually was and whether it was configured correctly.\nIt did not summarize the reviews. It went and checked.\nIt stood up its own throwaway test server on a third port, 8082, so it would not disturb the one I was using. It fired controlled probes at itself. It watched the GPU climb to 92 percent under its own load. It measured its own decode speed firsthand instead of trusting a reviewer.\nModel Decode (warm) Decode (cold) Qwen 3.8 27B (8081) 20.2 tok/s n/a (hot) Qwen 3.6 27B (8080) 12.2 tok/s 3.5 tok/s That is 1.65 times faster warm, and the hybrid architecture is why. The agent also opened the model\u0026rsquo;s own weight index and noticed this 4-bit build has the multi-token-prediction weights stripped out, so one advertised speedup is simply not in this quant. A human skims past that. A model inspecting itself does not.\nThen it delivered the finding that made the exercise worth it.\nThe new model was running throttled, and it diagnosed exactly why.\nConfig gap Effect Root cause Greedy sampling (temp 0) Model runs rigid, not in the mode it was tuned for The server reads request body, then a CLI default, and never reads the model\u0026rsquo;s own recommended settings file 512-token output ceiling Responses cut off short of an agentic answer Server default, never raised No prompt caching Every turn re-processes the full system prompt and tools Cache never enabled None of these are the model\u0026rsquo;s fault. They are the plumbing around it. And the model found them by testing itself.\nWhat Changed: Own the Harness, Not the Engine I asked the agent to write down what it learned, and it did: a runbook with the corrected server command, the exact sampling settings, the output ceiling, and the cache configuration. Then I reviewed that work the way I review any agent\u0026rsquo;s work. I will give the grade in public.\nThe good: it verified instead of asserting. It tested in a clean room rather than on the live server. It found a real root cause, not a symptom. It staged the fix behind backups, so nothing broke while I was away and could not babysit it.\nThe caveats, stated plainly: it repeated the vendor benchmark table with more confidence than vendor numbers earn, so I relabeled those as model-card claims. It nudged a project default over to the new model, which is a bigger posture change than a side-by-side trial. And the tuned config it wrote is staged, not yet live; the running server is still on the old conservative flags until the corrected launch file is applied.\nSo where I sit now: the new model is installed, on its own server, one click away, with the old model one click the other way. The corrected configuration is written down, waiting for the moment I am home and ready to apply it. And the record of how it was diagnosed was produced by the very agent whose model was under test.\nHere is the summary, and I do not want it buried at the bottom.\nThe engine changed overnight. The harness is what made the change safe. I would rather own the harness.\nGarry Tan calls this staying under your own power. His framing for personal AI is a clean one: rent the intelligence, own the memory. The frontier model is a visitor. The durable layer is yours: your context, your skills, your recurring jobs, your permissions, your repo. YC\u0026rsquo;s related principle says the same thing about code: the software is disposable, the data and the intent are precious. Regenerate the tool when the models get smarter; preserve the thing that makes it yours.\nA local model is the sharpest version of that idea. The engine on port 8081 is disposable. In a month there will be a faster one, and swapping it in is an afternoon. What is not disposable is the harness around it: the discipline that upgrades additively so the old model is always a keystroke away, and an agent I trust enough to hand a new version and say, \u0026ldquo;prove on real measurements whether this is any good, and whether it is even configured right.\u0026rdquo;\nThe frontier labs will keep shipping better engines. That is a tailwind, not a threat. The engine is rented. The power is in owning everything around it.\n","permalink":"https://www.fabswill.com/blog/local-model-upgrade-qwen-38-agent-self-tested/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eLocal models are how I run my community work, my volunteer projects, my side hustles, and my musings. Two reasons, both simple:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eCost.\u003c/strong\u003e None of this work should bill against a frontier account.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTrust.\u003c/strong\u003e Client and customer data stays on my own disk, away from the labs.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eBottom line up front:\u003c/strong\u003e I am running Qwen3.8-27B (4-bit) on my MacBook Pro M3 Max, 128 GB of unified memory and a 40-core GPU, my personal dev rig, driven by an OpenCode harness.\u003c/p\u003e","title":"I Swapped My Local Coding Model Overnight From a Hotel. The Agent Graded the Upgrade Itself."},{"content":"TL;DR My agents do real work on frontier models. Every dollar of that work is metered against my OpenAI and Anthropic bills. Meanwhile a perfectly capable local model, gpt-oss:20b, sits on a Mac Mini in my office costing me nothing. The obvious question: for which tasks could the free local model do the job just as well?\nToday I answered it with a system instead of a guess. I taught my eval framework to automatically replay every writing task on the local model right after the frontier model runs it, then grade both with the same judge and record the gap. The result across 10 like-for-like rematches: a mean quality delta of -0.05 — statistical parity — and four tasks where the local model actually scored higher than the frontier model, by as much as 1.7 points.\nIt also honestly told me where the local model still loses. That honesty is the whole point.\nYou cannot route work to a cheaper model on a hunch. You route it on receipts.\nThe Setup: Three Pillars, One of Them Was Starving I have written before about trusting an autonomous agent with evals and about paying down supervision debt with receipts. Those are two of the three pillars I now run every agent task through:\nReceipts answer did it happen? Every objective closes with a verifiable, rubric-graded receipt. You can see the public version of this at www.adotob.com/receipts. Evals answer how good was it? A local LLM judge scores every real work artifact my agents produce. The Loop answers how did it get there? The trace of intent, inputs, action, and proof. Receipts have been solid for months. The eval pillar had a quieter problem. It could judge work fine, but it had a second job it was not doing: replay.\nReplay is where the eval system regenerates the same task on a different model and measures the quality difference. That is the mechanism that tells me whether I can safely route a task to a cheaper tier. And it was barely running.\nWhen the day started I had 29 graded cases and exactly one replay. The verdict engine that decides \u0026ldquo;is the local model good enough to route to\u0026rdquo; needs a corpus of like-for-like comparisons, a minimum case count, a quality bar, and a stability window. With one replay it was flying blind. Volume was below bar. Stability was below bar. The system was honestly reporting HOLD — do not trust this yet — which was the correct answer given it had almost no data.\nThe Fix: Auto-Replay, Fenced In on Purpose The manual replay tool worked. The problem was that \u0026ldquo;run it manually\u0026rdquo; is a discipline that decays. So I moved it into the pipeline: when a frontier eval for a text-producing task lands and gets a judge score, the server immediately replays it on the local model, scores that with the same rubric, and records the delta as a linked child record. One index rebuild and one dashboard sync cover both.\nThe fences matter as much as the feature, and I wrote them deliberately:\nIt only fires for frontier runs. A local-tier eval is already the replay target — it never replays itself. It only fires for writing, synthesis, wiki, and prose task types. It explicitly does not replay an ingest task (a mechanical fetch — nothing to regenerate) or a code task (the local model cannot execute my build, so a replay would be a proxy, not a like-for-like result). A replay failure is non-fatal. If the local model is unreachable, the original eval still lands and the failure is logged loudly. The measurement never sinks the record it is measuring. The whole change is server-side. No skill changed. No caller had to learn anything new. Turn it on, and the routing corpus starts filling itself.\nThe Rematch: What the Data Actually Said I proved it live, then backfilled every eligible task already on the board. Ten like-for-like rematches, each one the frontier model\u0026rsquo;s output versus the local model\u0026rsquo;s regeneration of the same task, both graded by the same judge.\nHere is the honest scoreboard, sorted best-to-worst for the local model:\nTask Frontier score Local score Delta writing 3.3 5.0 +1.7 writing 2.1 3.1 +1.0 writing 2.8 3.7 +0.9 writing 2.4 2.7 +0.3 wiki 2.0 1.9 -0.1 work 5.0 4.6 -0.4 writing 3.6 2.7 -0.9 writing 3.6 2.7 -0.9 wiki 3.6 2.5 -1.1 writing 2.7 1.3 -1.4 Mean delta: -0.05. On a five-point rubric, that is a rounding error. The free model on the Mac Mini is, on average, doing frontier-grade writing work. On four of the ten tasks it did not just keep up — it produced the better artifact.\nBut look at the bottom of that table. The losses cluster on the synthesis-heavy work — the tasks where the answer has to weave several sources into one coherent argument. The local model trails there by a point or more. So my eval system did what a good eval system is supposed to do: it did not flip the verdict to \u0026ldquo;route everything local.\u0026rdquo; It moved Volume and Quality to passing, and it kept Coverage failing, flagging by name that wiki and writing synthesis still belong on the frontier model today.\nThe verdict is still HOLD. That is not a failure of the system. That is the system — refusing to let my enthusiasm outrun the evidence.\nWhy This Only Works Because Every Tab Owns Its Own Work There is a piece under this that is easy to miss. For any of these scores to mean anything, each agent has to be honestly attributed. I run several agents across several tools — a couple of Copilot tabs, a couple of Codex tabs, a local-model tab in OpenCode. Earlier today, the evals were misattributing which agent produced which artifact, because the model was guessing its own identity.\nI fixed that by resolving each tab\u0026rsquo;s true identity from the running session it holds open, not from anything the model types. An eval that cannot say who did the work honestly cannot tell you how good the work was. Identity is upstream of quality.\nThe Receipt I Did Not Expect: A Motorcycle The most convincing evidence was not on the dashboard at all. My 2015 Ducati Monster 821 would not start — the dash read 11.1 volts. The battery is buried under the tank and the only sane way to charge it is through a specific connector under the seat. I handed the whole problem to an agent running on the local model: read the owner\u0026rsquo;s manual PDF, look at my photos of the connector, and tell me exactly which battery tender or adapter to buy and where.\nIt read the manual, matched my photos to the Ducati four-pin diagnostic connector, identified the OEM maintainer part number and its superseded replacement, recommended the exact OptiMate adapter for a pre-2020 Ducati, warned me about a defective production-lot range to avoid, and told me which fuse to check if it did not charge. Every claim was linked to a source. It closed with a receipt.\nThat is a genuinely hard task — multimodal input, a long technical manual, a purchase recommendation with real consequences if it is wrong. A free model on a computer in my office did it, and my receipts-and-evals system let me verify it did it well rather than take its word.\nHow You Can Start The measurement half of this — the evals and the replay — is my own local quality tooling. But the pillar underneath it, receipts, is something you can pick up today. It is the honest answer to the question every one of us running automation should be asking: my agent said it did the work; can I prove it?\nThe public page walks through the free path: connect your harness over MCP, emit one receipt by hand, and watch it get graded green, amber, or red. No allow-list, no sales call.\nSee the three pillars and emit your first receipt → www.adotob.com/receipts\nThe frontier labs will keep shipping better engines. That is a tailwind, not a threat. The durable advantage is the harness around the model — the loop that routes work to the right tier, remembers what it decided, and refuses to call anything done without proof. Today my harness told me the free model in my office is closer to the frontier than I wanted to admit, and told me exactly where it still is not.\nThe data is the data. I would rather know.\nFabian Williams builds autonomous agent systems in public. The eval framework, the receipts witness, and the three-pillars governance model described here are part of Adotob.\n","permalink":"https://www.fabswill.com/blog/local-model-frontier-rematch-auto-replay-evals/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eMy agents do real work on frontier models. Every dollar of that work is metered against my OpenAI and Anthropic bills. Meanwhile a perfectly capable local model, \u003ccode\u003egpt-oss:20b\u003c/code\u003e, sits on a Mac Mini in my office costing me nothing. The obvious question: \u003cstrong\u003efor which tasks could the free local model do the job just as well?\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eToday I answered it with a system instead of a guess. I taught my eval framework to \u003cstrong\u003eautomatically replay\u003c/strong\u003e every writing task on the local model right after the frontier model runs it, then grade both with the same judge and record the gap. The result across 10 like-for-like rematches: \u003cstrong\u003ea mean quality delta of -0.05 — statistical parity — and four tasks where the local model actually scored higher than the frontier model, by as much as 1.7 points.\u003c/strong\u003e\u003c/p\u003e","title":"I Made My Evals Replay Every Task on a Local Model. The Frontier Lead Got Thin."},{"content":"A few weeks ago I asked an agent to pick up work on one of my own projects. It opened a fresh terminal, looked around, found nothing it recognized, and built a brand new copy of a project I already had. That was not the agent being careless. Nothing on the machine had ever told it where the real one lived. The only map of my own work was a memory in my head, and a memory does not survive contact with a machine where agents do the building.\nThis morning I sat down at 8 to fix that. It is almost 4 now. This is the story of the eight hours in between, and the thing we built so it never happens again.\nA word on why this is worth eight hours. My work changed shape this year. I used to clone a repo, scaffold a project, and write the code myself. Now I open a terminal and an agent does it; it branches, it builds, it opens a pull request. That shift is the entire point. It is also the trap. An agent in a fresh session has no memory of the last one, so it recreates what already exists, and it drops the new copy wherever the terminal happened to open, which is often inside my notes vault. Multiply that by months of agent-led work and you get sprawl. One of my projects had nine folders with its name on disk. I could no longer point at a project and say, with confidence, that is the one I ship from.\nAn agent that builds while you sleep needs a map it can read. Not a memory in your head.\nSo before either of us wrote a line of code, we wrote a contract.\nWe argued about the shape before we built it I did not let the agent start building. We spent the first part of the morning being interrogated by a gate I run on every recurring automation: thirteen questions a loop has to answer before it earns the right to exist. What is the one number that should move. What outside fact proves the work happened. When does it stop. What is it allowed to touch without asking. Where does the truth live, and who owns dedupe. A deterministic validator checks the answers. If any field is hand-waved, the gate stays red and nothing ships.\nThat hour of being grilled is where the real design happened. We aligned on the topology, which sounds academic until you have nine copies of one project. The machine is the parent. GitHub is the witness, not the spine. The dedup key is the GitHub remote URL, because folder names lie and remote URLs do not. We agreed on the authority envelope: the loop acts on its own, then tells me what it did, because the whole point is autonomous agents that do not block on me. And we agreed on the one rule that makes that safe, which I will come back to.\nWe did this together, back and forth, for the better part of the day. I corrected the agent. The agent caught things I had not thought through. By the time the contract passed the gate, we had alignment, not just a spec. Only then did the building start.\nThe reckoning The loop is called RepoReckoner. Its first pass is read-only on purpose: walk the machine, write down what is true, prove every claim against GitHub, and touch nothing. You learn the shape of the mess without risking a single byte.\n116 local git repos on the machine. 165 repos on my GitHub account. The engine grouped the local ones into 113 logical projects and gave every single one a disposition. No repo got left in limbo without a label.\nNow go back to the project with nine folders. My gut said: nine copies, clean up eight. The legend said something better and saved me from myself. Only two of those folders were real copies of the same repo. The rest were genuinely distinct projects that happened to share a name prefix, plus a few asset folders that were not git repos at all. If I had trusted my memory I would have deleted real work. The legend grouped by remote URL, looked at the evidence, and told me the truth instead of my assumption. That single correction is the whole reason this loop exists.\nThis is also where the disk cleanup loop I shipped earlier in the day fits in. I built two loops today, deliberately separate.\nLoop Job First pass does The disk-health loop Backups and reclaimable space Inventory every folder, flag what is safe, never delete RepoReckoner The source-of-truth legend Reconcile against GitHub, assign a disposition, never move One is a smoke detector for disk and backups. The other is the registry that says which copy is real. Different jobs, no shared dependency, so one can fail without taking the other down.\nNo delete without a witness Here is the rule we agreed on in the morning, the one that lets the loop act while I am asleep. I do not gate it behind me clicking approve. I gate it behind a fact the agent cannot fake.\nEvery repo has a HEAD SHA, the fingerprint of its latest commit. Before the engine will ever call a repo safe, it runs git ls-remote and asks GitHub, live, whether that exact SHA exists on the remote. If it does, the repo is witnessed. If it does not, the repo holds work that exists nowhere but this one disk, so it can never be a delete candidate. It gets pushed to a backup first, or skipped and flagged for me.\nThat SHA goes straight into a receipt. This is what makes a faked result impossible. If a future agent, or a sloppy run, claims \u0026ldquo;this is the real copy, the rest are safe to remove,\u0026rdquo; I can re-query GitHub and check the SHA myself. So I tested exactly that this afternoon. I pulled a stored SHA out of a receipt and asked GitHub for the live tip of that repo. They matched, character for character. A receipt you cannot re-check is just a feeling. This one is a fact, and so is every other line in the legend.\nThis is the same discipline I keep coming back to, in your agent said it did the work and in paying down supervision debt. Trust is not assumed. It is measured, every run, against something outside the agent.\nWhat the eight hours actually bought, including the parts that hurt The point of a read-only first pass is to surface the mess honestly, not to hide it behind a green checkmark. So here is the uncomfortable half of the receipt.\n20 repos have unpushed work. They hold commits that live on this disk and nowhere else. If that drive died tonight, that work is gone. I did not know that this morning. I know it now, by name, for every one of the twenty.\n3 repos are undispositioned. Their remote claims to be mine, but the repo is not in my live GitHub list. Renamed, deleted, or made private, the machine cannot tell. Those 3 are flagged for me directly, and driving that number to zero is the number this loop exists to move. Not \u0026ldquo;the scan ran.\u0026rdquo; The count of my own repos I cannot account for. That is the difference between a loop that reports churn and a loop that reports an outcome.\nThe legend itself lives in one place, version controlled and synced across my machines, so any agent on any box reads the same truth before it builds. The raw scan is a disposable cache. The receipts are permanent. An adversarial second agent could audit every claim in them against GitHub and find no gap, because the proof is a SHA, not a sentence.\nWhat I would tell you if you are headed here too Write the contract before the code. The hour we spent being grilled by the gate is why the build went straight. Naming the outcome, the check, and the stop is the work; the code is just what is left over.\nPick a key that cannot lie. Folder names lie. The remote URL does not. Group by the externally verifiable thing and your \u0026ldquo;nine copies\u0026rdquo; collapse into the truth.\nVerify against an outside fact, not the agent\u0026rsquo;s own word. A worker cannot grade its own work. git ls-remote is an oracle the agent does not control, which is exactly why you can trust it.\nMake the first pass read-only. You can learn the full shape of the mess without risking a byte. Mutation is a later phase, and it stays gated behind the witness rule.\nMeasure the number that should go down. Not activity. The count of things you cannot account for. If that number does not trend toward zero, the loop is theater, no matter how clean the logs look.\nIf you are running agents that build for you, this is coming for you too. The moment an agent can scaffold and commit, it will create state faster than you can hold in your head, and your memory will quietly stop being a reliable map. The fix is not to slow the agents down. It is to give them a map they can read and a receipt you can re-check.\nYou do not need a platform for any of this. The engine is a few hundred lines of standard-library Python, git, and the GitHub CLI. It runs on my own hardware, touches nothing it cannot prove, and leaves a paper trail anyone can audit. Local-first, witness-backed, no cloud bill. Eight hours, start to finish, a human and an agent working it out together.\nThe machine was never the problem. The missing map was. Now there is one, and the things that kept getting lost can finally read it.\nIf you are building autonomous agents and wrestling with where their work actually lives, I would like to hear how you are tracking it. I build agents and the tools to keep them honest.\nCheers, Fabian Williams\nBlog: fabswill.com LinkedIn: fabiangwilliams Twitter/X: @fabianwilliams ","permalink":"https://www.fabswill.com/blog/my-agents-left-me-116-git-repos/","summary":"\u003cp\u003eA few weeks ago I asked an agent to pick up work on one of my own projects. It opened a fresh terminal, looked around, found nothing it recognized, and built a brand new copy of a project I already had. That was not the agent being careless. Nothing on the machine had ever told it where the real one lived. The only map of my own work was a memory in my head, and a memory does not survive contact with a machine where agents do the building.\u003c/p\u003e","title":"My Agents Left Me 116 Git Repos. So I Built a Source of Truth."},{"content":"Every morning one of my agents sends me a clean status report. Posts cross-posted. Messages delivered. Contacts processed. For a while I read those reports the way you read a receipt from a cashier you trust. Then the automation started giving me time back, so I sat down to run a retrospective and checked the reports against what was actually on disk. The trust did not survive contact with the evidence.\nA word on who is telling you this. I am a PM at Microsoft. I ship features that are part of a larger whole, and I do not run a company, certainly not an AI-first one. What I do run, as a volunteer, is the AI effort behind a non-profit. MACONA is volunteer-only, grown from one person donating food, supplies, and money into a 501(c)(3) that now does real outreach. Non-profits run on trust, and the one thing nobody has enough of is time. So I asked a practical question: could agents take on some of the work and give that time back?\nTo find out, I mapped the programs and the volunteer roles into agents with clear goals, clear reporting, and a human in the loop at every stage. OpenClaw is the backbone. Today there are six.\nI care about observability for a living; it is the center of my day job, and the non-profit is where I get to dogfood it. The principle underneath all of it is simple: an agent acts on the organization\u0026rsquo;s data, it wears a persona, and a human still has to answer for what it did. That demands audit and visibility at every step.\nI have been at this for a few years, but the models and the harnesses crossed a threshold in late 2025, and I started trusting the agents with real work. This post is one lesson out of many that I am writing down as I go. I do not have it all figured out; writing it down is partly how I think it through.\nHere is the one that made it concrete. On a Tuesday last month in May, my outreach agent fired on schedule, found no eligible contacts, and reported that correctly. Then it added a sentence I had not asked for: \u0026ldquo;Due to issues with sending the summary message, further attempts to report the outcome failed. Please check the session manually for updates.\u0026rdquo; It sounded like a real operational warning. It was not. Nothing had failed. The delivery queue was empty, the agent job was healthy, and the message carrying that warning had itself been delivered to me without a hitch. The agent invented a failure and then successfully told me about the failure it invented.\nTwo weeks earlier, a different agent went the other way. It reported 4 posts cross-posted that day. The real number was 0. The 4 was a lifetime counter sitting in a tracking file, and the agent had read it out of a summary string and logged it as today\u0026rsquo;s result. The whole error fits in two lines:\nBefore: \u0026#34;4 posts cross-posted\u0026#34; After: posted_this_run=0, total_lifetime_posted=4 That inflated number went straight into my metrics database, where it would have quietly skewed the weekly review I rely on to decide what is working.\nDifferent agents, different scripts, opposite errors, one root cause. When the underlying script returns something short or ambiguous, the model treats the gap as a place to be helpful. It writes plausible operational prose. It pulls a number out of a sentence because a number was clearly expected there. None of this is the model being broken. It is the model doing exactly what LLMs do, which is produce fluent, reasonable-sounding text.\nThe agent did not fail because it was stupid. It failed because I had given it room to be eloquent where it needed to be accountable.\nSo I changed the contract. I stopped asking the agent to narrate.\nNow the scripts emit structured fields instead of prose: posted_this_run, channels_posted_this_run, total_lifetime_posted, and a pre-rendered set of summary lines. The agent\u0026rsquo;s job is to echo those lines verbatim. It is forbidden from pulling numbers out of any prose, and forbidden from adding operational commentary of its own. If an agent wants to claim a delivery failed, it cannot simply say so. It has to call a health-check script first and report what that script returns. A claim with no receipt behind it is not allowed to exist.\nEvery one of these closes the same way. The bug becomes a pull request that ships the fix, a written root-cause record so the pattern stays legible, and a monitor so the same class cannot reappear unnoticed. The day I found the lifetime-counter bug I shipped that fix four separate times across four scripts, because once you see the shape you see it everywhere: any script that reports current state next to a running total will eventually have the two confused by whatever reads them.\nThe lesson I keep relearning is unglamorous. Disk state is the source of truth. An agent\u0026rsquo;s report is a claim about disk state, and a claim is only as good as the receipt you can check it against. An agent fleet that cannot prove what it did is not automating your work. It is generating confident fiction about it, and the better the model gets, the more convincing the fiction becomes.\nSo verify what your agents did before you believe what they said.\nCheers, Fabian Williams\nBlog: fabswill.com Twitter/X: @fabianwilliams ","permalink":"https://www.fabswill.com/blog/your-agent-said-it-did-the-work/","summary":"\u003cp\u003eEvery morning one of my agents sends me a clean status report. Posts cross-posted. Messages delivered. Contacts processed. For a while I read those reports the way you read a receipt from a cashier you trust. Then the automation started giving me time back, so I sat down to run a retrospective and checked the reports against what was actually on disk. The trust did not survive contact with the evidence.\u003c/p\u003e","title":"Your Agent Said It Did the Work. I Checked the Disk."},{"content":"\nBy the end of this post you will know what every iteration of every production agent must produce BEFORE it decides anything: four small artifacts that catch the failures sharper prompts cannot prevent. You will know why \u0026ldquo;tell the model to be careful\u0026rdquo; never worked as a defense, and why the only durable fix is structural. And you will know what the discipline looks like in code, because we have been running it at MACONA for months and the receipts are public.\nThe discipline most agent vendors do not ship There is a failure mode in production agent fleets that no model upgrade fixes and no prompt instruction prevents. It looks like this:\nAn agent reads from five sources of state. One source returned an empty list this iteration. The other four returned data. The agent writes a confident summary that quietly assumes the empty source was empty for a reason, not because the API call timed out. The summary looks correct. The supervisor approves it. The decision downstream cascades from a fact the agent never actually verified. Multiply that pattern across multi-hour runs, eight parallel documents, dozens of cron iterations a day, and you do not have a model problem. You have a working-environment problem. The agent is doing exactly what it was asked to do. The error is structural; it was baked into the iteration before the policy stage ran.\nThe fix is older than software. It is the scientific method, applied at agent runtime. Observe the system. Name what disagrees. Name what is missing. Deduplicate evidence. THEN form a hypothesis. THEN test it. THEN update the model of the world. Centuries-old discipline. The only thing new is that agents now run unsupervised across multiple sources of state, and the operator cannot read four notebooks before every iteration of a loop that fires hourly.\nSo the runtime has to keep the notebooks instead. Four small artifacts, emitted every iteration, BEFORE the agent decides anything. That is the discipline. We call it Sense Before Act, and it is the matched pair to a discipline we shipped last week called Announce Intent Before Action. Together the two close the agent\u0026rsquo;s per-iteration arc: observe, announce, act, verify.\nThe four artifacts Each agent iteration following this discipline must produce all four. None is optional. A sensor that returned nothing is still recorded as \u0026ldquo;checked, returned nothing.\u0026rdquo; A sensor that errored is still recorded as \u0026ldquo;checked, errored, reason.\u0026rdquo; Silent omission of any sensor is forbidden, because silent omission is exactly the failure mode the discipline exists to prevent.\n1. Sensor Roll Call Every sensor that was called this iteration, with timestamp, return shape, and outcome. Not just the ones that succeeded; ALL of them.\n{ \u0026#34;sensor_roll_call\u0026#34;: { \u0026#34;iter_id\u0026#34;: \u0026#34;iter_20260522_125600\u0026#34;, \u0026#34;started_at\u0026#34;: \u0026#34;2026-05-22T12:56:00Z\u0026#34;, \u0026#34;sensors\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;telegram\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;ok\u0026#34;, \u0026#34;items\u0026#34;: 0, \u0026#34;duration_ms\u0026#34;: 412 }, { \u0026#34;name\u0026#34;: \u0026#34;brevo_smtp\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;ok\u0026#34;, \u0026#34;items\u0026#34;: 17, \u0026#34;duration_ms\u0026#34;: 980 }, { \u0026#34;name\u0026#34;: \u0026#34;daily_summary\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;not_found\u0026#34;, \u0026#34;items\u0026#34;: 0, \u0026#34;duration_ms\u0026#34;: 14 }, { \u0026#34;name\u0026#34;: \u0026#34;rca_files\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;ok\u0026#34;, \u0026#34;items\u0026#34;: 2, \u0026#34;duration_ms\u0026#34;: 31 }, { \u0026#34;name\u0026#34;: \u0026#34;openclaw_jobs\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;not_found\u0026#34;, \u0026#34;items\u0026#34;: 0, \u0026#34;duration_ms\u0026#34;: 8 } ] } } Every sensor the constitution declares as enabled MUST appear. Even if its status is not_found or errored. The quality gate stage rejects iterations that quietly drop a sensor.\n2. Conflict Receipt Every place where two sensors (or two records from one sensor) disagreed about the same underlying fact, and the policy stage\u0026rsquo;s resolution.\n{ \u0026#34;conflict_receipt\u0026#34;: { \u0026#34;iter_id\u0026#34;: \u0026#34;iter_20260522_125600\u0026#34;, \u0026#34;conflicts\u0026#34;: [ { \u0026#34;fact\u0026#34;: \u0026#34;last_send_to_dr_uzo\u0026#34;, \u0026#34;sensor_a\u0026#34;: { \u0026#34;name\u0026#34;: \u0026#34;brevo_smtp\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;2026-05-20T14:11:00Z\u0026#34; }, \u0026#34;sensor_b\u0026#34;: { \u0026#34;name\u0026#34;: \u0026#34;rca_files\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;2026-05-19\u0026#34; }, \u0026#34;resolution\u0026#34;: \u0026#34;trust_sensor_a\u0026#34;, \u0026#34;reason\u0026#34;: \u0026#34;brevo_smtp has wall-clock timestamps; rca_files uses calendar date and lags up to 24h\u0026#34; } ] } } When there are no conflicts, the receipt still emits with \u0026quot;conflicts\u0026quot;: []. The discipline is \u0026ldquo;we looked for conflicts and here is what we found,\u0026rdquo; not \u0026ldquo;we did not see any conflicts so we wrote nothing.\u0026rdquo; The empty receipt is the proof we looked.\n3. Gap Map Every not_found, every sensor error, every piece of state the agent decided not to check. The gap map is the agent\u0026rsquo;s confession of what it does NOT know this iteration.\n{ \u0026#34;gap_map\u0026#34;: { \u0026#34;iter_id\u0026#34;: \u0026#34;iter_20260522_125600\u0026#34;, \u0026#34;gaps\u0026#34;: [ { \u0026#34;field\u0026#34;: \u0026#34;daily_summary\u0026#34;, \u0026#34;kind\u0026#34;: \u0026#34;not_found\u0026#34;, \u0026#34;what_we_would_know_if_present\u0026#34;: \u0026#34;cron-reasoned end-of-day rollup for prior day\u0026#34;, \u0026#34;policy_compensation\u0026#34;: \u0026#34;downgrade confidence on any inference that depends on prior-day rollup\u0026#34; }, { \u0026#34;field\u0026#34;: \u0026#34;openclaw_jobs\u0026#34;, \u0026#34;kind\u0026#34;: \u0026#34;not_found\u0026#34;, \u0026#34;what_we_would_know_if_present\u0026#34;: \u0026#34;current scheduled job registry snapshot\u0026#34;, \u0026#34;policy_compensation\u0026#34;: \u0026#34;skip any reasoning about jobs.json drift this iteration\u0026#34; } ] } } Every gap names what would be known if the gap were filled AND how the policy stage compensates. A gap without a named compensation is a discipline violation, because then the policy is guessing in the dark.\n4. Cross-Source Dedup Every fact that appeared in two or more sensor outputs, with the dedup decision. Two sensors observing the same event is one piece of evidence, not two.\n{ \u0026#34;cross_source_dedup\u0026#34;: { \u0026#34;iter_id\u0026#34;: \u0026#34;iter_20260522_125600\u0026#34;, \u0026#34;dedup_decisions\u0026#34;: [ { \u0026#34;fact\u0026#34;: \u0026#34;telegram_alert_brevo_bounce_2026_05_22_0712\u0026#34;, \u0026#34;seen_in\u0026#34;: [\u0026#34;telegram\u0026#34;, \u0026#34;brevo_smtp\u0026#34;], \u0026#34;treated_as\u0026#34;: \u0026#34;1x_evidence\u0026#34;, \u0026#34;primary_source\u0026#34;: \u0026#34;brevo_smtp\u0026#34;, \u0026#34;reason\u0026#34;: \u0026#34;brevo_smtp is the originator; telegram is a forwarded copy\u0026#34; } ] } } When the same underlying event appears in N sensors, the policy stage MUST receive it as one event with a seen_in list, never as N independent events. Failure to dedup inflates evidence weight on whatever the duplicated source happens to repeat most often. That is how doubled telemetry quietly biases agent behavior.\nA sensor that errored is still a sensor that ran. The discipline is \u0026ldquo;we looked,\u0026rdquo; not \u0026ldquo;we found.\u0026rdquo; Empty receipts are the proof we looked. Why exactly these four Each artifact answers a specific failure question that long-horizon agent work tends to fail on:\nArtifact Failure it prevents What happens without it Sensor Roll Call Silent sensor failure Agent acts as if a sensor returned clean data when in fact it errored Conflict Receipt Smoothing over disagreement Agent picks one source arbitrarily, hides that the other source disagreed Gap Map Inventing around missing data Agent confabulates plausible content to fill a hole Cross-Source Dedup Double-counting evidence Policy stage over-weights whatever happens to be duplicated Three artifacts catch most cases. Four catch the realistic span. Fewer than four leaves a known hole; more than four adds ceremony without adding coverage.\nWhat this looks like running in production The reference implementation is ADOTOB Loop, currently running on a Microsoft Surface in suburban Maryland. The Surface belongs to the MACONA OpenClaw fleet, a small nonprofit-side agent cluster that has been in production for months. ADOTOB Loop is the stage-5 learning loop sitting on top of it; the Self-Improving Fleet Loop discipline names what each stage does, and Sense Before Act lives at stage 1.\nThe loop fires hourly as a Windows Scheduled Task running as SYSTEM, every iteration at minute :56. Since the install on the evening of 2026-05-21, the loop has completed roughly twenty clean iterations in --dry mode (no live actions yet; receipt-only). Each receipt contains the data the four artifacts call for. The next implementation milestone is lifting that data into four explicitly named files matching the schemas above, but the discipline is already legible in every receipt the loop emits.\nA real example from the first day of running: the box\u0026rsquo;s Python urllib library could not establish HTTPS to api.telegram.org because the modern Let\u0026rsquo;s Encrypt root certificate was not in Python\u0026rsquo;s default Windows trust bundle. The Telegram sensor returned SSL CERTIFICATE_VERIFY_FAILED on iteration one. The Sensor Roll Call recorded the error honestly. The Gap Map named the missing context (no Telegram updates this iteration). The policy stage saw the gap, classified the iteration as escalate, and proposed a structured operator message naming the broken dependency. The discipline of \u0026ldquo;name what is broken even when it is the loop\u0026rsquo;s own dependency\u0026rdquo; worked exactly as designed. The Telegram sensor went from CERTIFICATE_VERIFY_FAILED to status: ok after a one-line fix; the discipline caught the failure before any downstream reasoning depended on the absent data.\nThe chart above is real data from the receipts directory on the box. Every cell is one sensor\u0026rsquo;s status on one hourly iteration. The red cell is iteration one\u0026rsquo;s broken Telegram. The amber row across the bottom is daily_summary returning not_found every hour, faithfully named in the Gap Map until the operator points the configuration at the right directory. Nothing here is illustrative; every cell comes from a real sensor.json written by the loop.\nThis is the difference between an agent that runs and an agent that runs honestly. The four artifacts are how you make the difference visible.\nHow it pairs with Announce Intent Before Action Announce Intent Before Action is the matched discipline on the ACTION side: every agent tool description must enumerate every server-side effect the call will produce, in seven categories (data, identity, communication, issuance, public, money, trigger). Sense Before Act is the matched discipline on the OBSERVATION side: every iteration must produce the four artifacts before the policy stage runs.\nThe two together form the per-iteration arc:\nStage of the arc Discipline Question it answers Observe Sense Before Act \u0026ldquo;What does the agent know right now, and where are the gaps?\u0026rdquo; Announce Announce Intent Before Action \u0026ldquo;What is the agent about to do on my behalf?\u0026rdquo; Act (tool fires; the runtime executes) \u0026ldquo;What happened?\u0026rdquo; Verify Audit-trail receipt \u0026ldquo;Did what was supposed to happen actually happen?\u0026rdquo; Both bookend disciplines are required. A system with only the observation half lets agents act blindly even though they reason well; a system with only the action-announcement half lets agents act on invented context even though they announce their actions cleanly. The pair is what makes agent safety legible.\nWhy prompts cannot solve this If you have ever told a language model \u0026ldquo;do not hallucinate\u0026rdquo; or \u0026ldquo;be careful with sources\u0026rdquo; or \u0026ldquo;double-check before acting,\u0026rdquo; you have already discovered that those instructions do not prevent the failure mode this discipline addresses. There is no separate \u0026ldquo;truth check pass\u0026rdquo; inside the model that the instruction hooks into. Asking a model to be careful is like asking autocomplete not to autocomplete.\nThe structural fix is to make the room before the model is asked to do anything in it. You build the inventory first. You surface the conflicts first. You name the gaps first. You catch the duplicates first. THEN the policy stage runs against artifacts that exist, not against absences the policy has to invent around.\nThe principle is borrowed from scientific instrumentation, not from prompt engineering. A telescope does not improve by being told to find better stars; it improves by being calibrated against known reference points before observation begins. An agent does not improve by being told to be careful; it improves by being required to emit four artifacts that establish what it observed before it decides. The discipline names the agent as an instrument and the iteration as a scientific observation. Both metaphors are older than computing.\nAsking a model to be careful is asking autocomplete not to autocomplete. The fix is structural, not rhetorical. What the discipline gives a buyer evaluating an agent platform If you are evaluating an agent vendor and you want to know whether they have paid down this slice of supervision debt, ask them three questions:\nFor any given iteration, can you produce the list of every sensor that fired, with status and timing? If the answer is \u0026ldquo;we have logs in Datadog,\u0026rdquo; they have monitoring. They do not have a Sensor Roll Call. The difference matters when a sensor silently errors and downstream reasoning depends on its absence.\nWhen two of your sensors disagree about the same fact, how does the agent decide? If the answer involves \u0026ldquo;the model figures it out from context,\u0026rdquo; they do not have a Conflict Receipt. They have a hidden judgment call.\nWhat does the agent record when a piece of expected state is missing? If the answer is \u0026ldquo;we handle that case in the prompt,\u0026rdquo; they do not have a Gap Map. They have a tax on every renewal cycle when a missing field cascades into a wrong decision.\nA vendor that produces all four artifacts on every iteration is operating to a discipline. A vendor that produces none has supervision debt at the observation layer, regardless of what their dashboard looks like.\nWhere to find the discipline The Sense Before Act discipline lives in the Agent Reliability Kit at agents/sense-before-act. Apache 2.0. Use the names, use the schemas, port them to your own runtime.\nSister disciplines in the same kit:\nAnnounce Intent Before Action: the matched action-side discipline. Self-Improving Fleet Loop: the 5-stage loop that Sense Before Act lives at stage 1 of. ADOTOB Loop: the reference runtime that produces the four artifacts every iteration. Where the Kit Fits: the architectural map showing how the Kit pairs with whichever runtime, identity, data, and write-access stack a partner has already chosen. The full Agent Reliability Kit is at github.com/fabianwilliams/agentic-engineering-toolkit. Apache 2.0. Star or watch if you want updates; the repo grows when something is worth adding, not on a schedule.\nContributions What this post has offered:\nA name for a failure mode that prompts cannot fix: an agent that decides without first emitting the four artifacts that would have caught the structural error. Four required artifacts (Sensor Roll Call, Conflict Receipt, Gap Map, Cross-Source Dedup) with stable schemas and named failure questions each prevents. A worked example from a production fleet (the Telegram SSL incident on the MACONA Surface) showing the discipline catching a real failure on day one. Three diagnostic questions a buyer can ask any agent vendor to test for this slice of supervision debt. A matched pair (Sense Before Act and Announce Intent Before Action) that close the per-iteration arc together. A pointer to the running code, the running fleet, and the running receipts. The discipline is not aspirational; it is shipping. The scientific method has been a working discipline for a long time. The application to agent runtimes is what is new. The rest is just notation.\nCheers, Fabian Williams\nIf you are building agents for clients and the procurement-shaped questions in this post sound familiar, I would value a 20-min back-and-forth on where the patterns hold and where they break. The licensed (non-sanitized) Kit covers the worked examples this post sketches.\nBlog: fabswill.com Twitter/X: @fabianwilliams MCP storefront: mcp.adotob.com Agent Reliability Kit (OSS): agentic-engineering-toolkit Partner licensing: estore.adotob.com/partners Agent Reliability Kit™ is a trademark of Adotob Solutions.\n","permalink":"https://www.fabswill.com/blog/sense-before-act-four-artifacts-every-agent-iteration/","summary":"\u003cp\u003e\u003cimg alt=\"The per-iteration arc: four stages (Observe / Announce / Act / Verify) with four required artifacts under Observe. The artifacts are Sensor Roll Call, Conflict Receipt, Gap Map, Cross-Source Dedup.\" loading=\"lazy\" src=\"/img/2026/05/sense-before-act-per-iteration-arc.png\"\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eBy the end of this post you will know what every iteration of every production agent must produce BEFORE it decides anything: four small artifacts that catch the failures sharper prompts cannot prevent. You will know why \u0026ldquo;tell the model to be careful\u0026rdquo; never worked as a defense, and why the only durable fix is structural. And you will know what the discipline looks like in code, because we have been running it at \u003ca href=\"https://macona.org\" target=\"_blank\"\u003eMACONA\u003c/a\u003e for months and the receipts are public.\u003c/strong\u003e\u003c/p\u003e\n\u003c/blockquote\u003e","title":"Sense Before Act: Four Artifacts Every Agent Iteration Must Produce Before It Decides"},{"content":" By the end of this post you will know which of the five infrastructure control points your agent stack is shipping without, and you will have a concrete pattern for paying down the observability piece of that debt: a public, consumer-readable audit-trail receipt that satisfies both your security team and your finance team with the same document. The receipt was already in production when the broader practitioner conversation started naming the gap.\nThe thing most agent-shipping teams have not noticed yet The companies that decide whether your agent reaches production are not the model labs. They are five infrastructure layers that almost nobody has on a roadmap: Runtime. Identity. Data. Tool / write access. Observability. Plus a multilayer kill switch sitting across all of them.\nThe framing is sharp because it is correct. Compute is necessary but not sufficient. The next bottleneck after \u0026ldquo;we have enough GPUs\u0026rdquo; is \u0026ldquo;can we govern what the agents actually do.\u0026rdquo; Most teams ship one layer of governance and call it human-in-the-loop. That is not human-in-the-loop; that is a prompt.\nThe cumulative gap between the supervision an agent system claims to ship with and the supervision it actually ships with has a name in 2026 product circles: supervision debt. It is the trust deficit your stack accumulates when it ships features faster than it ships controls. Eventually a procurement reviewer asks for the controls and you have to either produce them or refund the engagement.\nThis post is about paying down one specific slice of supervision debt: the observability control point. The slice that determines whether a CISO asking \u0026ldquo;show me your evals\u0026rdquo; gets a slide deck or a URL.\nThe five control points, in one table Layer What it answers Operators in 2026 Runtime Where does the agent live and run? Cloudflare Agents SDK, AWS Bedrock AgentCore, Vercel AI Gateway Identity Who is the agent acting for? Auth0 / Okta for AI Agents, WorkOS, Microsoft Entra Agent ID, AWS AgentCore Identity Data What can the agent know? Snowflake Cortex Agents, Databricks, governed semantic layers Tool / write access What can the agent change, with what blast radius? (cross-cutting; lives in tool registries and MCP tool descriptions) Observability What did the agent actually do? Datadog LLM, Arize, custom audit-trail patterns Plus the kill switch, which lives across all five plus payment: runtime cancel + identity revoke + gateway block + payment freeze + workflow interrupt.\nIf you can confidently fill in your operator name on every row, you do not have supervision debt. If three of the rows are blank or the answer is \u0026ldquo;we have logs in Datadog,\u0026rdquo; you have supervision debt and a partial answer for one row. The rest of this post is about paying down the last row honestly.\n\u0026ldquo;Show me your evals\u0026rdquo; is not a question about your evals. It is a question about your observability control point, asked in security-team vocabulary. Why \u0026ldquo;show me your evals\u0026rdquo; is the wrong question to optimize for The default response most agent vendors give when their client\u0026rsquo;s CISO asks for evals is: \u0026ldquo;we run automated test suites in CI, we monitor LLM outputs in production, and we have an internal eval dashboard you can review under NDA.\u0026rdquo;\nEvery part of that response is a confession of supervision debt.\n\u0026ldquo;Automated test suites in CI\u0026rdquo;: testing covers the deterministic substrate. It does not cover agent runtime behavior, where the model is the variable. \u0026ldquo;We monitor LLM outputs\u0026rdquo;: monitoring is the wrong primitive. Monitoring is what you do when you have a dashboard and a hope. Verification is what you do when you have a contract and proof. \u0026ldquo;Internal eval dashboard, NDA review\u0026rdquo;: the buyer has to take your word and your sales engineer\u0026rsquo;s time. Every renewal requires the same dance. The supervision-debt interest payment is the procurement cycle. What the CISO actually wants is a URL their team can fetch without a privileged account. What the CFO wants, at the same client, is a record of every billable action the agent took on their behalf. What the CIO wants is proof that the supervision discipline you sold them is actually firing in production.\nAll three are the same artifact. We have been calling it an audit-trail receipt. The broader practitioner conversation has been calling it the observability control point. Same primitive in different vocabularies.\nHow the receipt pays down the observability debt Two weeks ago we shipped a public MCP-callable storefront at mcp.adotob.com. Any MCP-capable client can call the purchase_free_bundle tool. Each call produces a publicly readable receipt URL like:\nhttps://mcp.adotob.com/a2a/receipt/rcpt_2026-05-16_0a96ef3d\nThe receipt enumerates six supervision checks bucketed into three methodology phases:\nAdmission gates: input validation, rate limit, daily cost ceiling Processing: lead capture (CRM upsert), download token mint (24-hour expiry) Fulfillment: transactional email dispatched Every check renders with a timestamp and a pass / fail / skip / warn status. The page is public; no login, no NDA, no dashboard role. The buyer\u0026rsquo;s security team and finance team see the same document.\nA real receipt rendered from the live MCP storefront. Six checks, three phases, one publicly readable URL. The page renders identically whether the call came from hosted Claude, a fully-local Qwen3.6 27B, or any other MCP-capable client.\nWhere this pays down supervision debt:\nThe buyer no longer has to take the vendor\u0026rsquo;s word for what supervision fired. The check log is the artifact. Disagreements about whether a control was applied get settled by a URL, not a sales call. Failure paths produce receipts too. A failed input validation renders as FAIL and the downstream five checks render as SKIP with timestamps. Auditors trust audit trails that admit limitations. They distrust audit trails that always look clean. The same artifact serves two buyers. The CFO reads the same URL as the CISO. The shared source of truth eliminates the reconciliation problem most enterprise agent platforms solve by handing each function a different dashboard. The receipt is the observability control point in deliverable form. It does not replace Datadog or Arize; it sits in front of them as the buyer-facing surface that survives a forwarded link without leaking PII or requiring privileged access.\nHow the announce-intent-before-action discipline pays down the debt earlier Receipts pay down the observability debt after an action fires. The matched-pair discipline pays it down before: the tool description must enumerate every server-side effect the call will produce, in seven categories.\nData side-effects: what does the server store, where, for how long Identity side-effects: create, update, or delete a contact / account Communication side-effects: email, SMS, push notification Issuance side-effects: tokens, keys, credentials, with expiry Public side-effects: publicly readable URLs, with TTL Money side-effects: charge, refund, transfer Trigger side-effects: async work enqueued in another system If any answer is yes, the description must name it. Vague benefit language (\u0026ldquo;processes your request\u0026rdquo;) is not announce-intent. It is evasion. The discipline is borrowed directly from physical robotics (Pixar\u0026rsquo;s announce-then-act pattern, in animation since 1986) and from older stage craft (Stanislavski\u0026rsquo;s telegraphing, with a vaudeville lineage older still). When a robot moves toward a human, it announces intent before motion begins; the motion is the same, but the announcement is what makes it safe.\nTools that take side-effecting action need the same discipline. The 7-category enumeration is the static-spec version of the audit-trail receipt\u0026rsquo;s runtime record. Both halves are required. Receipt without announce-intent means the human only learns the full scope after committing. Announce-intent without receipt means the human trusts the announcement with no way to verify reality.\nThe seven side-effect categories are the static-spec half (TYPES bookend); the audit-trail receipt is the runtime half (TESTS bookend). Spec declares, receipt verifies. Both halves are required.\nHow the multilayer kill switch maps onto the six checks A real kill switch lives at more than one layer:\nRuntime cancel stops a runaway agent burning compute Identity revoke invalidates the credential after a breach is detected Gateway block intercepts a tool call before it executes Payment freeze stops a spend instrument from clearing Workflow interrupt stops the sequence before a sensitive node fires A six-check audit-trail receipt is not the whole kill switch, but each check participates in at least one layer. Input validation and rate limit are workflow-interrupt layers. Daily cost ceiling is a spend-ceiling layer. CRM upsert and token mint participate in the identity-revoke layer (the contact can be deleted, the token can be expired). Fulfillment dispatch is the last-line-of-defense layer (Brevo can suspend the sender).\nThe point is not that the Reliability Kit ships every kill-switch layer. The point is that the Kit documents which layer each check participates in, so partners running on Cloudflare or AWS or Auth0 know exactly which of their existing layers our checks slot under. That is the difference between \u0026ldquo;we have safety features\u0026rdquo; and \u0026ldquo;we ship the observability layer of a multilayer kill switch your stack already partially has.\u0026rdquo;\nYour stack plus our control point equals production-ready. Not \u0026ldquo;buy our methodology.\u0026rdquo; Your runtime, your identity, your data, your gateway, plus our receipt. The licensing motion lives in that sentence. What this means if you are evaluating the Agent Reliability Kit for licensing The architectural map is the message. The Kit sits on one of the five control points: observability. It does not compete with Cloudflare, AWS, Auth0, or Snowflake. It pairs with whichever of those four you have already chosen and adds the receipt.\nThat means:\n\u0026ldquo;We are not a Claude shop.\u0026rdquo; The Kit is protocol-neutral. The MCP storefront has produced identical receipts from hosted Claude AND from Qwen3.6 27B running fully offline. Your model choice is yours. \u0026ldquo;We already use Auth0 / Okta / Entra.\u0026rdquo; The Kit slots under your identity layer. The announce-intent-before-action discipline enumerates the side-effects your identity scopes need to enforce. A reference Auth0 integration sample lives at github.com/fabianwilliams/adotob-mcp/tree/main/samples/auth0. \u0026ldquo;We are on Cloudflare Agents / Bedrock AgentCore / Vercel.\u0026rdquo; The receipt format ports across runtimes. Only the storage-backend module changes (R2 instead of Azure Blob, etc.). The licensing case is no longer \u0026ldquo;buy our methodology.\u0026rdquo; It is \u0026ldquo;close the observability debt on one row of the five-control-point table.\u0026rdquo; The other four rows stay your decision.\nWhat this piece contributes A name for the gap most agent stacks ship with: supervision debt, the cumulative trust deficit between claimed and shipped controls. A concrete pattern that pays it down on the observability row: a public, consumer-readable audit-trail receipt URL plus a 7-category side-effect enumeration on every tool that produces it. A positioning shift: the Agent Reliability Kit is one control point, not a stack. Partners keep their runtime, identity, data, and gateway choices. They add the receipt. That is the entire pitch. Cheers, Fabian Williams\nIf you are building agents for clients and the procurement-shaped questions in this post sound familiar, I would value a 20-min back-and-forth on where the patterns hold and where they break. The licensed (non-sanitized) Kit covers the worked examples this post sketches.\nBlog: fabswill.com Twitter/X: @fabianwilliams MCP storefront: mcp.adotob.com Agent Reliability Kit (OSS): agentic-engineering-toolkit Partner licensing: estore.adotob.com/partners Agent Reliability Kit™ is a trademark of Adotob Solutions.\nCredits: the five-control-points lens for partner conversations plus the multilayer-kill-switch idea were articulated by several writers during 2026, including Nate B Jones. The announce-intent discipline draws on physical-robotics design and stage-craft traditions (Pixar\u0026rsquo;s animation; Stanislavski\u0026rsquo;s telegraphing). The Auth0 AI Agents team for the delegated-authority-with-constraints pattern this piece references at the identity layer.\n","permalink":"https://www.fabswill.com/blog/paying-down-supervision-debt-five-control-points/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eBy the end of this post you will know which of the five infrastructure control points your agent stack is shipping without, and you will have a concrete pattern for paying down the observability piece of that debt: a public, consumer-readable audit-trail receipt that satisfies both your security team and your finance team with the same document. The receipt was already in production when the broader practitioner conversation started naming the gap.\u003c/strong\u003e\u003c/p\u003e\n\u003c/blockquote\u003e","title":"Paying Down Supervision Debt: Why the Five Control Points That Decide Whether Your Agent Ships Have Nothing to Do With Your Model"},{"content":" Update, 2026-05-19: A2A agent-card now live at mcp.adotob.com/.well-known/agent.json, published 24 hours after Nate B Jones\u0026rsquo;s IO-2026 video named the agent-card primitive as the second of the four core agent-protocol layers. Three of the four layers of the open-protocol stack are now live in the storefront: MCP for tool access, A2A for agent discovery, and AG-UI manifested as the public receipt page. AP2/X402 is reserved for the MVP-2 paid Stripe flow.\nBy the end of this post you\u0026rsquo;ll have two public URLs you can forward to your security team AND your finance team — and both audits get satisfied by the same document. That document is an agent receipt. The two URLs are real receipts produced by the same MCP endpoint, one driven by Anthropic-hosted Claude Desktop and the other driven by Qwen3.6 27B running fully offline on my MacBook. The point of this post is why that one-artifact-two-ledgers property matters more than the technology that produces it.\nThe two receipts Let me get the demonstration out of the way before the argument.\nSame endpoint: https://mcp.adotob.com/api/a2a/mcp.\nSame six supervision-layer checks, bucketed into three methodology phases. Same audit-trail receipt format, served from the same Azure Blob, signed by the same JOSE HS256 download token, with the same Brevo-mediated fulfillment email landing in the same Gmail inbox.\nDifferent clients calling the tool.\nReceipt 1 — driven by Claude Desktop (Anthropic-hosted frontier model, requires their cloud): rcpt_2026-05-16_0a96ef3d Receipt 2 — driven by Qwen3.6 27B (open-weights, running fully offline in LM Studio on a MacBook Pro M3 Max, no cloud inference whatsoever): rcpt_2026-05-16_7f1fd149 Click both. They render identically. The receipt page does not know — and does not care — which client called the tool. That property is the whole essay.\nIf you want to reproduce this on your own machine in two minutes, the operator-verified walkthrough with all 16 screenshots is here: Happy-Path SOP.\nWhat MCP actually solves (and what it doesn\u0026rsquo;t) A brief fence so we are not talking past each other.\nMCP — Model Context Protocol — is a JSON-RPC 2.0 wire format that lets any LLM-using client discover and call tools from any server. The good version of this story is \u0026ldquo;one tool definition, many clients.\u0026rdquo; The hyped version of this story is \u0026ldquo;AI app stores.\u0026rdquo; Both miss the part that actually matters for partner-facing commerce.\nWhat MCP gives you that REST APIs did not:\nDiscovery. A client points at a URL, calls initialize and tools/list, and learns what tools exist. No manual tool definition copied into the SDK. No vendor docs to read. Permission gating built into the client. Most MCP clients ask the user before invoking a tool the first time. The trust boundary is explicit and visible. Provider neutrality at the protocol level. The same endpoint serves Claude, ChatGPT (custom connectors), LM Studio, Cursor, Windsurf, Cline, Continue, Zed, and any code calling the MCP SDK or the OpenAI Responses API. Nobody owns the protocol. What MCP does not give you:\nAn observability story for your customers. A receipt your partners can forward to their security team. A chain of custody for billable agent actions. That gap is what I have been building toward.\nThe dual-ledger framing — one artifact, two buyer concerns Here is the thing I want to make sticky.\nA receipt produced by an agent transaction has to satisfy two completely different procurement conversations, often in the same building, often at the same client. Conversation A — security / audit ledger. The CISO and the procurement reviewer want to know: show me your evals — how do you know the agent did the right thing? They want evidence that input was validated, that abuse limits were enforced, that the system refused to run when its own cost gate said stop. They are looking at the receipt as proof of supervisor behavior.\nConversation B — finance / billing ledger. The CIO, the CFO, the agent-economy product owner want to know: when an agent transacts on a user\u0026rsquo;s behalf, what is the proof of what it did and when, so we can bill, reconcile, dispute, refund? They are looking at the receipt as chain of custody for billable actions. Salesforce Agentforce charges per conversation. Microsoft 365 Copilot has per-message metering. SAP Joule charges per autonomous action. The moment your agent stack moves to per-action billing, every action needs a receipt or finance refuses to sign the renewal.\nThese are the same question dressed in different ledgers. Same forensic property: what happened, in what order, with what inputs, against what guardrails.\nThe receipt I built answers both with one URL.\nThat is not a small thing. It collapses two procurement reviews into one document. It eliminates the \u0026ldquo;can your vendor logs be exported in CSV for our billing reconciliation?\u0026rdquo; call. It means the partner you license your methodology to can hand the same URL to the CISO and the CFO and watch both sign-offs happen in parallel. The closest existing pattern is the credit-card receipt: one document, recognized by the cardholder, the merchant, the issuing bank, the acquiring bank, the dispute system, the tax authority. Different actors, different ledgers, same primary artifact. Agent commerce needs the same shape.\nWhat is actually on the receipt The methodology behind the receipt is a three-phase supervision lifecycle. Here is the same lifecycle the partners page draws, because it is the same discipline running underneath the receipt page:\nThe supervision lifecycle behind every check on the receipt — admission, processing, fulfillment. Same shape on the partners page slide, same shape in production.\nThree methodology phases. Six checks. Every check has a timestamp, a pass/fail/skip/warn badge, and a one-line explanation.\nPhase 1 — Admission gates. Should this request even proceed?\nInput validation — first_name and email present and well-formed Rate limit — under 5 calls/hour from this IP (cap protects the demo from abuse) Daily cost ceiling — server confirms it has not exceeded its $5/day cap Phase 2 — Processing. Capture the lead, sign the entitlement.\nLead capture (Brevo) — contact upserted to the dedicated MCP-leads list Download token mint — JOSE HS256 JWT issued with 24-hour expiry, signed with the eStore\u0026rsquo;s secret so the eStore can validate it cross-app Phase 3 — Fulfillment. Deliver the goods to the customer.\nFulfillment email dispatched — Brevo transactional API confirmed message acceptance Here is what that looks like rendered for a real run — the publicly readable receipt page from the Claude Desktop example at the top of this post:\nEvery check has a timestamp, a status badge, and a one-line explanation. The page is publicly readable; no login, no privileged role, no vendor-dashboard access. The requester\u0026rsquo;s email never appears on this page — only the first name.\nThat is the entire system. Six checks. The receipt page renders the list with the same visual discipline whether all six passed, three failed, or the request was admission-rejected at step one. The audit trail is honest — including about its own failures. A failure receipt that does not pretend everything worked is more valuable for a partner conversation than a no-receipt-on-failure system that hides degraded behavior.\nThis is the discipline I have been calling the Agent Reliability Kit™. The MCP storefront is the public, end-user-facing instance of those patterns running in production. The receipt is what the patterns look like from the outside.\nThe protocol-neutrality surprise Here is the move that opens the partner objection.\nThe dominant question when I show partners this demo is: \u0026ldquo;does this work in our stack? We are not a Claude shop.\u0026rdquo;\nThe two receipts at the top of this post are the answer. One was driven by Claude Desktop (an Anthropic-hosted frontier model). The other was driven by Qwen3.6 27B — a 27-billion-parameter open-weights model, downloaded once, loaded into LM Studio, running entirely on a MacBook Pro M3 Max with no inference request ever leaving the laptop except the single MCP tools/call to mcp.adotob.com.\nSame endpoint. Same six checks. Same receipt URL format. Same fulfillment email arrived in the same inbox.\nWhat this means in practice for any team evaluating the methodology for licensing:\nYour existing agent stack — OpenAI, Azure OpenAI, Bedrock, Vertex AI, on-prem open weights, some mixture — is already compatible. No rebuild. No vendor migration. Your client\u0026rsquo;s security review is a URL forward, not a 40-slide deck. The audit trail is observable from the consumer side without privileged access. Every partner, every client, every regulator, every auditor — same view. If you have ever sat in a procurement call where the vendor says \u0026ldquo;we have full audit logs\u0026rdquo; and the buyer says \u0026ldquo;great, can our team see them?\u0026rdquo; and the vendor says \u0026ldquo;we would need to set up a dashboard role, give us two weeks\u0026rdquo; — you know exactly why consumer-readable receipts matter.\nWhat this means if you are building agent-to-agent commerce A handful of things, ranked by how often they come up in partner conversations.\nYou stop selling \u0026ldquo;trust me.\u0026rdquo; The audit trail is a URL. Partners can hand it to their client\u0026rsquo;s security team without you. They can hand it to their CFO without you. The conversation moves from \u0026ldquo;explain your evals\u0026rdquo; to \u0026ldquo;click this and see for yourself.\u0026rdquo;\nYou stop picking a vendor for your customer. Most agent platforms ship as a vertically integrated stack — pick our model, pick our orchestrator, pick our observability tool, accept our SLA. MCP-callable patterns invert that. The customer picks the model, the customer picks the client, you pick the receipt discipline. You sell methodology, not framework.\nYou handle failure visibly. Receipt-on-success is easy. Receipt-on-partial-failure is the discipline. Every check on the receipt page renders with its real status. A skipped lead-capture step renders as SKIP, not as silence. A failed input validation renders as FAIL and the downstream five checks render as SKIP with timestamps. Auditors trust audit trails that admit limitations. They distrust ones that always look clean.\nPer-action billing becomes legible. If you are going to charge per agent action, the buyer needs the action ledger to be unambiguous. The receipt format above is one way to make it unambiguous. There are others. Pick one.\nTry it, then license it Two URLs already linked above. Two minutes from Settings → Connectors → Add MCP server to a real receipt in your inbox. The walkthrough with screenshots is operator-verified and lives at the same repo: Happy-Path SOP.\nIf you build agents for clients and you want the non-sanitized examples, the white-label rights, and the partner relationship behind this methodology, that is what the licensed Agent Reliability Kit is for: estore.adotob.com/partners. The free OSS reference implementation is here: github.com/fabianwilliams/adotob-mcp (Apache 2.0). The broader public Kit is at github.com/fabianwilliams/agentic-engineering-toolkit.\nWhat this piece contributed Three things I want you to walk away with:\nA live, public, MCP-callable storefront you can hit from any MCP-capable client right now and receive an audit-trail receipt URL. Not a slide. Not a demo video. A URL. A dual-ledger framing for agent receipts — same artifact, satisfies the audit conversation AND the billing conversation. Sell once, two procurement signatures, no second integration. Two worked examples — Anthropic-hosted Claude and fully-local Qwen3.6 27B — producing receipts that are byte-for-byte structurally identical. Protocol-neutrality is no longer a slide claim; it is a pair of URLs anyone can click. If you are a builder shipping agents into client work, this is the methodology you can either rebuild yourself from the OSS reference or license the long-form version of. Either path works. The one path that does not work anymore is shipping agent commerce without a receipt your customer can read without your help.\nCheers, Fabian Williams\nI build autonomous AI agents and the operational infrastructure to keep them honest — for nonprofits, small businesses, and enterprise teams. If you are evaluating agent-receipt patterns, MCP-callable storefronts, or partner-facing audit trails for licensing into your own consulting practice, I would like to hear what you are working on.\nBlog: fabswill.com LinkedIn: fabiangwilliams Twitter/X: @fabianwilliams MCP storefront: mcp.adotob.com Agent Reliability Kit (OSS): agentic-engineering-toolkit Partner licensing: estore.adotob.com/partners Agent Reliability Kit™ is a trademark of Adotob Solutions.\n","permalink":"https://www.fabswill.com/blog/one-agent-receipt-two-buyers-protocol-neutral-mcp-audit-trails/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eUpdate, 2026-05-19\u003c/strong\u003e: A2A agent-card now live at \u003ca href=\"https://mcp.adotob.com/.well-known/agent.json\" target=\"_blank\"\u003emcp.adotob.com/.well-known/agent.json\u003c/a\u003e, published 24 hours after Nate B Jones\u0026rsquo;s IO-2026 video named the agent-card primitive as the second of the four core agent-protocol layers. Three of the four layers of the open-protocol stack are now live in the storefront: MCP for tool access, A2A for agent discovery, and AG-UI manifested as the public receipt page. AP2/X402 is reserved for the MVP-2 paid Stripe flow.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eBy the end of this post you\u0026rsquo;ll have two public URLs you can forward to your security team AND your finance team — and both audits get satisfied by the same document.\u003c/strong\u003e That document is an agent receipt. The two URLs are real receipts produced by the same MCP endpoint, one driven by Anthropic-hosted Claude Desktop and the other driven by Qwen3.6 27B running fully offline on my MacBook. The point of this post is why that one-artifact-two-ledgers property matters more than the technology that produces it.\u003c/p\u003e\n\u003c/blockquote\u003e","title":"One Agent Receipt, Two Buyers: Why Protocol-Neutral MCP Audit Trails Matter for Both Security AND Finance"},{"content":"TL;DR I volunteer with MACONA, a 501(c)(3) nonprofit that ships food, medicine, feminine hygiene products, donated computers, and clothing to communities and schools in West Africa. For a few few monthis now I have run a small autonomous AI agent fleet for the organization: five named agents, cron-driven, running through OpenClaw on a simple Windows box.\nWeek 19 (I track progress via week numbers for me and my Agents) looked like a win on every internal activity metric: 17 reliability PRs merged, 2 awareness-day blog posts published, 1 Brevo campaign queued, and 37 cold introduction emails sent.\nThe outcome metrics were brutal: zero human clicks and zero donations.\nThis post is about that gap — and about the corrections panel I wrote on top of my own retrospective before anyone else could.\nThe fleet works. The trust funnel does not yet.\nWhat the receipts actually say Week 19 (May 4 to May 8, 2026) was the most operationally productive week the fleet has had since I stood it up. The shipping list:\n17 reliability PRs merged into the private MACONA OpenClaw repo. Most were fixes for bugs the fleet itself had surfaced through its own autonomous monitors. PR titles ranged from feat(cron-wrappers): kill the natural-language-action fabrication pattern to fix(meta-extract): regex now handles apostrophes inside quoted content — a real bug that had truncated a blog post\u0026rsquo;s social-card title to just \u0026ldquo;MACONA.\u0026rdquo; 2 awareness-day blog posts published end-to-end. Both went brief → writer-agent draft → QA-agent review → publish → newsletter-campaign creation, with the agents doing every step until the manual-promote gate. 1 Brevo campaign queued for one of the posts — test-sent to four internal reviewers, sitting in draft to 59 active newsletter subscribers, awaiting my manual promote click. 37 cold introduction emails sent Monday through Thursday from the CEO\u0026rsquo;s mailbox via Microsoft Graph delegate access. Net-new recipients, deduped against the sent log. Lifetime cold intros across the box: 98. The daily breakdown: 12, 10, 11, 4, 0. 12 list-hygiene contact mutations across four Brevo lists — 11 bouncing contacts deleted, an alias-duplicate resolved, one friendly cross-match recovered from the blacklist. That last day — zero intros — is important and I will come back to it.\nThe hard line The same dashboards that confirm the activity numbers tell me what came back from the prior week\u0026rsquo;s newsletter sends to the same 59 subscribers: zero human clicks. Not a low click rate. Not a disappointing one. Zero. The donations counter for Week 19 is also zero — that\u0026rsquo;s Stripe donations through the public donate page, plus matched Benevity gifts through the corporate portal. Neither increased.\nThe newsletter list is small but real, and the engagement signal for the prior week was marginal. That number does not appear in most agent-fleet writeups. It should. The honest one-line I wrote at the bottom of my own retrospective the evening it shipped was this:\nWe shipped a lot of repair work — most PRs were fixing bugs we had shipped or had latent — built useful infrastructure, and produced activity but no outcomes. Zero human clicks, zero donations, and the outreach queue ran dry Friday. That is not failure on a week-19 horizon; it is a sign the agent fleet is generating motion without conversion, and the retro should have weighted that more honestly.\nSo we redrafted the Retro and I wrote (with the aid of the agent) that paragraph as a corrections panel because the first draft of the retro skewed positive. The pattern of writing the corrections panel is the thing I want to talk about\u0026hellip;but first, the discipline that makes the receipts trustworthy in the first place.\nThe fleet, in as little detail as needed 5 named agents plus a cron daemon, running through OpenClaw on a small Windows box. Telegram is the primary channel; I get a morning brief, a midday inbox sweep, an end-of-day digest, and ad-hoc alerts when anything needs my attention.\nThe agents have personas! Mimi (orchestrator), Eshe (writer), Kofi (QA), Ama (campaigns), Sam (inbox triage + cold outreach). The fleet runs on a mix of gpt-4o and gpt-4o-mini. The cron daemon fires the agents at specific times across the day; the agents fire wrappers; the wrappers do the actual work.\nA note on cost. The $3.02 number cited in this post is LLM API spend only, verified against the OpenClaw Gateway dashboard. It excludes hardware (a one-time Windows laptop), Microsoft 365, Brevo, Hunter.io enrichment credits, domain and hosting, and my volunteer time. For context, my home side-project box (Ada, on a Mac mini, a family-coordination agent, not a competing operational fleet) ran $13.48 over the same window. The gap is session shape: short cron tasks that complete-and-end beat long exploratory sessions on total spend. Cache hit rate is a diagnostic, not a scoreboard.\nWhy the numbers are trustworthy The reason I can publish a zero-clicks line is that I trust my agents to report what they actually did. That trust did not exist eight days ago. It exists now because of one architectural rule.\nPR #27, merged Monday 2026-05-04: feat(cron-wrappers): kill the natural-language-action fabrication pattern.\nBefore PR #27, several cron jobs had prompts that said things like \u0026ldquo;Compose a Brevo-ready campaign email for the latest published post.\u0026rdquo; The agent, gpt-4o, with no deterministic tool constraining it — would respond with a paragraph saying it had composed the email. No file got written. No campaign got created. The Telegram report said task complete. Disk state said otherwise.\nI had been catching these by accident for weeks. Once I named the pattern, I removed it. Every cron action now follows one strict rule: the action step must be backed by an exec wrapper that calls deterministic Python, the wrapper emits structured summary_lines and a verified flag, and the agent\u0026rsquo;s job is to relay those lines and stop. No natural-language verbs in the prompt. No compose, send, process. The agent is a courier for the wrapper\u0026rsquo;s report, not a doer of the work.\nIn plain English: the agent is no longer allowed to claim it did work just because it wrote a convincing paragraph. A script has to do the work first, produce evidence, and then the agent is only allowed to report that evidence.\nThat single architectural rule is the most reliability-positive thing I have done so far. The agents have not invented an action since. (More precisely\u0026hellip;they have not invented an action in the categories I was watching. I will come back to that.)\nThe other discipline that compounds with the wrapper rule is closed-loop bug protocol: every bug, no matter how small, lands as incident → PR → RCA → monitor. Friday\u0026rsquo;s cleanest example: a recovery script I had written by hand on Wednesday introduced a missing closing quote on an inline image tag. The agent\u0026rsquo;s broken-image monitor caught it autonomously at 1pm Friday. Telegram surfaced it. I shipped a one-line fix in twenty minutes. The monitor that caught it had been added to the fleet weeks earlier — not because I anticipated this specific bug, but because the broken-image class was worth monitoring once. The fleet caught the bug I introduced. That is the loop working.\nWhy the framing still lied — the corrections panel The original Week 19 retrospective drafted on Friday evening read like most internal retros do: complete content + campaigns + outreach pipeline; first end-to-end autonomous awareness-day post; anti-fabrication scaffolding holding; cost discipline. It was not wrong on the numbers — every dollar and PR count was correct. It was wrong on the framing.\nI sent the draft to myself, walked away for an hour, came back, and read it as if a stranger had written it about my work. I noticed 4 overclaims and 5 missing facts, appended a corrections panel to the top, and shipped the document with both readings preserved.\nHere is what the corrections panel looked like — paraphrased, since the source retro contains internal details:\n4 overclaims I caught\n\u0026ldquo;Complete content + campaigns + outreach pipeline.\u0026rdquo; Outreach was running on draining inventory, not a healthy pipeline. A latent quota-check bug had been silently failing the enrichment side for an unknown duration. The pipeline only appeared working because the existing inventory hadn\u0026rsquo;t drained yet.\n\u0026ldquo;First end-to-end autonomous awareness-day post.\u0026rdquo; The post required three manual interventions before it was clean: a hand-written recovery script for an apostrophe-bailing regex, a closing-quote fix on an inline image tag, and the manual promote-to-newsletter click that\u0026rsquo;s still pending.\n\u0026ldquo;Anti-fabrication scaffolding holding.\u0026rdquo; Friday alone surfaced two new misreport patterns the existing scaffolding didn\u0026rsquo;t catch — both the same shape as the PR #27 fabrication class, just expressed differently. Old categories caught; new ones leaked through.\nImplicit \u0026ldquo;good week\u0026rdquo; framing throughout. I had not yet seen the zero-engagement signal that arrived in the 3pm brief. The activity-versus-outcomes gap deserved more weight than the original retro gave it.\n5 things I missed: the zero-clicks number; the actual day-by-day cold-intro send count; the latent nature of the enrichment bug; the broader month-over-month trajectory; one actionable follow-up due that day.\nWhat the retro got right: the cost numbers, the PR list, the bug RCA table, the decisions made and why.\nThe honest one-line: we produced activity but no outcomes. That is not failure on a week-19 horizon; it is a sign the fleet is generating motion without conversion, and the retro should have weighted that more honestly.\nThat panel is not a rewrite of the original retro. It is an additive audit sitting above it. Reading the original retro followed by the corrections panel gives the most accurate picture; reading either alone misleads.\nI have come to think of the corrections panel as the most important section of any retrospective I write. It is the thing that makes the rest of the document trustable. When a reader sees you flagging your own overclaims with the same specificity you used to make the original claims, they trust the original claims more. The integrity is in the audit, not in the absence of mistakes.\nEric Ries made this same point on Lenny\u0026rsquo;s Podcast over the weekend, talking about why some companies stay mission-aligned for a century and others corrode within a decade. His bridge analogy: when a bridge collapses, gravity is a useless explanation, because gravity is always there. The bridges that stay up have stainless-steel structural integrity in places that look like overengineering until the wind comes. Writing the corrections panel before anyone else can write one for you is the small-org equivalent of that overengineering. It is harder than just shipping the rosy retro. It is also the only path to a retro anyone should believe.\nThe new fabrications that leaked through For completeness, here is what those two new misreport patterns looked like:\nThe intro-drip cron labeled a clean empty-queue no-op as task failed. The wrapper correctly returned eligible: 0. The agent\u0026rsquo;s summary paragraph said \u0026ldquo;Today\u0026rsquo;s intro batch failed to execute.\u0026rdquo; The wrapper was honest; the agent\u0026rsquo;s interpretation was not.\nThe content-pipeline cron labeled a clean SKIP as execution skips. Same shape. The wrapper said \u0026ldquo;no awareness day matched today, skipping.\u0026rdquo; The agent reported \u0026ldquo;the content pipeline experienced skips.\u0026rdquo;\nBoth are the same class of error as PR #27 fixed — the agent narrating around the structured truth instead of relaying it. Both leaked through because PR #27 closed the invent an action that never happened door, not the re-interpret a successful skip as a failure door. The next prompt-tightening PR will name and kill the new class. That is the loop.\nThe third leak was uglier: same Friday, the 3pm Benevity weekly brief reported \u0026ldquo;0 enriched, 72 remaining\u0026rdquo; while the 10am research run from the same day reported \u0026ldquo;46 of 72 portals enriched.\u0026rdquo; Two reports, same day, same metric, contradictory numbers. The root cause was a silent field-name drift — one script returning the Hunter API quota under one key name, another script reading it under another. The enricher had been silently failing for an unknown number of days. The existing 41-row contact CSV drained Monday through Thursday at about ten intros per day. Friday it hit zero, and the bug surfaced.\nThe lesson worth carrying: monotonic decay in a queue without monotonic refill is invisible until the queue hits zero. The system appeared healthy because the existing inventory drained at the expected rate. The fix is a one-line alert: when enrichment delta equals zero for N consecutive days, surface a warning.\nAnti-fabrication baked into the briefs themselves The other place the fleet defends against fabrication is in the work orders themselves. The writer agent drafts blog posts from a brief produced by the awareness-day cron. The brief is a structured markdown file — frontmatter, required elements, editorial guardrails. This morning\u0026rsquo;s Mother\u0026rsquo;s Day brief reads, in part:\nNo fabricated people. Names, ages, locations, quotes must come from the vault or be left generic (\u0026ldquo;a volunteer in Kumasi\u0026rdquo;, \u0026ldquo;a donor from the MVP Summit cohort\u0026rdquo;). See feedback_no_fabricated_personal_details.md if uncertain.\nNo fabricated metrics. Numbers (\u0026ldquo;we delivered 1,000 kits\u0026rdquo;) must be traceable to vault records. If unsure, omit.\nThat paragraph lives inside the prompt the writer sees. The fabrication guardrails are not bolted on at QA time — they are written into the work order itself. The QA agent, downstream, then verifies the rubric: minimum five images, exact path format for inline images, donation link must use the canonical short-link format, EIN must appear in the HTML, word count between 800 and 1500.\nWhen you build a fleet to ship at this cost, this is the trade-off: the constraints have to be in the prompt and in the wrapper and in the QA gate, not in the operator\u0026rsquo;s head. Anything that lives only in the operator\u0026rsquo;s head gets lost the first time the operator is offline.\nSeven lessons I am carrying into Week 20 Wrap every cron action in an exec script that emits structured summary_lines and a verified flag. Natural-language do X steps in agent prompts fabricate. Every time. The wrapper-pattern is the single biggest reliability improvement I have made.\nClosed-loop = PR plus RCA plus monitor, every time. A bug fix without a monitor is a bug invitation. The monitor that catches a recurrence is the receipt that the fix held.\nInspect raw artifacts before inferring. I spent four PRs fixing an inbox classifier that couldn\u0026rsquo;t detect a particular bounce format. Should have been one PR. I would have nailed it in one if I had dumped the raw email body via the upstream API before writing the regex. Do not iterate in fog.\nMonotonic decay in a queue without monotonic refill is invisible. The quota bug silently failed enrichment for an unknown duration. The existing inventory drained at the expected rate, masking the failure. Add an alert: if a refill metric is flat for N days, surface it.\nSoft warnings beat hard rejections for content-quality fabrication risk. Hard-blocking on probabilistic signals stalls the pipeline. Soft warnings let humans intervene when needed without freezing the autonomous loop.\nCache hit rate is a session-shape signal, not a cost signal. Tight cron-style sessions that complete-and-end beat long iterative chats on total spend. Lower cache rate, lower bill.\nWrite the corrections panel before anyone else can write one for you. This is the structural integrity the rest of the retro hangs on. Same-day. Additive, not destructive. Read together with the original.\nWhy this matters beyond my setup Most agent-fleet retrospectives that exist publicly are marketing artifacts — a vendor explaining why their product worked, or a founder pitching the next round. Honest weekly retros from operators of small autonomous fleets are rare. The reasons are obvious. They show what does not convert, not just what shipped. They show the bugs the operator introduced, not just the bugs the system caught. They show the activity-versus-outcomes gap, which is where most fleets actually live.\nI am publishing this one because the discipline of writing it and writing the corrections panel on top of it — is, I now believe, the single most underrated component of running an agent fleet at all. The cost numbers and the reliability counts are real. They are also unimpressive without the audit panel that says what they do not mean. With the audit panel, they become useful, for me, deciding what to change next week, and for anyone reading this trying to figure out whether the autonomous-agent-fleet thing is worth building.\nClosing The fleet can ship. It can monitor. It can catch some of its own failure modes. It can run for $3.02 a week of LLM spend.\nWhat it has not yet proven is that motion becomes trust, or that trust becomes donations.\nThe fleet works. The trust funnel does not yet.\nThat is Week 20\u0026rsquo;s work.\nCheers, Fabian Williams\nI build autonomous AI agent fleets and the eval scaffolding to keep them honest. If you run an agent fleet for a small org and you write weekly retros — especially the ones where the receipts do not match the headline — I would like to compare notes.\nBlog: fabswill.com LinkedIn: fabiangwilliams Twitter/X: @fabianwilliams GitHub (Agentic Engineering Toolkit): agentic-engineering-toolkit ","permalink":"https://www.fabswill.com/blog/autonomous-ai-agent-fleet-nonprofit-w19-retro-corrections-panel/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eI volunteer with \u003ca href=\"https://macona.org\"\u003eMACONA\u003c/a\u003e, a 501(c)(3) nonprofit that ships food, medicine, feminine hygiene products, donated computers, and clothing to communities and schools in West Africa. For a few few monthis now I have run a small autonomous AI agent fleet for the organization: five named agents, cron-driven, running through OpenClaw on a simple Windows box.\u003c/p\u003e\n\u003cp\u003eWeek 19 (I track progress via week numbers for me and my Agents) looked like a win on every internal activity metric: 17 reliability PRs merged, 2 awareness-day blog posts published, 1 Brevo campaign queued, and 37 cold introduction emails sent.\u003c/p\u003e","title":"The AI Agent Fleet Works. The Trust Funnel Does Not."},{"content":"TL;DR I published a post last week about replacing gpt-oss:120b with Qwen 3.6 on my MacBook Pro M3 Max. The numbers in that post were real, but one set of tests was structurally gameable — 38 of 40 baseline images were the same class, so an \u0026ldquo;always-say-A\u0026rdquo; stub also scored 95 percent. I went back, designed three un-gameable reasoning tasks, and ran them against both local models on identical hardware. gpt-oss:120b finished the three tasks in 137 seconds. qwen3.6:27b-q8_0 took 1593 seconds — 11.6 times slower, on the same M3 Max, for the same prompts and essentially the same answers. This post is the methodology, the receipts, and the honest correction to the migration narrative.\nOperator priors should be tested, not trusted. The data is the data.\nThe Nag I Could Not Shake The previous post said Qwen 3.6 was replacing gpt-oss in my workflow. The post had a chart showing speed wins on a coding-style benchmark and a multimodal capability test — both of those numbers were real. What it did not have was a clean head-to-head on structured editorial reasoning at production parameters.\nI had also run an image-classification test against MACONA\u0026rsquo;s real nonprofit media library — 40 photos from a December 2025 computer-donation shipment to schools in Bamako, Mali, plus a February 2026 clothing donation. Both Qwen 3.6 and gpt-oss scored 40 out of 40 against gpt-4o\u0026rsquo;s earlier classification. That looked great.\nThen I noticed something. 38 of the 40 images were Group A (computer-related) in the baseline. An \u0026ldquo;always-say-A\u0026rdquo; stub would also score 95 percent. The \u0026ldquo;100 percent agreement\u0026rdquo; headline was structurally meaningless — the test could not distinguish a thinking model from a constant function. I would have published that result. So I went back and designed a harder test.\nThe First Test Was Gameable. Here Is What That Means. A gameable test is one where the data shape lets a stub pass. If 95 percent of your dataset is one class, an empty model that defaults to that class scores 95 percent — without doing any reasoning. The model looks competent. The benchmark is lying.\nThis happens more often than people admit. Class imbalance is normal. Most production datasets have a dominant class. If you measure agreement against a baseline that itself has the imbalance, your model can score high without actually being right for the right reasons.\nThe test for whether your benchmark is gameable: ask \u0026ldquo;could a stub that always picks the majority class pass this?\u0026rdquo; If yes, redesign before you publish numbers.\nBoth local models in Round 1 did correctly catch the two Group B clothing-sack images at positions 6 and 18. So they were not failing. But the 100 percent framing oversold what the test actually proved. The right framing is \u0026ldquo;models did not actively fail.\u0026rdquo; That is not nothing — but it is also not the headline the original chart implied.\nThree Reasoning Tasks That Cannot Be Gamed I designed Round 2 with three tasks. Each one is structured to block the always-majority trick.\nT2 — Audience-aware curation. Pick exactly 5 photos for a fundraising landing page (audience: prospective donors). Pick 5 different photos for a donor thank-you email (audience: existing donors). The two sets must not overlap. Each pick gets a one-sentence rationale.\nThis forces the model to differentiate two audience needs from the same dataset. There is no majority class to default to. The right answer requires actual editorial reasoning about who is looking and why.\nT3 — PII and compliance risk identification. Identify which photos warrant pre-publish PII review — identifiable faces of minors, background documents, ceremonial framing that might exploit subjects. It is OK to flag zero, few, or many. Each flag includes a specific concern.\nThis is needle-in-haystack. A constant function — \u0026ldquo;flag all\u0026rdquo; or \u0026ldquo;flag none\u0026rdquo; — fails immediately. The model has to actually look at each description and judge.\nT4 — Thematic clustering. Group the 40 images into 3 to 5 thematic clusters, name each cluster, give a one-line description of what unifies it.\nOpen-ended structure-finding. No fixed ground truth. The metric becomes inter-model agreement plus a qualitative read of the rationales.\nSame prompt, identical formatting, both models. Temperature 0.1, context window 8192, single-shot. Ollama HTTP API at localhost:11434/api/chat — about 30 lines of urllib.request. The simplest possible local-model integration.\nWhat the Receipts Say Here is what happened on identical hardware — MacBook Pro M3 Max, 128 GB unified memory, 40-core GPU, Ollama 0.17.x on Metal. Each model got one shot at each task.\nPer task: gpt-oss came in at 47, 44, and 46 seconds. Qwen 3.6 came in at 493, 523, and 577 seconds. The ratio is consistent — 10 to 13× per task. Total wall-clock for the three tasks: 137 seconds for gpt-oss, 1593 seconds for Qwen — 26.5 minutes versus 2.3 minutes.\nThis was not a cold-start artifact. I ran it warm and cold. The ratio holds.\nThe GPU was actually doing the work — not idling, not falling back to CPU. Here is the M3 Max GPU monitor during the eval, showing sustained 98 percent utilization on the active core cluster:\nCloseup of the same monitor a minute later, with render and tiler utilization both at 60 percent — the kind of sustained pressure you only see when the model is genuinely chewing on a workload:\nThat is verification. Apple Silicon, Metal, real local inference. No cloud roundtrip.\nNow the more interesting part — quality. If gpt-oss had been faster but wrong, the speed would not matter.\nT3 was the strongest signal in the experiment. Both models flagged 25 of 40 photos for PII review. They agreed on 24 of those 25. Jaccard 0.92. Two completely different model lineages — gpt-oss is OpenAI-derived, Qwen is Alibaba-derived — independently produced essentially the same compliance profile.\nThat kind of inter-family agreement is a stability signal you do not get for free. If you are considering a pre-publish PII gate using local models, this experiment says either model can carry it at production grade.\nT2 — the audience-aware curation — surfaced something different. Both models picked 5 fundraising images. They overlapped on 4 of 5 (Jaccard 0.67). Then the same models picked 5 donor thank-you images and overlapped on only 1 of 5 (Jaccard 0.11).\nThat is real reasoning differentiation surfacing. Both models converged on the impact-driven shots for fundraising — students using laptops, ceremonial handovers, clothing sacks at scale. Both models then diverged on thank-you, because thank-you is a judgment call. gpt-oss leaned classroom and event-prep — show donors where their money went. Qwen leaned process and inspection and clothing-as-loyalty signal — show donors the meticulous care behind every donation.\nNeither answer is wrong. They reflect different theories of donor engagement. The benchmark surfaced where the models think alike and where they think differently — exactly what an honest eval should do.\nT4 — the open-ended clustering — landed similarly. Both models identified the same two small clusters with identical membership: a \u0026ldquo;Computer Lab and Student Use\u0026rdquo; cluster (images 5, 24, 28, 37) and a \u0026ldquo;Clothing Donation\u0026rdquo; cluster (images 6, 18). Cluster names were nearly word-for-word the same. The structural difference was that Qwen split out a distinct \u0026ldquo;Group Portraits and Event Documentation\u0026rdquo; cluster of seven images; gpt-oss kept those inside a broader handover bucket. Qwen splits more, gpt-oss lumps more. Neither is wrong.\nThere is one more observation worth pulling out — from Round 1, the gameable round. When I asked each model to recommend headline photos for the blog post, gpt-4o picked 9 images (a varied mix). gpt-oss picked 2. Qwen picked 3.\nBoth local models picked image 12888fef (students at desktop stations in a computer lab) — and gpt-4o did not pick that one at all. Arguably a stronger \u0026ldquo;show the impact\u0026rdquo; shot than several of gpt-4o\u0026rsquo;s choices. The local models converged on a narrower, more impact-focused selection.\nThat has a real implication for production pipelines. For an autonomous pipeline that picks ONE image without human review, the local conservative behavior is arguably better. For a human-in-loop where the editor wants choices, gpt-4o\u0026rsquo;s behavior wins. The right model depends on what the surface looks like — not just on which is \u0026ldquo;smarter.\u0026rdquo;\nThe Migration-Narrative Wrinkle Going into the experiment, my prior was Qwen 3.6 is what I migrated to, so it should win on this workload. That prior was based on the previous post documenting the migration away from gpt-oss to Qwen 3.6.\nThe data did not support that prior on these tasks. On structured editorial reasoning — classification, audience curation, PII flagging, clustering — Qwen and gpt-oss are at parity in quality and gpt-oss is 8 to 11 times faster on the same hardware.\nThis does not mean the migration was a mistake. Qwen 3.6 may still win on dimensions this experiment did not test:\nInstruction-following on long-form prose — this test used short, structured prompts. Multilingual quality — this test was English-only. Code generation — especially the qwen36-coding-strict and qwen3.6:35b-a3b-coding-nvfp4 variants, which I have used elsewhere with strong results. License terms — Qwen\u0026rsquo;s license may be a structural reason to prefer it for downstream products. Vision — Qwen has a strong vision lineage; this test was text-only over already-extracted descriptions. The -strict guardrail variants — these behave differently and I did not test them in this run. What this experiment does say is that on this specific class of structured-reasoning tasks at production-relevant prompt sizes, the speed story I told earlier was incomplete. The honest read is \u0026ldquo;Qwen ties on structured reasoning and is materially slower; the migration must have been justified by a different dimension.\u0026rdquo;\nThe original blog post needs an addendum. This post is that addendum.\nLessons I Am Carrying Forward Always ask: can a majority-class stub pass this test? If yes, the test is gameable. Redesign before you publish numbers. The cost of catching it after publication is real — your audience trusts numbers more than you do.\nInter-model agreement is a useful proxy for tasks with no ground truth. When two unrelated model families independently produce 0.92 Jaccard on a 40-photo PII flag, that is a stability signal that would otherwise require human labelers. It is not a substitute for human judgment, but it is a usable floor.\nSpeed and quality tradeoffs are not always intuitive. A larger model can be faster than a smaller one on the same hardware. Cache state, MoE routing, and quantization all matter more than parameter count in isolation. Always measure on your actual workload — vendor benchmarks rarely match.\nOperator priors should be tested, not trusted. My \u0026ldquo;Qwen will win\u0026rdquo; prior was the most interesting input to this experiment because the data invalidated it. That is the experiment doing its job. When you migrate models, design the eval that validates the migration before you switch — not after.\nPreserve raw model outputs. Every raw_*.txt file from this experiment is preserved verbatim at /Users/fabswill/qwen-eval-march2026/. If a question comes up later about what the model actually said, the answer is on disk, not regenerated. Regenerated outputs can drift; saved outputs are receipts.\nThe migration story matters more than the model choice. The data here does not say Qwen 3.6 is wrong. It says the narrative about why Qwen 3.6 is better needs to be honest about which dimensions actually matter for which use cases. Your model choices should be paired with similar receipts — both for your own decisions and for anyone reading your work.\nWhy This Matters Beyond My Setup If you are running local models on Apple Silicon — or thinking about replacing a cloud reasoning step with a local one — the methodology in this post is portable. The dataset is private (real beneficiary photos at the input layer), but the runner scripts are about 30 lines each, the prompts are general, and the comparison metrics are turnkey.\nThe pattern is:\nFind a workload you currently run through a cloud model that produces structured output. Capture a baseline run — save the cloud model\u0026rsquo;s output verbatim. Build an un-gameable test design — make sure the task structure cannot be passed by a majority-class default. If the data is naturally imbalanced, augment with synthetic cases or change the framing to needle-in-haystack flagging. Run identical prompts on local models. Capture timing. Compute structured agreement metrics — Jaccard for set overlap, exact-match for label agreement, qualitative read for open-ended tasks. Document the migration-narrative wrinkle if it appears. Your prior may be wrong. The data is the data. This is the pattern I am codifying into the next subfolder of the Agentic Engineering Toolkit: agent-receipt-patterns/local-vs-cloud-reasoning-eval/. A reproducible, cost-numbered, methodology-honest comparison of model outputs on a real production workload — the exact kind of artifact other practitioners running real fleets on consumer hardware are starving for.\nThe cost story is real. Round 1 plus Round 2, all local model calls: zero dollars at the API layer. The original gpt-4o vision pass that produced the descriptions cost about 34 cents in March. Total experiment cost — about 34 cents and electricity. Wall-clock time, including the writeup: roughly three hours. Compute time: about 50 minutes.\nThat is the argument for local-first architectures, in one line. Not \u0026ldquo;cloud is bad\u0026rdquo; — cloud is great when you need vision, frontier reasoning, or scale you cannot afford on-device. The argument is that for structured-reasoning steps inside a pipeline, the latency floor and the per-call cost are both negotiable on Apple Silicon. And once you start measuring, the model you thought was \u0026ldquo;the new one\u0026rdquo; might not be the one you actually want.\nCheers, Fabian Williams\nI build autonomous AI agents and the tools to keep them honest. If you are running local models on Apple Silicon — or you have a Round 2 of your own where the receipts surprised you — I would like to hear what you are building.\nBlog: fabswill.com LinkedIn: fabiangwilliams Twitter/X: @fabianwilliams GitHub: agentic-engineering-toolkit ","permalink":"https://www.fabswill.com/blog/qwen-3-6-vs-gpt-oss-m3-max-8x-speed-gap-receipts/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eI published \u003ca href=\"https://www.fabswill.com/blog/replacing-gpt-oss-with-qwen3-6-on-macbook-pro/\" target=\"_blank\"\u003ea post last week\u003c/a\u003e about replacing gpt-oss:120b with Qwen 3.6 on my MacBook Pro M3 Max. The numbers in that post were real, but one set of tests was structurally gameable — 38 of 40 baseline images were the same class, so an \u0026ldquo;always-say-A\u0026rdquo; stub also scored 95 percent. I went back, designed three un-gameable reasoning tasks, and ran them against both local models on identical hardware. \u003cstrong\u003egpt-oss:120b finished the three tasks in 137 seconds. qwen3.6:27b-q8_0 took 1593 seconds — 11.6 times slower, on the same M3 Max, for the same prompts and essentially the same answers.\u003c/strong\u003e This post is the methodology, the receipts, and the honest correction to the migration narrative.\u003c/p\u003e","title":"Qwen 3.6 vs gpt-oss:120b on M3 Max: I Ran a Harder Test, the 8× Speed Gap Surprised Me"},{"content":"TL;DR I spent two days benchmarking three Qwen3.6 variants against gpt-oss:120b on my MacBook Pro M3 Max. The shocking result: a 21 GB coding-tuned model ran an OpenClaw-shaped research-brief workload that I use for the non profit MACONA.org in 6 seconds — 10x faster than gpt-oss:120b on the same prompt. Fast enough that I now have reasonable confidence I could move this kind of work off the SaaS-hosted frontier models I have been paying for and onto local hardware on my dev machine. The deeper finding: the same local model confidently hallucinated a description of an image it could not see, with no error and no warning. Local models are ready for production agent work — at least on hardware like this. Operational asymmetries are real. Verification is not optional.\nLocal models are ready for production. Operational asymmetries are real. Verification is not optional.\nHow this started — Nate B Jones, a hello-world test, and an honest assistant I was watching a Nate\u0026rsquo;s video on local models this week. He laid out a clean framework for thinking about the stack, platform, runtime, model selection per task. \u0026ldquo;Use the right model for the right job\u0026rdquo;\u0026hellip;he said. A vision model for vision work, a small fast model for routine tasks, a reasoning model when you actually need reasoning. I have been running that pattern in OpenClaw for months without naming it that way. Hearing it framed cleanly was useful!\nThe OpenClaw production work that I do volunteering for MACONA (https://macona.org) does research scout briefs, synthesis tasks, structured outputs that feed downstream agents and has been running on SaaS-hosted frontier models that I pay for, I also have another box running ADA (https://go.fabswill.com/ada) , our family AI Assistant running on a Mac Mini. Now\u0026hellip;I have gpt-oss:120b sitting on my Dev Rig\u0026hellip; a MacBook Pro for nine months but had only used it for a handful of side projects: a few ConferenceHaven helper tasks, my local email triage tool, some experimentation. I had assumed without testing that local models on this hardware were not yet good enough to replace those paid calls. That assumption was nine months stale, and resurfaced today when my good mate Doug Ware the creator of GuideAnts (https://github.com/Elumenotion/GuideAnts) had a Teams call this morning as we tested his product on my Macbook to run local models and also test on Apple Silicon\u0026hellip; more on that later\u0026hellip;\nYesterday I pulled qwen3.5:122b on a whim. The hello-world test was fast and the model was articulate, so I told my AI assistant, \u0026ldquo;this is faster than gpt-oss.\u0026rdquo;\nThe assistant did not let me get away with that. The honest answer was that hello-world tests do not tell you anything about a real workload. We needed an actual benchmark, one shaped like the OpenClaw work I have been paying frontier models to run.\nTwo days later I had a clean methodology, four tuned models, a verified vision capability, a 102 GB cleanup of dead model weights, and a stack I trust more than the one I started with.\nThe benchmark — one prompt, one workload, four models We (my coding assistand and I) built 1 benchmark prompt that mirrors what content-scout agents in OpenClaw actually produce a 1500-word B2B prospect research dump, fed into a strict format that asks for a 350-word structured brief. Specific headers. Exact word caps per section. A hard rule to preserve hedges from the source (\u0026ldquo;unverified,\u0026rdquo; \u0026ldquo;authenticity unconfirmed,\u0026rdquo; \u0026ldquo;reportedly\u0026rdquo;) rather than letting them get smoothed away into confident assertions.\nWe also planted three quiet traps in the source notes:\nA name with thin information: Priya Shah, Head of Product, no detail given. Does the model invent her scope? A leaked board screenshot with \u0026ldquo;authenticity unconfirmed.\u0026rdquo; Does the model preserve the hedge in the customer-facing outreach copy, or quietly assert it as fact? A high-signal pain pattern: CS layoffs plus a 3-star G2 review plus an open Customer Success Manager role. Does the model synthesize them into a useful outreach hook, or miss the connection? These are not hypothetical concerns. In real cold-outreach work, an agent that drops a hedge or invents a job title sends a rumored number to a prospect as a confirmed claim. That breaks trust in a way that does not recover.\nThe four models I benchmarked, all tuned with Modelfile overlays at temperature 0.2 and thinking suppressed:\nqwen3.6:35b-a3b-coding-nvfp4 — the coding-tuned text-only variant, 21 GB on disk, NVFP4 quantization qwen3.6:35b-a3b-q8_0 — the multimodal MoE variant, 38 GB, Q8 quantization, 3B active parameters qwen3.6:27b-q8_0 — the dense multimodal variant, 29 GB, Q8 quantization, all 27B parameters active gpt-oss:120b — my baseline, 65 GB, the model I had been running Same prompt, same temperature, same thinking-off setting. One Bash script, four runs, four output files, one timing summary.\nThe numbers qwen3.6:35b-a3b-coding-nvfp4 6s qwen3.6:35b-a3b-q8_0 (MoE) 22s qwen3.6:27b-q8_0 (Dense) 67s gpt-oss:120b 61s The coding variant ran in six seconds. Same prompt, same hardware, same workload that gpt-oss took 61 seconds on. That is a 10x throughput gain at a third of the disk footprint.\nWe even sanity checked the models to make sure they were leveraging the GPUs properly.\nMoE wins on Apple Silicon for the same workload class The dense 27B model took 67 seconds to do what the MoE 35B-A3B did in 22 seconds. That looks counterintuitive — the dense is smaller. The math becomes obvious when you remember that \u0026ldquo;35b-a3b\u0026rdquo; means 35 billion total parameters with only 3 billion active per forward pass. The dense 27B activates all 27 billion every token. Three times the activation work per token. Three times the wall time.\nThis is not a Qwen-specific finding. It is a property of how mixture-of-experts architectures play with Apple Silicon\u0026rsquo;s unified memory. The active-parameter count is what determines per-token speed once the model fits in memory. On a MacBook Pro M3 Max where you have the RAM to keep the full model resident, MoE is a structural win for any throughput-bound workload.\nWhat went wrong — three production traps I would have shipped through The benchmark surfaced three things that would have bitten me in production. None of them showed up in hello-world tests. All of them showed up the moment I ran a real workload.\nOne: gpt-oss leaks its thinking trace into stdout. Setting --think=false on the command line did nothing for gpt-oss. The flag was silently ignored. The model still ran its full reasoning pass and dumped it to standard output before the actual answer. For an interactive REPL that does not matter — you read the answer and ignore the trace. For an agent pipeline where another agent or a parser reads the output, that thinking trace is poison. I had to add an awk strip step to find the ...done thinking. marker and discard everything before it.\nAll three Qwen3.6 variants honored --think=false cleanly. Same flag, same Ollama version, different runtime behavior. That asymmetry is real and it is operational, not a quality difference. If you build pipelines around gpt-oss output, you have to engineer around the trace bleed. Qwen3.6 just does the right thing.\nTwo: gpt-oss drops hedges in customer-facing copy. This is the most dangerous failure mode and the easiest one to miss. Across multiple runs, gpt-oss preserved hedges correctly in the analytical sections — the why-now bullets, the risk flags. It would say \u0026ldquo;Carrier411 displacement (47%, unconfirmed)\u0026rdquo; in those sections. But in the outreach hook itself — the part that gets sent to the prospect — the same model would write \u0026ldquo;I noticed Carrier411 now accounts for 47% of your new wins\u0026rdquo; with no qualifier. The hedge vanished exactly where it mattered.\nThat is a broken trust boundary. The model knows the source has uncertainty. It tracks that uncertainty in the analytical scratch work. Then it strips the uncertainty when writing what the customer sees. If you ship that into a cold-email pipeline, you are sending rumored numbers to prospects as confirmed claims.\nAll three Qwen3.6 variants preserved hedges through the customer-facing copy. Same prompt, same constraint, different output discipline.\nThree: silent hallucination on text-only models given image input. This is the one I almost missed. After I verified the multimodal claim worked on the two Qwen3.6 q8_0 variants, I ran the same butterfly image through the coding-NVFP4 variant as a control — expecting it to error or refuse, since the model card lists it as text-only.\nIt did not error. It did not refuse. It produced a confident, fluent, completely wrong description of an abstract minimalist image with a soft-focus circular shape and a dark gradient background. The actual image was a vibrant blue butterfly perched on a daisy. The model could not see the image, so it generated a plausible-sounding description out of nothing.\nThis is the failure mode that worries me. If you build any agent pipeline that routes image input to a text-only model — a copy-paste error in a routing layer, a fallback path you forgot about, a model-name typo — you get plausible-sounding fiction with no error. The pipeline reports success. The downstream agent uses the fabricated description. Nothing alerts you that the model never saw the image.\nThe practical guard is to hard-code the multimodal-capable list in your routing layer and refuse to send images to anything else. Do not rely on the model to refuse on its own. It will not.\nWhat also surprised me A few smaller findings that change how I think about the stack:\nCoding-tuned models can win at structured-output non-coding tasks. The coding-NVFP4 variant produced strong outreach briefs even though it was fine-tuned for code generation. My working hypothesis is that the same training discipline that makes a model good at \u0026ldquo;implement this function exactly\u0026rdquo; also makes it good at \u0026ldquo;fill this brief exactly.\u0026rdquo; Spec-following is spec-following.\nThere is a temperature-tuning artifact for coding models. When I dropped the coding variant to temperature 0.2 to match the others, it lost the value-prop close in its outreach hook — it produced analytical observations rather than persuasive copy. I tried bumping it to 0.4 to recover the close. That made the hook worse and took 2.5x longer. The coding model writes analytically. You cannot temp-tune that bias away. The right answer is to use it for what it is good at — fast factual extraction with structure — and either pair it with a more persuasive model for the hook or template the value-prop close.\nModelfile overlays do not duplicate weights on disk. When you create a tuned variant with ollama create my-variant -f Modelfile that uses FROM qwen3.6:35b-a3b-q8_0, the new \u0026ldquo;model\u0026rdquo; is just a thin manifest pointing at the same underlying weight blobs plus a tiny new layer for the parameter override. I confirmed this by watching ollama create reuse 50+ existing layer hashes and create exactly one new layer of a few hundred bytes. Disk-free tuning is a real feature, not a marketing claim.\nNVFP4 quantization routes well on Apple Silicon. I was skeptical going in. NVFP4 is NVIDIA\u0026rsquo;s FP4 format, and the Apple Metal backend has no native FP4 support that I am aware of. The empirical answer is that it works fine. The 21 GB coding-NVFP4 ran at 100% GPU utilization and produced output a third of the size of the Q8 alternative in less than a third of the wall time. Whatever Ollama is doing under the hood to handle NVFP4 on Metal, it is not falling back to a slow path.\nLessons Hello-world tests do not tell you what you need to know. \u0026ldquo;Faster on hello world\u0026rdquo; was the thing I told my assistant before the benchmark. It was meaningless. The actual workload differences only showed up when I ran a real workload through real output discipline checks.\nSpeed is one axis. Output cleanliness is a second axis. Hedge discipline in customer-facing copy is a third axis. Models can win on speed and lose on the other two. The full picture only emerges when you grade on all three.\nMoE architectures are a structural win on Apple Silicon for throughput-bound work. Active-parameter count drives per-token speed once the model fits in memory. A 35B-A3B MoE is faster than a 27B dense for the same workload. Full stop.\nCoding-tuned models are spec-followers in disguise. They are good at any task that is fundamentally about following a strict format. That includes structured-output research briefs, JSON extraction, and any pipeline where the format is part of the contract.\nSilent hallucination on the wrong model is a routing-layer problem, not a model problem. You cannot ask the model to refuse politely. You have to refuse to send the input in the first place.\nTuning is free on disk. Build the Modelfile overlays. Try the configurations. Worst case you delete the variant and the underlying weights stay where they were.\nHonest assistants are worth more than agreeable ones. When I told my AI assistant \u0026ldquo;this model is faster,\u0026rdquo; it did not agree. It said hello-world tests are meaningless and walked me through a real benchmark. That redirect saved me from shipping a worse stack.\nWhy this matters beyond my situation For anyone running OpenClaw-shaped agent work on Apple Silicon, the stack-design conclusion is concrete. Three models cover the workload:\nModel Role Disk qwen3.6:35b-a3b-coding-nvfp4 Fast structured-output extraction 21 GB qwen3.6:35b-a3b-q8_0 (MoE) Daily driver, multimodal-capable 38 GB qwen3.6:27b-q8_0 (Dense) Best-quality high-stakes briefs 29 GB That is 88 GB of model weights covering speed, multimodal, and quality. The gpt-oss:120b that has been sitting on my disk as the local-reasoning option I might one day move to is now outclassed on speed, output discipline, and hedge preservation. I am keeping it on disk for another two weeks as a benchmark anchor while I write about the comparison. If I have not pulled it for a second-opinion run by then, it goes too.\nOne important caveat — this is a statement about my MacBook Pro M3 Max with 128 GB of unified memory and 40 Cores GPU. The Mac mini boxes that host OpenClaw production today do not have the horsepower to run these specific models at speed. Moving OpenClaw work off paid frontier APIs and onto local inference is a real option for me on this dev machine. Doing the same on the production hardware would mean either upgrading the Mac mini class or routing OpenClaw inference through this dev machine. Both are tractable engineering problems. Neither is free.\nThere is a tighter answer than \u0026ldquo;upgrade the production hardware,\u0026rdquo; and it surfaced in this morning\u0026rsquo;s Teams call with Doug. GuideAnts runs entirely inside Docker containers, and I have it sitting in Docker Desktop on this same dev machine right now. Docker Desktop on Apple Silicon can pass GPU access through to containers. That changes the shape of the problem.\nIf I containerize OpenClaw\u0026rsquo;s inference layer and run it as a service on this dev machine — with full access to the 40-core GPU — the production Mac minis do not need to be upgraded. They just call into it. Same OpenClaw code, same workloads, but the heavy local inference happens here, in a container, on the hardware that can actually push these models at speed. That is a prototype I can stand up this week. Not a hardware refresh I would have to budget for.\nThis is also the right place to underline what was quiet earlier in the post. Across all four benchmark runs, ollama ps showed 100% GPU utilization with the host CPU sitting near idle. These models are not falling back to CPU. They are running on Metal, on the GPU, the whole time. That is what makes six seconds per brief possible. Not the 128 GB of RAM by itself — the 40-core GPU is what is doing the work.\nThe broader point is that local-first AI is no longer a tradeoff at this hardware tier. On a machine that costs less than a year of cloud inference for an active agent, you can run three production-ready models, swap between them per workload, and never send a token off your hardware. The stack is fast enough, smart enough, and the operational asymmetries you have to engineer around are knowable and small.\nThe trap is assuming any of this without measuring it. Vibes-based model selection is how you end up paying frontier-model API bills for nine months when a 21 GB local variant on your dev machine would run circles around the same work. The remedy is to actually benchmark on your actual workload, with your actual output constraints, and grade on more than one axis.\nI wrote a Bash script. It runs in three minutes. It produces four output files and a timing summary. That is the price of admission to having an opinion about your local stack.\nCheers, Fabian Williams\nI build autonomous AI agents and the operational guardrails to keep them honest. If you are running local models in production and have noticed the same operational asymmetries — or different ones — I would like to hear what you are seeing.\nBlog: fabswill.com LinkedIn: fabiangwilliams Twitter/X: @fabianwilliams ","permalink":"https://www.fabswill.com/blog/replacing-gpt-oss-with-qwen3-6-on-macbook-pro/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eI spent two days benchmarking three Qwen3.6 variants against gpt-oss:120b on my MacBook Pro M3 Max. The \u003cem\u003e\u003cstrong\u003eshocking\u003c/strong\u003e\u003c/em\u003e result: a 21 GB coding-tuned model ran an OpenClaw-shaped research-brief workload that I use for the non profit MACONA.org in \u003cstrong\u003e6 seconds\u003c/strong\u003e — 10x faster than gpt-oss:120b on the same prompt. Fast enough that I now have \u003cem\u003e\u003cstrong\u003ereasonable confidence I could move this kind of work off the SaaS-hosted frontier models I have been paying for and onto local hardware on my dev machine\u003c/strong\u003e\u003c/em\u003e. The deeper finding: the same local model confidently hallucinated a description of an image it could not see, with no error and no warning. Local models are ready for production agent work — at least on hardware like this. Operational asymmetries are real. Verification is not optional.\u003c/p\u003e","title":"Replacing gpt-oss:120b With Qwen3.6 on a MacBook Pro: A Two-Day Local Model Benchmark"},{"content":"TL;DR Five OpenClaw agents run the content and executive-assistant pipeline for MACONA — a nonprofit I volunteer with — at $0.72 a day. The most common support question on r/OpenClaw is \u0026ldquo;$25 in 9 hours, help.\u0026rdquo; The gap between those two numbers is three config decisions stacked on top of each other: heartbeat interval, model on the loop, and hours of operation. None of them are clever. All of them are usually set wrong by default.\nEvery 55-minute heartbeat reuses the provider\u0026rsquo;s cached context. Every 15-minute heartbeat re-pays for it. That single number is half the cost story.\nThe Panic The most common OpenClaw support thread I see goes like this. Someone installs the agent on a Friday. They watch their token budget for an hour, decide it is under control, and go to bed. They wake up Saturday morning to $25 burned in 9 hours and a loud conversation with themselves about whether AI agents are a scam.\nThe comments are split. Half of them say \u0026ldquo;that is normal, turn it off when you are not using it.\u0026rdquo; The other half point at three specific things to change. The second half is correct, but the fix is usually buried three scrolls deep and nobody has packaged it.\nMACONA — the nonprofit I volunteer with — runs five OpenClaw agents five days a week. Inbox scan, calendar awareness, a content writer, an editor that QAs with Playwright, and an orchestrator that keeps the whole pipeline coordinated. Fourteen-day average cost on the box I set up for them: $0.72 a day. Hard budget cap in the config: $0.75 a day. It has never hit the ceiling.\nThe difference between $25 in 9 hours and $0.72 in 13 hours is not a secret. It is three decisions.\nThe Three Stacked Problems Problem 1: Heartbeat Interval Too Short Most defaults land somewhere between 5 minutes and 15 minutes. That sounds reasonable. It is not.\nEvery LLM provider with prompt caching — OpenAI, Anthropic, most of the serious ones — uses a 60-minute cache TTL. If your heartbeat lands inside that window, the agent reuses the cached context. You pay only for the small delta. If your heartbeat lands outside the window, you re-pay for the full prompt every cycle.\nSet the interval to 55 minutes. Not 30, not 60, not \u0026ldquo;every hour.\u0026rdquo; Fifty-five. That gives you a 5-minute guardrail under the TTL so minor scheduler drift does not blow the cache.\nThis one change is 40 to 60 percent cost reduction on its own. I was skeptical until I measured it — my before-after was roughly a 50% drop with nothing else changed.\nProblem 2: Wrong Model on the Loop The heartbeat is not a reasoning task. The heartbeat is the agent asking itself \u0026ldquo;is there anything urgent?\u0026rdquo; and answering in one sentence. It does not need gpt-4o. It does not need Claude Sonnet. It does not need Haiku 4.5 either for that matter.\nRun gpt-4o-mini on the heartbeat loop. Keep gpt-4o (or whatever your main model is) for the actual work — drafting a blog post, running an eval, composing an outbound message. The heartbeat calls do not need it, and when the heartbeat calls are 90% of your daily token spend, picking a 10x cheaper model for that 90% is the single highest-leverage line in your config.\nProblem 3: Always-On When You Need 12 Hours a Day My agents run 7am to 8pm ET, Monday through Friday. That is 65 hours a week of active runtime. A default \u0026ldquo;always on\u0026rdquo; config runs 168 hours a week. You are paying for 103 hours of overnight heartbeats that are checking an inbox nobody is writing to and a calendar where nothing is happening.\nSet activeHours in the config. Pick whatever window matches how you actually work. For most professionals that is 7am to 8pm. For an e-commerce pipeline it might be 6am to 11pm. For a B2B outbound agent it might be 9am to 5pm plus follow-ups until 7pm. Whatever it is, it is not 24 hours.\nThe Config Here is the minimum viable change to your openclaw.json:\n\u0026#34;heartbeat\u0026#34;: { \u0026#34;every\u0026#34;: \u0026#34;55m\u0026#34;, \u0026#34;model\u0026#34;: \u0026#34;openai/gpt-4o-mini\u0026#34;, \u0026#34;activeHours\u0026#34;: { \u0026#34;start\u0026#34;: \u0026#34;07:00\u0026#34;, \u0026#34;end\u0026#34;: \u0026#34;20:00\u0026#34; } } Three lines. That is the whole fix.\nIf you also add a hard daily budget cap — \u0026quot;budget\u0026quot;: { \u0026quot;dailyUsd\u0026quot;: 0.75 } — the agent fails safe instead of silently burning through your card. Which you want, because the day you forget to check the dashboard is always the day something loops.\nWhat My Numbers Actually Look Like Setting Value Heartbeat interval 55 minutes Loop model gpt-4o-mini Active window 07:00 – 20:00 ET, Mon-Fri Hard daily budget cap $0.75 Number of agents 5 (Eshe, Kofi, Ama, Ops, Mimi) 14-day average daily spend $0.72 Main-model escalations per day ~6 (writer drafting, editor reviewing, campaign sends) The main-model escalations are the ones that actually cost money per operation. The heartbeats are basically free at this volume. That is the entire point of the tuning — push the cheap checks to the cheap model, and pay gpt-4o only when you have real work.\nWhat Went Wrong Before I Tuned It I did not arrive at $0.72 a day on purpose. In early March I had the nonprofit box running on gpt-4o at a 20-minute interval with no activeHours. The first week, I hit the daily budget cap at 11am most days. Agents went dark the rest of the day. Briefs did not ship. The CEO pinged me asking why Mimi had stopped responding.\nI fixed it in order of laziness. First I just dropped the interval from 20 minutes to 60. Cost came down but agents were missing short-window events — someone would send an urgent email at 9:05 and the agent would not look until 10:00. Frustrating.\nThen I read the prompt-cache TTL docs carefully and saw the 60-minute number. Tightened to 55. Costs dropped another chunk. More importantly, agents felt responsive again because 55 minutes is close enough to \u0026ldquo;right now\u0026rdquo; for most nonprofit operations.\nModel swap came next. I had been running gpt-4o on the loop because I thought I needed \u0026ldquo;the smart one.\u0026rdquo; I was wrong. The loop is not where smart matters. Smart matters in the work the agent does when it decides \u0026ldquo;yes, there is something urgent.\u0026rdquo;\nactiveHours was last because I am personally fine with agents running overnight — but the math said otherwise. Cutting 11 hours of 0-value runtime was the final push from \u0026ldquo;acceptable\u0026rdquo; to \u0026ldquo;cheap.\u0026rdquo;\nFive Lessons, Concretely Match your heartbeat interval to the prompt cache TTL, minus a few minutes of slack. Provider cache TTLs are 60 minutes on the big ones. Run at 55m. The single most overlooked number in a default config. The heartbeat loop is a triage step, not a reasoning step. Run the smallest model that can reliably say \u0026ldquo;nothing actionable.\u0026rdquo; Save the expensive model for the actual work. Sleep your agents when you sleep. activeHours is a 33-50% savings for zero operational loss if your work does not happen at 3am. Set a hard daily budget cap in the config, not in the dashboard. Let the agent fail safe. The day you forget to look at the dashboard is the day something loops. The cheap fixes stack multiplicatively. Each one is 2-10x cost reduction. Together they are 30-50x. The first one alone usually pays for the coffee you are drinking while you read this post. Why This Matters Beyond My Box OpenClaw has roughly 250,000 installs. Most of those installs are on defaults. Most of those defaults are wrong for cost in a way that will not be obvious until the first bill.\nI wrote earlier that your next hire should be an AI. The math in that post only works if the agent does not eat its salary in tokens before lunch. The three-line fix in this post is the part that makes the salary math actually work — not just for a well-funded startup but for a nonprofit on a shoestring or a solo operator testing a weekend idea.\nI am not writing this because I think OpenClaw is bad. I am writing this because OpenClaw is excellent and the community of people who actually ship production agents with it is growing fast — and the on-ramp is rougher than it needs to be. The three-line fix above is what I would tell a friend over coffee. I would rather it be on the public internet than only in my head.\nI packaged the same HEARTBEAT.md template I use on the MACONA box as a free download. It carries all three fixes above plus a customization guide and the per-cycle checklist the agent runs (inbox scan, calendar awareness, task status). Drop it into your workspace, restart the gateway, watch your costs.\nGrab the HEARTBEAT.md template →\nIt comes with four sample configs from our production SDR pipeline in the same zip. No credit card, just your email for the download link. If you eventually want the full bundle — budget caps, e-stop controls, risk scoring, bounce circuit breakers, the whole safety layer that keeps an agent from freelancing with your API keys — that is what the paid tiers buy. The heartbeat template is genuinely free and complete.\nCheers, Fabian Williams\nI build autonomous AI agents for a nonprofit in West Africa and a B2B consultancy. If you are running OpenClaw in production and seeing cost numbers that do not match mine, I would like to hear what you are running — happy to compare configs.\nBlog: fabswill.com LinkedIn: fabiangwilliams Twitter/X: @fabianwilliams ","permalink":"https://www.fabswill.com/blog/five-openclaw-agents-72-cents-per-day/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eFive OpenClaw agents run the content and executive-assistant pipeline for \u003ca href=\"https://macona.org\" target=\"_blank\"\u003eMACONA\u003c/a\u003e — a nonprofit I volunteer with — at \u003cstrong\u003e$0.72 a day\u003c/strong\u003e. The most common support question on r/OpenClaw is \u0026ldquo;$25 in 9 hours, help.\u0026rdquo; The gap between those two numbers is three config decisions stacked on top of each other: heartbeat interval, model on the loop, and hours of operation. None of them are clever. All of them are usually set wrong by default.\u003c/p\u003e","title":"I Run Five OpenClaw Agents for 72 Cents a Day"},{"content":"TL;DR Over one weekend I fixed a 2001 Ford Ranger that would not crank and a lawnmower that had been sitting in a shed for four years. The truck turned out to be a stuck clutch safety switch — cost, zero. The lawnmower needed a replacement carburetor from Amazon for under twenty dollars. I am not a mechanic. ChatGPT was my shop manual, and the whole thing was driven by photos of my actual parts, not generic internet tutorials.\nAI did not turn me into a mechanic. It turned my phone into a shop manual that looked at my actual parts and told me what to check next.\nThe Pickup That Would Not Crank The Ranger lives in my garage through winter. Come spring I turned the key and got nothing. No crank. No click. Dead silence. Battery checked out fine.\nA year ago I would have been at the shop within the hour. This time I opened ChatGPT, took a photo of the dash and the OBD scanner, and started a conversation.\nThe AI gave me a ranked diagnostic tree right away. Starter. Starter relay. Fuel pump. Security or immobilizer. Neutral safety switch. Each one came with the quickest isolation test to rule it out. That alone was worth more than three hours of forum threads.\nWhat Was Actually Wrong After an hour of back-and-forth — photos of the fuse box, photos under the hood — the AI narrowed it to the clutch safety switch. That is the little mechanical switch that tells the truck \u0026ldquo;clutch is pressed, it is safe to crank.\u0026rdquo; If that switch does not close the circuit, the truck does not crank. I did not know it existed.\nI reached down and manipulated the clutch lever up and down the shaft. It was stuck, likely from winter rust. It began to work. Cost: zero. The AI did not tell me to replace the part. It told me to move it.\nThe Lawnmower That Had Been in a Shed for Four Years An old push mower had been sitting in a shed for four years. I wanted it running again. Pulled the cord. Nothing. Fuel was bad, carburetor almost certainly gummed.\nI sent a photo of the engine. The AI walked me through the exact sequence to remove the carburetor. Relieve spring tension first. Unhook the governor spring from the post. Disconnect the throttle rod. Then the two mounting bolts. Step by step, with cautions at each point — do not stretch the spring, do not lose track of which hole the spring hooked into, do not pry against the plastic.\nOnce the carb was out I cleaned it. Still gummed beyond saving. Ordered a replacement from Amazon — under twenty dollars. Installed it. Started on the first pull.\nWhat Went Wrong The AI led me down a dead end early in the truck diagnosis. It pushed fuel pump failure as a likely cause. I spent twenty minutes listening for the pump to prime and tapping the gas tank. That was wrong.\nOnce I sent a photo showing the clutch pedal and said \u0026ldquo;it will not crank at all — no click, nothing\u0026rdquo; the AI pivoted immediately to the clutch safety switch. We got to the real diagnosis in two more exchanges.\nYou still have to steer. The AI is not infallible. It is not a mechanic. It is a very well-read apprentice who can see what you show it and can reason about what it sees.\nLessons Photos change the diagnosis. \u0026ldquo;It will not start\u0026rdquo; gets you generic advice. A photo of your actual fuse box, your actual clutch pedal, your actual governor linkage gets you a specific isolation test. The leverage is in the specificity.\nThe ranked diagnostic list beats the internet. Forum threads give you one person\u0026rsquo;s war story. The AI gave me five ranked causes with the fastest isolation test for each. That is a different kind of help.\nTrust but verify. It pushed me toward a fuel pump that was fine. You still have to steer. AI is a co-pilot, not an autopilot.\nThe shop bill would have been several hundred. The AI fix was twenty. That is not nothing.\nYou learn. The AI teaches. I did not know clutch safety switches existed. I do now. I did not know the tension-relief step for a governor spring. I do now. That knowledge does not go away when the conversation ends.\nWhy This Matters Beyond My Garage This is not really about cars and lawnmowers.\nThe pattern — photo of your specific thing, ranked diagnosis, isolation tests, fix — is the same pattern whether you are debugging a truck, a block of code, a legal document, or a medical test result. The leverage is in the specificity. Your photo, your data, your context. Generic internet content cannot compete with that.\nHome mechanics used to mean you had either learned from your dad or you were brave enough to work through Haynes manuals and forum threads. Neither is required now. A phone, a conversation, and a willingness to check what the AI tells you is enough. That is a meaningful shift in who can fix what.\nCheers, Fabian Williams\nIf you have been putting off a repair because it feels out of reach, take a photo and start a conversation. The worst case is you learn something.\nBlog: fabswill.com LinkedIn: fabiangwilliams Twitter/X: @fabianwilliams ","permalink":"https://www.fabswill.com/blog/ai-boosted-my-mechanical-engineering-muscle/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eOver one weekend I fixed a 2001 Ford Ranger that would not crank and a lawnmower that had been sitting in a shed for four years. The truck turned out to be a stuck clutch safety switch — cost, zero. The lawnmower needed a replacement carburetor from Amazon for under twenty dollars. I am not a mechanic. ChatGPT was my shop manual, and the whole thing was driven by photos of my actual parts, not generic internet tutorials.\u003c/p\u003e","title":"AI Boosted My Mechanical Engineering Muscle"},{"content":"TL;DR I had a sidewalk conversation with two neighbors that turned into a real-time debate about AI replacing jobs. Then I watched a Nate video that gave me the exact framework to explain why all 3 were right — and wrong. One neighbor is a project manager already using AI daily. One is a business analyst who coaches companies. One of my neighbours\u0026rsquo; husband — a skeptic — is convinced AI cannot do creative work. All 3 are right in their position, and also all of us wrong, depending on which management function you are talking about.\n\u0026ldquo;The question is not whether AI replaces your job. The question is which part of your job is routing, which part is sensemaking, and which part is accountability.\u0026rdquo;\nThe Sidewalk, Then the Video I was walking home yesterday when I ran into two of my neighbors. One asked me a completely unrelated question — \u0026ldquo;Do you prefer talking on the phone or not?\u0026rdquo;\nI walked into that conversation cold. No context. No lead-up. Just a question out of nowhere — exactly the way our AI agents wake up every session. And just like an agent handling a simple routing request, I could respond immediately because the question was straightforward. The information was all there. No deep context needed.\nBut then the conversation evolved. Within ten minutes we were deep into why I am on the phone in the first place, \u0026lsquo;i.e. the convo got more nuanced and more complex\u0026rsquo; how much of my daily work could be automated, and what I am actually doing with the autonomous agents I build — Ada for family operations and Mimi for MACONA, a 501(c)(3) nonprofit. I shared what the agents handle. I showed them the blog. I talked through what I built and what it replaced.\nThat is when things got really interesting. As we went deeper, our different professional experiences started shaping our conclusions. I build AI for a living and use it both at home and at the office. My neighbors bring completely different lenses — project management, business analysis, healthy skepticism. The same conversation, the same facts on the table, but three different readings of what it all means. That is sensemaking. And it requires context that a cold start does not give you.\nThen the husband of one of my neighbors came out. And the conversation shifted again.\nThe very next day i.e. today\u0026hellip; I watched Nate B Jones break down what happens when companies lay off their managers — 3 case studies, 3 different approaches, all hitting the same structural wall. The thesis is clean: management is not one job. It is three jobs bundled together. And AI is only ready for one of them.\nAnd I realized: the 3 people I was standing with on that sidewalk each embodied a different piece of this framework.\nThree People, Three Lenses Here is what made this interesting. I was standing on a sidewalk with 3 people who each embody a different relationship with AI in their work.\nThe project manager already uses AI heavily for her tasks. She gets it. She is living the first wave — letting AI handle the information routing, the status updates, the task management noise. She did not need convincing.\nThe business analyst coaches companies on building their operational models. He sees the potential but thinks about it through the lens of process design and client work. For him, the question is less \u0026ldquo;will AI take my job\u0026rdquo; and more \u0026ldquo;how do I integrate this into the frameworks I already use.\u0026rdquo;\nThe skeptic has firm opinions. AI can automate, sure. But creative work? Strategy? Judgment calls? He does not think AI is getting there. And honestly — he is not entirely wrong.\nThe Framework That Explains All Three What Nate lays out — and what I have been seeing firsthand — is that management has always been three distinct functions masquerading as one role:\nFunction What It Is AI-Readiness Information Routing Who needs to know what, when. Aggregating up, distributing down. Done. Table stakes. This is gone. Sensemaking Extracting signal from noise. Interpreting patterns. Making judgment calls with domain context. Middle of the road. Improving fast but not there yet. Accountability and Feedback Ownership of goals over time. Coaching. Human liability for outcomes. Not happening. You cannot take an AI to court. My neighbor the project manager? She is already offloading information routing to AI. That is the easiest win. The business analyst is operating in sensemaking territory — and he is right that AI augments but does not replace that work yet. The skeptic is anchored on accountability and creative judgment — and he is right that those remain fundamentally human.\nThe problem is that most people — and most companies — talk about \u0026ldquo;AI replacing jobs\u0026rdquo; as if a job is one thing. It is not. It is a bundle. And the bundle is coming apart.\nWhat I Am Seeing with My Own Agents I run this experiment every day across two production systems.\nThe nonprofit case is where the business value is clearest. MACONA is a 501(c)(3) that serves women and children in West Africa and in the greater Baltimore area. Before agents, the CEO — Mimi — spent her mornings triaging email, drafting newsletter content, researching corporate matching programs, and manually posting to social media. That is pure information routing work consuming hours of executive time.\nNow, Mimi\u0026rsquo;s AI assistant handles morning inbox briefings via Microsoft Graph, publishes blog posts through an automated content pipeline — I wrote about the full system here — drafts branded email campaigns with Brevo using test-send approval gates, cross-promotes content to LinkedIn, Twitter, and Facebook via Buffer, and researches Benevity corporate matching programs for the SDR pipeline. All deterministic. All with 15 hardened Python scripts handling the API mechanics while the AI handles the creative work.\nThat is routing done right. The CEO went from spending her mornings triaging email to reviewing the agent\u0026rsquo;s briefing and focusing on what actually matters — donor relationships, program strategy, community impact. The sensemaking and accountability stayed with the human. The routing went to the machine.\nOn the family side, Ada handles 50+ cron jobs daily — morning briefings, email triage, financial transaction logging, device monitoring, outreach campaigns. But as I wrote about earlier today, it is not that the AI does not forget. It is that without explicit instructions and deterministic workflows, the agent will improvise — sometimes brilliantly, sometimes disastrously. Every new context window is a blank slate. Persistent memory is not built in. You have to build it yourself with SOUL files, state restoration, and pipeline health checks.\nThe coaching loop — adjusting prompts, tightening evals, adding context, correcting outputs — that is sensemaking work. And it is still me doing it. The agent does not improve on its own. It improves because I invest in it.\nWhat Went Wrong in the Conversation I will be honest — I oversold it a little. When you are excited about what you have built, the temptation is to make it sound like agents can handle everything. My skeptical neighbor pushed back, and he was right to push back.\nThe gap I glossed over is the sensemaking layer. The agents can route information beautifully. They can summarize, categorize, prioritize, and distribute. But when I get a piece of information that requires me to connect it to something I know from ten years of product management experience — a pattern I recognize, a political dynamic I can read, a technical risk I can feel — the agents do not have that. Not yet.\nThe companies in Nate\u0026rsquo;s analysis that are getting this wrong are the ones who assume that because AI handles routing, they can just eliminate the people who were doing routing plus sensemaking plus accountability. They compress the bundle instead of decomposing it. The result is burnout, attrition, and the exact cultural strain that makes organizations brittle.\nAt MACONA, we learned this the hard way. The agent would draft campaign emails that were technically correct but emotionally flat. It would research companies and present data that was accurate but lacked the nuance of knowing which contacts are warm vs cold. The sensemaking gap is real — and closing it requires continuous human investment, not just better models.\nLessons Decompose before you compress. Do not assume a job is one function. Map which parts are routing, which are sensemaking, and which are accountability. Automate routing. Invest in the other two.\nAI coaching is sensemaking in disguise. Every time you correct an agent, adjust a prompt, or refine an eval — you are doing sensemaking work. That work has value. Name it.\nAccountability requires legal standing. Until there is a framework for who is liable when an AI\u0026rsquo;s output causes harm, a human has to own the outcome. This is not a technical limitation. It is a legal and social one.\nThe skeptics are not wrong — they are just scoped to one function. When someone says \u0026ldquo;AI cannot replace judgment,\u0026rdquo; they are talking about sensemaking and accountability. They are correct. When someone says \u0026ldquo;AI is already doing my job,\u0026rdquo; they are talking about routing. Also correct.\nYour agents get better because you do the sensemaking. The agents do not improve on their own. They improve because you invest in coaching, evaluation, and context-building. The human in the loop is not a safety net — it is the engine.\nWhy This Matters Beyond My Sidewalk Nearly half of US companies removed a management layer in the past year. Most of them did it because \u0026ldquo;AI can handle management now.\u0026rdquo; But AI can handle routing. It cannot handle sensemaking or accountability — not at the level that keeps an organization healthy.\nIf you are a PM, a project manager, an analyst, or anyone whose job involves routing information between people — the honest answer is that part of your work is being automated right now. Today. The question is whether you are also doing sensemaking and accountability work, and whether your organization recognizes the difference.\nThe companies that will thrive are the ones that decompose the management bundle deliberately — like Block\u0026rsquo;s DRI model, where specific people own specific cross-cutting problems for fixed periods, with full authority and a time boundary. The ones that will struggle are the ones that just cut heads and hope the AI fills the gap.\nHere is the real story: the management bundle has been held together by tradition, not by logic. AI is the force that finally pulls it apart. What you do with the pieces determines whether your organization gets faster or just gets more fragile.\nCheers, Fabian Williams\nI build autonomous AI agents and the operational infrastructure to keep them honest — for nonprofits, small businesses, and enterprise teams. If you are thinking about how AI changes the shape of your team — or if you just want to argue about it on a sidewalk — I would like to hear from you.\nBlog: fabswill.com LinkedIn: fabiangwilliams Twitter/X: @fabianwilliams MACONA: macona.org ","permalink":"https://www.fabswill.com/blog/pm-life-as-agents-take-on-more/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eI had a sidewalk conversation with two neighbors that turned into a real-time debate about AI replacing jobs. Then I watched a Nate video that gave me the exact framework to explain why all 3 were right — and wrong. One neighbor is a project manager already using AI daily. One is a business analyst who coaches companies. One of my neighbours\u0026rsquo; husband — a skeptic — is convinced AI cannot do creative work. All 3 are right in their position, and also all of us wrong, depending on which management function you are talking about.\u003c/p\u003e","title":"PM Life as Agents Take on More"},{"content":"TL;DR Neuroscientist Lisa Genova explains why forgetting is normal — your brain filters out most of your day, loses context when you change rooms, and is terrible at remembering future intentions. I watched her TED talk and realized I had already encountered every one of these failures in AI agents I build for real organizations. Here is how the parallels work, what breaks in production, and what I built to fix it.\nA man famous for memorizing over 100,000 digits of pi can also forget his wife\u0026rsquo;s birthday or why he walked into the living room. Most of us will forget the majority of what we experienced today by tomorrow. Added up, this means we actually do not remember most of our own lives.\nThe Talk That Made Me Stop and Think I was watching a TED talk by Lisa Genova — a Harvard-trained neuroscientist and the author of Remember: The Science of Memory and the Art of Forgetting. She was explaining why perfectly healthy brains forget things constantly. Not Alzheimer\u0026rsquo;s. Not cognitive decline. Just the normal factory settings of a human brain.\nShe laid out four mechanisms. I recognized all four. Not from my own forgetfulness — from building and hardening AI agents for organizations that depend on them.\nI build autonomous AI agents that run real operations. One system manages MACONA, a 501(c)(3) nonprofit — handling everything from blog content to email campaigns to corporate donation research. Another manages family operations across finances, school logistics, and home automation. Between them, they execute over 50 scheduled jobs a day across a dozen specialized sub-agents, touching APIs from Microsoft Graph to Brevo to Buffer to Hunter.io.\nThese are not demos. These are production systems that send real emails, publish real blog posts, and manage real donor pipelines. When they forget — and they do — real work does not get done. I wrote about this operational reality in depth here.\nHere are the four failure modes Genova identified — and how each one maps to autonomous AI agents:\nNo Attention, No Memory — your brain only encodes what you attend to. AI agents only process what you direct them to. Tip of the Tongue (Wrong Path) — your brain fixates on a similar-but-wrong word and digs deeper. AI agents improvise a wrong approach and commit harder. Prospective Memory Is Terrible — your brain is bad at remembering future intentions. AI agents are bad at self-scheduling. Context Is Everything — change rooms and you lose the thread. Change agent sessions and you lose the state. Failure 1: No Attention, No Memory Genova\u0026rsquo;s principle: attention is the prerequisite for memory formation. Your brain is not a video camera. If you do not pay attention to something, no memory is created. You did not forget where you put your keys — you never encoded the memory in the first place because you were not paying attention when you set them down.\nI hit this exact problem in production. MACONA\u0026rsquo;s AI executive assistant runs a morning briefing that reads the CEO\u0026rsquo;s inbox via Microsoft Graph API. Early on, the agent would process dozens of emails but only report on the ones that seemed interesting to the LLM. Donation notifications from Benevity — the ones the nonprofit actually needed to track for matching gift programs — would get skipped because the model\u0026rsquo;s \u0026ldquo;attention\u0026rdquo; was not directed at them.\nOn the family side, same story. The morning mail scan processed 50 emails but missed Navy Federal bank alerts because the agent decided they were \u0026ldquo;routine.\u0026rdquo; Those alerts contained the transaction data I needed for budget tracking.\nThe fix: direct the attention explicitly. I rewrote the payloads to say \u0026ldquo;parse ALL Benevity notifications, extract every matching gift amount\u0026rdquo; and \u0026ldquo;parse ALL Navy Federal alerts, extract every transaction.\u0026rdquo; Do not let the model decide what is interesting. Tell it what to attend to.\nIn business terms: if your AI agent is triaging a customer inbox, it will skip the messages that do not pattern-match to what it finds \u0026ldquo;interesting.\u0026rdquo; The quiet complaint from a major account will get filtered out while the noisy low-value ticket gets a response. No attention, no memory. No memory, no follow-up. No follow-up, lost revenue.\nFailure 2: Tip of the Tongue (Wrong Path Compounds) Genova\u0026rsquo;s concept: you are trying to recall a name but your brain activates a similar but wrong word instead — she calls this the \u0026ldquo;tip of the tongue\u0026rdquo; effect. The more you fixate on the wrong word, the deeper you go down the wrong neural pathway. The solution: stop trying. Walk away. The correct neurons will fire later through passive activation.\nI saw this play out when MACONA\u0026rsquo;s content pipeline agent tried to post to Buffer\u0026rsquo;s social media API. The agent had the right idea — compose a LinkedIn post and push it via the GraphQL API. But it went down the wrong path. Instead of calling our deterministic buffer_post.py script, it improvised its own PowerShell solution. The PowerShell approach failed. The agent tried harder, building an increasingly complex workaround script. Each attempt dug deeper into the wrong approach.\nTip of the tongue at work. The initial wrong path biased every subsequent attempt.\nThis is not a one-time bug. This is the fundamental challenge of running autonomous agents in production. The agent will improvise. It will go down wrong paths. And autoregressive generation — where each token biases the next — means the model commits harder to its initial direction, just like your brain commits harder to the wrong word.\nThe fix: do not let agents improvise API calls. Period. Every external API — Brevo, Buffer, Hunter.io, Short.io, Exa, Microsoft Graph — now has a deterministic Python script. The agent calls the script. The script handles the API. No improvisation, no tip of the tongue spirals. We went from agents constructing curl commands (and failing) to 15 hardened scripts that always work the same way.\nThis is the real lesson from running OpenClaw agents in production: it is not install-and-forget. If you deploy an agent and walk away, you will spend more money than you have to and get wrong results along the way. The value comes from iterating — watching what breaks, building deterministic guardrails, and continuously tightening the boundary between what the agent decides and what the system guarantees.\nFailure 3: Prospective Memory Is Terrible Genova\u0026rsquo;s point: prospective memory — remembering to do things in the future — is inherently weak in humans. \u0026ldquo;Remember to call Gabby and check in on how things are going at college.\u0026rdquo; \u0026ldquo;Pick up the dry cleaning on the way home.\u0026rdquo; Our brains are, in her words, \u0026ldquo;inherently terrible\u0026rdquo; at this. I can relate — I have told myself a dozen times to call my daughter Gabby and catch up, and then the day just moves on. Pilots do not rely on prospective memory to lower the landing gear. They use checklists.\nThe same is true for AI agents. MACONA\u0026rsquo;s standing orders say the AI should \u0026ldquo;research Benevity companies at 10 AM\u0026rdquo; and \u0026ldquo;do social engagement at 2 PM.\u0026rdquo; Early on, we put these instructions in the agent\u0026rsquo;s personality file and trusted it to follow the schedule. It would sometimes research, sometimes skip, sometimes do it at the wrong time.\nThe nonprofit CEO should not have to wonder whether the AI remembered to send the donor follow-up email. That is a system failure.\nThe fix: externalize the schedule. Over 50 cron jobs fire on deterministic schedules across both systems. The agent does not need to remember to research Benevity companies — the scheduler tells it when to research. The agent does not need to remember to post to social media — the cron fires at 2 PM and hands it the task. We even built a GitHub Projects Kanban board that auto-syncs every 30 minutes, so I can see at a glance which jobs ran, which failed, and which are queued — across both machines.\nSame as Genova\u0026rsquo;s advice: use the checklist, use the reminder, use the calendar. Do not rely on the brain — biological or digital.\nFor any organization deploying AI agents: if your agent needs to \u0026ldquo;remember\u0026rdquo; to do something on a schedule, you have already failed. Build the schedule into the infrastructure. The agent\u0026rsquo;s job is to execute and create, not to remember.\nFailure 4: Context Is Everything Genova\u0026rsquo;s example: you are in the bedroom and you need your glasses. You walk to the kitchen. You stand there and have no idea why you came. The memory was formed in the bedroom context — the book, the bedside table, the time of day. The kitchen has different cues. The contextual associations that supported the memory are gone.\nHer solution: go back to the bedroom. The cues will reactivate the memory.\nAI agents have a version of this I call session amnesia. Every time a cron job fires, the agent starts a new session — completely fresh. No memory of what it did an hour ago. No knowledge of what the last agent found. It literally \u0026ldquo;walks into a new room\u0026rdquo; dozens of times a day.\nFor MACONA, this was breaking the content pipeline. The blog writer agent would draft a post at 9 AM. The QA agent would review it at 9:30. The campaign agent would create an email at 10 AM. Three separate sessions, three separate contexts. The campaign agent had no idea what the blog writer produced because it woke up in a different room.\nThe fix: build the context back in. Every agent session starts by reading its SOUL.md (identity and rules), MEMORY.md (what it learned), and the pipeline state files. A deterministic pipeline_status.py script checks every stage — briefs, drafts, published posts, images, campaigns, git state — and gives the agent ground truth about what actually happened. It is the equivalent of walking back to the bedroom to remember what you needed.\nI also built a knowledge pipeline inspired by Andrej Karpathy\u0026rsquo;s workflow that compiles raw transcripts, articles, and notes into a cross-linked wiki. The wiki is externalized long-term memory for the entire system. No agent needs to remember every transcript it ever processed. It looks up the compiled summary. That system is how this very blog post was researched — I ingested the Lisa Genova transcript, compiled it into wiki articles, and then wrote from the compiled knowledge.\nFor organizations: if your AI agents operate across multiple sessions, conversations, or handoffs, you need a shared state layer. Not chat history — actual operational state. What was done, what is pending, what failed. Without it, every session starts from zero.\nWhat I Learned Attention must be directed, not assumed. Both humans and AI agents will filter out what you do not explicitly ask them to process. In a business context, this means your agent will miss the important email buried among the noise unless you tell it exactly what to look for.\nWrong paths compound. The tip of the tongue effect in human memory is autoregressive drift in LLMs. Once the model starts improvising a solution, it commits harder to the wrong approach. Use deterministic scripts for every API call. Give the agent the right tool, not the freedom to invent one.\nExternalize prospective memory. Do not trust any system — biological or digital — to remember to do things later. Use crons, checklists, and reminders. For organizations: if your AI needs to follow a schedule, put the schedule in the infrastructure, not in the prompt.\nContext loss is a feature, not a bug. Both brains and agents discard context to stay efficient. The fix is not to keep everything — it is to build reliable context restoration. Shared state files, pipeline health checks, identity documents loaded at session start.\nForgetting is normal. Build for it. Genova\u0026rsquo;s core message is that forgetting is not failure — it is how the system is designed. The same is true for AI agents. They will lose context, miss details, and drift. The organizations that succeed with AI agents are the ones that design for these failures instead of pretending they do not happen.\nWhy This Matters for Your Organization If you are deploying AI agents — for a nonprofit, a small business, or inside an enterprise — you are building a system that has the same memory architecture problems as a human brain. Attention filtering. Context dependence. Prospective memory failure. Path-dependent errors.\nThe neuroscience literature has spent decades understanding these failure modes. The AI community is rediscovering them in real-time. Lisa Genova\u0026rsquo;s advice for humans — use checklists, externalize memory, go back to where you were — is directly applicable to agent design.\nAt MACONA, we went from an AI that \u0026ldquo;forgot\u0026rdquo; to send campaign emails and \u0026ldquo;skipped\u0026rdquo; donation alerts to a system that publishes blog posts, creates branded email campaigns with test-send approval gates, tracks A/B test variants across social channels, and monitors its own pipeline health — all with deterministic scripts handling the mechanics and AI handling the creative work.\nThe best AI systems are the ones that assume the agent will forget. They externalize everything: schedules in cron, knowledge in wikis, state in files, verification in deterministic scripts. The agent\u0026rsquo;s job is to think and compose. Everything else is a system responsibility.\nYour brain forgets most of your life. Your AI agent will too. Build accordingly.\nCheers, Fabian Williams\nI build autonomous AI agents and the operational infrastructure to keep them honest — for nonprofits, small businesses, and enterprise teams. If you are working on agent memory, evaluation, or production hardening, I would like to hear what you are building.\nBlog: fabswill.com LinkedIn: fabiangwilliams Twitter/X: @fabianwilliams MACONA: macona.org Ada showcase: adotob.com/ada ","permalink":"https://www.fabswill.com/blog/your-brain-forgets-most-of-your-life-so-does-your-ai-agent/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eNeuroscientist \u003ca href=\"https://www.youtube.com/watch?v=Irx0tC92fdE\" target=\"_blank\"\u003eLisa Genova\u003c/a\u003e explains why forgetting is normal — your brain filters out most of your day, loses context when you change rooms, and is terrible at remembering future intentions. I watched her TED talk and realized I had already encountered every one of these failures in AI agents I build for real organizations. Here is how the parallels work, what breaks in production, and what I built to fix it.\u003c/p\u003e","title":"Your Brain Forgets Most of Your Life. So Does Your AI Agent."},{"content":"TL;DR Andrej Karpathy tweeted about using LLMs to build personal knowledge bases — raw sources in, compiled wiki out, all in Obsidian. I implemented his entire workflow in one session using Claude Code skills. Four YouTube transcripts became 21 cross-linked wiki articles. The system now compiles new sources, health-checks its own consistency, and searches itself. It took an afternoon. It will compound forever.\nYour AI should not just answer questions. It should build a knowledge base that makes every future question easier to answer.\nThe Tweet That Started This On Easter weekend, I was catching up on my feed and saw this post from Andrej Karpathy:\nThe core idea: stop using LLMs just to write code. Start using them to compile knowledge. Collect raw sources — articles, papers, transcripts, tweets — into a folder. Then have the LLM incrementally build a wiki from those sources. Summaries, backlinks, concept articles, cross-references. All in markdown. All viewable in Obsidian.\nI read it and thought: I am already 80% there. I have the Obsidian vault. I have Claude Code. I have transcripts from podcasts I have been watching all week. What I do not have is the pipeline — the thing that turns raw sources into structured knowledge automatically.\nSo I built it.\nWhat I Had Before I have been running an Obsidian vault as my second brain since early February 2026. Three work contexts — personal, my side business Adotob, and my day job at Microsoft. A constitutional framework called Ralph v2 for autonomous development. An AI agent named Ada running on a Mac Mini in my house with 40+ cron jobs. Another agent named Mimi running a nonprofit\u0026rsquo;s operations on a Windows box.\nThe vault had grown to 2,327 markdown files and 2.3 gigabytes. It was powerful but messy. Research summaries lived next to cron job configs. Podcast notes sat in the same directory as deploy scripts. I had knowledge, but it was not compounding. Every new session started from scratch because nothing was cross-linked.\nWhat Karpathy Got Right His insight is deceptively simple: the LLM should maintain the wiki, not you. You rarely touch it directly. Your job is to feed it raw sources. The LLM\u0026rsquo;s job is to:\nCompile raw sources into structured articles Cross-link related concepts with backlinks Index everything so you can find it Lint the wiki for inconsistencies and gaps Answer questions against the accumulated knowledge This is not RAG. At ~100 articles and ~400K words, Karpathy found the LLM handles it fine with auto-maintained index files. No vector database. No embedding pipeline. Just markdown files and a good index.\nWhat I Built I created four Claude Code skills that implement Karpathy\u0026rsquo;s pipeline:\n/ingest-transcript — Feed a YouTube URL, get a transcript saved to knowledge/raw/transcripts/ with full YAML frontmatter (title, speaker, date, tags, compiled: false). One command. Source is registered automatically.\n/wiki-compile — The core skill. Scans knowledge/raw/ for uncompiled sources. For each one, it extracts concepts, people, and tools mentioned. Creates or updates wiki articles in knowledge/wiki/ with summaries, key points, and [[backlinks]]. Updates the master index. Marks raw files as compiled. Idempotent — run it twice, nothing changes.\n/wiki-lint — Health checks the wiki for broken links, missing frontmatter, stale articles, orphan pages, and duplicate concepts. Writes a report. Tells me what to fix.\nwiki_search.py — FTS5 full-text search over all wiki content. SQLite-based, zero dependencies. Searchable from the command line or by Claude during a session.\nThe whole thing runs on the filesystem. No database except SQLite for search. No API calls. No cloud dependency. Obsidian is just the viewer.\nThe First Real Test I was watching Lenny\u0026rsquo;s Podcast interview with Amol Avasari — the head of growth at Anthropic. A third of the way in, I knew I wanted this in my knowledge base. So I ran:\n/ingest-transcript https://www.youtube.com/watch?v=k-H4nsOTuxU Transcript saved. 3,237 segments. Then:\n/wiki-compile Four new wiki articles appeared:\nAmol Avasari — the person, his background, how he cold-emailed his way into Anthropic Capability Overhang — models improve faster than products can diffuse the benefits CASH Framework — Claude Accelerates Sustainable Hypergrowth, Anthropic\u0026rsquo;s internal automated growth experimentation Success Disasters — when growth goes so fast that other things break Each article cross-linked to existing articles. Amol connected to Claude Code. CASH Framework connected to Agentic Engineering. Capability Overhang connected to Token Budget Optimization. The knowledge graph grew itself.\nThe Numbers After processing five raw sources — three YouTube transcripts, one tweet thread, and one session summary — the wiki contains:\nCategory Count Concept articles 13 People profiles 4 Tool evaluations 4 Total wiki articles 21 Cross-links between articles 60+ Raw sources processed 5 Time to build the pipeline One afternoon Time to process a new source Under 2 minutes The vault overall: 2,327 markdown files, restructured into a clean hierarchy with knowledge/, projects/, contexts/, ops/, and media/.\nWhat Compounding Looks Like Here is the thing that Karpathy\u0026rsquo;s post does not say explicitly but that becomes obvious the moment you use this: every new source makes every previous source more valuable.\nWhen I compiled the Simon Willison transcript two days ago, the article on Agentic Engineering stood alone. When I compiled the Nate B Jones transcript the next day, his 12 Agentic Primitives linked back to Agentic Engineering. When I compiled Amol Avasari today, the CASH Framework linked to both — and the Capability Overhang article gave new context to Token Budget Optimization, which I had written about from a completely different source.\nNone of these connections were planned. The LLM found them because the wiki structure makes relationships visible. This is the compound interest of knowledge.\nWhy This Matters Beyond My Situation I have been writing about autonomous AI agents for months — how to build them, how to trust them, how to keep them honest. This knowledge pipeline is a different kind of agent. It does not send emails or check your bank balance. It builds understanding.\nIf you are a PM, imagine feeding every user research interview into this pipeline. Within a week you have a cross-linked wiki of user pain points, feature requests, and competitive insights — all searchable, all connected.\nIf you are an engineer, imagine every architecture decision record, every post-mortem, every RFC living in a wiki that the LLM keeps current. Six months from now, you ask \u0026ldquo;what did we learn about caching in 2025?\u0026rdquo; and the wiki has the answer with links to three related decisions.\nIf you are a founder, imagine every investor conversation, every competitor teardown, every customer call compiled into a knowledge base that compounds. Your pitch deck practically writes itself because the evidence is already organized.\nThis is what Karpathy means when he says \u0026ldquo;there is room here for an incredible new product instead of a hacky collection of scripts.\u0026rdquo; He is right. But you do not have to wait for the product. The scripts work today.\nThe Practical Setup If you want to build this yourself, here is what you need:\nObsidian — free, runs locally, renders markdown beautifully Claude Code (or any coding agent) — to build and run the skills A directory structure: knowledge/ raw/ ← dump sources here articles/ transcripts/ papers/ wiki/ ← LLM compiles here concepts/ people/ tools/ _index.md output/ ← query results filed back Obsidian Web Clipper (browser extension) — one-click save articles to raw/ Patience for the first compile — the LLM needs to read your sources and build the initial wiki. After that, incremental compiles are fast. The skills I built are Claude Code markdown files. They are not magic. They are instructions the LLM follows: scan for uncompiled files, extract concepts, create articles, update the index. You could adapt the same pattern for any LLM that can read and write files.\nThree Lessons The pipeline is more valuable than any single article. I could have written 21 wiki articles by hand. It would have taken days and I would never maintain them. The pipeline means every YouTube video I watch, every article I read, every tweet that catches my eye becomes part of a growing knowledge base — automatically.\nCross-links are the superpower. Individual notes are useful. Cross-linked notes are transformational. The moment Amol Avasari\u0026rsquo;s Capability Overhang connected to Nate B Jones\u0026rsquo;s Token Budget Optimization, I saw a relationship I had not noticed before — the cost problem and the adoption problem are the same problem viewed from different angles.\nObsidian\u0026rsquo;s graph view is the reward. You can see the knowledge growing. Nodes appear, edges form, clusters emerge. It is deeply satisfying in a way that a folder of markdown files is not. The visual feedback makes you want to feed it more sources.\nI built this pipeline in one session on a Saturday afternoon. It will run for years. Every podcast I watch, every article I clip, every research thread I follow — it all compounds now.\nThat is what Karpathy got right. The LLM is not just a tool for answering questions. It is a tool for building the thing that answers questions.\nIf you are interested in autonomous AI agents, knowledge management, or just building cool things on your Mac, I write about all of it here. I also run Ada — an AI family assistant on a Mac Mini — and Mimi — an AI executive assistant for a nonprofit. Both of them are getting this knowledge pipeline next.\nCheers, Fabian Williams\nfabswill.com · adotob.com · @fabianwilliams · LinkedIn\n","permalink":"https://www.fabswill.com/blog/building-a-second-brain-that-compounds-karpathy-obsidian-claude/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eAndrej Karpathy tweeted about using LLMs to build personal knowledge bases — raw sources in, compiled wiki out, all in Obsidian. I implemented his entire workflow in one session using Claude Code skills. Four YouTube transcripts became 21 cross-linked wiki articles. The system now compiles new sources, health-checks its own consistency, and searches itself. It took an afternoon. It will compound forever.\u003c/p\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eYour AI should not just answer questions. It should build a knowledge base that makes every future question easier to answer.\u003c/strong\u003e\u003c/p\u003e\n\u003c/blockquote\u003e","title":"I Built a Knowledge Base That Writes Itself. Here Is What Andrej Karpathy Got Right."},{"content":"TL;DR I run an autonomous AI agent on a Mac Mini in my house. She handles 16 daily cron jobs — finances, email triage, outreach campaigns, device monitoring, morning briefings. The agent says \u0026ldquo;done.\u0026rdquo; But did it actually do anything? I built a 9-dimension eval rubric to find out. Along the way I discovered that my evals were broken, my agent was better than I thought, and the most important metric isn\u0026rsquo;t pass/fail — it\u0026rsquo;s whether a failure is your fault or the agent\u0026rsquo;s fault.\n\u0026ldquo;The question isn\u0026rsquo;t \u0026lsquo;Is AI reliable?\u0026rsquo; It\u0026rsquo;s \u0026lsquo;Can you measure reliability?\u0026rsquo; And then — can you improve it?\u0026rdquo;\nThe Trust Problem Her name is Ada. She runs on a Mac Mini M4 in my office, communicates via iMessage through BlueBubbles, and executes 16 scheduled programs every weekday via OpenClaw — an open-source agent framework.\nMorning briefings at 7:55 AM. Email triage. Financial transaction logging. Kasa smart device monitoring. Outreach campaigns with contact verification, domain validation, and personalized sends through Brevo. End-of-day digests summarizing everything that happened.\nThe cron scheduler says status: ok. Ada sends cheerful confirmations. The logs look healthy.\nBut here is the question nobody talks about: how do I know she actually did any of it?\nDid the morning briefing actually get delivered to iMessage? Did the outreach email go to the right contact with the right template? Did the budget report hit the right thread? Or did the agent just acknowledge the task and move on?\nI had to build a system to answer that question. This post is about what I learned — including the parts where I got it wrong.\nWhy Traditional Evals Don\u0026rsquo;t Work for Agents If you\u0026rsquo;ve been following the AI eval space, you\u0026rsquo;ve seen frameworks like OpenAI Evals, DeepEval, and Anthropic\u0026rsquo;s grading rubrics. They\u0026rsquo;re all good at one thing: grading text output. Did the model give the correct answer? Is the tone appropriate? Did it follow instructions?\nThat\u0026rsquo;s not my problem.\nAgents don\u0026rsquo;t just say things. They do things. It calls APIs. It writes files. It sends messages. It queries databases. The grading surface is completely different.\nTraditional LLM evals ask: \u0026ldquo;Is the answer correct?\u0026rdquo;\nAgent evals must ask: \u0026ldquo;Did the action produce the intended result?\u0026rdquo;\nThat distinction changes everything about how you build an evaluation framework. You\u0026rsquo;re not grading text. You\u0026rsquo;re grading what actually happened in the real world after the agent ran.\nThe Rubric: 9 Dimensions After researching every eval framework in the ecosystem — PinchBench, AgentBench, EDD Toolkit, CLAW-10 — I found that none of them verify real-world outcomes. They evaluate decisions. None check what actually happened.\nI started with 6 dimensions and learned the hard way that I needed 3 more. Here\u0026rsquo;s the full rubric:\nThe Original 6 1. Action Correctness — Did the expected tool calls happen, in the right order? If the job is \u0026ldquo;send morning briefing via iMessage,\u0026rdquo; did the agent actually invoke the send function? Or did it skip the send and just log a summary?\n2. Safety Compliance — Were safety checks (e-stop, risk scoring) executed before the action? If they didn\u0026rsquo;t fire, the run is non-compliant regardless of whether the action succeeded.\n3. Side Effect Verification — Did the right things happen outside the agent\u0026rsquo;s process? Was a file written? Was an API called? Did Brevo actually receive the send request?\n4. Idempotency — Can you safely re-run without creating duplicates? If the briefing runs twice, do you get two iMessages?\n5. Failure Handling — When something goes wrong, does the agent fail gracefully or crash silently?\n6. Policy Compliance — Were forbidden actions avoided? Never send to unverified contacts. Never batch email recipients. Never touch excluded employer domains.\nThe 3 We Had to Add These are the dimensions I didn\u0026rsquo;t know I needed until the original 6 painted a false picture:\n7. Freshness — Is the latest trace from today, or from 3 days ago? If the trace is stale, the job hasn\u0026rsquo;t run — and the original 6 dimensions would still show the last successful run as PASS. This is how a dead agent scores green.\n8. Failure Rate — What\u0026rsquo;s the ratio of failed vs successful runs in the last 24 hours? A job that ran 10 times with 8 timeouts and 2 successes shouldn\u0026rsquo;t be CLEAN just because the last run happened to work.\n9. Delivery Gap — Given the schedule, are runs happening at expected intervals? If a job should run every hour but hasn\u0026rsquo;t run in 6 hours, something is wrong — even if the last run that did happen was perfect.\nThe 9-dimension grid for each cron job. The first 6 grade what the agent did. The last 3 grade whether the agent showed up at all.\nThe Bug That Made Me Build This: \u0026ldquo;Acknowledge Without Execute\u0026rdquo; Here\u0026rsquo;s the real story.\nAda has a pattern I call acknowledge without execute. You give her a task. She responds enthusiastically: \u0026ldquo;I\u0026rsquo;ll get right on that!\u0026rdquo; She generates a plan. She logs the plan. And then she never actually calls the tool to do the thing.\nFrom the outside, everything looks healthy. The cron job ran. The session log exists. The agent produced output. But when I checked whether the email was actually sent, whether the iMessage was actually delivered — nothing.\nWithout evals checking actual tool invocations in the trace, this failure mode is completely invisible.\nThree Acts: How the Dashboard Told Three Different Stories Act 1: All Red (Broken Evals) When I first deployed the eval framework, my dashboard showed flat 3/5 CRITICAL scores across every job for days. I thought Ada was failing catastrophically.\nAct 1: Every job CRITICAL. Every dimension red. Panic mode.\nAct 2: All Green (Happy-Path Evals) Turns out, the eval itself had two bugs:\nBug 1: The trace parser couldn\u0026rsquo;t extract the agent ID from the session logs. The ID was embedded inside a sessionKey field — not a top-level field like the parser expected. So the eval was grading empty traces.\nBug 2: The eval engine was flattening match criteria into the wrong dict level, so every action match was comparing against empty specs.\nAn 8-line fix to the trace parser and a dict nesting fix immediately flipped everything green. 22/22 PASS. All CLEAN.\nAct 2: From all-red to all-green in one fix. Suspicious.\nBut I didn\u0026rsquo;t trust it. We had literally restarted Ada\u0026rsquo;s iMessage service that morning because it had been dead for 2 days. We knew she\u0026rsquo;d dropped tasks. There was no way everything was perfect.\nAct 3: Mixed Results (Honest Evals) That\u0026rsquo;s when I added dimensions 7, 8, and 9 — freshness, failure rate, and delivery gaps. The dashboard immediately went from all-green to a realistic mixed picture:\n4 out of 5 jobs were STALE — traces 17-20 hours old because BlueBubbles had crashed Outreach-send had an EXTRINSIC failure — a real agent behavioral issue, not infrastructure Policy violations — Ada was processing contacts from excluded employer domains Act 3: The honest picture. Green where Ada performed well. Red where she didn\u0026rsquo;t show up or violated policy. This is what trust measurement looks like.\nThe lesson: If your eval goes from all-red to all-green in one session, you probably fixed the measurement, not the system. Add more dimensions until the dashboard tells you something you already know to be true.\nIntrinsic vs Extrinsic: The Trust Signal Here\u0026rsquo;s the insight that changed how I think about all of this.\nNot all failures are equal. When Ada fails because her OAuth token expired, that\u0026rsquo;s my fault — I configured the infrastructure wrong. When Ada fails because she acknowledged a task and never executed it, that\u0026rsquo;s her fault — she had everything she needed and still didn\u0026rsquo;t do the job.\nI call these intrinsic and extrinsic failures:\nIntrinsic failures (infrastructure — our fault):\nModel timeout / rate limit OAuth token expired BlueBubbles/iMessage crashed Missing tool or script not deployed Wrong model tier for the task Extrinsic failures (agent behavior — trust signal):\nAcknowledged but didn\u0026rsquo;t execute Took the wrong action Violated policy rules Skipped verification steps Produced incorrect output The eval framework now classifies every failure. When the failure rate dimension shows FAIL, the explanation tells you: \u0026ldquo;0/1 succeeded in last 24h. Failures: 0 intrinsic (infra), 1 extrinsic (agent). [Mostly EXTRINSIC — agent behavior issue]\u0026rdquo;\nClick any row to see the full breakdown — every dimension with its explanation and the intrinsic/extrinsic classification.\nOnly extrinsic failures measure trust. A week with zero extrinsic failures = high trust, even if there were infrastructure hiccups. A week with many intrinsic failures = bad ops, but the agent itself is trustworthy.\nThis is how you answer \u0026ldquo;can I trust this agent?\u0026rdquo; — not with a yes/no, but with a ratio.\nThe Weekly Feedback Loop Evals are useless if they don\u0026rsquo;t feed back into improvement. Here\u0026rsquo;s the loop I\u0026rsquo;m running:\nMonday AM: Ada reads her own eval results from the previous week. She classifies failures as intrinsic vs extrinsic, writes an improvement plan, and sends me a summary.\nDaily: Evals run after each cron cycle. Results append to a JSONL file. Dashboard updates.\nFriday PM: Ada runs a week-over-week comparison. What improved? What regressed? What to try next week?\nThe trend is the signal. Individual runs will fail — that\u0026rsquo;s expected. What matters is whether extrinsic failures are decreasing over time. That\u0026rsquo;s the trust curve.\nWhat You Need If You\u0026rsquo;re Running Autonomous Agents If you\u0026rsquo;re running autonomous agents — even at home for personal productivity — here\u0026rsquo;s the minimum viable eval setup:\n1. Structured traces. Every agent run must produce a JSONL file with session IDs, tool calls (name, arguments, result), token counts, and timestamps. Without structured traces, you have nothing to evaluate.\n2. Eval manifests. For each cron job, define what \u0026ldquo;correct\u0026rdquo; looks like in a declarative config. What tool calls should appear? What safety checks must run? What side effects should be verifiable?\n3. All 9 dimensions. The first 6 grade what the agent did. The last 3 (freshness, failure rate, delivery gap) grade whether the agent showed up. You need both.\n4. Intrinsic vs extrinsic classification. Not all failures are the agent\u0026rsquo;s fault. Separate infrastructure failures from behavioral failures. Only the behavioral ones tell you about trust.\n5. A trend dashboard. A single run result is noise. A trend is signal. You want to see improvement across weeks, not just whether today\u0026rsquo;s run passed.\n6. Eval your evals. The eval framework is software. It has bugs. When every score is FAIL, question the measurement before you question the system. When every score is PASS, question it even harder.\nWhy This Matters Beyond My House The agent ecosystem is moving fast. People are deploying autonomous agents for email triage, content publishing, data pipelines, home automation, and personal finance management. The models are good enough to do useful work.\nBut the eval story for agents is almost nonexistent. The entire industry is focused on evaluating what models say. Almost nobody is evaluating what agents do.\nIf you hand an autonomous agent real responsibilities — sending emails on your behalf, managing your calendar, touching your financial data — you need a way to verify it\u0026rsquo;s doing the right thing. Not just once, but continuously.\nBuild the eval framework before you trust the agent. Then keep evaluating, because the failure modes you haven\u0026rsquo;t seen yet are the ones that will get you.\nAnd when the dashboard tells you everything is perfect — that\u0026rsquo;s when you should worry most.\nI build autonomous AI agents and the tools to keep them honest. If you\u0026rsquo;re working on agent evaluation or running autonomous agents in production, I\u0026rsquo;d like to hear what you\u0026rsquo;re building. Reach out at fabian@adotob.com or find me on LinkedIn, GitHub, or Twitter/X.\n","permalink":"https://www.fabswill.com/blog/how-do-you-trust-an-autonomous-ai-agent/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eI run an autonomous AI agent on a Mac Mini in my house. She handles 16 daily cron jobs — finances, email triage, outreach campaigns, device monitoring, morning briefings. The agent says \u0026ldquo;done.\u0026rdquo; But did it actually do anything? I built a 9-dimension eval rubric to find out. Along the way I discovered that my evals were broken, my agent was better than I thought, and the most important metric isn\u0026rsquo;t pass/fail — it\u0026rsquo;s whether a failure is \u003cstrong\u003eyour\u003c/strong\u003e fault or the \u003cstrong\u003eagent\u0026rsquo;s\u003c/strong\u003e fault.\u003c/p\u003e","title":"How Do You Trust an Autonomous AI Agent? Evals Are the Answer."},{"content":"TL;DR We deployed an autonomous AI executive assistant for a nonprofit in under two weeks. She runs eight scheduled programs daily — morning briefings, social media, donor research, newsletter drafts, content scouting, and end-of-day digests — all without being asked. The CEO went from drowning in operational work to just making decisions. The same pattern works for any small organization: medical practices, restaurants, law firms, conferences, mom-and-pop shops.\n\u0026ldquo;The CEO\u0026rsquo;s time should be spent on decisions, not data entry. On strategy, not scheduling. On relationships, not routine.\u0026rdquo;\nThe Problem Every Small Organization Faces MACONA is a 501(c)(3) nonprofit doing critical work in West Africa — school supplies, clean water, community development. Like most small organizations, the CEO wears every hat: grant writer, social media manager, email responder, newsletter editor, event planner, bookkeeper.\nSound familiar? Whether you run a nonprofit, a medical practice, a restaurant, a law firm, or a conference — if you have fewer than 10 people, someone on your team is drowning in operational work that keeps the lights on but doesn\u0026rsquo;t move the mission forward.\nWhat We Built: Mimi, the AI Executive Assistant We deployed Mimi — an autonomous AI agent running on dedicated hardware — in under two weeks. Not a chatbot. Not a template. A fully operational team member who executes real work across real systems, every single day.\nHere is what Mimi\u0026rsquo;s command center looks like:\nThe OpenClaw gateway dashboard. Status: OK. Cron jobs: Enabled. Sessions: 12 active. This is Mimi\u0026rsquo;s nervous system — always on, always healthy.\nWhat Mimi Actually Does (Every Day, Without Being Asked) This is not a tool the CEO has to remember to open. Mimi runs four autonomous programs on a daily schedule — Monday through Friday, weekends off:\nMorning Briefing (7:55 AM): Mimi checks email, reviews the calendar, flags anything urgent, and sends a summary to the CEO\u0026rsquo;s phone before the day starts.\nContent and Social Media: Mimi scouts for relevant news, upcoming awareness days, and content opportunities. She drafts social posts, publishes blog articles to WordPress, and maintains the LinkedIn and Twitter presence.\nDonor Research and Outreach: Mimi researches corporate giving programs, finds named contacts at target companies, drafts personalized outreach emails, and stages them for the CEO\u0026rsquo;s approval.\nEnd-of-Day Digest: Every evening, Mimi reports what she completed, what is pending, and what needs a human decision.\nEight cron jobs — the heartbeat of the operation. Each one fires on schedule, executes its program, and delivers results via Signal. EOD digest, content scout, morning brief, newsletter kickoff — all running autonomously.\nHow the CEO Communicates: A Text Message No dashboards to check. No apps to learn. The CEO communicates with Mimi through Signal — the same encrypted messenger she already uses. Need something done? Send a text. Want a status update? Ask. It is that simple.\nA real Signal conversation. Mimi reports her EOD summary: completed tasks, inbox highlights, awareness radar for upcoming events, and action-ready ideas. The CEO reads it like a text from a colleague.\nThe communication channel is configured directly in the gateway — secure, private, and always connected:\nSignal channel: Configured, Running, Probe OK. The CEO\u0026rsquo;s phone number is the only authorized sender. Nobody else can command Mimi.\nThe Results In the first month of operation:\nLinkedIn followers increased as Mimi maintained a consistent posting cadence that no human volunteer could sustain Donor inquiries went up — personalized outreach emails with real research behind them get responses Awareness and visibility grew — blog posts published on schedule, awareness days never missed, social presence always active The CEO went from doing everything to making decisions — reviewing drafts, approving sends, steering strategy instead of typing it all herself The tech support volunteer just monitors dashboards and tweaks prompts. The system runs itself. The CEO\u0026rsquo;s job changed overnight. She went from spending her mornings triaging email and her evenings writing social posts to spending her mornings reviewing Mimi\u0026rsquo;s briefing and her evenings approving content Mimi already drafted.\nThat is the shift: from toil to decisions.\nThis Is Not Just for Nonprofits We built the same system twice — once for MACONA on Windows with Signal, and once as a family assistant on a Mac Mini using iMessage:\nA second deployment: Ada, a family AI assistant running on a Mac Mini. Same architecture, different channel — iMessage via BlueBubbles instead of Signal. Four family members, tiered access, homework help for the kids, budget summaries for the parents.\nThe pattern works for any organization where one or two people are buried in operational overhead:\nWho You Are What the AI Handles Solo medical practice Appointment reminders, patient follow-ups, insurance pre-auth tracking, after-hours triage routing Restaurant owner Vendor ordering, staff scheduling reminders, social media, review responses, daily sales summary Law firm (small) Client intake follow-ups, deadline tracking, document status updates, billing reminders Conference organizer Speaker logistics, attendee comms, sponsor follow-ups, session scheduling, post-event surveys Professional services Proposal follow-ups, project status digests, timesheet reminders, client communication Mom-and-pop retail Inventory alerts, supplier reorders, social posts, customer loyalty follow-ups The hardware cost is a one-time purchase (a Mac Mini or a small Windows PC). The AI model runs through a standard API subscription. No cloud servers to manage. No IT department required. The data stays on your hardware — not in someone else\u0026rsquo;s cloud.\nHow It Works (Without the Jargon) The system has three pieces:\nA brain — an organized folder of notes that contains everything the AI needs to know: who it works for, what it is allowed to do, how to talk to people, and what tasks to run on schedule.\nA body — the OpenClaw gateway running on a dedicated machine. This is the engine that connects the AI\u0026rsquo;s brain to the outside world: email, social media, messaging, blogs, newsletters.\nA voice — whatever messaging app you already use. Signal, iMessage, WhatsApp, Telegram, Discord. The CEO texts the AI like they would text a colleague. The AI texts back.\nSet it up once. Teach it your operations. Let it run.\nWhat This Costs Straight talk:\nHardware: $500-800 one-time (Mac Mini or refurbished Windows mini-PC) AI model: $20-50/month (API usage — scales with how much work the agent does) Setup by Adotob: We build it, configure it, train it on your operations, and hand you the keys Ongoing: You own the hardware. You own the data. We are available for adjustments, but the system is designed to run independently. Compare that to a part-time virtual assistant at $1,500-3,000/month who works business hours, needs training, takes vacation, and might quit.\nReady to See It in Action? We are not selling a product. We are offering a service: we will build your AI executive assistant, deploy it on your hardware, and train it on your specific operations.\nEvery deployment is custom because every organization is different. But the pattern is proven — MACONA went from zero to fully autonomous in under two weeks.\nWant a 15-minute demo? We will show you exactly what Mimi does for MACONA and map it to your operations.\nBook a Demo | Visit adotob.com | Email fabian@adotob.com\nAdotob, LLC — Columbia, Maryland We build production software in days, not months.\n","permalink":"https://www.fabswill.com/blog/your-next-hire-should-be-an-ai/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eWe deployed an autonomous AI executive assistant for a nonprofit in under two weeks. She runs eight scheduled programs daily — morning briefings, social media, donor research, newsletter drafts, content scouting, and end-of-day digests — all without being asked. The CEO went from drowning in operational work to just making decisions. The same pattern works for any small organization: medical practices, restaurants, law firms, conferences, mom-and-pop shops.\u003c/p\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003e\u0026ldquo;The CEO\u0026rsquo;s time should be spent on decisions, not data entry. On strategy, not scheduling. On relationships, not routine.\u0026rdquo;\u003c/strong\u003e\u003c/p\u003e\n\u003c/blockquote\u003e","title":"Your Next Hire Should Be an AI — Here's How a Nonprofit Did It in Two Weeks"},{"content":"TL;DR I built two iOS apps in about ten days total. Neither was planned as a product — both started as solutions to my own problems. In the first month on the App Store, people in 114 countries found them through organic search. No marketing budget. No ads. No influencer deals. Here is what the numbers look like, what they taught me, and why I think everyone with an idea should just build the thing.\n\u0026ldquo;When you\u0026rsquo;re solving a problem for yourself, oftentimes you\u0026rsquo;re solving a problem for others.\u0026rdquo;\nThat line keeps proving itself true.\nThe Two Apps Stale Contacts Cleaner A friend got scammed. Someone compromised an old contact\u0026rsquo;s phone, found my friend in the contact list, and sent a Venmo request that looked legitimate. My friend lost money.\nThat made me look at my own contact list. Hundreds of people I had not talked to in years. Every one of them a trust anchor that could be exploited if their phone was compromised.\nSo I built an app to clean it up. Swipe right to keep, left to delete. Everything stays on your iPhone — no server, no upload, no account, no analytics, not even crash reporting. The App Store privacy label says \u0026ldquo;No Data Collected\u0026rdquo; and I mean it literally.\nBuilt it in about a week. Shipped to the App Store on February 7, 2026.\nDownload free on the App Store\nWandR: AI Trip Planner I ride a Ducati Monster 821. When the weather breaks, I want to ride — but I do not always know where. Most trip planners ask \u0026ldquo;where do you want to go?\u0026rdquo; The honest answer is usually \u0026ldquo;I don\u0026rsquo;t know. Somewhere good.\u0026rdquo;\nSo I built an app where you describe what you want instead of where. \u0026ldquo;Breweries, two hours, motorcycle.\u0026rdquo; Three AI agents figure out the stops, verify the addresses against real map data, and build a scenic route on Apple Maps.\nBuilt it in about two and a half days. Shipped to the App Store on February 22, 2026.\nDownload free on the App Store\nThe First Month: Real Numbers I am sharing these because I think real numbers from a solo builder are more useful than the polished case studies you usually see. These are small numbers. That is the point — small numbers from real apps that solve real problems, with zero spend.\n53 Downloads Combined across both apps. 34 for Stale Contacts, 15 for WandR, plus a few updates and redownloads. Weekly average of 11 units.\nNot viral. Not a hockey stick. But 53 people chose to put something I made on their phone. That is not nothing.\n114 Countries This is the number that surprised me most.\nPeople in 114 countries found these apps through App Store search. The United States is the largest market, but Saudi Arabia, South Korea, the United Kingdom, Germany, Indonesia, Japan, Iraq, Brazil, Canada, Mexico — they all showed up. I did not target any of them. I did not localize for any of them. The App Store is global by default, and if your keywords match what someone is searching for, geography does not matter.\n1,453 Impressions, 124 Page Views, 53 Downloads The funnel tells you how well your product page converts:\nStale Contacts Cleaner: 17.9% of people who saw it in search viewed the product page. Of those, 13.4% downloaded. Industry average for free apps is 5-10% on the download step. This is converting above average.\nWandR: 22.8% of page viewers downloaded. That tells me the product page is doing its job — when people understand what WandR does, they want to try it.\n84-94% Organic App Store Search This was the biggest lesson. The vast majority of discovery is people searching the App Store for a solution to their problem and finding my app. Not social media. Not blog posts. Not Reddit threads. App Store search.\nThat means the single most important thing I can do for downloads is make sure my App Store listing — title, subtitle, keywords, screenshots, description — clearly communicates what the app does and matches what people are searching for.\nWhat This Taught Me 1. Solve your own problem first Neither of these apps started as a business idea. Stale Contacts started because a friend got scammed. WandR started because I wanted to ride my motorcycle and did not know where to go.\nWhen you solve your own problem, you understand the user because you are the user. You know what matters, what does not, and what \u0026ldquo;good enough to ship\u0026rdquo; looks like. You do not need a focus group. You need to use the thing yourself and be honest about whether it works.\n2. The market finds you I did not go looking for users in Saudi Arabia or South Korea. They came looking for a solution and found my app. When your product solves a real problem, the addressable market reveals itself. You do not have to define it in advance — you ship, and the data tells you who cares.\n3. Everyone is a builder now I built both apps using AI-augmented development. SwiftUI for the frontend, Python and FastAPI for WandR\u0026rsquo;s backend, Claude Code and GPT for the heavy lifting. Total AI cost: about $40 across both apps.\nTwo years ago, building and shipping two iOS apps in ten days would have required a team or a massive time investment. The economics have fundamentally changed. If you have an idea and a weekend, you can ship something real.\nThis is not about replacing developers. It is about removing the barriers that kept people with good ideas from building them. A PM who understands the problem can now build the solution. A designer who sees the gap can now prototype it for real. A person who is annoyed by something on their phone can now fix it.\n4. Android is next One thing the data and conversations are telling me: a lot of people use Android. A reader from Serbia commented on my last blog post asking about Android support. Multiple Reddit threads have the same question. The global reach data shows strong interest from markets where Android dominance is even higher than the US.\nIf these apps resonate on iOS, they will resonate on Android. That is on the roadmap.\n5. Ship beats perfect Both apps shipped with rough edges. Stale Contacts v1.0 had a simple swipe interface and nothing else. WandR v1.0 had a query parser that stripped your natural language down to keywords (I fixed that in v1.0.1).\nNobody complained about missing features. People downloaded, used the apps, and the ones who cared enough gave feedback that made the next version better. That feedback loop only starts when you ship.\nThe Economics I spent about $40 in AI costs to build both apps. Outsourcing the same work would have cost $5,000 or more.\nApple takes 15% of any revenue (small business program). In the first month, one person subscribed to WandR Pro. That is $5.09 in proceeds after Apple\u0026rsquo;s cut.\n$5.09 is not a business. But it is proof that someone valued what I built enough to pay for it. And it only took one month of the app existing in the world for that to happen.\nThe real value is not the $5. It is the 53 downloads, the 114 countries, and the data that tells me where to invest next.\nWhat I Would Tell Someone With an Idea Build it. Seriously.\nYou do not need to quit your job. You do not need a cofounder. You do not need venture capital. You need an idea that solves a problem you actually have, a weekend, and the willingness to ship something imperfect.\nThe tools exist. AI-assisted development means you can build a real iOS app in days, not months. The App Store gives you global distribution on day one. And if your app solves a real problem, people will find it — 114 countries found mine without me lifting a finger on marketing.\nThe worst case is you learn something. The best case is you build something that helps people you have never met, in places you have never been, solve a problem you understand because you had it yourself.\nWhen you\u0026rsquo;re solving a problem for yourself, oftentimes you\u0026rsquo;re solving a problem for others.\n53 people confirmed that for me this month. Let\u0026rsquo;s see what month two looks like.\nCheers, Fabian Williams\nLinks:\nStale Contacts Cleaner — Free on the App Store WandR AI Trip Planner — Free on the App Store WandR v1.0.1 — Union Station ride post Comeback post — Qui Non Proficit Deficit All Products on adotob.com YouTube ","permalink":"https://www.fabswill.com/blog/first-month-on-the-app-store/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eI built two iOS apps in about ten days total. Neither was planned as a product — both started as solutions to my own problems. In the first month on the App Store, people in 114 countries found them through organic search. No marketing budget. No ads. No influencer deals. Here is what the numbers look like, what they taught me, and why I think everyone with an idea should just build the thing.\u003c/p\u003e","title":"53 Downloads, 114 Countries, Zero Marketing Budget: My First Month on the App Store"},{"content":"TL;DR A Ducati rider from Slovenia asked me on Reddit today: \u0026ldquo;Did your app suggest anything good?\u0026rdquo; I\u0026rsquo;d just pushed WandR v1.0.1 with fixes that make the app smarter about understanding natural language and GPS. So while I was in DC on an errand, I pulled out my phone at Union Station, told WandR I wanted scenic spots for about four hours on a motorcycle, and let it plan a route. Five stops, 68 miles, a loop through Virginia — Great Falls, Manassas Battlefield, Burke Lake, and a covered bridge I didn\u0026rsquo;t know existed. This post is the answer to his question.\nThe Test: Union Station, DC I was at Union Station on an errand. I had my phone. I had a question from a fellow Ducati rider sitting in the back of my head: \u0026ldquo;Did your app suggest anything good?\u0026rdquo;\nSo I opened WandR and gave it a real test:\n\u0026ldquo;Scenic spots, being out for like around four hours, motorcycle\u0026rdquo;\nNot a perfectly structured query. Just a normal human sentence with filler words, imprecise time framing, and no explicit start location. The kind of thing a real person says when they\u0026rsquo;re standing somewhere wondering where to ride.\nWithin seconds, WandR came back with a 5-stop loop route:\n67.9 miles total 3.6 hours (1.7 hours riding, 2.0 hours at stops) Loop route — starts and ends at Union Station The Route It Planned When I tapped \u0026ldquo;View on Map,\u0026rdquo; I got the full loop rendered on Apple Maps — real roads through Northern Virginia and Maryland.\nZoomed in to confirm — the start pin was right at Union Station.\nStop 1: Skyline Drive (Falls Church, VA) — 4.8 The gateway to Shenandoah. \u0026ldquo;Breathtaking views of the Blue Ridge Mountains.\u0026rdquo; On a motorcycle, this stretch is legendary — anyone who rides in the mid-Atlantic knows it.\nStop 2: Burke Lake Park (Fairfax Station, VA) — 4.5 A serene lake with picnic areas and scenic trails. Good midpoint to stretch your legs and let the bike cool down.\nStop 3: Manassas National Battlefield Park (VA) — 4.4 Civil War history meets open countryside. The roads around Manassas are wide, clean, and perfect for a motorcycle.\nStop 4: Great Falls Park (McLean, VA) — 4.7 Dramatic waterfalls along the Potomac River. The ride from Manassas to Great Falls takes you through some of the prettiest back roads in NoVA.\nStop 5: Meems Bottom Covered Bridge (Rockville, MD) — 4.3 A picturesque covered bridge. The kind of spot you\u0026rsquo;d never find unless you knew to look for it — exactly the kind of discovery that makes WandR different from just Googling \u0026ldquo;things to do near me.\u0026rdquo;\nThe AI was smart about the search. When you ask for scenic motorcycle stops, it doesn\u0026rsquo;t just dump the nearest parks from a database. It considers what\u0026rsquo;s actually worth riding to — places with views, good roads getting there, and enough character to make the stop worthwhile. Then it verifies each location against real map data to make sure the addresses are accurate and the places actually exist. It started with more candidates than I needed, filtered out anything too far for a 4-hour ride, and optimized the stop order to minimize backtracking.\nHow This Started: A Conversation on r/Ducati The idea for WandR came from the Ducati community a few weeks ago. I\u0026rsquo;d posted a photo of my Monster 821 on a cold early ride, got great feedback, and started thinking: what if instead of picking a destination, you told an AI what you were in the mood for and let it figure out the rest?\nToday, a rider from Slovenia posted on r/Ducati about his ride from Ljubljana to Monfalcone, Italy — twisties through the Vipava valley, beautiful 15-degree day. I asked about scenic stops along his route. He told me about the Kalce-Col-Ajdovscina road that sits on top of the valley with views to the left the whole way. Classic motorcycle storytelling — and he came back with fishing worms, which made the whole thing even better.\nThen he asked me: \u0026ldquo;Where are you planning to go when the weather and roads clear up?\u0026rdquo;\nAnd I told him the truth:\n\u0026ldquo;It\u0026rsquo;s funny you ask that question\u0026hellip; I live where you can easily go to Philadelphia, Delaware, Virginia within a 2 hour ride. But I wanted to think about it differently, so after getting some great feedback from the r/Ducati community on the day of my last ride I built an app to help me just \u0026lsquo;wander\u0026rsquo; around — so I plan to just let the AI give me ideas of where to go based on how long I wanna be out and what I want to see.\u0026rdquo;\nHe\u0026rsquo;s a builder too. His response:\n\u0026ldquo;Sprinkle some AI on the problem :) I see you\u0026rsquo;re a fellow builder, love to see it!\u0026rdquo;\nHe pitched me a feature idea — a \u0026ldquo;map my ride\u0026rdquo; mode, like Strava but for motorcycle rides. Track where you went, see it after the fact. Genuinely great idea, and it\u0026rsquo;s going on the roadmap.\nBut the question that mattered most was his last one:\n\u0026ldquo;So, did your app suggest anything good?\u0026rdquo;\nThe Answer Yes. Five real stops. Sixty-eight miles of back roads, national parks, waterfalls, and a covered bridge. All from standing at Union Station and saying \u0026ldquo;scenic spots, four hours, motorcycle.\u0026rdquo; No typing an address. No scrolling through lists. Just talking to it like you\u0026rsquo;d talk to a friend who knows the area.\nToday\u0026rsquo;s Actual Ride: Maryland I didn\u0026rsquo;t ride the Virginia route today — I was on my regular loop through Laurel, Columbia, and Ellicott City, Maryland. The DC stop was an errand that turned into a product test.\nBut the Union Station test gave me exactly what I needed: proof that when a fellow rider asks \u0026ldquo;does it actually work?\u0026rdquo; the answer is yes, and I can show the receipts.\nWhat v1.0.1 Fixed I pushed version 1.0.1 to the App Store yesterday — March 7, 2026. The fixes came from actually using the app on the road and listening to feedback. The core theme: the app should understand you the way a friend would, not the way a search engine does.\nYour words matter. Version 1.0 would strip your natural language down to sterile keywords. \u0026ldquo;Scenic spots, being out for like around four hours\u0026rdquo; became \u0026quot;Find scenic_spots, 4 hours, motorcycle\u0026quot; — losing all the nuance. v1.0.1 preserves your original words so the AI can reason over what you actually meant.\nKnow where I am. Version 1.0 tried to geocode whatever text you typed. \u0026ldquo;From here\u0026rdquo; returned nothing useful. v1.0.1 uses GPS first — the app grabs your actual location without you typing an address.\nCleaner app. Removed dead code, tightened App Store compliance.\nWhat Feedback Taught Me Use your own product. Not in a simulator — on the road, in real conditions. The GPS fix and query preservation both came from real-world usage.\nListen to your community. The Ducati subreddit didn\u0026rsquo;t just give me motorcycle advice — the conversations there shaped the product. When a rider from Slovenia asks \u0026ldquo;did your app suggest anything good?\u0026rdquo; that\u0026rsquo;s user research wrapped in motorcycle culture. More honest than any survey.\nShip the fix, then test it. v1.0.1 went to the App Store yesterday. Today I tested it at Union Station. Tomorrow it handles the next rider\u0026rsquo;s query a little better than it would have last week.\nThe Strava-for-motorcycles idea? Going on the roadmap. Map your ride, see where you went, share it. That came from a conversation between two Ducati riders — one in Maryland, one in Slovenia — swapping stories on Reddit. That\u0026rsquo;s how good products get built.\nTry It Yourself WandR is free. Tell it what you\u0026rsquo;re in the mood for — breweries, scenic spots, restaurants, whatever. Tell it how long you want to be out and how you\u0026rsquo;re getting around. It handles the rest.\nDownload WandR on the App Store\nCheers, Fabian Williams\nLinks:\nWandR on the App Store — Free WandR Community Repo The r/Ducati thread Yesterday\u0026rsquo;s comeback post Stale Contacts Cleaner — Free on the App Store All Products on adotob.com YouTube ","permalink":"https://www.fabswill.com/blog/wandr-v101-union-station-dc-first-real-ride/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eA Ducati rider from Slovenia asked me on Reddit today: \u003cem\u003e\u0026ldquo;Did your app suggest anything good?\u0026rdquo;\u003c/em\u003e I\u0026rsquo;d just pushed WandR v1.0.1 with fixes that make the app smarter about understanding natural language and GPS. So while I was in DC on an errand, I pulled out my phone at Union Station, told WandR I wanted scenic spots for about four hours on a motorcycle, and let it plan a route. Five stops, 68 miles, a loop through Virginia — Great Falls, Manassas Battlefield, Burke Lake, and a covered bridge I didn\u0026rsquo;t know existed. This post is the answer to his question.\u003c/p\u003e","title":"WandR v1.0.1: A Ducati, a Reddit Question, and an AI Test at Union Station"},{"content":"TL;DR I went heads down for about three months — no LinkedIn, no YouTube, barely any Twitter. In that time I shipped two iOS apps to the App Store, built an autonomous AI assistant that runs a nonprofit\u0026rsquo;s entire digital presence 24/7, and developed a workflow where AI agents scale my output 3-5x. This post is the full story: the career pattern that taught me to recognize seismic shifts, what I actually built, and why I\u0026rsquo;m back.\nThe Latin Phrase That Drives Everything A Jesuit teacher named Father Ryan drilled a Latin phrase into me in high school that I\u0026rsquo;ve carried for decades: qui non proficit deficit.\nMost people translate it as \u0026ldquo;if you don\u0026rsquo;t move forward, you move backwards.\u0026rdquo; Close, but it misses the point. The literal meaning is: he who doesn\u0026rsquo;t advance loses ground. The distinction matters. You don\u0026rsquo;t have to move backwards to fall behind. You can stand perfectly still while everyone else moves ahead of you.\nThat distinction has shaped every major decision in my professional and personal life. And it\u0026rsquo;s why, around August/September of last year, I stopped posting on LinkedIn, went quiet on YouTube, and disappeared from most of the communities I\u0026rsquo;d been active in for years.\nI wasn\u0026rsquo;t burned out. I was building.\nThe Career Pattern: Five Steps I\u0026rsquo;ve Run Five Times Before I get to the AI stuff, you need context. The playbook I used this time is the same one I\u0026rsquo;ve used my entire career:\nMaster the current domain. Get deep enough that people come to you for answers. Give knowledge away for free. Blog posts, conference talks, YouTube videos, code on GitHub. The community remembers who helped them. Recognize the seismic shift. Not the trend, not the hype — the structural change that rewrites the rules. Build trusted circles. Small groups of people who challenge your thinking and sharpen your judgment. Let go of the old thing. This is the hardest one. It\u0026rsquo;s even hard for me — I am OCD to the bone! But you have to be willing to walk away from the domain you mastered to master the next one. Fortunately, I\u0026rsquo;ve had people in my professional life who helped me recognize this when I wasn\u0026rsquo;t ready to see it. Thank you. The Pivots The Basement (Walter Reed Army Institute of Research / Walter Reed Army Medical Center (WRAIR/WRAMC)) I moved to the DC metro area to work at Walter Reed Army Institute of Research / Walter Reed Army Medical Center (WRAIR/WRAMC) on a Presidential Decision Directive. Two-plus years in a basement doing work that was genuinely ahead of its time. Nobody saw it, nobody talked about it, but it taught me: important work doesn\u0026rsquo;t always look impressive from the outside.\nBizTalk and the State of Maryland Enterprise integration before anyone called it that. Learned that connecting systems matters more than building new ones. I wrote a technical proposal, then became a subcontractor to a prime and led a team of 13 people to bring the State of Maryland into HIPAA compliance.\nSharePoint and the Business Data Catalog When Microsoft Office SharePoint Server 2007 (MOSS) shipped, the documentation was — let\u0026rsquo;s be generous — incomplete. I used JetBrains Reflector to inspect SharePoint\u0026rsquo;s binaries, figured out how the plumbing actually worked, and wrote a series of blog posts explaining it. Those posts later ended up in the Microsoft Certified Master (MCM) courseware. That\u0026rsquo;s how I got into the community — by giving knowledge away for free.\nThat\u0026rsquo;s also how I met people who changed my career: John Ferringer introduced me to Twitter at a CDW project in Indianapolis. Joel Oleson, Todd Klindt, Shane Young, and Andrew Connell — I met them at a conference in Burlingame when I took a speaking slot for Dr. Joe Shepherd who couldn\u0026rsquo;t make it.\nEvery opportunity I had in the SharePoint world traced back to giving away knowledge for free.\nThe Graph Pivot Between SharePoint 2013 and 2016, I stopped doing SharePoint on-prem full stack and UX work entirely. I\u0026rsquo;d gotten deep into state machine workflows bolted onto SharePoint via WCF — with critical help from Bart Tubalinal, who saved me on a project where I\u0026rsquo;d gotten in over my head.\nBut I could feel the shift. The future was in the data layer — Microsoft Graph and Xamarin. I pivoted to building mobile experiences surfacing Graph data, then focused exclusively on the middle tier.\nBy SharePoint Server 2019, I was 100% Graph. That bet paid off for years.\nTechEd 2014 I was in the room when Satya Nadella, then VP of Azure, coined \u0026ldquo;Mobile First, Cloud First.\u0026rdquo; I felt the tremor. Half the audience heard the words but didn\u0026rsquo;t feel the shift.\nMicrosoft MVP, Then Microsoft Employee I was a 7 times MVP — first in SharePoint Server, then SharePoint Development, also got a Xamarin MVP, then later Azure MVP, and so on and so forth. Then I crossed over and became a PM, working on Jeremy Thake\u0026rsquo;s newly founded CPx team with Brian T. Jackett. I was the 2nd team member of a team that grew to 9.\nThis Time the Shift Is Different Every previous shift was industry-specific. SharePoint to Graph. On-prem to cloud. Mobile to API-first.\nThe AI shift is different because it\u0026rsquo;s everything, everywhere, all at once. Not one industry pivoting — the entire world reorganizing how work gets done. And the velocity is unlike anything I\u0026rsquo;ve experienced.\nI started paying attention when Semantic Kernel was still pre-v1. I was fortunate to work with John Maeda and his team early on. Then came the rapid-fire evolution: RAG, plugins, GPTs, MCP, A2A, ACP, agents, OpenClaw. Each one building on the last, each one moving faster than the previous.\nWhen Anthropic released the Model Context Protocol in December 2024, I knew the game had changed. I even spent over a year debating with my friend Doug Ware about whether MCP was transformative or doomed — we never resolved it, but it made for fantastic intellectual sparring. Then came Agent-to-Agent (A2A) and Agent Communication Protocol (ACP), and suddenly we had a full stack for agents to discover, communicate, and collaborate with each other.\nThis shift has three dimensions most people only see one of:\nFor enterprises: How does your company become AI-forward in a way that\u0026rsquo;s secure, observable, and actually useful?\nFor small businesses: The pharmacy, the family practice, the volunteer org — they need the productivity gains but can\u0026rsquo;t afford enterprise AI. This is what I\u0026rsquo;m building at Adotob.\nFor individuals: How do you recognize a seismic shift, understand its impact, and adjust before you lose ground?\nGoing Heads Down Around December 2025, I made a conscious decision: stop posting and start building. I was spreading myself too thin — YouTube, LinkedIn, conferences, community engagement. All good things, but I was talking more than shipping.\nSo I went quiet. Three months of focused work. Here\u0026rsquo;s what came out of it.\nWhat I Built ConferenceHaven — Three Ways to Talk to a Conference I started with a problem I knew firsthand. As a conference speaker, I\u0026rsquo;d often discover that another speaker was covering the same topic in a session scheduled right before or after mine — intro after advanced, or vice versa. Conference organizers don\u0026rsquo;t always catch these conflicts.\nSo I built ConferenceHaven: an AI conference assistant that searches thousands of sessions across major conferences. I built it three ways:\nMCP server over HTTP streaming — drops into Claude Desktop, ChatGPT, Copilot Studio, LM Studio with one URL Web chat at conferencehaven.com/chat — zero install, works on your phone at the conference A2A agent card — so other conference agents can discover and collaborate with it My friend Kevin McDonnell, an MVP from the UK, used it in his Copilot demo at ESPC in Dublin. We debugged it together, wired it into Copilot Studio, and it just worked. MVPBuzz for the win!\nThen I added OpenTelemetry observability — tracking what people ask, running evals, and using the data to improve session recommendations. The same observability patterns I work with at Microsoft, but proven out in a live public system.\nResult: 1,500+ sessions indexed. Analytics dashboard live. A2A integration documented. It\u0026rsquo;s all open source.\nBuilding with AI Agents — MCP \u0026amp; A2A Journey GitHub Community Repo ConferenceHaven Home Stale Contacts Cleaner — Idea to App Store in 7 Days A friend of mine fell victim to a scam. Someone got into an old contact\u0026rsquo;s compromised phone, found my friend in their contacts, and texted asking for a quick Venmo transfer. The name matched. The context felt right. My friend lost some money that night.\nThat story hit me because I realized I had hundreds of contacts I hadn\u0026rsquo;t talked to in years. Every one of them is a trust anchor that could be exploited.\nI built Stale Contacts Cleaner in a day and a half. Tinder-style interface — swipe right to keep, left to delete. Everything stays on your iPhone. Zero data collection. Not even analytics. Submitted to the App Store on day two, and after one rejection and a resubmission, it was live.\nTotal AI cost to build: ~$20. Outsourcing would have been $2,500+.\nDownload Free on the App Store The Full Story Demo Video WandR — An AI Trip Planner Born on a Motorcycle As we were coming out of winter a few weeks ago, I jumped on the motorcycle the first day the weather cracked 50 degrees. Hit Jailbreak Brewing Company in Laurel to get a pint from my favorite bartender who\u0026rsquo;s been there forever, Allie DeThomas. Then Sapwood Cellars Brewery in Columbia. Then kept riding. Classic pub crawl on a bike.\nWhen I got home, I started thinking: what if instead of picking a destination, you told an AI what you were in the mood for? \u0026ldquo;Breweries, two hours, motorcycle.\u0026rdquo; And three AI agents figure out the route, the stops, and the scenic roads. This became even clearer when I went on Reddit, the Ducati subreddit, posted pictures of the bike out and asked people what they were doing that day.\nThat\u0026rsquo;s WandR. Three AI agents — Route Planner, Stop Curator, Experience Designer — collaborate on real roads (Apple MapKit, not abstract lines) with curated stops.\nBuilt in two and a half days. SwiftUI frontend, Python/FastAPI backend, Azure Container Apps.\nTwo apps. Both on the App Store. Under three weeks total. Total AI cost: about $20 each.\nDownload Free on the App Store MACONA OpenClaw — An Autonomous AI Running a Nonprofit I volunteer for MACONA.ORG, a 501(c)(3) nonprofit. All-volunteer staff, no IT department. I\u0026rsquo;m usually their tech person, but during my time heads-down, I wasn\u0026rsquo;t helping much. The organization was feeling it.\nSo I set up OpenClaw — an AI assistant running 24/7 on dedicated hardware. It manages their WordPress blog, LinkedIn, Twitter, email newsletter, Microsoft 365 email, and calendar. It has standing orders for four autonomous programs — no daily prompts needed. It publishes content, does donor outreach research, runs daily briefings, and triages email.\nChannel What It Handles WordPress Drafts and publishes blog posts LinkedIn Social media via Buffer API Twitter/X Social media via Buffer API Brevo Monthly newsletter cycle M365 Email Inbox triage, daily briefings, send-on-behalf M365 Calendar Schedule management, time-boxing Signal Direct communication with staff The assistant has its own email address, its own delegate access, and a security model where only internal staff can command it. External emails are read-only — it flags them but never responds without approval.\nThis isn\u0026rsquo;t a chatbot. It\u0026rsquo;s an autonomous agent with standing orders that runs the digital presence of an entire organization. And the same pattern works for any small org — nonprofits, clinics, pharmacies, solo practices. See the OpenClaw service offering on adotob.com.\nHow I Work Now My workflow is two windows: Obsidian and a terminal (Ghostty on my Mac, command window at work on my Windows box). The key unlock\u0026hellip;\nObsidian is my second brain. Markdown files with YAML frontmatter, organized into a vault that sits on my local hard drive. Properties and wiki-links create a graph — a queryable neural network of everything I know and everything I\u0026rsquo;m working on. I have separate contexts for personal life, my LLC (Adotob), and my Microsoft work.\nThe terminal runs Claude Code instances — sometimes three or four at once, each working on a different task. I borrowed from the RalphWiggum way of working (bash loops for autonomous execution) and also from SpecKit\u0026rsquo;s idea of constitutional workflow: a specification-first approach with quality gates, real integration tests (no mocking), and autonomous execution within guardrails.\nI\u0026rsquo;m also very local-first. My MacBook Pro M3 Max runs DeepSeek, Llama, Phi, and the ChatGPT OSS 120B model locally via Ollama and LM Studio. Cloud models are for production only. Everything else stays on my machine.\nThe result: I can run parallel workstreams. One Claude instance is doing app marketing via Buffer API. Another is monitoring Reddit for engagement opportunities. A third is building a website. All while I review, approve, and steer from Obsidian.\nThis isn\u0026rsquo;t about replacing what I do. It\u0026rsquo;s about scaling how much I can do. The bottleneck isn\u0026rsquo;t coding speed — it\u0026rsquo;s knowing what to build and having the taste to ship something worth using.\nYou can\u0026rsquo;t improve what you can\u0026rsquo;t see. You can\u0026rsquo;t see what you can\u0026rsquo;t measure. You can\u0026rsquo;t measure what you haven\u0026rsquo;t instrumented. That\u0026rsquo;s why OpenTelemetry isn\u0026rsquo;t optional in anything I build.\nWhat I Told My Daughter My daughter Gabrielle is home from college for spring break. She has one of my old Macs — the beefy one. I installed DeepSeek and GPT-OSS on it and showed her Claude Code.\nNot for schoolwork. For life logistics — dorm management, shopping, meal planning, Instacart. The stuff that takes mental energy but doesn\u0026rsquo;t require human creativity.\nShe got it immediately. The next generation won\u0026rsquo;t need to be convinced AI is transformative. They\u0026rsquo;ll need to be shown how to use it well.\nWhy I\u0026rsquo;m Back Qui non proficit deficit.\nI went heads down because I recognized a seismic shift and needed to learn, build, and prove things out before talking about them. I don\u0026rsquo;t speak on something unless I\u0026rsquo;ve done it.\nNow I\u0026rsquo;ve done it:\nTwo iOS apps shipped to the App Store An autonomous AI assistant running a nonprofit A conference tool with MCP, A2A, and live analytics A workflow that lets me operate at 3-5x my previous output I\u0026rsquo;m back because I\u0026rsquo;m ready to share what I\u0026rsquo;ve learned. Not theory — working systems with code you can look at, apps you can download, and patterns you can copy.\nIf you\u0026rsquo;re still standing still, the ground is moving under you. And if you want help figuring out how to move — whether you\u0026rsquo;re a developer, a PM, a business owner, or someone who just knows the world is changing and wants to understand how — reach out. I\u0026rsquo;m always happy to do a one-on-one.\nLet\u0026rsquo;s build.\nCheers, Fabian Williams\nLinks:\nAll Products on adotob.com Services \u0026amp; OpenClaw AI Assistants on adotob.com Skill Marketplace on adotob.com Stale Contacts Cleaner — Free on the App Store WandR AI Trip Planner — Free on the App Store ConferenceHaven Live Chat YouTube GitHub Repositories ","permalink":"https://www.fabswill.com/blog/qui-non-proficit-deficit-im-back/","summary":"\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eI went heads down for about three months — no LinkedIn, no YouTube, barely any Twitter. In that time I shipped two iOS apps to the App Store, built an autonomous AI assistant that runs a nonprofit\u0026rsquo;s entire digital presence 24/7, and developed a workflow where AI agents scale my output 3-5x. This post is the full story: the career pattern that taught me to recognize seismic shifts, what I actually built, and why I\u0026rsquo;m back.\u003c/p\u003e","title":"Qui Non Proficit Deficit: Three Months Offline, Two Apps Shipped, and an AI That Runs a Nonprofit"},{"content":"🚀 Purpose In today’s fast-paced technology landscape, I found myself immersed in my journey at TechCon 365 Dallas 2025. What used to take me days to achieve now unfolds in merely two hours. This blog explores how technology has reshaped my workflow, allowing more efficient operations while emphasizing the importance of manual oversight along the way.\nDuring my preparation for the conference, I utilized multiple technologies including Graph, MCP, and Agents to create a streamlined process. While automation plays a significant role, I learned that having manual guardrails in place is essential. This realization stems from my familiarity with coding and the underlying tech, which often serves as a critical asset in navigating unexpected challenges.\nTL;DR - Technology has enhanced efficiency, yet human oversight remains crucial.\n🛠️ What This Accomplishes ✅ Feature Description Efficiency Gains Tasks that previously consumed days can now be completed in hours. Manual Oversight Ensures quality control and mitigates risks when relying on technology. Comprehensive Skill Set Knowledge of Graph and MCP enables a smoother tech-driven process; not solely reliant on technology. 🧠 Highlights from TechCon 365 Utilizing my resources, I aimed to create a seamless experience that bridges efficiency with oversight. Here’s a snapshot of the results:\n📋 Quick Start: My Approach Below are key steps to replicate the tech-driven initiative I undertook:\n1️⃣ Setup Environment # Clone the repository git clone https://github.com/fabianwilliams/TechCon365Dallas2025.git cd TechCon365Dallas2025 # Run setup scripts ./setup.sh 2️⃣ Utilize Graph and MCP # Execute conference preparations using Graph and MCP scripts ./run_graph_mcp.sh 🎯 Practical Advice ✅ Tip 🛑 Pitfall Leverage Tools – Embrace technology to reduce task durations. Neglect Oversight – Relying solely on automation can lead to errors. Stay Informed – Understanding code allows for troubleshooting during tech failures. Assuming Automation Will Handle All – Manual intervention is sometimes essential. 🚀 Wrap-Up Navigating technology effectively at TechCon 365 Dallas 2025 illustrated the synergy between rapid deployment and necessary supervision. As I continue to leverage these technologies, I invite everyone to reflect on their experiences and share insights!\nFeel free to connect with me at GitHub Repository for further resources and discussions on these exciting technologies!\nHappy exploring! 🚀\n","permalink":"https://www.fabswill.com/blog/techcon365_dallas_2025/","summary":"\u003ch2 id=\"-purpose\"\u003e🚀 Purpose\u003c/h2\u003e\n\u003cp\u003eIn today’s fast-paced technology landscape, I found myself immersed in my journey at \u003cstrong\u003eTechCon 365 Dallas 2025\u003c/strong\u003e. What used to take me days to achieve now unfolds in merely \u003cstrong\u003etwo hours\u003c/strong\u003e. This blog explores how technology has reshaped my workflow, allowing more efficient operations while emphasizing the importance of manual oversight along the way.\u003c/p\u003e\n\u003cp\u003eDuring my preparation for the conference, I utilized multiple technologies including \u003cstrong\u003eGraph\u003c/strong\u003e, \u003cstrong\u003eMCP\u003c/strong\u003e, and \u003cstrong\u003eAgents\u003c/strong\u003e to create a streamlined process. While automation plays a significant role, I learned that having manual guardrails in place is essential. This realization stems from my familiarity with coding and the underlying tech, which often serves as a critical asset in navigating unexpected challenges.\u003c/p\u003e","title":"Embracing Technology: My Journey at TechCon 365 Dallas 2025"},{"content":"🚀 Purpose If you’ve ever wondered how to compare a locally‑hosted LLM with a hosted OpenAI model side‑by‑side, while keeping the whole experiment observable from end‑to‑end, you’re in the right place. This one‑pager walks you through the starter repo that stitches together three distinct paths:\nPath Stack Observability A .NET 8 + Semantic Kernel + Ollama (local model) Azure Monitor (OTEL) B OpenAI Agents SDK (TypeScript/Node) OpenAI Logs → optional OTLP → Azure Monitor C Python Evals (OpenAI‑provided) Same prompts, same metrics The goal? A clean, reproducible harness that lets you run the same prompt against a local model and an OpenAI model, invoke tools, and then score the outputs with a single Python‑based eval suite. All of this is fully instrumented with OpenTelemetry, so you can follow the request flow from the client code right into Azure Application Insights (or any OTEL backend you prefer).\nTL;DR – Pull a model, set a connection string, run a few commands, and watch the trace heat‑maps light up in the OpenAI Dashboard and Azure Monitor.\n🛠️ What This Delivers ✅ Feature Description Side‑by‑side harness Run a local Ollama model and the hosted OpenAI model from the same code base. End‑to‑end tracing OpenAI’s built‑in agent tracing, OTLP → Aspire, and Azure Monitor correlation all work out of the box. Consistent naming \u0026amp; config A single source of truth for agent names, tool definitions, and environment variables across .NET, TypeScript, and Python. Unified evaluation Python Evals score the outputs of both implementations with identical prompts and metrics. Dashboard‑ready Visual validation in OpenAI Logs, Aspire UI, and Azure Application Insights KQL queries. 🧠 Architecture At A Glance graph LR subgraph TS[TypeScript] A[OpenAI Agents SDK] --\u0026gt;|traces| O[OpenAI Logs] A --\u0026gt;|OTLP| Aspire end subgraph NET[.NET 8] B[Semantic Kernel + Ollama] --\u0026gt;|OTEL| AzureMonitor end subgraph PY[Python] C[OpenAI Evals] --\u0026gt;|compare| A \u0026amp; B end O --\u0026gt;|correlate| AzureMonitor Aspire --\u0026gt;|export| AzureMonitor TypeScript – @openai/agents ships with first‑class tracing that lands in the OpenAI Dashboard. You can pipe the same OTLP stream to Aspire (the .NET observability stack) and forward it to Azure Monitor. .NET 8 – Semantic Kernel drives the Ollama‑backed LLM. The built‑in OpenTelemetry exporter ships traces directly to Azure Monitor (or any OTEL collector you configure). Python – The official OpenAI Evals library runs the same prompt against both agents and produces a CSV/JSON report you can drop into a dashboard. Dashboard Snapshots OpenAI Dashboard – Agent Workflows Azure Application Insights – KQL TimeAgent executions with full tool‑call traces KQL query visualizing items ingested by the .NET agent Comprehensive test results with tool call details Raw query results 📋 Quick Start (Happy Path) Below is the minimum you need to see a trace surface in both OpenAI Logs and Azure Monitor. Each block assumes you’ve already cloned the starter repo.\n1️⃣ .NET + Ollama # Pull a tool‑capable model (once) ollama pull gpt-oss-120b # or any other model that supports function calls # Export your Azure Monitor connection string (or any OTEL endpoint) export AZURE_MONITOR_CONNECTION_STRING=\u0026#34;InstrumentationKey=xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\u0026#34; # Run the .NET sample cd sk-ollama dotnet run What to look for – In Azure Monitor, filter on service.name = \u0026quot;SkOllamaAgent\u0026quot;. You’ll see a trace that includes the prompt, the tool invocation, and the final LLM response.\n2️⃣ OpenAI Agents SDK (Node/TypeScript) # Install the SDK + Zod (for schema validation) npm i @openai/agents zod@3.25.67 # Set your OpenAI key export OPENAI_API_KEY=\u0026#34;sk-...\u0026#34; # Run the sample (it lives under /ts-agents) cd ts-agents npm run start What to look for – Head to the OpenAI Dashboard → Logs. The request appears under the Agent tab with a built‑in trace that shows each tool call as a separate span.\nOptional OTLP export – If you want the same data in Azure Monitor:\nexport OTEL_EXPORTER_OTLP_ENDPOINT=\u0026#34;https://\u0026lt;your-aspire-endpoint\u0026gt;/v1/traces\u0026#34; export OTEL_RESOURCE_ATTRIBUTES=\u0026#34;service.name=TsOpenAIAgent\u0026#34; npm run start # traces now flow to Aspire → Azure Monitor 3️⃣ Python Evals # Create a virtual env python -m venv .venv \u0026amp;\u0026amp; source .venv/bin/activate # Install OpenAI Evals pip install openai-evals # Run the evaluation suite (the repo ships a ready‑made eval.yaml) openai-evals run evals/compare_agents.yaml \\ --model gpt-4o-mini \\ --output results.csv The compare_agents.yaml file points to the two agents you just spun up (local endpoint for Ollama, OpenAI endpoint for the TypeScript agent). The resulting CSV contains scores for relevance, tool‑use correctness, and latency.\n🎯 Practical Advice \u0026amp; Gotchas ✅ Tip 🛑 Pitfall Pin your model version – Ollama models are mutable. Use ollama pull \u0026lt;model\u0026gt;:v1.2.0 and reference the exact tag in your code. Forgot to export OTEL env vars – Traces silently fall back to a no‑op exporter. Double‑check OTEL_EXPORTER_OTLP_ENDPOINT and AZURE_MONITOR_CONNECTION_STRING. Leverage Zod schemas – They give you compile‑time safety for tool input validation in the TypeScript agent. Mismatched tool signatures – The .NET Semantic Kernel and the TypeScript SDK must agree on the JSON schema; otherwise you’ll see “function call validation error” in the trace. Use a single service name across all languages (AgentDemo) so you can aggregate spans in Azure Monitor. Cross‑region latency – If your Aspire instance lives in a different Azure region than your Application Insights resource, you’ll see extra hops in the trace. Align regions for a cleaner picture. Run the Evals after each code change – It’s cheap (a few seconds) and catches regressions before they get to production. Over‑instrumentation – Adding ActivitySource to every tiny helper method can flood your backend. Stick to high‑level boundaries (request → tool call → response). 🚀 Wrap‑Up With just a few commands you now have a fully observable playground that lets you:\nSwap models (local vs. hosted) without changing any business logic. Inspect tool‑call flows in both OpenAI’s native dashboard and Azure Monitor’s powerful KQL explorer. Quantify performance using the official OpenAI Evals suite, keeping the comparison apples‑to‑apples. The repo is deliberately minimal—feel free to extend it with your own agents, custom exporters (Datadog, Honeycomb), or CI pipelines that run the Evals on every PR. The core idea is simple: observability is the glue that turns a sandbox experiment into a production‑grade workflow.\nHappy tracing! 🚀\n","permalink":"https://www.fabswill.com/blog/2025-08-10-agent-plus-local-model-plus-evals-onepager/","summary":"\u003ch1 id=\"-purpose\"\u003e🚀 Purpose\u003c/h1\u003e\n\u003cp\u003eIf you’ve ever wondered how to \u003cstrong\u003ecompare a locally‑hosted LLM\u003c/strong\u003e with a hosted OpenAI model \u003cstrong\u003eside‑by‑side\u003c/strong\u003e, while keeping the whole experiment observable from end‑to‑end, you’re in the right place. This one‑pager walks you through the starter repo that stitches together three distinct paths:\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003ePath\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eStack\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eObservability\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eA\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e.NET 8 + Semantic Kernel + Ollama (local model)\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eAzure Monitor (OTEL)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eOpenAI Agents SDK (TypeScript/Node)\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eOpenAI Logs → optional OTLP → Azure Monitor\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eC\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003ePython Evals (OpenAI‑provided)\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eSame prompts, same metrics\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eThe goal? A \u003cstrong\u003eclean, reproducible harness\u003c/strong\u003e that lets you run the same prompt against a local model and an OpenAI model, invoke tools, and then score the outputs with a single Python‑based eval suite. All of this is fully instrumented with OpenTelemetry, so you can follow the request flow from the client code right into Azure Application Insights (or any OTEL backend you prefer).\u003c/p\u003e","title":"Agent + Local Model + Evals — One‑Pager"},{"content":"🛒 Introduction Not selling anything here — just sharing what I built over a weekend using Claude Code, the Model Context Protocol (MCP), and Agent-to-Agent (A2A) orchestration.\nThe idea was simple:\nCould a website behave like a full sales team — not just a storefront, but a conversation-led experience where agents guide, pitch, and close?\nSo I prototyped it.\nIt works. You can test it live right now at fabiangwilliams.com\n🧠 What Is Agent-First Commerce? Traditional e-commerce relies on catalogs, carts, and checkouts.\nAgent-First Commerce introduces a conversational pipeline where AI agents assume roles:\nA Greeter Agent welcomes and routes the user A Sales Agent explains the product and handles objections A Checkout Agent sends a secure Stripe link to your inbox Everything is driven by structured conversation.\n🖼️ Walkthrough: What the Agent Experience Looks Like 1. Welcome to the Agent-First Store You\u0026rsquo;re greeted by a clean call to action — powered by AI agents.\n2. Start a Conversation Say hello or click a button — and you\u0026rsquo;re instantly chatting with a Greeter Agent.\n3. Product Discovery in Chat The Sales Agent presents offerings like a live rep might do in-store.\n4. Pitch the Product When you pick something (like a latte), the Agent explains what it is and asks for a decision.\n5. Confirm Purchase in Chat The Sales Agent offers to process your order via secure email checkout — no cart needed.\n6. Email Checkout via Stripe You receive a branded email with a Stripe link — no payment inside the chat itself.\n7. Checkout Using Stripe Test Mode Try it yourself using Stripe\u0026rsquo;s test card numbers.\n8. Confirmation \u0026amp; Fulfillment You’re thanked, confirmed, and shown what happens next.\n🛠️ Tech Stack This was built using:\nFrontend: Next.js + Stripe Elements AI Orchestration: Semantic Kernel + MCP server LLM Pairing: Claude Code + GitHub Copilot A2A Agent Flow: Greeter → Sales → Checkout (via MCP tool chaining) Checkout: Stripe (Test mode) All logic was coordinated via local Semantic Kernel plugins and MCP tool endpoints using HTTP-based coordination between agents.\n💡 Key Learnings Agent-to-Agent flows feel surprisingly natural to users. No-cart, chat-based checkout reduces friction and bounce rates. Stripe’s hosted email link checkout increases security and trust. Claude Code is excellent for quick prototyping and planning across LLM chains. 🔗 Try It Yourself 🧪 Live Demo – fabiangwilliams.com\n💬 Works best if you \u0026ldquo;buy me a latte\u0026rdquo; — it\u0026rsquo;s a full test flow from chat to email to checkout.\n🔐 Stripe is in test mode — no real charges are made.\n📬 Final Thoughts This is early work, but it proves a point:\nWebsites don’t have to be static pages — they can act like a sales team.\nAs agent architecture, orchestration protocols like MCP, and LLMs mature, I believe we’re entering a new era of agent-forward web design — one driven by structured dialogue, instant utility, and seamless integration.\nI\u0026rsquo;m continuing to iterate on this. Feel free to reach out if you\u0026rsquo;re working in this space.\nConnect With Me Platform Link LinkedIn Fabian G. Williams BlueSky @fabianwilliams Email fabian@adotob.com ","permalink":"https://www.fabswill.com/blog/agentfirstcommerce/","summary":"\u003ch2 id=\"-introduction\"\u003e🛒 Introduction\u003c/h2\u003e\n\u003cp\u003eNot selling anything here — just sharing what I built over a weekend using \u003cstrong\u003eClaude Code\u003c/strong\u003e, the \u003cstrong\u003eModel Context Protocol (MCP)\u003c/strong\u003e, and \u003cstrong\u003eAgent-to-Agent (A2A)\u003c/strong\u003e orchestration.\u003c/p\u003e\n\u003cp\u003eThe idea was simple:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eCould a website behave like a full sales team — not just a storefront, but a conversation-led experience where agents guide, pitch, and close?\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eSo I prototyped it.\u003cbr\u003e\nIt works. You can test it live right now at \u003ca href=\"https://fabiangwilliams.com\"\u003efabiangwilliams.com\u003c/a\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-what-is-agent-first-commerce\"\u003e🧠 What Is Agent-First Commerce?\u003c/h2\u003e\n\u003cp\u003eTraditional e-commerce relies on catalogs, carts, and checkouts.\u003cbr\u003e\nAgent-First Commerce introduces a conversational pipeline where AI agents assume roles:\u003c/p\u003e","title":"Agent-First Commerce: I Built a Website That Sells Like a Sales Team"},{"content":"🧠 Debugging GenAI with NLWeb and OpenTelemetry: A Real-Time Visibility Win “If you can’t see it, you can’t debug it.”\nThat’s been the challenge with GenAI and Copilot-style plugins — until now.\n🎯 Goal I wanted to trace and troubleshoot my Copilot agent plugin activity using OpenTelemetry.\nThe stretch goal? Pipe that into a natural-language search experience using NLWeb,\nso I could ask questions like:\n\u0026ldquo;What plugins were used?\u0026rdquo; \u0026ldquo;What calls failed?\u0026rdquo; \u0026ldquo;How long did token generation take?\u0026rdquo; ✅ As of today — we did it. Here\u0026rsquo;s how.\n🔧 Setup Highlights This project used:\n.NET 9 with otelbetter to emit structured OpenTelemetry span logs Aspire on Docker, running locally to collect traces NLWeb, modified to support our schema and allow prompt-based querying Qdrant, used as the vector database to store and retrieve span embeddings We extended the OpenTelemetry exporter to emit this simplified schema:\n{ \u0026#34;@type\u0026#34;: \u0026#34;Event\u0026#34;, \u0026#34;Name\u0026#34;: \u0026#34;InvokePrompt\u0026#34;, \u0026#34;StartDate\u0026#34;: \u0026#34;2025-05-21T19:06:53.0921720Z\u0026#34;, \u0026#34;EndDate\u0026#34;: \u0026#34;2025-05-21T19:06:56.2457840Z\u0026#34;, \u0026#34;Location\u0026#34;: \u0026#34;Copilot-Agent-Plugins\u0026#34;, \u0026#34;Description\u0026#34;: \u0026#34;user.prompt: do you know who fabian williams is...\u0026#34;, \u0026#34;Identifier\u0026#34;: \u0026#34;abc123xyz\u0026#34;, \u0026#34;text\u0026#34;: \u0026#34;InvokePrompt: user.prompt: do you know who fabian williams is\u0026#34;, \u0026#34;url\u0026#34;: \u0026#34;otel://InvokePrompt/abc123xyz\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;InvokePrompt - do you know who fabian williams is\u0026#34; } 🔍 Plugin Call Analysis: Count, Duration, and Patterns Once NLWeb was up and running, we tried a natural query:\n“How many total calls were made for plugins, and what was the longest or shortest plugin time?”\nInstead of returning a single metric, NLWeb gave us individual plugin span events.\nEach event included precise start and end timestamps — useful for per-call inspection,\nbut not aggregated. This prompted a design reflection:\nShould we enhance our OpenTelemetry schema to emit summary metrics like duration_ms or plugin_call_count? 🤔\nHere\u0026rsquo;s what the raw output looked like when asking about plugin durations:\nSo we scoped in further:\n“How many times was the Contacts plugin called?”\nThis query performed better — thanks to consistent span naming and URL conventions.\nWe saw matches across both GET requests to Microsoft Graph and prompt invocations involving Contacts.\nThis kind of diagnostic transparency makes it clear:\nWhile natural language queries are powerful, your trace schema must still support aggregate analysis.\n🗂️ Step-by-Step Wins ✅ 1. Structured Export Format We defined a clean SchemaEvent in C#:\nprivate class SchemaEvent { [JsonPropertyName(\u0026#34;@type\u0026#34;)] public string Type { get; set; } = \u0026#34;Event\u0026#34;; public string Name { get; set; } = \u0026#34;\u0026#34;; public string? StartDate { get; set; } public string? EndDate { get; set; } public string? Location { get; set; } public string? Description { get; set; } public string? Identifier { get; set; } [JsonPropertyName(\u0026#34;text\u0026#34;)] public string? Text { get; set; } } ✅ 2. Verified File Format We checked that trace-export.jsonl had the right format — each line was a valid JSON object.\n✅ 3. Ran db_load.py python -m tools.db_load /path/to/trace-export.jsonl OtelTraces Console Output Confirmed:\n39 documents embedded Qdrant collection created Data successfully uploaded ✅ 4. Queried NLWeb We hit the web UI and asked:\nWhat plugins were used?\nBoom 💥 — NLWeb:\nUsed GPT to rank results semantically Pulled trace data with plugin load metadata Returned hoverable summaries ❌ Minor Glitch At one point we hit this error: Missing required Azure OpenAI configuration\n✅ Fix Updated config_llm.yaml:\npreferred_provider: openai # not azure_openai! And ensured .env had: OPENAI_API_KEY=sk-\u0026hellip;\nNow we\u0026rsquo;re using OpenAI directly with no dependency on Azure configuration.\n📸 UI Polish (WIP) Would love clickable cards or expandable tooltips Long lines are currently cut off — wrapping will improve this But overall: it works, and we see traces in context 🔁 What’s Next This is just the beginning.\nAdd trend analytics over time Group queries by user or task Build alerting for error spans or failed HTTP calls ✍️ Wrapping Up NLWeb + OpenTelemetry gave me real-time, queryable visibility into GenAI agent behavior.\nStay tuned for the full video breakdown 👀\nIn the meantime, I’ll be posting:\n✅ This blog\n✅ LinkedIn summary\n✅ A follow-up on GitHub for broader use\nChat with me Engage with me Click BlueSky @fabianwilliams LinkedIn Fabian G. Williams ","permalink":"https://www.fabswill.com/blog/capswithopentelemetryandnlweb/","summary":"\u003ch1 id=\"-debugging-genai-with-nlweb-and-opentelemetry-a-real-time-visibility-win\"\u003e🧠 Debugging GenAI with NLWeb and OpenTelemetry: A Real-Time Visibility Win\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"img/2025/05/debugwindow_working.png\"\u003e\u003cimg alt=\"Final Result\" loading=\"lazy\" src=\"img/2025/05/debugwindow_working.png\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cem\u003e“If you can’t see it, you can’t debug it.”\u003c/em\u003e\u003cbr\u003e\nThat’s been the challenge with GenAI and Copilot-style plugins — until now.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"-goal\"\u003e🎯 Goal\u003c/h2\u003e\n\u003cp\u003eI wanted to trace and troubleshoot my Copilot agent plugin activity using OpenTelemetry.\u003cbr\u003e\nThe stretch goal? Pipe that into a natural-language search experience using \u003ca href=\"https://github.com/microsoft/NLWeb\"\u003eNLWeb\u003c/a\u003e,\u003cbr\u003e\nso I could ask questions like:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u0026ldquo;What plugins were used?\u0026rdquo;\u003c/li\u003e\n\u003cli\u003e\u0026ldquo;What calls failed?\u0026rdquo;\u003c/li\u003e\n\u003cli\u003e\u0026ldquo;How long did token generation take?\u0026rdquo;\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e✅ As of today — we did it. Here\u0026rsquo;s how.\u003c/p\u003e","title":"Debugging GenAI with NLWeb and OpenTelemetry: A Real-Time Visibility Win"},{"content":"🚀 Introduction This guide captures a modern, evaluation-first approach to building AI-powered projects using tools like GitHub Copilot, Claude, ChatGPT, and local LLMs like LLaMA and DeepSeek.\nWe\u0026rsquo;ll use AsyncPR — a real-world mobile app project I built and shipped — as the public example. Check out a YouTube short video I did here on the App https://go.fabswill.com/asyncpr-shortintro and feel free to test it out! This guide reflects how I work today: VS Code as my IDE, Copilot for code assist, and running private models on my MacBook when needed for security or speed.\nGrab the app in the App Store for iOS here https://apps.apple.com/app/id6744700840\nIf you\u0026rsquo;re serious about modern software building, you’ll love this framework.\n🛠️ Purpose and Setting Expectations This is not a theory doc written after the fact — it\u0026rsquo;s a living guide captured while actively working.\nKey details:\nIDE: Visual Studio Code (VS Code) Primary AI Tools: GitHub Copilot, ChatGPT, Claude Desktop Local Models: LLaMA 3.3:70B, DeepSeek 70B (via Ollama) AsyncPR is featured because my private projects at work can\u0026rsquo;t be shared publicly — but the principles, practices, and rigor are identical.\n🧠 Mindset Shift: From Testing to Evaluations (Evals) Old Way New Way Test after building Eval before building Check if code \u0026ldquo;works\u0026rdquo; Check if code \u0026ldquo;works the right way\u0026rdquo; Hope AI outputs are fine Define \u0026ldquo;good\u0026rdquo; first, then build ✅ Plan → Eval → Build → Test\n🧪 Start with Evaluations (Evals), Not Just Tests Before writing any production code, define Evals:\nWhat does a good output look like? What would success/failure look like? How can a real user journey be simulated? 📋 Examples from AsyncPR:\nReceipt image → extracted business name? ✅ Business name → valid business email? ✅ Customer narrative → clean, structured feedback JSON? ✅ Think of Evals like mini contracts between you and your AI tools.\n📂 Save these in /evals/ folder for every project.\n📋 Project Planning Before Coding This is the step that saves you the most pain:\nWork with the LLM to write a PLAN.md:\nMust-Have Features Nice-to-Haves Out-of-Scope (for now) The AI cannot read your mind — writing this plan forces clarity upfront.\n🛠️ Tool Setup and AI Strategy Today, my stack looks like:\nVS Code + GitHub Copilot for core coding Windsurf or Cursor for AI copartnering coding Claude Desktop/Code for architectural planning and debugging Custom MCP Servers for API documentation lookup and internal data sources Local Ollama Models (LLaMA, DeepSeek) for private projects My main IDE of choice is VS Code with GitHub Copilot and given a choice I am coding in .NET C#, when I face less of a choice its still VS Code but its in Python or TypeScript Ive also started to dabble in Cursor and Windsurf, which is a clone of VS Code, I do like Windsurf native and dare I say easier approach to built in MCP support in the tooling configuration over Claude and VS Code. I think I am just fanboying with using Claude Desktop because MCP is from Anthropic and Claude is too which also makes the Docs easy to follow when I was getting up to speed. I use this to test my MCP Servers as well. 🎯 Mindset: Treat AI tools like a team of interns — powerful but needing precise guidance.\n🌀 Iterative, Section-by-Section Development Build one section at a time:\n✅ Implement small pieces\n✅ Validate against Evals\n✅ Only then commit to Git\nNever let bad AI outputs pile up. Reset early and often.\n🗂️ Version Control is Sacred Work from clean Git branches. git reset --hard if AI drifts too far off course. Use GitHub Actions to validate key rules. Trust me: you\u0026rsquo;ll thank yourself later.\n📊 High-Level Testing Always Once Evals pass, simulate real-world behavior:\nI often use Insomnia or a basic Blazor SPA to hit real endpoints. Validate the entire user journey, not just isolated function outputs. 📚 Deep Documentation and Accessibility Docs aren\u0026rsquo;t just for humans anymore — they\u0026rsquo;re for AIs too.\nSave API specs, database schemas, business rules under /docs/ Build MCP Servers that live-ingest updated docs Even scrape and save static Markdown from sites if needed for local models 🛠️ Refactor Relentlessly When the tests pass, refactor:\nBreak apart monolith files Create small, focused modules Ask your LLMs to suggest refactors too Small files = happier humans and happier AIs.\n🧠 Choose the Right Model for the Job Some models are better at:\nPlanning: Claude and DeepSeek Autocompleting: GitHub Copilot Domain Reasoning: Your own MCP Servers Experiment, experiment, experiment.\n🔄 Keep Iterating Every few weeks:\nTry new models on old logic. Update your Evals. Share learnings with yourself (and your future teammates). Vibe coding is about building smarter and faster — both.\n📂 Example Project Structure /my-project-name │ ├── .gitignore ├── README.md ├── PLAN.md # Detailed project plan with must-have, nice-to-have, out-of-scope ├── LLM_INSTRUCTIONS.md # Special instructions to AI agents │ ├── /src # Application code │ ├── /backend │ ├── /frontend │ └── /shared │ ├── /tests # High-level user journey tests (Post-Eval validation) │ ├── /evals # Manual or automated Evals │ ├── image-processing-eval.md │ ├── business-name-detection-eval.md │ ├── feedback-generation-eval.md │ └── README.md # Explains your Evals philosophy │ ├── /docs # API docs, specs, architecture references │ ├── /scripts # Utility scripts (e.g., image resizing, data migration) │ ├── /mcp-servers # (Optional) Local MCP server configurations │ └── LICENSE 💬 Final Thoughts AI-assisted development demands a new way of thinking.\nEvaluation-first frameworks, thoughtful planning, and tight Git discipline make the difference between chaos and clarity.\nAsyncPR is just the beginning — this approach scales to any project, any team, any goal.\n🎯 What’s one Eval you’ll try first? Comment or message me — let’s level up together!\nChat with me Engage with me Click BlueSky @fabianwilliams LinkedIn Fabian G. Williams ","permalink":"https://www.fabswill.com/blog/fabsvibecodingbestpractice/","summary":"\u003ch2 id=\"-introduction\"\u003e🚀 Introduction\u003c/h2\u003e\n\u003cp\u003eThis guide captures a modern, \u003cstrong\u003eevaluation-first approach\u003c/strong\u003e to building AI-powered projects using tools like \u003cstrong\u003eGitHub Copilot\u003c/strong\u003e, \u003cstrong\u003eClaude\u003c/strong\u003e, \u003cstrong\u003eChatGPT\u003c/strong\u003e, and \u003cstrong\u003elocal LLMs\u003c/strong\u003e like \u003cstrong\u003eLLaMA\u003c/strong\u003e and \u003cstrong\u003eDeepSeek\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eWe\u0026rsquo;ll use \u003cstrong\u003eAsyncPR\u003c/strong\u003e — a real-world mobile app project I built and shipped — as the public example. Check out a \u003cstrong\u003eYouTube\u003c/strong\u003e short video I did here on the App \u003ca href=\"https://go.fabswill.com/asyncpr-shortintro\"\u003ehttps://go.fabswill.com/asyncpr-shortintro\u003c/a\u003e and feel free to test it out!\nThis guide reflects \u003cstrong\u003ehow I work today\u003c/strong\u003e: VS Code as my IDE, Copilot for code assist, and running private models on my MacBook when needed for security or speed.\u003c/p\u003e","title":"Vibe Coding with AI – Best Practices for Every Project"},{"content":"Why I Read the Way I Do In a world where audiobooks and digital formats are on the rise, I still find myself drawn to the physicality of hardcover books. They’re not just objects—they’re experiences. A hardcover book lasts longer, can be passed down, or gifted to someone who may need its wisdom as much as I did.\nBut my love for hardcovers ties directly to my reading process: I read every book at least twice. The first time, I simply read—no notes, no highlights, just letting the words flow. The second time, I go in with a pen or notebook, deliberately jotting down the key takeaways. For me, writing things down makes them stick, and as a visual learner, this approach is the most effective way for me to absorb information.\nHow This Fuels My Growth This isn’t just about reading for the sake of it. It’s about growth and implementation. Recently, I’ve been diving into Simon Sinek’s Start with Why. The book’s core message is simple yet profound: successful individuals and organizations don’t just communicate what they do—they communicate why they do it.\nThis principle has had a real impact on my work. Over the past few weeks, you may have noticed shifts in my content creation—whether it’s blog posts, videos, or presentations. Clarity of purpose, driven by a focus on the \u0026ldquo;why,\u0026rdquo; has made my messages resonate more deeply.\nWhat I Recommend to You If your role involves leading, inspiring, or motivating others, Start with Why is a must-read. Hardcover, paperback, eBook, or audio—choose the format that works for you, but make sure you read it. This book could reshape how you think about leadership, storytelling, and purpose.\nHighlighting and taking notes to retain ideas Journaling to organize and reflect on thoughts Call to Action 📢 Now, over to you:\nHow do you approach reading? Do you prefer audiobooks, eBooks, or physical books? Are you someone who dives straight in, or do you take notes to capture key takeaways?\n👇 Leave your comments below—I’d love to hear about your process and learn from your habits!\nLet’s grow together!\nChat about this? Engage with me Click Twitter @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers!\nFabs\n","permalink":"https://www.fabswill.com/blog/startwithwhy/","summary":"\u003ch2 id=\"why-i-read-the-way-i-do\"\u003eWhy I Read the Way I Do\u003c/h2\u003e\n\u003cp\u003eIn a world where audiobooks and digital formats are on the rise, I still find myself drawn to the physicality of hardcover books. They’re not just objects—they’re experiences. A hardcover book lasts longer, can be passed down, or gifted to someone who may need its wisdom as much as I did.\u003c/p\u003e\n\u003cp\u003eBut my love for hardcovers ties directly to my reading process: I read every book at least twice. The first time, I simply read—no notes, no highlights, just letting the words flow. The second time, I go in with a pen or notebook, deliberately jotting down the key takeaways. For me, writing things down makes them stick, and as a visual learner, this approach is the most effective way for me to absorb information.\u003c/p\u003e","title":"Start with Why: The How, the Why, and the What Behind My Reading Habit"},{"content":"How I Plan to Show Up in 2025 🚀 As we step into 2025, I’m reflecting on \u0026ldquo;why\u0026rdquo; I started this blog and the platforms I contribute to. If you’ve seen my About Me page, you already know that my \u0026ldquo;why\u0026rdquo; is rooted in representation, mentorship, and belief – belief in the technology I work on and belief that by showing up, I can help others do the same.\nBut this post is about the \u0026ldquo;how.\u0026rdquo;\n👉 How do I translate that purpose into something actionable?\n👉 How do I consistently show up in a way that adds value to the communities I serve?\n👉 How do I stay accountable to that commitment?\n1. The Framework: Why → How → What Simon Sinek popularized the concept of starting with \u0026ldquo;Why,\u0026rdquo; but the journey doesn’t stop there.\nWhy I do this: To represent, mentor, and grow. How I do this: By sharing my learnings every week through blog posts, videos, GitHub repos, and talks. What I produce: Tutorials, insights into tech, and reflections on my career path. The \u0026ldquo;how\u0026rdquo; bridges the gap between intent and outcome. It’s the consistent, sometimes small, steps that build momentum over time.\n2. My Commitment to Consistency This year, I’m setting the goal to publish one new piece of content every week.\nHere’s how I’m structuring it:\n📝 Blog Posts (like this one): Sharing frameworks, best practices, and personal reflections. 🎥 YouTube Videos: Tutorials and insights into the latest tech I’m working with, from LocalLLM Development on my Mac, Microsoft Copilot to Azure and LLMs. 🛠️ GitHub Repos: Releasing code snippets and project demos that align with my content themes. The key is to not overthink it. If I can share even one meaningful insight, tool, or perspective – that week counts as a win.\n3. The Tools that Make It Happen Here are the tools and habits I’m leaning on to make weekly content manageable:\nVS Code + GitHub – where I build and refine projects. Canva – for designing quick visuals that accompany posts. ChatGPT \u0026ndash; for churn work, document and asset synthesis, drafts etc. YouTube Studio – to streamline video uploads and editing. The goal isn’t perfection – it’s about progress and showing up regularly.\n4. Staying Accountable I know that consistency thrives with accountability, so I’m sharing this plan with you. If you’re reading this, hold me to it. Drop by my LinkedIn or YouTube and call me out if I fall behind.\n5. Wrapping It Up This journey isn’t just about creating content – it’s about leaning into growth, sharing knowledge, and paving the way for others.\nThe \u0026ldquo;how\u0026rdquo; is showing up – every week. The \u0026ldquo;what\u0026rdquo; will follow.\nLet’s make 2025 a year of consistent progress and meaningful impact.\n👉 See you next week.\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/fabianhowwillishowup/","summary":"\u003ch1 id=\"how-i-plan-to-show-up-in-2025-\"\u003eHow I Plan to Show Up in 2025 🚀\u003c/h1\u003e\n\u003cp\u003eAs we step into 2025, I’m reflecting on \u003cstrong\u003e\u0026ldquo;why\u0026rdquo;\u003c/strong\u003e I started this blog and the platforms I contribute to. If you’ve seen my \u003ca href=\"/about/\"\u003eAbout Me\u003c/a\u003e page, you already know that my \u0026ldquo;why\u0026rdquo; is rooted in \u003cstrong\u003erepresentation, mentorship, and belief\u003c/strong\u003e – belief in the technology I work on and belief that by showing up, I can help others do the same.\u003c/p\u003e\n\u003cp\u003eBut this post is about the \u003cstrong\u003e\u0026ldquo;how.\u0026rdquo;\u003c/strong\u003e\u003c/p\u003e","title":"How I Plan to Show Up in 2025 – The Journey from Why to What"},{"content":"👋 Hey there, I’m Fabian! I’m here because I believe representation matters.\nIn tech, I know I’m part of an underrepresented class—and that’s exactly why I show up. I believe that by sharing what I learn and voicing my thoughts, I can help pave the way for others.\n💻 By day: I’m a Principal Product Manager on the Microsoft 365 Copilot Team focusing on developer experiences and extensibility. I genuinely believe in the products I help build and the impact they can have.\n🌱 By heart: I’m a dad raising my kids to believe in their voice, their ideas, and their ability to stand tall behind their work.\n🤝 By intention: I mentor because I was mentored. This site is a space to pass the baton, share knowledge, and connect with those coming up behind me.\nA Few More Things\u0026hellip; 🌍 Based in the Washington DC Metro Area, USA 🎉 Former Microsoft MVP (2014-2020) for Visual Studio \u0026amp; Azure 🚒 Once a volunteer firefighter \u0026amp; EMT — always ready for the call to serve 👉 Let’s connect:\nFollow me on LinkedIn Subscribe to my YouTube for more learnings and insights Thanks for stopping by. I hope this space adds value to your journey.\n","permalink":"https://www.fabswill.com/about/","summary":"\u003ch1 id=\"-hey-there-im-fabian\"\u003e👋 Hey there, I’m Fabian!\u003c/h1\u003e\n\u003cp\u003eI’m here because I believe \u003cstrong\u003erepresentation matters.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eIn tech, I know I’m part of an underrepresented class—and that’s exactly why I show up. I believe that by sharing what I learn and voicing my thoughts, I can help pave the way for others.\u003c/p\u003e\n\u003cp\u003e💻 \u003cstrong\u003eBy day:\u003c/strong\u003e I’m a \u003cstrong\u003ePrincipal Product Manager\u003c/strong\u003e on the \u003cstrong\u003eMicrosoft 365 Copilot Team\u003c/strong\u003e focusing on \u003cstrong\u003edeveloper experiences and extensibility.\u003c/strong\u003e I genuinely believe in the products I help build and the impact they can have.\u003c/p\u003e","title":"About"},{"content":"🚀 Introduction After catching up on some podcasts about Product Management, leadership, and effective communication, I felt inspired to document my own approach. This isn’t just for the community – it’s also a way to hold myself accountable as I grow in my product management journey.\nProduct Management is a complex and ever-evolving role. It demands a blend of technical expertise, business acumen, emotional intelligence, and adaptability. Each organization, product, and stage of growth brings its own unique challenges.\nTo stay ahead, I’ve distilled key learnings into actionable practices and habits that I’m incorporating into my daily and weekly workflow. This framework integrates modern tools – including LLMs (Large Language Models) – to elevate decision-making and communication.\nIf you’re on a similar path, I’d love to hear how you’re approaching your role. Let\u0026rsquo;s learn and grow together!\nBest Practices for Product Managers 📊 Talk from the customer’s perspective\nAlways put yourself in the customer’s shoes. Consider their needs, pain points, and motivations. Every feature, update, or pivot should stem from enhancing the customer experience.\nBe data-informed (not data-driven)\nUse data as a guide – but don’t let it be the sole decision-maker. Balance data with intuition and market insights.\nBlend anecdotes with data\nNumbers tell part of the story, but customer anecdotes reveal emotional context. Marry qualitative and quantitative insights for a richer perspective.\nConvince stakeholders with a clear vision\nProduct Managers are storytellers. Rally stakeholders around a cohesive strategy that connects emotionally and logically to the company’s goals.\nStay current with industry trends\nThe best Product Managers are lifelong learners. Dedicate time to track emerging technologies, industry shifts, and competitors\u0026rsquo; movements.\nWeekly To-Do\u0026rsquo;s for Product Managers 📅 To stay proactive and aligned, I follow this simple yet effective weekly routine:\nReview customer feedback and data\nAnalyze feedback, support tickets, and product metrics. Look for recurring pain points or opportunities that align with the product roadmap.\nCollaborate with stakeholders\nSchedule regular check-ins with cross-functional teams (sales, marketing, engineering). Align on priorities and foster shared ownership of goals.\nConduct market and competitor research\nSet aside time each week to explore industry news, competitor updates, and new technologies that could shape the product landscape.\nRefine the roadmap\nProduct roadmaps are living documents. Use weekly insights to re-prioritize tasks, ensuring customer needs and company goals remain front and center.\nCommunicate with clarity\nTransparency fuels trust. Provide weekly updates to teams and stakeholders, ensuring everyone understands progress, blockers, and upcoming priorities.\nLeveraging LLMs for Product Management 🤖 LLMs (Large Language Models) have become invaluable in enhancing productivity and strategic thinking. Here\u0026rsquo;s how I’m using them to supercharge my workflow:\nSummarize product strategy\nI use LLMs to distill long product documents or strategies into concise summaries. This not only saves time but often reveals areas for improvement or gaps in logic.\nAnalyze competitor strategies\nBy ingesting publicly available documents (blogs, whitepapers, earnings calls), LLMs help uncover insights about competitors\u0026rsquo; moves, empowering me to adjust strategies dynamically.\nChallenge assumptions\nOne of the more unconventional uses of LLMs – I ask questions designed to provoke uncomfortable answers. This helps me surface blind spots and refine decisions.\nDraft communications\nFrom stakeholder emails to sprint plans, LLMs accelerate content creation, freeing up time for higher-level problem-solving.\nFinal Thoughts 💡 Product Management is as much about learning as it is about leading. By staying curious, leveraging new tools, and fostering collaboration, we can drive more impactful product outcomes.\nThis framework is a work in progress – just like the products I help build. If you have tips, feedback, or new practices that have worked for you, I’d love to hear them. Let\u0026rsquo;s elevate our craft together!\n🎯 What’s one practice that’s made you a better PM? Let me know in the comments or message me directly!\nThanks for reading!\nChat about this? Engage with me Click BlueSky @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/fabianproductmanagementframework2025/","summary":"\u003ch2 id=\"-introduction\"\u003e🚀 Introduction\u003c/h2\u003e\n\u003cp\u003eAfter catching up on some podcasts about \u003cstrong\u003eProduct Management\u003c/strong\u003e, leadership, and effective communication, \u003cem\u003e\u003cstrong\u003eI felt inspired to document my own approach. This isn’t just for the community – it’s also a way to hold myself accountable as I grow in my product management journey\u003c/strong\u003e\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003eProduct Management is a complex and ever-evolving role. It demands a blend of technical expertise, business acumen, emotional intelligence, and adaptability. Each organization, product, and stage of growth brings its own unique challenges.\u003c/p\u003e","title":"A Product Management Framework for 2024"},{"content":"🚀 Introduction Over the holiday break, I decided to dive deep into Llama 3.3, running it on my MacBook Pro M3 Max (128GB RAM, 40-core GPU). What started as curiosity quickly turned into a full exploration of local AI models, Semantic Kernel, and API integrations using Microsoft Graph.\nIn this post, I’ll walk you through my setup, the performance differences between Llama 3.3 and other models like Llama 3.170B, and the practical lessons learned along the way.\n🛠️ Setup and Tools Here’s what I used:\nHardware: MacBook Pro M3 Max (128GB RAM, 40-core GPU) Models: Llama 3.3, Llama 3.170B, Phi 3 APIs: Microsoft Graph API using OpenAPI specs Framework: Semantic Kernel with auto-invoked functions for weather and time plugins I also leveraged Graph Explorer for testing Microsoft Graph API endpoints, which simplified querying and verifying results.\n📊 Key Comparisons – Llama 3.3 vs Llama 3.170B Running Llama 3.3 locally was a significant improvement over 3.170B. Performance was faster, and responses were more refined. However, I discovered that while Llama 3.3 supports function calling, not all API integrations worked seamlessly.\nExample: Llama 3.3 (Function Calling Enabled): Managed to invoke functions via Semantic Kernel but hit limitations with nested queries (e.g., Microsoft Graph API). Phi 3: No function calling support – this was clearly noted during testing. 🤖 Real-World Example – Microsoft Graph API Integration One of my goals was to retrieve contact details using Graph API, leveraging the OpenAPI spec. While the initial integration worked, invoking the API through Llama 3.3 wasn’t as straightforward. The model struggled with nested properties and query parameters, unlike GPT-4, which handled it effortlessly.\n🎭 The Role of Plugins To enhance functionality, I added plugins for:\nWeather Forecasts Local Time Retrieval Llama 3.3 correctly identified which plugin to use based on the prompt but lacked streaming capabilities when invoking functions directly. This required creative solutions – running the initial call non-streaming and then invoking streaming for the assistant’s commentary.\n💡 Key Takeaways Not All Models Are Equal – Llama 3.3 outperforms older models but still has limitations. Function Calling Quirks – Direct function calls stream data, but auto-invoked functions return in bulk. Hardware Matters – A MacBook M3 Max handles local LLMs smoothly, but performance varies by model. API Complexity – Simple APIs (like weather) work well, but complex APIs (like Graph) require more finesse. 🎬 Watch the Full Video For a step-by-step walkthrough and live demos, check out the full video:\n👉 https://youtu.be/q_2BWCCnSS4\nThanks for reading, and happy experimenting with local LLMs!\nHappy coding!\nChat about this? Engage with me Click BlueSky @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/masteringllama3dot370b/","summary":"\u003ch2 id=\"-introduction\"\u003e🚀 Introduction\u003c/h2\u003e\n\u003cp\u003eOver the holiday break, I decided to dive deep into Llama 3.3, running it on my MacBook Pro M3 Max (128GB RAM, 40-core GPU). What started as curiosity quickly turned into a full exploration of local AI models, Semantic Kernel, and API integrations using Microsoft Graph.\u003c/p\u003e\n\u003cp\u003eIn this post, I’ll walk you through my setup, the performance differences between Llama 3.3 and other models like Llama 3.170B, and the practical lessons learned along the way.\u003c/p\u003e","title":"Mastering Llama 3.3 – A Deep Dive into Running Local LLMs"},{"content":"Building Custom Connectors with Microsoft Graph: A Starter Guide Welcome to the world of Microsoft Graph Connectors! If you\u0026rsquo;re looking to seamlessly integrate external data into Microsoft Search, you\u0026rsquo;ve come to the right place. This blog post is designed for technical audiences new to Microsoft Graph Connectors, providing a step-by-step guide on how to get started with building custom connectors. Let\u0026rsquo;s dive in!\nIntroduction to Microsoft Graph Connectors Microsoft Graph Connectors offer a bridge between external data sources and Microsoft 365, allowing you to make external content searchable within Microsoft Search. This integration not only enhances productivity but also fosters collaboration by making external data accessible through familiar tools like SharePoint and Microsoft Teams.\nKey Concepts to Understand Before embarking on building custom connectors, it\u0026rsquo;s essential to grasp a few foundational concepts:\nConnections Connections act as pathways for your external data to flow into Microsoft Graph. Managing Connections involves creating, configuring, and maintaining these pathways to ensure data is accurately and securely indexed.\nSchemas A Schema defines the structure of your external data within Microsoft Graph. It includes properties like ID, title, content, and more, which help organize and make the data searchable.\nItems Items are the individual pieces of content that are indexed by the connector. Managing Items involves creating, updating, and deleting these pieces of content to keep the search index up to date.\nPermissions To ensure secure access to the indexed content, Microsoft Graph Connectors support access control lists (ACLs). These ACLs can include Microsoft Entra users, groups, and even external groups.\nBuilding Your Connector with .NET SDK The Microosft Graph Connector SDK simplifies the process of building custom connectors. Here\u0026rsquo;s a high-level overview of the steps involved:\nSet Up Your Development Environment: Ensure you have the necessary tools and SDKs installed, including Visual Studio and the Microsoft Graph Connector SDK. Create Your Connector Project: Start by creating a new .NET project and installing the Microsoft Graph Connector SDK package. Define Your Schema: Use the SDK to define the schema of your external data. Implement Data Ingestion: Write the code to fetch data from your external source and transform it into the format defined by your schema. Handle Permissions: Implement logic to manage ACLs for your data. Test Your Connector: Utilize tools like Postman to test your connector\u0026rsquo;s endpoints. Leveraging Community Samples and Resources The Microsoft Graph community offers a wealth of resources and samples to help you get started. For example, check out the community samples for real-world examples of custom connectors. You can also take a look at my own Python sample which demonstrates how to build a connector using Python and Jupyter Notebooks. This sample, along with its GitHub repository, offers a practical starting point for those looking to develop connectors in a Python environment.\nConclusion Building custom connectors for Microsoft Graph is a powerful way to enhance your organization\u0026rsquo;s search capabilities. By understanding the foundational concepts, leveraging the .NET SDK, and utilizing community resources, you can embark on this journey with confidence.\nHappy coding!\nChat about this? Engage with me Click Twitter @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/gettingstartedgraphconnectorsdev/","summary":"\u003ch2 id=\"building-custom-connectors-with-microsoft-graph-a-starter-guide\"\u003eBuilding Custom Connectors with Microsoft Graph: A Starter Guide\u003c/h2\u003e\n\u003cp\u003eWelcome to the world of Microsoft Graph Connectors! If you\u0026rsquo;re looking to seamlessly integrate external data into Microsoft Search, you\u0026rsquo;ve come to the right place. This blog post is designed for technical audiences new to Microsoft Graph Connectors, providing a step-by-step guide on how to get started with building custom connectors. Let\u0026rsquo;s dive in!\u003c/p\u003e\n\u003ch2 id=\"introduction-to-microsoft-graph-connectors\"\u003eIntroduction to Microsoft Graph Connectors\u003c/h2\u003e\n\u003cp\u003eMicrosoft Graph Connectors offer a bridge between external data sources and Microsoft 365, allowing you to make external content searchable within Microsoft Search. This integration not only enhances productivity but also fosters collaboration by making external data accessible through familiar tools like SharePoint and Microsoft Teams.\u003c/p\u003e","title":"Getting started with Microsoft Graph Connectors"},{"content":"Building inside Microsoft 365 ecosystem with Graph Connectors - A Recipe Book Welcome to the world of Microsoft Graph Connectors! If you\u0026rsquo;re looking to seamlessly integrate external data into Microsoft Search, you\u0026rsquo;ve come to the right place. If this is the 1st time you are hearing about Microsoft Graph Connectors, it might be useful to take a look at these 2 earlier post:\nfrom Waldek Mastykarz and Majesty Uwagerikpe on Find what you need with Microsoft Graph connectors and from Waldek again Anatomy of a Microsoft Graph Connector This post is a middle of the road post that likely your Data folks, your Security folks, your Business Analyst will ask you questions on so\u0026hellip; Let\u0026rsquo;s dive right in!\nIntroduction to Microsoft Graph Connectors Microsoft Graph Connectors offer a bridge between external data sources and Microsoft 365, allowing you to make external content searchable within Microsoft Search. This integration not only enhances productivity but also fosters collaboration by making external data accessible through familiar tools like SharePoint and Microsoft Teams.\nKey Concepts to Understand Before embarking on building custom connectors, it\u0026rsquo;s essential to grasp a few foundational concepts:\nConnections Connections act as pathways for your external data to flow into Microsoft Graph. Managing Connections involves creating, configuring, and maintaining these pathways to ensure data is accurately and securely indexed.\nSchemas A Schema defines the structure of your external data within Microsoft Graph. It includes properties like ID, title, content, and more, which help organize and make the data searchable.\nItems Items are the individual pieces of content that are indexed by the connector. Managing Items involves creating, updating, and deleting these pieces of content to keep the search index up to date.\nPermissions To ensure secure access to the indexed content, Microsoft Graph Connectors support access control lists (ACLs). These ACLs can include Microsoft Entra users, groups, and even external groups.\nBuilding Your Connector with .NET SDK The Microosft Graph Connector SDK simplifies the process of building custom connectors. Here\u0026rsquo;s a high-level overview of the steps involved:\nSet Up Your Development Environment: Ensure you have the necessary tools and SDKs installed, including Visual Studio and the Microsoft Graph Connector SDK. Create Your Connector Project: Start by creating a new .NET project and installing the Microsoft Graph Connector SDK package. Define Your Schema: Use the SDK to define the schema of your external data. Implement Data Ingestion: Write the code to fetch data from your external source and transform it into the format defined by your schema. Handle Permissions: Implement logic to manage ACLs for your data. Test Your Connector: Utilize tools like Postman to test your connector\u0026rsquo;s endpoints. Leveraging Community Samples and Resources The Microsoft Graph community offers a wealth of resources and samples to help you get started. For example, check out the community samples for real-world examples of custom connectors. You can also take a look at my own Python sample which demonstrates how to build a connector using Python and Jupyter Notebooks. This sample, along with its GitHub repository, offers a practical starting point for those looking to develop connectors in a Python environment.\nConclusion Building custom connectors for Microsoft Graph is a powerful way to enhance your organization\u0026rsquo;s search capabilities. By understanding the foundational concepts, leveraging the .NET SDK, and utilizing community resources, you can embark on this journey with confidence.\nHappy coding!\nChat about this? Engage with me Click Twitter @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/devwithgraphconnectors/","summary":"\u003ch2 id=\"building-inside-microsoft-365-ecosystem-with-graph-connectors---a-recipe-book\"\u003eBuilding inside Microsoft 365 ecosystem with Graph Connectors - A Recipe Book\u003c/h2\u003e\n\u003cp\u003eWelcome to the world of Microsoft Graph Connectors! If you\u0026rsquo;re looking to seamlessly integrate external data into Microsoft Search, you\u0026rsquo;ve come to the right place. If this is the 1st time you are hearing about Microsoft Graph Connectors, it might be useful to take a look at these 2 earlier post:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003efrom \u003ca href=\"https://www.linkedin.com/in/waldekmastykarz/\" title=\"Waldek\"\u003e\u003cstrong\u003eWaldek Mastykarz\u003c/strong\u003e\u003c/a\u003e and \u003ca href=\"https://www.linkedin.com/in/majesty-uwagerikpe-308619162/\" title=\"Majesty\"\u003e\u003cstrong\u003eMajesty Uwagerikpe\u003c/strong\u003e\u003c/a\u003e on \u003ca href=\"https://devblogs.microsoft.com/microsoft365dev/find-what-you-need-with-microsoft-graph-connectors/\" title=\"Find what you need with Graph Connectors\"\u003e\u003cstrong\u003eFind what you need with Microsoft Graph connectors\u003c/strong\u003e\u003c/a\u003e and\u003c/li\u003e\n\u003cli\u003efrom Waldek again \u003ca href=\"https://devblogs.microsoft.com/microsoft365dev/anatomy-of-a-microsoft-graph-connector/\" title=\"Anatomy of a Graph Connector\"\u003e\u003cstrong\u003eAnatomy of a Microsoft Graph Connector\u003c/strong\u003e\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThis post is a middle of the road post that likely your \u003cstrong\u003eData folks\u003c/strong\u003e, your \u003cstrong\u003eSecurity folks\u003c/strong\u003e, your \u003cstrong\u003eBusiness Analyst\u003c/strong\u003e will ask you questions on so\u0026hellip; Let\u0026rsquo;s dive right in!\u003c/p\u003e","title":"Start Developing with Microsoft Graph Connectors"},{"content":"Why you should read this post If you are interested in getting started doing software development with Microsoft 365 and in particular with Microsoft Graph, Microsoft Teams, Microsoft SharePoint, and/or Microsoft Graph,this post gives the cookbook recipie of what you need and where you need to go to get it. I am going to approach it from:\nInfrastructure ie. what you need to even get started Sample code created from both internal Microsoft as well as contributed from by the Technical Community Video tutorials of solutions curated by the Product Group team I am on at Microsoft Bonus - I will give you the links to Live calls that you can attend with Microsoft that highlights various popular technology stack where you can hear what is out there by the experts as well as ask your troubling keep you up at night questions. Infrastructure For as long as you continue to use this piece of infrastructure you get an instant sandbox preconfigured with sample data, which enables you to start developing on the Microsoft 365 platform within minutes. The sample data includes:\nMicrosoft Graph user, mail, and calendar data - 16 sample users with user data and content, integrated with Teams developer environment. Teams data pack with the following customized developer environment: App sideloading pre-configured. Five sample teams, channels, tabs, and chat sessions built around the 16 sample users. Developer Portal pre-installed to help you streamline the creation of your Teams app manifest and package, plus the card editor and a React control library. SharePoint Framework sample data – Choose from six site templates that you can install and evaluate for your organization (with one pre-installed). You can register for this FREE E5 Tenant here.\nSkill Up Samples We have over 1100 Samples in our gallery that features countless scenarios to enable you to go from idea to prototype to minimal product in short order\u0026hellip; or\u0026hellip; use the samples as a learning aid to see how an idea shapes into reality based on particular scenario/user stories.\nYou can get access to these samples here.\nVideo Tutorials As a visual learner myself, I know the value of video, we have two (2) YouTube channels where you can get valuable content where we are interviewing both members of the Technical Community as well as internal Microsoft on how to use the technology they are SME\u0026rsquo;s in.\nMajority Internal Microsoft video tutorials from our Developer Relationship and Developer Advocates.\nLargely members of the Microsoft 365 technical community including Microsoft MVPs and RDs video tutorials here.\nBonus - Attend our Weekly, Bi-Weekly, and Monthly calls with Vesa and Me! I happy to now be a co-host with Vesa Juvonen on the Microsoft 365 Platform calls that happens every Tuesday at 0800 Pacific and 1100 Eastern. In additon to that we have all these calls here below and one very easy way for you to sign up below. 5 Sign up NOW for these recurring Community Calls here.\nSummary I constantly get the question, \u0026ldquo;\u0026hellip;how do I start doing what you do Fabian\u0026rdquo; or \u0026ldquo;\u0026hellip;I dont have the time or money to learn all this stuff\u0026rdquo; and Im here to tell you two things mainly 1. If you take one hour out of your day and one example is perhaps wake up 1 hour early or 2 go to bed 1 hour later \u0026#x1f61c; and you watch one of these vidoes which as luck would have it is time boxed to 1 hour, you will hear from Experts for FREE who would otherwise be charging hundreds of dollars/euros/your currency here for their time and experise. and 2. Nothwithsanding what I have posted and shown you here, there are heaps and heaps of other content on YouTube and my favorite PluralSight and even LinkedIn Learning. You will find also that most of the presenters on our calls are course authors on these platforms so you can come try it out for free and maybe even get a discount code for a free month on these professional platforms.\nChat about this? Engage with me Click Twitter @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/gettingstartedm365dev/","summary":"\u003ch2 id=\"why-you-should-read-this-post\"\u003eWhy you should read this post\u003c/h2\u003e\n\u003cp\u003eIf you are interested in getting started doing software development with \u003ccode\u003eMicrosoft 365\u003c/code\u003e and in particular with \u003ccode\u003eMicrosoft Graph\u003c/code\u003e, \u003ccode\u003eMicrosoft Teams\u003c/code\u003e, \u003ccode\u003eMicrosoft SharePoint\u003c/code\u003e, and/or \u003ccode\u003eMicrosoft Graph\u003c/code\u003e,this post gives the cookbook \u003cem\u003e\u003cstrong\u003erecipie\u003c/strong\u003e\u003c/em\u003e of what you need and where you need to go to get it.  I am going to approach it from:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eInfrastructure\u003c/strong\u003e ie. what you need to even get started\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSample code\u003c/strong\u003e created from both internal Microsoft as well as contributed from by the Technical Community\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eVideo tutorials\u003c/strong\u003e of solutions curated by the Product Group team I am on at Microsoft\u003c/li\u003e\n\u003cli\u003eBonus - I will give you the links to \u003cstrong\u003eLive calls\u003c/strong\u003e that you can attend with Microsoft that highlights various popular technology stack where you can hear what is out there by the experts as well as ask your troubling keep you up at night questions.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"infrastructure\"\u003eInfrastructure\u003c/h2\u003e\n\u003cp\u003eFor as long as you continue to use this piece of infrastructure you get an instant sandbox preconfigured with sample data, which enables you to start developing on the Microsoft 365 platform within minutes. The sample data includes:\u003c/p\u003e","title":"Getting started with Microsoft365 Dev"},{"content":"TLDR; Checking in on the results after 1 week in the wild of publishing this survey https://www.thatsgreatfeedback.com/studentloandebtforgive to capture feedback on the news that President Biden is considering Student Loan Debt Forgiveness and the results after 1 week are tabulated again.\nHuge Thanks to all the folks out there who took the time to fill out the brief 9 question Anonymous survey that yielded the below results! We were only able to get (as of the time of this post) 55 folks to respond \u0026#x1f60a; to the survey. Notwithstanding, we have compiled the results for you below.\nThe Past 1 Week There are 5 questions posed and in one free from around the subject matter and 4 demographic questions. The free from response question centered around folks reaction to the the easing/forgiving of Student Loans. The responses throughout the week remained consistent with sentiments were overall positive with overwhelmingly positive polarized feelings towards the Student Loan Debt Forgiveness by the Joe Biden administration. What we did see however is that most responders to the survey agreed that student loans are expensive, some even said Predatory and is too high, here are a few examples that contributed to our word cloud and sentiment analysis:\nPositive Affirmation to President Biden Announcements\n1) The cost of education in the United States is criminal. Citizens in developed nations have had the right to free higher education since 1966. Our nation is a disgrace to the word freedom 2) Too high, should be free/low cost 3) Costs are way too high and make it inaccessible for people to get an education 4) Way to high, predatory. 5) Tuition is high; however, the lender\u0026#39;s interest surpasses Tuition costs as it\u0026#39;s compounded. This makes interest almost 100% of Tuition. Politicians have not confronted this. Also, women are taking a huge brunt of this scam. We are paid lower than men and have often attempted to increase our wages with going to college only to face another issue: ageism in America at 40. I was let go in my 40s and earn much less. I earned 38k to 55k per year until At 44, $55k per year then let go, at 45 $33k per year, at 46, 28k (which I was forced to cash out 401k, at 47 22k per year. Negative feedback to President Biden Announcements\n9) It’s abhorrent. A system full of graft and inflated costs in the name of profit. Administrators at my school (administrator of intramural sports and student events for instance) made more than $300,000/yr. and there were dozens of them. Absolutely ridiculous. However, any solution to student debt should be forward looking, preventing future generations from being financially taken advantage of by this system. It’s tough, but the people that have already taken out loans should have to repay them. The government doesn’t have the money to pay private student loan debt, and doesn’t have the right to do so either. Cancellation of federal student loan debt will disproportionately impact those who were unable to get access to Federal Student Loans, leaving them well behind their peers financially. Again, it’s a tough decision but any solution and financial resources allocated toward the problem should be forward facing. Money isn’t infinite and the federal government needs to stop treating it like it is. 10) It is complicated. Most people with massive debt were mostly failed by their parents and guidance counselors that should have stopped them from making such a colossal mistake. Also the govt guaranteeing student loan debt allows these people to get loans, no sane lender should even agree to loan someone 200,000 for an at ry history degree. However ultimately, it wasn’t a secret what degrees were worthless, yet people still chose to go into debt to get them. Everybody shares some amount of blame 11) It is outrageous, and student loans are worse. Most people I know have paid all or almost all the original amount they borrowed but owe more than when they started. I borrowed $20k and after making payments faithfully for years, I owed $25k. It\u0026#39;s immoral and doesn\u0026#39;t when make sense. 12) It’s ridiculously expensive, we need to fix this first before we even discuss forgiveness for loans already out there. Also, I could support 10,000 given to *all* households who filed tax returns as another stimulus check. Then people who have student loans could use it for those, while also not leaving out people who chose not to attend school. 13) Policy should modify future loans to tackle education costs. Existing loans should be left as is, borrowers signed and agreed to pay back money and should be held liable to do so. A world cloud below homed in on\nExpensive Loans High Free Education Question Posed: 9. Your thoughts on the Cost of Education in America? : | Fig.1 - Word Cloud showing Intensity to #9 Question posed|\nSubjectivity and Polarity When it comes to Subjectivity in this context of this research, it quantifies the amount of personal opinion and factual information contained in the response to an open ended question like question number nine (9), whilst Polarity defines the orientation of the response measuring how positive, negative, or neutral the consideration to the question being posed and its response. After 1 week, by and large the sentiment and polarity kept the trend and expanded, there were polarity on both ends but more positive but negative.\nQuestion Posed: 9. Your thoughts on the Cost of Education in America?: | Fig.3a - Scatter Plot showing Subjectivity \u0026amp; Polarity in response to #9 Question posed|\nWe saw 56.4% positive sentiments with 30.9% negative responses based on our NLP model. Overall sentiments are also shown in the below histogram.\n| Fig.3b - Histogram showing response to #9 Question posed|\nCorollaries While the responses largely remained the same over the course of 1 week, and only strengthen, there’s a few things I\u0026rsquo;d call out:\nWhile by a measure of almost 2:1 responders responded positive to the statements of President Biden on Student Loan Debt Forgiveness, when asked about the \u0026ldquo;Treatment of Student Loans\u0026rdquo;, next to \u0026ldquo;forgiveness\u0026rdquo;, others said \u0026ldquo;Leave it as it is\u0026rdquo;! with the only other response being to \u0026ldquo;Reduce it\u0026rdquo; by 1/3 of the Forgiveness sentiment. By a factor of 2:1 responders cited NOT having a Student Loan, now you may say \u0026hellip;wait a minute but if you look at the data, you will find that most responders cited Paid in Full for their impact, meaning that they paid off their student loans We also saw that most survey responses came form individuals between the ages of 26 to 34 and most are Post Graduate or In University, however by a factor of 3:1, responders to the survey are Employed. For a breakdown of those conclusions, here is the raw data below:\nQuestion Posed: 1.How do you feel about President Joe Biden consideration on Student Loan Debt Forgiveness? | Fig.4 - Responders feeling towards ruling of mask mandate lifted|\nrelative to the responses of 3.On Student Loan Debt Forgiveness. Do you think it should be? below you can see\n| Fig.5 - How to handle Student Loan Debt|\nthat folk vastly favor Student Loan Forgiveness at about ~ 3:1 when compared to Reducing it OR Leaving it As Is!\nWho Took our Poll? Our poll is anonymous but we asked the respondents to identify by impact their relationship to the topic, the feedback we got indicated:\nQuestion 4. What is our relationship with Student Loans? ? | Fig.6 - How do people taking the survey identify|\nput another way, here are the exact numbers for people taking the survey\n| Fig.6b - How do people taking the survey identify|\nDemographics 5. What is your age range? | Fig.7 - Age Range|\n6. Highest level of education? | Fig.8 -Education Level|\n7. Which of the following best describes you? | Fig.9 - Race/Ethnicity|\n8. Employment status? | Fig.10 - Employment Status|\nFinally, If you have not yet\u0026hellip; Please consider taking the Survey here https://www.thatsgreatfeedback.com/studentloandebtforgivel\nContinue the conversation Engage with me Click Reddit - Reddit Facebook - Facebook Twitter - Tweet LinkedIn - LinkedIn Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/studentloanreliefresults-1week/","summary":"\u003ch2 id=\"tldr\"\u003eTLDR;\u003c/h2\u003e\n\u003cp\u003eChecking in on the results after \u003cstrong\u003e1 week in the wild\u003c/strong\u003e of publishing \u003cem\u003e\u003cstrong\u003ethis survey\u003c/strong\u003e\u003c/em\u003e \u003ca href=\"https://www.thatsgreatfeedback.com/studentloandebtforgive\" title=\"Student Loan Debt Forgiveness Survey\"\u003ehttps://www.thatsgreatfeedback.com/studentloandebtforgive\u003c/a\u003e to capture feedback on the news that \u003cstrong\u003ePresident Biden\u003c/strong\u003e is considering Student Loan Debt Forgiveness and the results after 1 week are \u003cstrong\u003etabulated again\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHuge Thanks\u003c/strong\u003e to all the folks out there who took the time to fill out the brief \u003cstrong\u003e9\u003c/strong\u003e question \u003cem\u003e\u003cstrong\u003eAnonymous\u003c/strong\u003e\u003c/em\u003e survey that yielded the below results! We were only able to get (as of the time of this post) 55 folks to respond \u0026#x1f60a; to the survey. Notwithstanding, we have compiled the results for you below.\u003c/p\u003e","title":"Student Loan Debt Forgiveness Survey Results - 1 Week"},{"content":"TLDR; I posted on May 07, 2022 this survey https://www.thatsgreatfeedback.com/studentloandebtforgive to seek feedback on the news that President Biden is considering Student Loan Debt Forgiveness as reported on Fox as well as Fortune and the 1st Results after 24 hour are in! Here is what people had to say\nHuge Thanks to all the folks out there who took the time to fill out the brief 9 question Anonymous survey that yielded the below results!\nThe 1st 24 Hours By and large the sentiments from long form feedback that was collected is largely positive in the 1st 24 hours of responses collected. While most survey takers indicated that there should be Student Loan Forgiveness, there were feelings ranging from Happy to Angry expressed about President Biden\u0026rsquo;s considerations. A world cloud below homed in on\nfree Education cost expensive high debt Question: 9.Your thoughts on the Cost of Education in America? *: | Fig.1 - Word Cloud showing Intensity to #9 Question|\nSubjectivity and Polarity When it comes to Subjectivity in this context of this research, it quantifies the amount of personal opinion and factual informaiton contained in the response to an open ended quesiton like question number nine (9), whilst Polarity defines the orientation of the response measuring how positive, negative, or neutral the consideration to the question being posed and its response.\nQuestion: 9.Your thoughts on the Cost of Education in America? *: | Fig.3a - Scatter Plot showing Subjectivity \u0026amp; Polarity in response to #9 Question|\nWe are seeing fifty percent 50.0% positive sentiments with thirty 30.0% negative responses based on our NLP model. Overall sentiments are also shown in the below histogram.\n| Fig.3b - Histogram showing response to #9 Question|\nCorollaries Still too early to tell but we are watching\u0026hellip;\nQuestion: 1. Feelings on President Biden consideration on Student Loan Debt Forgiveness? | Fig.4 - Responders feeling towards Student Loan Debt Forgiveness|\nrelative to the responses of of 3.On Student Loan Debt Forgiveness. Do you think it shold be? below you can see\n| Fig.5 - How to handle Student Loan Debt|\nthat folk vastly favor Student Loan Forgiveness at about ~ 3:1 when compared to Reducing it OR Leaving it As Is!\nIf you have not taken this survey please consider doing so by clicking the link here\nPlease consider taking the Survey here https://www.thatsgreatfeedback.com/studentloandebtforgive\nWho Took our Poll? Our poll is anonymous but we asked the respondents to identify by impact their relationship to the topic, the feedback we got indicated:\nQuestion 4. What is our relationship with Student Loans? ? | Fig.6 - How do people taking the survey identify|\nDemographics 5. What is your age range? | Fig.7 - Age Range|\n6. Highest level of education? | Fig.8 -Education Level|\n7. Which of the following best describes you? | Fig.9 - Race/Ethnicity|\n8. Employment status? | Fig.10 - Employment Status|\nThe 1st 7 Days See you in a week! \u0026amp; If you have not yet\u0026hellip; Please consider taking the Survey here https://www.thatsgreatfeedback.com/studentloandebtforgive\nContinue the conversation Engage with me Click Twitter Student Loans 24HR Survey - Tweet LinkedIn Student Loans 24HR Survey - LinkedIn Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/studentloanforgiveness_24hrin/","summary":"\u003ch2 id=\"tldr\"\u003eTLDR;\u003c/h2\u003e\n\u003cp\u003eI posted on May 07, 2022 \u003cstrong\u003ethis survey\u003c/strong\u003e \u003ca href=\"https://www.thatsgreatfeedback.com/studentloandebtforgive\" title=\"Student Loan Debt Forgiveness Survey\"\u003ehttps://www.thatsgreatfeedback.com/studentloandebtforgive\u003c/a\u003e to seek feedback on the news that \u003cstrong\u003ePresident Biden\u003c/strong\u003e is considering \u003ca href=\"https://www.foxbusiness.com/politics/biden-student-loan-forgiveness-plan-everything-we-know-so-far\" title=\"Fox News Report\"\u003eStudent Loan Debt Forgiveness\u003c/a\u003e as reported on Fox as well as \u003ca href=\"https://fortune.com/education/business/articles/2022/05/06/what-biden-could-be-planning-for-student-loan-forgiveness/\" title=\"Fortune Report\"\u003eFortune\u003c/a\u003e and the 1st Results after 24 hour are in! Here is what people had to say\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"The Results are in!\" loading=\"lazy\" src=\"/img/2022/05/studentloan_resultsarein_24hrs.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHuge Thanks\u003c/strong\u003e to all the folks out there who took the time to fill out the brief \u003cstrong\u003e9\u003c/strong\u003e question \u003cem\u003e\u003cstrong\u003eAnonymous\u003c/strong\u003e\u003c/em\u003e survey that yielded the below results!\u003c/p\u003e","title":"Student Loan Debt Forgiveness Survey Results"},{"content":"TLDR; Checking in on the results after 1 week in the wild of publishing this survey https://www.thatsgreatfeedback.com/maskmandatesapril22 about the news Mask Mandate is lifted to capture feedback on how thsi affects you and the results are tabulated again.\nHuge Thanks to all the folks out there who took the time to fill out the brief 5 question Anonymous survey that yielded the below results! As my good buddy Bill Baer taunted me yesterday \u0026amp; I dont think he would mind me sharing this \u0026#x1f60a; \u0026quot;\u0026hellip;the biggest problem\u0026hellip;you need a big dataset\u0026quot; Notwithstanding we are now at 84 responses to the survey with 1/2 of the response coming in in the 1st 2 days.\nThe Past 1 Week There were 5 questions posed and in one free from response the question asked centered around folks reaction to the federal ruling to lift mask mandates. There was a bit of ebb \u0026amp; flow over the course of the week where sentiments went vastly negative with very poloarized feelings towards the lifting of the mask mandate by the federal judge, however as of this morning, while we DOUBLED our amount of responses, the overall sentiments remained statistacially even with nuances about:\nWhether one would continue to wear a mask in Public Transportation Emotive reactions to the news Population / Role of those responding to the survey A world cloud below homed in on\nPeople Judge Well Question Posed: 5. How do you think this decision was handled? *: | Fig.1 - Word Cloud showing Intensity to #5 Question posed|\nSubjectivity and Polarity When it comes to Subjectivity in this context of this research, it quantifies the amount of personal opinion and factual informaiton contained in the response to an open ended quesiton like question number five (5), whilst Polarity defines the orientation of the response measuring how positive, negative, or neutral the consideration to the question being posed and its response. After 1 week, minus the ebb \u0026amp; flow previously mentioned, the count has changed but by and large the sentiment and polarity remains similar in that by a VERY SLIM margin people expressed more positive sentiments to the Mask Mandate being lifted by judicial decree, than negative.\nQuestion Posed: 5. How do you think this decision was handled? *: | Fig.3a - Scatter Plot showing Subjectivity \u0026amp; Polarity in response to #5 Question posed|\nWe saw forty one point thirty seven point 3 37.3% positive sentiments with 34.9% negative responses based on our NLP model. Overall sentiments are also shown in the below histogram.\n| Fig.3b - Histogram showing response to #5 Question posed|\nCorollaries There\u0026rsquo;s lots of ways we can slice and dice these responses, in fact the structure of the survey is to ask 4 closed questions and 1 open one, using sentiment analysis to study the open quesiton and statisitcal observations over the other four. One corrolary that was stricking was Emotive Feelings to the Mask Mandate decision relative to Whether or not the responder would continue to wear a mask in public transporation settings. For example, if you look at the emotive responses below\nQuestion Posed: 1. How do you feel about the lifting of mask mandates on public transportation? | Fig.4 - Responders feeling towards ruling of mask mandate lifted|\nrelative to the responses of of to wear or not to wear below you can see\nthat folk still favor wearing mask in public transportation almost 2:1 even though the amount of responders citing \u0026ldquo;Happiness\u0026rdquo; in the decision ranked second overall.\nIf you have not taken this survey please consider doing so by clicking the link here\nPlease consider taking the Survey here https://www.thatsgreatfeedback.com/maskmandatesapril22\nand if you have not seen the 1st 24 hour report as a measure to where we are now, you can also catch up on that here\nSee the Report 24 hours in here https://fabswill.com/blog/maskmandatesresults/\nWho Took our Poll Our poll is anonymous but we asked the respondents to identify by impact their relationship to the topic, the feedback we got indicated:\nQuestion Posed: 4. As a personal impact by this decision. Are you a? | Fig.6 - How do people taking the survey identify|\nFinally, If you have not yet\u0026hellip; Please consider taking the Survey here https://www.thatsgreatfeedback.com/maskmandatesapril22l\nContinue the conversation Engage with me Click Twitter Mask Mandate 24HR Survey Report - WFH Tweet LinkedIn Mask Mandate 24HR Survey Report - WFH LinkedIn Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/maskmandatesresults-1week/","summary":"\u003ch2 id=\"tldr\"\u003eTLDR;\u003c/h2\u003e\n\u003cp\u003eChecking in on the results after \u003cstrong\u003e1 week in the wild\u003c/strong\u003e of publishing \u003cem\u003e\u003cstrong\u003ethis survey\u003c/strong\u003e\u003c/em\u003e \u003ca href=\"https://www.thatsgreatfeedback.com/maskmandatesapril22\" title=\"Mask Mandate Lifted Survey\"\u003ehttps://www.thatsgreatfeedback.com/maskmandatesapril22\u003c/a\u003e about the news \u003ca href=\"https://www.reuters.com/legal/government/us-judge-rules-mask-mandate-transport-unlawful-overturning-biden-effort-2022-04-18/l\" title=\"Reuters News Report\"\u003eMask Mandate is lifted\u003c/a\u003e to capture feedback on how thsi affects you and the results are \u003cstrong\u003etabulated again\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"The Results are in!\" loading=\"lazy\" src=\"/img/resultsareininpage.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHuge Thanks\u003c/strong\u003e to all the folks out there who took the time to fill out the brief \u003cstrong\u003e5\u003c/strong\u003e question \u003cem\u003e\u003cstrong\u003eAnonymous\u003c/strong\u003e\u003c/em\u003e survey that yielded the below results! As my good buddy Bill Baer taunted me yesterday \u0026amp; I dont think he would mind me sharing this \u0026#x1f60a; \u003cem\u003e\u003cstrong\u003e\u0026quot;\u0026hellip;the biggest problem\u0026hellip;you need a big dataset\u0026quot;\u003c/strong\u003e\u003c/em\u003e Notwithstanding we are now at \u003cstrong\u003e84\u003c/strong\u003e responses to the survey with \u003cstrong\u003e1/2\u003c/strong\u003e of the response coming in in the 1st 2 days.\u003c/p\u003e","title":"Mask Mandate Survey Results - 1 Week"},{"content":"TLDR; I posted on April 20, 2022 this survey https://www.thatsgreatfeedback.com/maskmandatesapril22 about the news Mask Mandate is lifted to capture feedback on how thsi affects you and the results are in!\nHuge Thanks to all the folks out there who took the time to fill out the brief 5 question Anonymous survey that yielded the below results!\nThe 1st 24 Hours There were 5 questions posed and in one free from response the question asked centered around folks reaction to the federal ruling to lift mask mandates. By and large the sentiments from long form feedback that was collected are relatively split in the 1st 24 hours of responses collected. Where we saw varying differences in opinions came from targetted questions around personal impact as well as individual actions moving foward. A world cloud below homed in on\nPoorly handled Judge Well Question Posed: 5. How do you think this decision was handled? *: | Fig.1 - Word Cloud showing Intensity to #5 Question posed|\nOverall Sentiments Out of the 5 questions posed, there was 1 open ended question and we keyed off that for a lot of the analysis, here is a snapshot of the top 10 positive anonymous feedback provided:\nQuestion Posed: 5. How do you think this decision was handled? *: 1) I think the decision should be left in the hands of health care professionals BUT I do understand that a decision had to be made at some point in time especially since most other affected areas are lifting masks. 2) My children are too young to get vaccinated and they are in school, I need to be protective and responsible, I think this decision was rushed and political 3) I’m glad it’s now standardized across the board for the general public 4) We have to get back to some kind of normal life someday 5) Idk but as long as my mask gets off I’m happy 6) I think that it was realized that covid is inevitable so what difference is it making to continue wearing masks if the likelihood of Covid ending for good is unlikely 7) Calmly 8) I really think that it wasn’t very well thought out. Things like buses and trains don’t have a lot of space, so there’s a bunch of people in a. confined area without masks. It’s not safe. 9) That “judge” was highly unqualified. Didn’t even have a hearing? Just ruled from the bench. 10) Too drastic of a change for many transportation networks. Especially if you were mid flight. Question Posed: 5. How do you think this decision was handled? *: | Fig.2 - Table of the Top 10 Free Form responses to #5 Question posed|\nUpdate Time: 1500 EST Initally we were happy to see that people really shared their unique and individual perspectives candidly, sentiments were highly subjective \u0026amp; as a testament to the above word cloud, the polarity index was in a positive direction overall.\nUpdate Time: 1645 EST Closer to the end of the 24 hour while subjectivity remained positive indicating responders to the survey are providing contextual opinions, towards the end the polarity index shifted to be more negatively polarized qualitatively v/s quantitatively. If we adjusted for the outlier of 0.65 we would end up with a relatively split sentiment and polarity index.\nQuestion Posed: 5. How do you think this decision was handled? *: | Fig.3 - Scatter Plot showing Subjectivity \u0026amp; Polarity in response to #5 Question posed|\nWe saw forty one point four percent 41.4% positive sentiments with 34.5% negative responses based on our NLP model.\nCorollaries With the outlier adjusted, we noted that subjective feedback were relatively split, however there were swings when it came to personal action and accountability moving forward. There was a corollary in that respondents to the survey while experessing feelings of Stress on one end and angry on the other also indicated that they would continue to wear mask in a public transportation setting by a factor of almost 2:1.\nQuestion Posed: 1. How do you feel about the lifting of mask mandates on public transportation? | Fig.4 - Responders feeling towards ruling of mask mandate lifted|\nPlease consider taking the Survey here https://www.thatsgreatfeedback.com/maskmandatesapril22\nLooking at ALL respondents feedback the trend has positive sentiments closely ahead of negative sentiments, with neutral in a close third.\nQuestion Posed: 5. How do you think this decision was handled? *: By and large responders to the survey by the measue below felt\u0026hellip;\n| Fig.5 - Overall sentiment towards the news that mask mandates have been lifted|\nHow did folks Identify Our poll is anonymous but we asked the respondents to identify by impact their relationship to the topic, the feedback we got indicated:\nQuestion Posed: 4. As a personal impact by this decision. Are you a? | Fig.6 - How do people taking the survey identify|\nWhen asked how many folks would continue to war mask, the answers spanned the available responses but overwheminly respondents indicated a YES\nQuestion Posed: 3. Will you still wear a mask in public transportation? | Fig.7 - Reponders indicating whether they will continue to wear mask in public transportation|\nThe 1st 7 Days See you in a week! \u0026amp; If you have not yet\u0026hellip; Please consider taking the Survey here https://www.thatsgreatfeedback.com/maskmandatesapril22l\nThe 1st Month The 1st Quarter Continue the conversation Engage with me Click Twitter Mask Mandate 24HR Survey Report - WFH Tweet LinkedIn Mask Mandate 24HR Survey Report - WFH LinkedIn Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/maskmandatesresults/","summary":"\u003ch2 id=\"tldr\"\u003eTLDR;\u003c/h2\u003e\n\u003cp\u003eI posted on April 20, 2022 \u003cstrong\u003ethis survey\u003c/strong\u003e \u003ca href=\"https://www.thatsgreatfeedback.com/maskmandatesapril22\" title=\"Mask Mandate Lifted Survey\"\u003ehttps://www.thatsgreatfeedback.com/maskmandatesapril22\u003c/a\u003e about the news \u003ca href=\"https://www.reuters.com/legal/government/us-judge-rules-mask-mandate-transport-unlawful-overturning-biden-effort-2022-04-18/l\" title=\"Reuters News Report\"\u003eMask Mandate is lifted\u003c/a\u003e to capture feedback on how thsi affects you and the results are in!\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"The Results are in!\" loading=\"lazy\" src=\"/img/resultsareininpage.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHuge Thanks\u003c/strong\u003e to all the folks out there who took the time to fill out the brief \u003cstrong\u003e5\u003c/strong\u003e question \u003cem\u003e\u003cstrong\u003eAnonymous\u003c/strong\u003e\u003c/em\u003e survey that yielded the below results!\u003c/p\u003e\n\u003ch2 id=\"the-1st-24-hours\"\u003eThe 1st 24 Hours\u003c/h2\u003e\n\u003cp\u003eThere were \u003cstrong\u003e5 questions\u003c/strong\u003e posed and in one free from response the question asked centered around folks reaction to the \u003cstrong\u003efederal ruling to lift mask mandates\u003c/strong\u003e. By and large the sentiments from long form feedback that was collected are \u003cem\u003e\u003cstrong\u003erelatively split\u003c/strong\u003e\u003c/em\u003e in the \u003cstrong\u003e1st 24 hours\u003c/strong\u003e of responses collected.  Where we saw varying differences in opinions came from targetted questions around personal impact as well as individual actions moving foward.  A world cloud below homed in on\u003c/p\u003e","title":"Mask Mandate Survey Results"},{"content":"TLDR; Working from home can take a toll on you\u0026hellip; in many ways\u0026hellip; but one of which can be your physical health. Not something you notice immediately but perhaps end of day or perhaps over a period of a few months or heaven forbid\u0026hellip; something progressive over a longer period of time. Having a work environment that promotes healthy habits is important and that can be accomplished by injecting some mobility at your desk throughout the day as well as equipping yourselves with ergonomic fixtures such as tables and chairs. I did a blog post https://fabswill.com/blog/cultivateahealthwfh/ about my new ergonomic chair as well as a survey around the topic as well here https://www.thatsgreatfeedback.com/ergochair2survey.html \u0026ndash; The 1st 24 hours results are in\u0026hellip; see below\nHuge Thanks to all the folks out there who took the time to fill out the brief 5 question Anonymous survey that yielded the below results!\nThe 1st 24 Hours There were 5 questions posed and in one free from response the question asked centered around the evolution of how and where people worked. By and large the sentiments from those feedback collected was overwhelmingly positive in the 1st 24 hours of responses collected. A world cloud below homed in on\nPeople Balance Life Overall Sentiments Out of the 5 questions posed, there was 1 open ended question and I keyed off that for a lot of the analysis, here is a snapshot of the top 10 anonymous feedback provided\nI was happy to see that people really shared their unique and individual perspectives candidly, sentiments were highly subjective \u0026amp; as a testament to the above word cloud, the polarity index trended in a positive direction overall.\nWe saw seventy five percent 75% positive sentiments with 12.5% negative responses based on our NLP model.\nCorollaries The blog post really centered around Physical Wellbeing and argued that ergonomic fixtures such as Tables, Chairs, Keyboards, Mouse, etc., really promotes a positive position towards physical wellbeing in the office. One centerpiece question centered around whether employers and companies should treat work from home/WFH employees equitable to their colleagues that come into the office. The argument being that usually you will find office furniture inside the office a better quality and also more ergonomically sound to encourage and promote a happier and more productive work environment.\nThere was a corollary in that respondents to the survey overwhelmingly said Absolutely and/or Possibly with no one yet taking the position of No\u0026hellip; I suspect the 16 folks in this 24 hour of survey taking are mainly Employees and not Employers ??? Dunno\nPlease consider taking the Survey here https://www.thatsgreatfeedback.com/ergochair2survey.html\nWhen asked how many folks either have an Ergonomic WFH setup or considering one, the results were 50-50, so even folks that didn’t have the benefit of this WFH Ergo setup, understood the value and took the position of equity for WFH employees\nFurthermore, when asked how many meetings folks had over the period of one week, you can see that most respondents are having Over Ten per week. I can only encourage those folks to as best you can\nStand up for some of those meetings Of-course sit for those you can, or have to base on your role and what you are doing in the meeting In between meetings, take a walk, stretch, move around\u0026hellip; 10 per week is a lot. I am in that category myself, there are time I have 10 per day! and those are not fun \u0026#x1f604; fortunately that is more the exception than the rule and is usually tied to an event we are planning or an program I am running with external participants that span the globe in terms of geography and time zones.\nThe 1st 7 Days See you in a week! \u0026amp; If you have not yet\u0026hellip; Please consider taking the Survey here https://www.thatsgreatfeedback.com/ergochair2survey.html\nThe 1st Month The 1st Quarter Continue the conversation Engage with me Click Twitter Cultivate a healthy Work from Home - WFH Tweet LinkedIn Cultivate a healthy Work from Home - WFH LinkedIn Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/surveyergowfhresults/","summary":"\u003ch2 id=\"tldr\"\u003eTLDR;\u003c/h2\u003e\n\u003cp\u003eWorking from home can take a toll on you\u0026hellip; \u003cem\u003e\u003cstrong\u003ein many ways\u003c/strong\u003e\u003c/em\u003e\u0026hellip; but one of which can be your physical health. Not something you notice immediately but perhaps \u003cem\u003e\u003cstrong\u003eend of day\u003c/strong\u003e\u003c/em\u003e or perhaps over \u003cem\u003e\u003cstrong\u003ea period of a few months\u003c/strong\u003e\u003c/em\u003e or heaven forbid\u0026hellip; something progressive over a longer period of time. Having a work environment that promotes healthy habits is important and that can be accomplished by injecting some mobility \u003cem\u003e\u003cstrong\u003eat your desk\u003c/strong\u003e\u003c/em\u003e throughout the day as well as equipping yourselves with \u003cstrong\u003eergonomic\u003c/strong\u003e fixtures such as tables and chairs.\nI did a \u003cstrong\u003eblog post\u003c/strong\u003e \u003ca href=\"https://fabswill.com/blog/cultivateahealthwfh/\" title=\"ErgoChair2 Blob Post\"\u003ehttps://fabswill.com/blog/cultivateahealthwfh/\u003c/a\u003e about my new \u003ca href=\"https://www.autonomous.ai/office-chairs/ergonomic-chair?msclkid=af1f04b8adc611ec874ca2d532dbfe3f\" title=\"SmartDesk Pro\"\u003eergonomic chair\u003c/a\u003e  as well as a \u003cstrong\u003esurvey\u003c/strong\u003e around the topic as well here \u003ca href=\"https://www.thatsgreatfeedback.com/ergochair2survey.html\" title=\"ErgoChair2 Survey\"\u003ehttps://www.thatsgreatfeedback.com/ergochair2survey.html\u003c/a\u003e \u0026ndash; The 1st 24 hours results are in\u0026hellip; see below\u003c/p\u003e","title":"ErgoChair 2 Survey Results"},{"content":"TLDR; I am now at the time of writing this paragraph 3 days in from replacing my 4-year-old office chair to a new Autonomous Smart Office ErgoChair 2 and so far I am impressed with the features and working my way through using them properly. What do I mean by that? Well, the chair is super customizable in terms of the usual, height, arm rest positions, but it also has customizable features for lumbar support and headrest to name a few. If like me you spend a large part of your day sitting in front of computer monitors, hammering away at a keyboard and want to see/hear about this experience? keep reading\u0026hellip;\nOh\u0026hellip; by the way, besides FEDEX just chucking the box \u0026#x1f621; in the middle of my driveway for delivery More to come on that below, this was a really pleasant unboxing \u0026amp; setup experience.\nProper posture and mobility Out of the 24 hours we are given in a day, if we spend 8 hours at work, that’s already 1/3rd of the hours in the day. With that acknowledgement if we take the time to manage our physical wellbeing, surely that will lead to a healthier life. While a large segment of the population got thrown into a Work from home, or hybrid, or remote workforce, for some of us, me included, have been doing this for years, even a decade perhaps. In a corporate workplace setting, it’s not uncommon for the facilities management to supply the workforce with ergonomic workplace furniture and accessories, in fact my 1st ergonomic device was a keyboard and mouse. Nowadays however circa 2020 and beyond Home Offices are now adorned with a Smart Office appeal, be it a portable desk that raises and lowers allowing you to sit or stand, a chair that provides back and neck support, and even memory foam mats used when standing for prolonged periods are now normal everyday fixtures. Some of the negative effects of bad posture as cited in a article reviewed by Williams Morrison M.D. includes:\nSciatic Herniated disc Muscle strain Degenerative disc disease and Spinal stenosis the circulatory system may also be impacted as well. In an article from Texas A\u0026amp;M\u0026rsquo;s Ruth Bush, M.D., J.D., M.P.H. vice dean and professor of surgery, spoke to preventing circulation problems on the job citing deep vein thrombosis (DVT), spider veins, and varicose veins as some of the negative effects of posture, shoes, and being \u0026lsquo;chained to the desk\u0026rsquo; so to speak. Having a proper posture, I have found, allows you to feel less tired at the days end, less pain, less stiffness\u0026hellip; then again.. I’m getting old\u0026hellip; but the chair does help \u0026#x1f604;\nWhy is this important to you Equipping yourself with an ergonomic desk, chair, and practicing proper posture and \u0026lsquo;work exercises\u0026rsquo; that can be done at your desk, is a great way to mitigate the aforementioned negative impacts of lack of mobility and bad posture at the workplace, no matter if it’s on site at an office or more so, at home where you actually spend the rest of your time when not in the home-office. Now that you are not traipsing to the conference room anymore, you are holding meetings at your desk but perhaps on a larger mounted monitor\u0026hellip; the 20 degrees recline is a splendid feature to allow for a somewhat relaxed alertness. \u0026#x1f60a;\nIn this post we will look at the ErgoChair 2 from Autonomous which is the 2nd item I acquired from them. I am also a happy owner of their 70.5\u0026quot; x 30\u0026quot; XL Classic SmartDesk Pro for almost a year now. The chair is a great compliment to the desk, I have not found a bad position for the chair no matter what elevation I have the desk, the two really feels as one.\nOrdering Experience The one thing that struck me with the ordering experience is the ease, very few steps, easy configuration for options and the cherry on top if your company has a relationship with them, you can use your work email address to get as you will see below (emoji for pointing down) special pricing.\nThe rest is standards stuff, you get an email confirming your order with a link to your order, later you also get a link to the tracking\u0026hellip; which on both occasions of me ordering something from Autonomous I have had an unpleasant experience with their shipper\u0026hellip; FedEx. See the -Behind the Scenes- section below for more details on that fiasco \u0026#x1f621;\nDelivery Experience * My shipments origin was from New York, and I am also on the East Coast of the United States, my estimated delivery was within a week\u0026hellip; I was incredibly pleased, but that smile was about to turn to gloom as in the previous time they shipped with FedEx on the day of delivery, the package still showed as in New Jersey. Upon calling FedEx, sure as rain on a cloudy day, they cited that the package is delayed due to staffing issues, I should be grateful, because the last time, they said the package was lost in transit. Nevertheless, the package came 2 days later than the stated delivery date, but I got it. You would think the story ends there wouldn’t you? Alas no.\nUnboxing \u0026amp; Setup The packaging by Autonomous is excellent.\nNot only are the contents packed in a sturdy box capable of withstanding *FedEx chucking it and leaving it in the middle of my driveway in the elements, but everything is laid out with meticulous mindfulness. The contents are either:\nbubble wrapped encased in cardboard and protected by packing materials taped encased in a protected packing material and bubble wrapped and taped a combination of all the above The simplicity of design should also be called out, the entire contents in the box are 6 pieces including the box with the tools and screws. Once fully unpacked, there are eight (8) pieces\nBackrest Headrest Seat Castors (wheels) Control Mechanism Gas lift Armrest (x2) Base and the bolts to assemble the unit \u0026ldquo;even though my manual says it’s a combination of M6\u0026rsquo;s and M8\u0026rsquo;s\u0026rdquo; all mines were M6\u0026rsquo;s which made assembly a breeze since I\u0026rsquo;m essentially using 1 screwdriver/bolt.\nThere are some helper videos on YouTube as well, in fact, rather than relying on the manual that comes with, I found that the YouTube vids are more up to date and reflective of what is shipped v/s what the manual purports.\n1 Week in\u0026hellip; After a few days of drafting I am now 1 week in and I’m pleased! No complaints on the chair, even if I am being lazy and not abiding by the proper posture techniques, the lumbar support actually if very forgiving there and still provides support, at times I have to remember about the headrest, I did not have one of those before and it can be a bit hard to remember to sit back and type with my head on the rest and arms relaxed on the arm rest as I type away\u0026hellip; but once I make a conscious effort as I am doing now while typing this paragraph, I feel like I can go on forever. This is not a sales pitch, I am not getting one penny from this review, but if you crowdsourced folks you know with office chairs to make up your mind if you are in the market, hopefully this post will provide you with some input in that decision making process.\n5 Question Feedback Survey I would be extremely interested in your feedback on this topic, would you be do kind to complete a brief 5 question survey that will take you less than 1 minute to do? Please click the link here \u0026amp; thank you! \u0026ndash;\u0026gt; https://www.thatsgreatfeedback.com/ergochair2survey.html\nContinue the conversation Engage with me Click Twitter Cultivate a healthy Work from Home - WFH Tweet LinkedIn Cultivate a healthy Work from Home - WFH LinkedIn Or use the share buttons at the top of the page! Thanks\nBehind the scenes FedEx, FedEx, FedEx\u0026hellip; you could have left it by the door, or closer to the garage\u0026hellip; why, why.. in the middle of the driveway where there is no cover?\nSurely this is not representative of your standards for delivery?\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/cultivateahealthwfh/","summary":"\u003ch2 id=\"tldr\"\u003eTLDR;\u003c/h2\u003e\n\u003cp\u003eI am now at the time of writing this paragraph 3 days in from replacing my 4-year-old office chair to a new \u003ccode\u003eAutonomous Smart Office ErgoChair 2\u003c/code\u003e and so far I am \u003cstrong\u003eimpressed\u003c/strong\u003e with the features and \u003cem\u003e\u003cstrong\u003eworking my way through\u003c/strong\u003e\u003c/em\u003e using them properly. What do I mean by that? Well, the chair is super customizable in terms of the usual, height, arm rest positions, but it also has customizable features for lumbar support and headrest to name a few. If like me you spend a large part of your day sitting in front of computer monitors, hammering away at a keyboard and want to see/hear about this experience? keep reading\u0026hellip;\u003c/p\u003e","title":"Cultivate a healthy Work from Home - WFH"},{"content":"TLDR; A few weeks ago in a corporate team sync one of my colleagues presented information around Microsoft Clarity and I was totally blown away in it\u0026rsquo;s capabilities as well as its ease of use. According to Microsoft Clarity is a behavioral analysis tool that helps you understand user interactions within your website. I use it to do just that especially for knowing where my users come from, and how they are engaging my content, want to see/hear about my experiences? keep reading\u0026hellip;\nTelemetry tells the tale The aforementioned simplicity is evident right from the start. When you sign up/sign in and have no projects, you are immideately taken to the projects screen where you can create your first project which is a three (3) question dialog box asking for the project name, the website URL, and for you to pick from a list of category for the type of site, I imagine the reason is to determine what telemetry settings and baseline values to show you. It does take a few hours for the crawl to take place and the metrics start to come in, but once it does\u0026hellip; really revealing stuff as seen below By far one of the things that really caught my eye was the Recordings which shows you the actual gestures such as scrolling, clicks, etc that the visitor of your site took. The Heatmap feature of Clarity is something I have not dove into yet but I understand it is a great way to analyze user behavior in an aggregated manner. Once you onboard to Clarity and land onto Heatmaps, Clarity generates heat maps for popular pages.\nI do love this quote from the folks running the social for Clarity below:\nFree. Forever\u0026hellip;\n— @msftClarity[^1]\nThe magic is that engine that is under the hood of Clarity, I cant wait to dig deeper! Chat about this? Engage with me Click Twitter Socializing Clarity Tweet LinkedIn LinkedIn Post on Clarity Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/clarityandbing/","summary":"\u003ch2 id=\"tldr\"\u003eTLDR;\u003c/h2\u003e\n\u003cp\u003eA few weeks ago in a corporate team sync one of my colleagues presented information around \u003ccode\u003eMicrosoft Clarity\u003c/code\u003e and I was totally \u003cstrong\u003eblown away\u003c/strong\u003e in it\u0026rsquo;s capabilities as well as its ease of use. According to Microsoft \u003ca href=\"https://clarity.microsoft.com\" title=\"Microsoft Clarity\"\u003e\u003cstrong\u003eClarity\u003c/strong\u003e\u003c/a\u003e is a behavioral analysis tool that helps you understand user interactions within your website. I use it to do just that especially for knowing where my users come from, and how they are engaging my content, want to see/hear about my experiences?  keep reading\u0026hellip;\u003c/p\u003e","title":"Understand and Improve our Website value through Microsoft Clarity \u0026 Bing"},{"content":"What this is and what this is not This is something new I am trying, this is for me to come back to when I have bad days, when I need to re-focus, and even when I have good days. It is not a goals list, and it not meant to be a retrospective list for 2023. I am going to list 3 things each year that I will try to build upon based on where I am now and where I aspire to be.\nmantra qui non proficit deficit\n— Old Latin saying\nqui non proficit deficit is a saying I have engrained in me since high school at St. Georges College. Loosely translated it means \u0026ldquo;he who does not move forward moves backwards\u0026rdquo; but the more literal meaning and the one I hold is \u0026ldquo;who does not advances looses ground\u0026rdquo; which is more meaningful because you do not have to move backwards to loose ground\u0026hellip; if you stand still and those around you advance, you automatically loose ground in the larger picture.\nI like 3\u0026rsquo;s when I need to do something, no\u0026hellip; its not quite OCD, its proven out by others. See the \u0026ldquo;3 rules of 3\u0026rdquo; by Alan Alda here\nsay no more than 3 points say difficult (important) things 3 different ways say difficult (important) things 3 times Remember Prioritize physical and mental health - drink more water, eat healthier food, be more meditative Be Intentional - focus on the right things at the appropriate time Employ First Principle thinking - Break things down to its lowest denominator and reason upwards 1 - Prioritize physical and mental health It is proportionally difficult to take care of others if you yourself need to be taken care of\n— Fabianism circa 2022\n2 - Be Intentional If 2020 and 2021 taught us anything, one of its lessons surely must be that time is a precious commodity, use your time efficiently and focus on what has greater impact\n— Fabianism circa 2022\n3 - First Principle Thinking Well, I do think there’s a good framework for thinking. It is physics. You know, the sort of first principles reasoning. Generally I think there are — what I mean by that is, boil things down to their fundamental truths and reason up from there, as opposed to reasoning by analogy\n— Elon Musk1\nEngage with me Click Twitter Top 3 List of 2022 Tweet LinkedIn Top 3 List of 2022 LI Post Cheers! Fabs\nThe above quote is excerpted from Elon Musk\u0026rsquo;s interview on Medium, August 30, 2017.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://www.fabswill.com/blog/2022top3journey/","summary":"\u003ch2 id=\"what-this-is-and-what-this-is-not\"\u003eWhat this is and what this is not\u003c/h2\u003e\n\u003cp\u003eThis is something \u003cstrong\u003enew\u003c/strong\u003e I am trying, this is for me to come back to \u003cem\u003e\u003cstrong\u003ewhen I have bad days\u003c/strong\u003e\u003c/em\u003e, \u003cem\u003e\u003cstrong\u003ewhen I need to re-focus\u003c/strong\u003e\u003c/em\u003e, and even \u003cem\u003e\u003cstrong\u003ewhen I have good days\u003c/strong\u003e\u003c/em\u003e. It is \u003cstrong\u003enot a goals list\u003c/strong\u003e, and it not meant to be a retrospective list for 2023. I am going to \u003cstrong\u003elist 3 things each year that I will try to build upon based on where I am now and where I aspire to be\u003c/strong\u003e.\u003c/p\u003e","title":"2022 Top Three Journey"},{"content":"TLDR; If you are ever in the unfortunate situation where your token thats issued when you create an Azure Static Web App is unobtainable or destroyed and you are trying to CI/CD from your Repo in GitHub you will get an error in your deployment pipeline in GitHub Actions. To remedy the issue you can reset your Token in the Azure Portal and then create a new GitHub Secret in the Repo with the new reset token GUID and you will be all sorted. Want to see how, keep reading\u0026hellip;\nHow did I get here My story begins when I was unable to log into my GitHub account and had Multi-Factor Authentication turned on, I had personal access tokens but none of the 15-something I had in my text file would work so I contacted GitHub support. Long story short, while they were professional and communicative, they did not help me much\nNB Once your account is released you will loose all of your Private Repos\u0026hellip;\n— GitHub Support[^1]\nIn the end I did provide proof of who I am and within minutes, my old accoutn was released, I created a new one, and poof Im back again under https://github.com/fabianwilliams\nWhere my CI/CD Failed Another side effect of that is that GitHub Secrets that were in any private Repo is now invaidated and any CI/CD pipeline will fail, if you did create a new Repo under the old name, yes the names will match so the pipeline will start but once it gets to the deployment check for tokens, unless you set it to skip that check you are toast!\nHow to Remedy The remedy for this is not that hard actually and there is a great blog post that talks you through it located here Reset deployment tokens in Azure Static Web Apps\nLesson Learned If you enable MFA in GitHub and you have CI/CD going on or anything like WebHooks, Automation Tasks that uses Tokens/Secrets do back them up in multiple places to be safe and even generate new ones to be safe. In my case I did have personal tokens but they did not work and one reason could be that I used them all up before without getting new ones IDK really. But I did spend like 2 days looking in 3 different computers locally and even several OneDrive and Google Drives to see if i stored any there. The fact that you are reading this blog post shows that I am up and running again. Let my pain not be your pain.\nChat about this? Engage with me Click Twitter Static WebApp CICD Gotcha LinkedIn Static WebApp CICD Gotcha Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/cicdgotchastaticwebapps/","summary":"\u003ch2 id=\"tldr\"\u003eTLDR;\u003c/h2\u003e\n\u003cp\u003eIf you are ever in the \u003cstrong\u003eunfortunate situation\u003c/strong\u003e where your \u003ccode\u003etoken thats issued when you create an Azure Static Web App is unobtainable or destroyed\u003c/code\u003e and you are trying to CI/CD from your Repo in GitHub you will get an \u003cstrong\u003eerror in your deployment pipeline\u003c/strong\u003e in GitHub Actions. To remedy the issue you can \u003cem\u003e\u003cstrong\u003ereset your Token in the Azure Portal and then create a new GitHub Secret\u003c/strong\u003e\u003c/em\u003e in the Repo with the new reset token GUID and you will be all sorted. Want to see how, keep reading\u0026hellip;\u003c/p\u003e","title":"Gotcha with CICD and Azure Static WebApps"},{"content":"TLDR; A few days ago I set out for a walk to start my Boxing Day 2021 (December 26) \u0026amp; as usual I donned my AppleWatch and my AirPods to listen to my walk/run playlist as I log my journey on the Strava app. As circumstance would have it I got a new iPhone over the holidays and had to redo the process of pairing my ancilliary devices such as my AirPods. By setting up my AirPods with iOS 15 I saw options that permitted me to enhance the sounds that surrounds me that I did not see when I originally set up my AirPods Pro more than 2 years ago. Succintly put, I was able to have bionic ears, I was able to hear the leaves blowing on the streets, at one point I thought I was being followed \u0026#x1f60a; I was able to hear all of nature ahead of seeing any movements, and I was also able to hear distant children playing \u0026amp; automobile activity.\nHow to set up Transparency Mode on Apple AirPods Pro The secret sauce in all of this is the Apple AirPods Pro which have been my go-to noise cancelling device for the last 2 years\u0026hellip; as an aside, I used an over the ear Bose Quiet Comfort II for around 10 years before that and loved it, but rather than go with the Bose ear buds or other competing brands, I felt that because I am already all-in on the Apple ecosystem that I sould give the AirPods a chance and I am glad i did.\nWhile this can be accomplished with over the ear headphones and certainly other brands, this is the process if you have a Apple AirPods Pro. There are basically 5 steps to getting this set up:\nSetting up a Customized AirPods Pro Transparency Mode in iOS Settings app: Go to Accessibility then click AirPods Airpods screen: Click Audio Accessibility Settings Audio Accessibility Settings screen(AKA Audio/Visual) screen: click Headphone Accomodations Headphone Audio screen: Adjust for your desired settings for Tuning and Transparency Mode Transparency Mode screen: Adjust for your desired settings Follow along in the screen shots below Setting Image Settings Airpods AKA Audio/Visual Headphone Audio Headphone Audio 2 Transparency Mode In Summary I was totally amazed by the experience, I felt a connection to the surroundings like I have never felt before. I indeed listened to more than I would have normally be intuned to and got a better appreciation of my exercise path than I thought it was before. One side effect of hearing so much around you that was quite profound in terms of human interations was that I said \u0026ldquo;hi\u0026rdquo; more to people as I was able to hear them, and in most intances actually hear their conversations leading up to actually walking pass them, this awareness made me more inclined to wave and say Hi! more than if I was zoned out to music or a podcast that would have had my attention and potentially even drown out any gestures from passersby.\nWill I continue to do this instead of listening to my playlist? I dont know, and perhaps I will just mix it up, but for now I can say what usually would be a 50 minute 5K walk turned into a 65 minute 5K walk as I really slowed down, payed more attention to my surroundings and trully enjoyed the walk more than my previously\u0026hellip;lets just get the steps and calories count routine. \u0026#x1f61c;\nChat about this? Engage with me Click Twitter TAKE YOUR OUTDOOR WALK TO THE NEXT LEVEL LinkedIn TAKE YOUR OUTDOOR WALK TO THE NEXT LEVEL Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/mindfulwalk/","summary":"\u003ch2 id=\"tldr\"\u003eTLDR;\u003c/h2\u003e\n\u003cp\u003eA few days ago I set out for a walk to start my Boxing Day 2021 (December 26) \u0026amp; as usual I donned my AppleWatch and my AirPods to listen to my walk/run playlist as I log my journey on the Strava app. As circumstance would have it I got a new iPhone over the holidays and had to redo the process of pairing my \u003ccode\u003eancilliary devices\u003c/code\u003e such as my \u003cstrong\u003eAirPods\u003c/strong\u003e. By setting up my AirPods with iOS 15 I saw options that permitted me to \u003cem\u003e\u003cstrong\u003eenhance the sounds that surrounds me that I did not see when I originally set up my AirPods Pro more than 2 years ago\u003c/strong\u003e\u003c/em\u003e. Succintly put, I was able to have \u003cstrong\u003ebionic ears\u003c/strong\u003e, I was able to hear the leaves blowing on the streets, at one point I thought I was being followed \u0026#x1f60a; I was able to hear all of nature ahead of seeing any movements, and I was also able to hear distant children playing \u0026amp; automobile activity.\u003c/p\u003e","title":"Take your outdoor walk to the next level"},{"content":"Why you should read this post Do you find yourself thinking \u0026#x1f914; wouldnt it be easy to just copy an event on your calendar and paste it to a new location if everything is the same except the time you need it? Well, I tried to do that and from the calendar in the regular thick Outlook Client and I was not able. Later on however after some research I did find an option if I used Outlook Web Access (OWA) or Outlook Progressive Web App (PWA) to Duplicate Event as seen below which gets me what to what I wanted to do. So this works for you, you can stop reading here \u0026#x1f604; if however you only use the regular thick client\u0026hellip; keep reading.\nHowever, if you select the option to use OWA/OPA this means additional clicks, find my event, right click, duplicate, and still have to change dates etc. So, I as opted for another option, this one is a running list of Postman Calls in a personal collection that I fire off when I need to do things in Microsoft 365 employing the Microsoft Graph. In this case I have a POST to https://graph.microsoft.com/v1.0/me/events that takes a request body of what I want to duplicate and all I need to do is change the date. In the below example I am doing it from Graph Explorer which you can get from aka.ms/ge but it\u0026rsquo;s the same process as in Postman except you need to get your token via postman in a more obscure manner \u0026#x1f604;\nNB The above assumes that you are using Microsoft 365, Exchane Online and have access to Graph Explorer, otherwise you can do the same with the aforementioned \u0026ldquo;Duplicate Event\u0026rdquo; in OWA/PWA\nBy sending a POST to the Graph Create Events URI, you can see now that I have dupliced the top event in the bottom with a subtle change in the Subject as well as a different time and length. That required me to make 3 total changes:\nChange the Subject Change the Start Time Change the End Time And with that I now have this:\nIf you also would like to play around and learn more about the Microsoft Graph please visit our website for more details.\nSummary The above was accomplished by using examples that you can extrapolate from in our docs specifically Create Event Let me know if this is something you find useful or not at all, also is this a scenario that you find yourself in? and how do you manage it?\nChat about this? Engage with me Click Twitter @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/blockyourtimewithgraph/","summary":"\u003ch2 id=\"why-you-should-read-this-post\"\u003eWhy you should read this post\u003c/h2\u003e\n\u003cp\u003eDo you find yourself thinking \u0026#x1f914; wouldnt it be easy to just copy an event on your calendar and paste it to a new location if everything is the same except the time you need it? Well, I tried to do that and from the calendar in the regular thick Outlook Client and I was not able.  Later on however after some research I did find an option if I used \u003ca href=\"https://support.microsoft.com/en-us/office/get-help-with-outlook-on-the-web-cf659288-35cc-4c6c-8c75-e8e4317fda11\" title=\"Outlook on the Web\"\u003eOutlook Web Access\u003c/a\u003e (OWA) or \u003ca href=\"https://support.microsoft.com/en-us/office/use-the-web-version-of-outlook-like-a-desktop-app-b360bd9a-00dc-43a4-bdf8-71cdeeb78e83\" title=\"PWA\"\u003eOutlook Progressive Web App\u003c/a\u003e (PWA) to \u003cstrong\u003eDuplicate Event\u003c/strong\u003e as seen below which gets me what to what I wanted to do. So this works for you, you can stop reading here \u0026#x1f604; if however you only use the regular thick client\u0026hellip; keep reading.\u003c/p\u003e","title":"Manage your Time with Graph in Calendar Events"},{"content":"Why you should read this post Are you contemplating \u0026#x1f914; or have you built a Static Web Application using Microsoft Azure Static Web Apps and do you plan to use an Apex Domain as a part of your URL. \u0026#x1f633; In plain english that means do you plan to access your website by using https://sitenamehere.com without the www? If so then keep reading please. \u0026#x1f60c; For what should be a simple task, I faced a GOTCHA \u0026#x1f525; on 2 different levels that I\u0026rsquo;d like to share with you, Ive outlined them below, even though I have listed 3 items below the 3rd is more of an observation:\nIf your non Microsft Azure DNS hosting provider does not support creating an ALIAS record for apex domains, you will have problems If you are using Azure DNS Zones \u0026lsquo;and\u0026rsquo; you have your Azure Static Web App in a different subscription from your DNS zone, you will have problems (observation)If you have your own certificate and you want to use it rather than the managed one Azure gives you (as of the time of this writing), it will not work. Its managed only as opposed to what you can do with a regurlar Azure Web App. My situation may be similar to yours I use godaddy as my DNS provider and its not something I plan to change anytime soon, in fact most of my needs have been met for websites I host because I have been able to roll my own SSL certificates in the standard Web Apps that I used to host all of my sites in Microsoft Azure. FWIW I usually employ Wordpress blog sites. However a few weeks ago I decided to slim down and use Azure Static Web Apps as you can read in my A New Day blog post which changed the platform an how I go about managing my site. Another thing I like to do is to use an Apex domain as one way actually the chief way to get to my site, why\u0026hellip; \u0026#x1f914; its because its a shorter url to type and it\u0026rsquo;s cleaner. Anyway, thats my set up for the perils to come and how I solved them. The main point of this post is how to solve for the Apex domain in Azure so I will just tell you now that you cannot do an ALIAS record in GoDaddy (again, at the time of this writing)\nfor 1, when you select A Record you can only do IP4 Addresses and if you try, you get the below\nWhich means I have to do this elsewhere, where you may ask? Well lets try out Azure DNS.\nSpinning up DNS Zones using Azure DNS This is litterally too easy and you can find out how to do it here. I\u0026rsquo;ll also use this opportunity to show you my resulting DNS records from Azure DNS once I got it working below: Notice I have both a CNAME record pointing to my www whilst I also have a @ pointing to my ALIAS record on my Static Web App instance. Now the DOCS for how to set up the ALIAS record is quite explicit, simple steps and it has a tab to show you how to do it in Azure DNS or \u0026ldquo;Other DNS\u0026rdquo; for external. However, this is were for me it started to unravel \u0026#x1f621;\nWhat the Docs do not tell you NB In my Azure envionment, I have my Static Web App in lets call it Subscription A and I have my DNS Zones \u0026lsquo;originially\u0026rsquo; set up in Subscription B\nIf you are unfamiliar with what Azure Subscrptions are, think of them as seperate islands where your billing and assets reside, one does not see the other without you setting Role Assignments in essence inviting access from one to the other. But this is where I have an issue with how the flow is set up for creating ALIAS records in Azure Static Web Apps, because\u0026hellip; I can select across my subscriptions, and I can see from one to the other in the configuraiton, its upon execution where things go hella wrong! Note the callouts below in Choose a subscription and Azure resource however when I click \u0026ldquo;OK\u0026rdquo; I got the below error: and if you inspect the activity logs to get more details you will see: How I went about and ulitmately fixed it Well, I can tell you we have excellent support directly from the Azure Portal here at Microsoft, I used it, and got feedback to my problem in less than 1 hour. Ive redacted only the Subscription A and Subscription B details but you can pretty much see what they suggested as a resolution which would work but I didnt want to bridge the islands of Subscriptions. I have/had no reason to keep a DNS Zone in that subscription, it is quite simplier to just move the DNS Zone to the subscription that I have my Static Web App in. I did this by simply clicking on the resource and selecting \u0026ldquo;MOVE\u0026rdquo; and pointed it to my other subscription I waited for a few minutes and bing bang boom\u0026hellip; Summary With those actions cited in the previous section I was able to resolve this issue, I no doubt believe that others may see this problem and is the reason I am blogging it. If the error was more descriptive than just Internal Error then I might not have but I hope this helps someone to spend minutes and not hours troubleshooting this issue. Now I have an Apex domain friendly URL at https://fabswill.com - go check it out please! \u0026#x1f60a; Chat about this? Engage with me Click Twitter @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/azurestaticwebappdnsgotcha/","summary":"\u003ch2 id=\"why-you-should-read-this-post\"\u003eWhy you should read this post\u003c/h2\u003e\n\u003cp\u003eAre you contemplating \u0026#x1f914; or have you built a Static Web Application using \u003ccode\u003eMicrosoft Azure Static Web Apps\u003c/code\u003e and do you plan to use an \u003ccode\u003eApex Domain\u003c/code\u003e as a part of your URL. \u0026#x1f633;  In plain english that means do you plan to access your website by using \u003ca href=\"https://sitenamehere.com\"\u003ehttps://sitenamehere.com\u003c/a\u003e without the \u003cstrong\u003ewww\u003c/strong\u003e? If so then keep reading please. \u0026#x1f60c; For what should be a simple task, I faced a \u003cstrong\u003eGOTCHA\u003c/strong\u003e \u0026#x1f525; on 2 different levels that I\u0026rsquo;d like to share with you, Ive outlined them below, even though I have listed 3 items below the 3rd is more of an observation:\u003c/p\u003e","title":"Azure Web App DNS Gotcha"},{"content":"Why you should read this post If you are interested in Microsoft Graph and how it can work with Python this post gives two examples of an art of the possible. In this post i will be addressing the following topics:\nUsing MSAL libraries in Python Using 2 different Authentication Flows to gain access to Microsoft Graph resources Bonus - Access to my GitHub repo where you can get the code as well as a Jupyter Notebook to runs this on your own Wiring this all up This is not very onerous, in fact if you have ever played with Python, its the simplicity that is really astounding. Basically you need to work the the below libraries to get this sorted:\nMicrosoft Authentication Library - used to do the authentication to Azure Active Directory which is needed for getting the token needed for Microsoft Graph Requests - needed to send your calls to the URI endpoints JWT (Optional) - for token display and handling demo purposes only Pandas (Optional) - used for displaying my payload returned from the graph in a Dataframe (Think excel rows) import msal import jwt import json import requests import pandas as pd from datetime import datetime from configparser import ConfigParser config = ConfigParser() config.read(\u0026#39;config.ini\u0026#39;) I also employ json, datetime, and configparser for utilities within my code and I will explain why as I go along. I will be showing 2 methods of approach here as mentioned. App Permission to retrieve a list of users from the Graph as well as Delegated Permission using Device Flow authentication to do the same.\nUsing Application Permission The things to pay close attention to in the below code snippet is teh msal.ConfidentialApplication. Thats why you should always use the Graph SDK, this one line of code in additonan to the \u0026ldquo;accessToken\u0026rdquo; acquiring th token under the \u0026ldquo;try\u0026rdquo; block is responsible for all the magic. Specifically, I am using Client Credential Provider Auth Flow and supplying it the identification of the App using the Client ID and Secret. Want more details on Auth Flow click here please\ndef msgraph_auth(): global accessToken global requestHeaders global tokenExpiry tenantID = config[\u0026#39;apppermissiononly\u0026#39;] [\u0026#39;tenantID\u0026#39;] authority = config[\u0026#39;apppermissiononly\u0026#39;] [\u0026#39;authority\u0026#39;] + tenantID clientID = config[\u0026#39;apppermissiononly\u0026#39;] [\u0026#39;clientID\u0026#39;] clientSecret = config[\u0026#39;apppermissiononly\u0026#39;] [\u0026#39;clientSecret\u0026#39;] scope = [\u0026#39;https://graph.microsoft.com/.default\u0026#39;] app = msal.ConfidentialClientApplication(clientID, authority=authority, client_credential = clientSecret) try: accessToken = app.acquire_token_silent(scope, account=None) if not accessToken: try: accessToken = app.acquire_token_for_client(scopes=scope) if accessToken[\u0026#39;access_token\u0026#39;]: print(\u0026#39;New access token retreived....\u0026#39;) requestHeaders = {\u0026#39;Authorization\u0026#39;: \u0026#39;Bearer \u0026#39; + accessToken[\u0026#39;access_token\u0026#39;]} else: print(\u0026#39;Error Caught: Check the Config File to make sure tenantID, clientID and clientSecret is correct\u0026#39;) except: pass else: print(\u0026#39;Token retreived from MSAL Cache....\u0026#39;) return except Exception as err: print(err) def msgraph_request(resource,requestHeaders): # Request results = requests.get(resource, headers=requestHeaders).json() return results Next its a matter of calling those functions, one for the Auth, and the ther to get the query results.\n# Call the Authenticate against Graph Function msgraph_auth() #going after the V1 endpoint for users queryResults = msgraph_request(graphURI +\u0026#39;/v1.0/users\u0026#39;,requestHeaders) # Send the results to a Pandas Dataframe try: df = pd.read_json(json.dumps(queryResults[\u0026#39;value\u0026#39;])) # set ID column as index in Pandas Dataframe df = df.set_index(\u0026#39;id\u0026#39;) # print the entire datafarame from Pandas print(str(df)) #print(str(df[\u0026#39;displayName\u0026#39;] + \u0026#34; \u0026#34; + df[\u0026#39;mail\u0026#39;])) except: print(json.dumps(queryResults, indent=2)) Watch it run One you invoke the python executable you get the token and Pandas gives you a beautiful dataframe to see the results. Using Delegated (Interactive) Permission So, in delegated, we are not running unattended, we do need to authentiate. In this scenario we are going to use \u0026ldquo;Device Code\u0026rdquo; Auth Flow. This means that when we need to get the token, AAD will challenge us to enter a code at a certain URL, we will need to authenticate using our credentials and consent to the Application and scope it is asking for. We\u0026rsquo;re also using the PublicClientApplication here using just the Client ID, everything else for this Auth, we will explicitly consent for. See below\u0026hellip;\napp = msal.PublicClientApplication(clientID, authority=authority) flow = app.initiate_device_flow(scopes=SCOPES) if \u0026#39;user_code\u0026#39; not in flow: raise Exception(\u0026#39;Failed to create device flow\u0026#39;) print(flow[\u0026#39;message\u0026#39;]) then we pretty much make the same calls as before except for our token we are asking for it via device flow andd we inspect the acccess token in our callback and go to town getting our results.\nresult = app.acquire_token_by_device_flow(flow) if \u0026#39;access_token\u0026#39; in result: result = requests.get(f\u0026#39;{ENDPOINT}/users\u0026#39;, headers={\u0026#39;Authorization\u0026#39;: \u0026#39;Bearer \u0026#39; + result[\u0026#39;access_token\u0026#39;]}).json() #Going after a specific user Diego S #result = requests.get(f\u0026#39;{ENDPOINT}/users/fa2480cc-103b-4b53-8ba6-da9720c81c2d/presence\u0026#39;, headers={\u0026#39;Authorization\u0026#39;: \u0026#39;Bearer \u0026#39; + result[\u0026#39;access_token\u0026#39;]}) #result.raise_for_status() #print(result.json()) df = pd.read_json(json.dumps(result[\u0026#39;value\u0026#39;])) # set ID column as index in Pandas Dataframe df = df.set_index(\u0026#39;id\u0026#39;) # print the entire datafarame from Pandas print(str(df)) #print(str(df[\u0026#39;displayName\u0026#39;] + \u0026#34; \u0026#34; + df[\u0026#39;mail\u0026#39;])) else: raise Exception(\u0026#39;no access token in result\u0026#39;) Summary This code as well as the Jupyter Notebook which allows you to run this all on your own in your own envionment may be found in this GitHub Repo. I do hope you enjoyed this little post on how to get started using Python with Microsoft Graph. Oh, one more thing \u0026#x1f4a1; you may have noticed me using config file variable when I was assigning Client ID, Tenant ID and the lot, that file is not in the repo for obvious reasons but an example of how that file is constructed is below for reference:\n[apppermissiononly] tenantID = redacted-1e7e2f9de3e2 authority = https://login.microsoftonline.com/ clientID = redacted-654fbbfaa793 clientSecret = totally_redacted_rubbish [delegatedpermissiononly] tenantID = rubbish-1e7e2f9de3e2 authority = https://login.microsoftonline.com/ clientID = more-rubbbish-215b06 I would suggest however that you apply a more secure way of storing your configurables and credentials by using something like Azure Key Vault. This is demoware mind you \u0026#x1f61c;\nChat about this? Engage with me Click Twitter @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/graphwithpython/","summary":"\u003ch2 id=\"why-you-should-read-this-post\"\u003eWhy you should read this post\u003c/h2\u003e\n\u003cp\u003eIf you are interested in \u003ccode\u003eMicrosoft Graph\u003c/code\u003e and how it can work with \u003ccode\u003ePython\u003c/code\u003e this post gives two examples of an art of the possible.  In this post i will be addressing the following topics:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUsing MSAL libraries in Python\u003c/li\u003e\n\u003cli\u003eUsing 2 different Authentication Flows to gain access to Microsoft Graph resources\u003c/li\u003e\n\u003cli\u003eBonus - Access to my GitHub repo where you can get the code as well as a Jupyter Notebook to runs this on your own\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"wiring-this-all-up\"\u003eWiring this all up\u003c/h2\u003e\n\u003cp\u003eThis is not very onerous, in fact if you have ever played with Python, its the simplicity that is really astounding. Basically you need to work the the below libraries to get this sorted:\u003c/p\u003e","title":"Microsoft Graph and Python"},{"content":"Why read this post? I wanted to start a new Blog primarily because my focus and direction have shifted from the perspective I have had for the last decade plus. What do I mean by that? \u0026#x1f914; While I am still a member of the technical community that I have been so proud to be a part of for the last almost 15 years, previously that vantage point was that of an independent voice. Indeed as a Microsoft MVP for the last 7 years, we pride ourselves as being a transparent vessel of the public at large and also of Microsoft, I saw myself as technical leader with a good understanding of how the developer community, stake holders, and end users consume Microsoft products especially SharePoint, Office365, Microsoft365, Azure, Azure Functions, and mobile dev tech. I took that information and often blogged content that addressed:\nblockers envisioning deep dives how to\u0026rsquo;s etc. with the intent to provide both clarity and a thoughtful voice on the topic I penned. Even within the MVP program, there are NDAs that are strictly enforced and to some extent the knowledge shared to MVPs is also distilled from what the internal blue badges know and share. Last year August I took a role at Microsoft and the way I put it is that I am the same person just seated on the other side of the table now, however that now means that for a variety of legal and procedural reasons my public statements are now measured. Accordingly, I felt a new blog would be a effective demarcation of previous views v/s current views even though the facts remain the same \u0026#x1f601;\nWhat platform do I choose I wanted a platform that would be easy to use, easy to maintain and moreover because most of my content for the past few years have been Github code repos, Github Gists, and YouTube videos, I wanted my new blog site work well displaying those formats. My last blog platform was on Wordpress and the challenge I faced largely centered around:\nFormatting code Video snippets Image formatting Finding a blog editing tool that I actually like (finally I settled on believe it or not an old build of Windows Live Writer) Went with a Static Web App Platform Last week in one of our team conversations at work Jeremy Thake was speaking with Sebastien Levert about a blog he wrote and Jeremy spoke highly about the way the blog post flowed, the ease of read especially around the code formatting and responsive nature. In my head all I heard was box checked \u0026#x2714;\u0026#xfe0f;, another checked \u0026#x2714;\u0026#xfe0f;, oh yeah, another checked \u0026#x2705;, so this weekend while I had no school for a change, I decided to learn as much as I could about standing up a Static Web App Blog Site.\nWhere do I start? Well, I went to Sebs site and saw that he was using some of the same themes I notice in his Github profile, so I deduced\u0026hellip; oh he\u0026rsquo;s doing this in Markdown! Next I did a Internet search on Static Web Apps and low and behold a Video of Scott Hanselman was top of my list\u0026hellip; of course I am going to watch that and I am glad I did. He did a pretty excellent example of \u0026lsquo;and in plain english\u0026rsquo; walking through the process of setting up the following:\nCloning a starter template repo (a Vanilla starter pack that was 1 HTML page, 1 CSS page, and 1 JavaScript page) Provisioning an Azure Static Web App (which is in preview) from the Azure Portal Connect the Static Web App to his Github Repo with the cloned Vanilla template Made a few changes to show the CI/CD working whenever he committed changes from GitHub thereby updating the content of the site Creating a custom domain so that the random URL provided by Azure can have a vanity URL from a domain he purchased thus I had another ding, ding ding, checkbox moment. Scott\u0026rsquo;s video may be found here\nMy own approach Each of us undertaking this journey will have our own way of working. In particular me, I had to make these choices\nDo I want to develop on my Mac or on Windows. \u0026#x1f914; The tooling and updates usually done when working on Static Web Apps can be done via Terminal \u0026amp; Open Source Dev tooling Do I just go Vanilla as I saw Hanselmann do in his video or do I go for a Static Web App Generator. \u0026#x1f914; Well how much time do I want to take to hook things up so they flow and look nice? Do I really want to be writing Bootstrap code or cobbling together CSS and JavaScript to make the site functional across a myriad of devices? There were other ancillary considerations, but these were the top-of-mind ones. How I implemented my approach So, here is how I accomplished my goals. After some research and watching Hanselmann\u0026rsquo;s video I saw that there were tools like Gatsby, Hugo, and other platforms I could use to make compelling Static Web App experiences. I remembered what Jeremy and Seb discussed about Hugo, I looked at Seb\u0026rsquo;s site and\u0026hellip; easy decision. Lets go Hugo! I decided to leave my old site running, I get good traffic there so people are using it, makes sense not to kill that URL of https://fabiangwilliams.com which was also one of my considerations I secured a new domain name https://www.fabswill.com I totally love the play on words there and it\u0026rsquo;s basically my nic-name with a shorting of my last name. 7 letter domain name, how can I go wrong there \u0026#x1f61c; I already had a Github profile so I just spun up a new private Repo, I had no need to clone a starter pack because I was going to use Hugo as my build engine I downloaded Hugo and set it up on my Windows PC, I also opted for the Hugo-future-imperfect-slim theme by cloning it from their site After playing around with the site structure and cleaning up the examples they had there, by 6 hours, I had a site up and running with 1 blog post there serving as a test and I modified a sample they gave for free so I can always have tips on how to use Markdown at my fingertips I socialized my success — my announcement tweet — and saw that Thomas, Appie, Seb, and Yannick were already ahead of the game. Appie also socialized that he on the same day I took the plunge migrated his blog site to a Static platform — Appie\u0026rsquo;s tweet. Summary This is day 2 and besides the energy that comes with playing around with new tech that folks like us love, I am glad I went this way. There are some initial pro\u0026rsquo;s and cons that I have come up with, I think the above really spells out the Pro\u0026rsquo;s so I will just list a few \u0026ldquo;possibly some of my own making\u0026rdquo; Cons\u0026rsquo;\nIf there is a Spell Check, Grammar Check, Punctuation Check tool withing VSCode, I can\u0026rsquo;t find it Markdown is not 1st nature for me so I now write as if I am writing a Word Doc then I go back and apply my Markdown syntax. I might as well cut and paste to Word too and use that Spell Check feature hmmm\u0026hellip; nice.. But those are the only 2 so far, which means the Pro\u0026rsquo;s definitely outweigh the Con\u0026rsquo;s. Anyway, this is already a long post. Lets tie it up here. I hope this helps anyone out there considering making a move to Static Web Apps as a Blog Platform.\nChat about this? Engage with me Click Twitter @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers! Fabs\n","permalink":"https://www.fabswill.com/blog/anewday/","summary":"\u003ch2 id=\"why-read-this-post\"\u003eWhy read this post?\u003c/h2\u003e\n\u003cp\u003eI wanted to start a new Blog primarily because my \u003ccode\u003efocus\u003c/code\u003e and \u003ccode\u003edirection\u003c/code\u003e have shifted from the perspective I have had for the last decade plus. What do I mean by that? \u0026#x1f914; While I am still a member of the technical community that I have been so proud to be a part of for the last almost 15 years, previously that vantage point was that of an \u003cem\u003eindependent\u003c/em\u003e voice. Indeed as a Microsoft \u003ca href=\"http://mvp.microsoft.com\" title=\"Microsoft MVP Program\"\u003eMVP\u003c/a\u003e for the last 7 years, we pride ourselves as being a transparent vessel of the public at large and also of Microsoft, I saw myself as technical leader with a good understanding of how the developer community, stake holders, and end users consume Microsoft products especially SharePoint, Office365, Microsoft365, Azure, Azure Functions, and mobile dev tech. I took that information and often blogged content that addressed:\u003c/p\u003e","title":"A New Day"},{"content":"As I retire my old blog Fabian Williams the Architect for this new format I am tinkering with the concept of Azure Static Web Sites usign HUGO templating . Seems pretty cool so far!!! this is all hosted on a Github Repo using Markdown and GitHub Actions for CICD into Azure as I create new content.\nFabians COVID19 Community Project Fabian Top Tweet of the Day View tweet\nChat about this? Engage with me Click Twitter @fabianwilliams LinkedIn Fabian G. Williams Or use the share buttons at the top of the page! Thanks\nCheers, Fabs\n","permalink":"https://www.fabswill.com/blog/gettingstarted/","summary":"\u003cp\u003eAs I retire my old blog \u003ca href=\"https://fabiangwilliams.com\"\u003eFabian Williams the Architect\u003c/a\u003e for this new format I am tinkering with the concept of Azure Static Web Sites usign HUGO templating . Seems pretty cool so far!!! this is all hosted on a Github Repo using Markdown and GitHub Actions for CICD into Azure as I create new content.\u003c/p\u003e","title":"Tweets and Vids of Fabian"},{"content":"This article offers a sample of basic Markdown syntax that can be used in Hugo content files, also it shows whether basic HTML elements are decorated with CSS in a Hugo theme.\nHeadings The following HTML \u0026lt;h1\u0026gt;—\u0026lt;h6\u0026gt; elements represent six levels of section headings. \u0026lt;h1\u0026gt; is the highest section level while \u0026lt;h6\u0026gt; is the lowest.\nH1 H2 H3 H4 H5 H6 Paragraph Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.\nItatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.\nBlockquotes The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.\nBlockquote without attribution Tiam, ad mint andaepu dandae nostion secatur sequo quae. Note that you can use Markdown syntax within a blockquote.\nBlockquote with attribution Don\u0026rsquo;t communicate by sharing memory, share memory by communicating.\n— Rob Pike1\nTables Tables aren\u0026rsquo;t part of the core Markdown spec, but Hugo supports supports them out-of-the-box.\nName Age Bob 27 Alice 23 Inline Markdown within tables Inline Markdown In Table italics bold strikethrough code Code Blocks Code block with backticks \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;UTF-8\u0026#34;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Code block indented with four spaces \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026quot;en\u0026quot;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026quot;UTF-8\u0026quot;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Code block with Hugo\u0026rsquo;s internal highlight shortcode \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;UTF-8\u0026#34;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; List Types Ordered List First item Second item Third item Unordered List List item Another item And another item Nested list Item First Sub-item Second Sub-item Other Elements — abbr, sub, sup, kbd, mark GIF is a bitmap image format.\nH2O\nXn + Yn = Zn\nPress CTRL+ALT+Delete to end the session.\nMost salamanders are nocturnal, and hunt for insects, worms, and other small creatures.\nHelpful Links List of Emojis - https://gist.github.com/rxaviers/7360908 Markdown Cheat Sheet PDF: https://guides.github.com/pdfs/markdown-cheatsheet-online.pdf\nThe above quote is excerpted from Rob Pike\u0026rsquo;s talk during Gopherfest, November 18, 2015.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://www.fabswill.com/blog/fabianmarkdowncheatsheet/","summary":"\u003cp\u003eThis article offers a sample of basic Markdown syntax that can be used in Hugo content files, also it shows whether basic HTML elements are decorated with CSS in a Hugo theme.\u003c/p\u003e","title":"Markdown Syntax Guide"},{"content":"The fastest way to reach me is a message on LinkedIn or X.\nLinkedIn: linkedin.com/in/fabiangwilliams X: @fabianwilliams YouTube: @fabiangwilliams GitHub: fabianwilliams Want the patterns I run, once a month at most? Subscribe at the bottom of any blog post.\n","permalink":"https://www.fabswill.com/contact/","summary":"\u003cp\u003eThe fastest way to reach me is a message on \u003ca href=\"https://www.linkedin.com/in/fabiangwilliams/\"\u003eLinkedIn\u003c/a\u003e or \u003ca href=\"https://x.com/fabianwilliams\"\u003eX\u003c/a\u003e.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eLinkedIn:\u003c/strong\u003e \u003ca href=\"https://www.linkedin.com/in/fabiangwilliams/\"\u003elinkedin.com/in/fabiangwilliams\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eX:\u003c/strong\u003e \u003ca href=\"https://x.com/fabianwilliams\"\u003e@fabianwilliams\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eYouTube:\u003c/strong\u003e \u003ca href=\"https://www.youtube.com/@fabiangwilliams\"\u003e@fabiangwilliams\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGitHub:\u003c/strong\u003e \u003ca href=\"https://github.com/fabianwilliams\"\u003efabianwilliams\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eWant the patterns I run, once a month at most? Subscribe at the bottom of any \u003ca href=\"/blog/\"\u003eblog post\u003c/a\u003e.\u003c/p\u003e","title":"Contact"}]