{"slug": "pi-is-bad-or-the-positive-effects-of-friction-in-automated-development", "title": "Pi Is Bad; Or, The Positive Effects of Friction in Automated Development", "summary": "A developer reports that the AI harness Pi from pi.dev ignored MCP server instructions and deviated from project skills during a Clojure-to-Common-Lisp port, while the Goose harness from Goose-docs.ai performed better due to its friction. The author, djha-skin, tested both harnesses with OpenRouter's deepseek-v4-flash model and found Pi's lazy MCP loading caused it to miss bead-related instructions, requiring multiple corrections.", "body_md": "# Introduction\n\nI have recently tried the AI harness [Pi](https://pi.dev/) . I'm coming from it\nfrom a harness that I first picked up when all this stuff was sort of newer\ncalled [Goose](https://Goose-docs.ai/). I can see what all the hype is about,\nbut I actually had a bit of a [\"better is\nworse\"](https://dreamsongs.com/WorseIsBetter.html) experience with it. I think\nI'll be sticking with Goose for now. I have come to the conclusion that it is\nbecause of the friction Goose introduces into the system makes it better.\n\nIn the rest of this blog post, I describe the differences in my experience\nrunning Pi versus Goose using Open Router's\n[deepseek-v4-flash](https://openrouter.ai/deepseek/deepseek-v4-flash) model. Goose configuration that I used may be found [here](https://github.com/djha-skin/dotfiles/blob/main/dot-config/goose/config.yaml). Pi global configuration may be found [here](https://github.com/djha-skin/dotfiles/tree/main/dot-pi/agent). Goose project-level wrapper may be found [here](https://github.com/djha-skin/dsolv/blob/main/scripts/goosew). Pi project-level configuration may be found [here](https://github.com/djha-skin/dsolv/tree/main/.pi).\n\n# Experiment Design\n\nI type a short three-to-four sentence prompt into Goose and it just works. Sometimes I would need to provide guidance, but once I get it going, I can often step away from my desk and come back. I often heard anecdotes about how AI could \"slip the leash,\" like cheat on unit tests, implement the wrong thing, do exactly what they were told not to do, that sort of thing. I really didn't understand these complaints. I would just write stuff, give the AI the occasional dont-do-that-do-this, and it would do okay. However, I tried the same short-style prompting on Pi, and it immediately started slipping the leash.\n\nI tested using Pi on [a project I'm porting from Clojure to Common\nLisp](https://github.com/djha-skin/dsolv/). [I wrote a skill that told it how I\nlike Common Lisp to be\nwritten](https://github.com/djha-skin/dsolv/tree/main/.agents/skills/djha-skin-common-Lisp).\nIn there I said to write a bunch of\n[beads](https://github.com/gastownhall/beads). I initially set up Pi to write\nbeads via the [bead MCP\nserver](https://github.com/gastownhall/beads/blob/main/integrations/beads-mcp/README.md).\nThen I told the AI to use the beads MCP in the skill I wrote and later it was\nalso in the AGENTS.md file. I started Pi up, and told it to read AGENTS.md and I\nalso gave it an initial prompt to use the skill and start porting code.\n\n# Problem 1: Pi Ignores MCP Servers\n\nWhen I started Pi up, it also immediately ignored what I told it to do in the skill. It didn't write any beads and just started writing code almost immediately. I had to yell at it two or three times before it figured out \"oh yeah, I should stop and write beads.\" I stopped Pi and did some research to determine the underlying cause of this flagrant ignorance on the part of the AI.\n\nThe [Pi MCP plugin](https://Pi/packages/pi-mcp-adapter) lazily loads the MCP\nservers into the context by default. Mario Zechner [wrote an interesting blog\npost](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/) about\nhow MCP might not be great because it introduces tokens into the context window\nabout the MCP tools whether you use them or not. The MCP adapter in Pi follows\nthis philosophy. It only loads the definitions of the MCP tools into the\ncontext. Because of this, my mention of beads was probably the first occurrence\nof beads that the AI saw. Not knowing what to do about it, it probably just blew\npast it.\n\nI started it up again with a bead plugin instead of using the bead MCP server.\nHowever, I couldn't take this approach with the Common Lisp\n[cl-mcp](https://github.com/cl-ai-project/cl-mcp) MCP server. No one had written\nan equivalent plugin. Pi kept deviating from my telling it to use the MCP\nserver, and this was a big problem. Running Common Lisp code from the CLI often\ndrops into the Lisp interactive debugger. [Common Lisp doesn't like being vibe\ncoded](https://blog.djhaskin.com/blog/writing-lisp-is-ai-resistant-and-im-sad/),\nand the interactive debugger is one of those reasons, but there are many.\nLong-running REPL development, REPL reloading, one-off Lisp evaluations within\nthe REPL environment, Lisp-form-level editing (rather than line editing), and\nparenthesis balancing are all problems with which AIs often struggle. The cl-mcp\nserver fixes several of these problems, and more besides.\n\nGoose handles the Lisp debugger really poorly when it runs Lisp code through the\nCLI. In Goose, the debugger totally hangs the Goose session and Goose must be\nrestarted. When I restart it, I tell Goose \"You used Lisp CLI tools again, don't\ndo that, use the MCP server.\" I use Goose's [Top Of Mind\nfeature](https://goose-docs.ai/docs/mcp/tom-mcp/) to remind Goose to use the MCP\nserver instead. When Top Of Mind enabled, I have more or less stopped having\nthis problem with Goose.\n\nPi handles the debugger and even parenthesis balancing\nmore gracefully than Goose, but this actually caused problems within the\nsession. Pi seems to put the Lisp process in its own shell and handles the\ninteractive prompt gracefully by killing it when it gets to the debugger prompt.\nLike with Goose, though, I still wanted to enforce the use of cl-mcp. Pi didn't\nhave a top-of-mind-style context injection system available in its package\nsystem, when I was running this test, so I made a [top of mind plugin for\nPi](https://www.npmjs.com/package/@djhaskin987/pi-top-of-mind) and used that to\nremind Pi of the MCP server. Even with my putting it into the context every 10\ntools calls or so though, Pi kept messing up and stopped using the MCP server.\nIt kept getting big enough rewards from the ad-hoc interactions it had with\nCommon Lisp through the CLI that it stopped using the proper tool for the job,\nspecifically designed to help it get better results.\n\n# Problem 2: Pi Is Too Fast\n\nWith the same model and API backend, Pi generates text much, much faster than\nGoose. It also doesn't allow the user to stop the generation by default. Pi\ndidn't stop when I wanted to talk to it, just kept barrelling toward ruin. The\nspeed would make me feel white-knuckled, like \"what is it going to screw up this\ntime.\" I ended up installing the [pi-stop](https://Pi/packages/pi-stop?page=41) plugin. This\nhelped immensely because I could now stop Pi. However, it still generated text\nso fast that I couldn't process what it was generating. Often, by the time I had\nfigured out it needed steering, it generated a lot of garbage that sat there\npoisoning its context, not to mention the bad code or incorrect beads that it\nwrote. Eventually, after any given Pi session, I would have to\nswitch back to Goose because the AI got confused about what to do next. This\nspeed was not only a problem for context poisoning, but since it generated a lot\nof churn that then needed cleaned up in a very short amount of time, it costed a\nlot more money on OpenRouter while yielding poorer results. It simply goes too\nfast and too easily makes mistakes without providing enough time for steering to\ntake place.\n\n# Problem 3: Pi Package Whack-a-Mole\n\nGoose comes with top-of-mind, full-stop steering, maximum turns before stop, and\n(though I don't use it) fine-grained permissions system allowing you to fine\ntune what tools are exposed to the AI and which are not. Finally, it has a\nmaximum context token setting (I had to install yet-another-plugin in Pi for\nthis, [pi-context-cap](https://pi.dev/packages/pi-context-cap?page=46). All of\nthis comes out of the box with Goose. I had to hunt around for these features\nwith Pi, and in one case, I had to write my own extension. Worse, the plugins\noften had only hundreds of downloads, making me think they were one-off garage\nprojects (like the top-of-mind plugin I just wrote for Pi was!) that weren't\nreally maintained by their creators. It made me feel like I was playing\nwhack-a-mole. \"Oops! Pi doesn't have x, guess I have to go shopping.\" I don't go\nshopping around for different seat belts for my car. I just hope the\nmanufacturer had them built-in. Plug-ins are awesome, and a vibrant package\necosystem is awesome, but my time in the trenches with Jenkins has taught me\nthat plugins shouldn't be used *everywhere*.\n\n# The Grass Is Not Always Greener\n\nGoose's heavy use of MCP makes it work better. Goose has\n[hooks](https://Goose-docs.ai/docs/guides/context-engineering/hooks/) and\n[plugins](https://Goose-docs.ai/docs/guides/context-engineering/plugins/), but\nmost extensions are simply implemented via MCP. It loads the definitions into\nthe context window up front, as far as I can tell. It uses the sequential\nthinking MCP. It uses the to-do MCP. It uses the beads MCP. It often does this\nwithout me explicitly prompting it to do so because I already sort of did by\nloading those things. Because all of\nits MCP tool definitions are loaded into it all at once, the AI thinks it needs\nto use them. That load was an implied suggestion that these MCP tools\nare to be used. In Pi, there are a bunch of plugins I have like [the task\nplugin](https://github.com/tintinweb/pi-tasks), but it doesn't use it unless I\ntell it do so so. I figured out eventually how to eagerly load the MCP servers\nin Pi eagerly into the context, but at first this was a problem. [Goose's\nphilosophy](https://goose-docs.ai/blog/2025/12/21/code-mode-doesnt-replace-mcp)\nis to limit the MCP servers to just the ones you use. Having had this problem of\nplease-use-my-mcp-no-seriously with cl-mcp, I agree with the sentiment. If you\n*do* want the AI to use the tool, you SHOULD have MCP definitions, skills, and\nother sundry tools you *want* the thing to use loaded up front.\n\nCode is generated at a much more manageable pace in Goose. Goose is written in Go. Go has excellent asynchronous tools, but the author doesn't seem to have used them. Everything feels more or less single threaded. This is objectively worse, but it's also objectively better. It's easy to stop the AI from doing something wrong. It slows the AI down a little bit, but speed is not the AI's problem. My cognitive load trying to keep up with the AI is the problem. Just like with cars and roads, my AI tools need speed limits to allow for the reaction time of the driver.\n\nWith Goose, I set the session up, then spend about 20 minutes watching it. I will often have to give it one-sentence steering messages, but this drops in frequency as the session goes on. It is very often at first, but after a while, it just gets \"into a groove\" and starts cranking out good, high quality code. After that, I check on it every so often, sometimes stopping it and writing one-sentence steering messages, and then go back to what I was doing. If I forget about the session and come back, it will often have hit its configured maximum token limit or configured maximum number of turns, but it will still have written good stuff.\n\nIt all just makes me feel like Goose was written by people who really cared about bringing the AI under control without fuss. Goose just works. It feels boring. Boring is good.\n\n# Conclusion\n\nNow we can see the worse-is-better effect in my experiences. More wasted context is better, since it tells the AI how to think. Slower is better, since it allows me time to think about what the AI is generating. The Lisp debugger breaking Goose but not Pi is better, since it forced me to force the AI to use the MCP server.\n\nIt makes me think about Golang versus JavaScript since those are the two languages in which Goose and Pi were written. Typed languages famously made the trade-off of slower development, but the friction they introduced help write more precise code. This is awful if you're writing a front end, because the front end needs to change faster than that, but lower down, things need to change less and be more correct since it's hard to inspect the effects of your code when you're outside the browser. I feel these positive effects of a slower, heavier AI harness when I use Goose.\n\nI use NeoVim as an editor, and it felt like I was switching from Vim to VS Code\nwhen I went from Goose to Pi. I found what I thought I would find: a better\nplug-in system, a rich extension ecosystem, a more polished UX, just like VS\nCode. However, I also had worse results in coding. The one thing that Goose\nneeded to be better at, it *was* better at, just like with Vim. There are still\nsome really awesome things that I like about Pi, just like there are some really\nawesome things about VS Code. However, Vim has always been a better fit for my\nbrain.\n\nI think I'm going to stick with Goose for a little while longer. Form is nice, but in this business, function is non-negotiable.", "url": "https://wpnews.pro/news/pi-is-bad-or-the-positive-effects-of-friction-in-automated-development", "canonical_source": "https://blog.djhaskin.com/blog/the-positive-effects-of-friction-in-automated-development-or-pi-is-bad/", "published_at": "2026-08-04 21:55:20+00:00", "updated_at": "2026-08-04 22:23:45.721810+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-agents"], "entities": ["Pi", "Goose", "OpenRouter", "deepseek-v4-flash", "MCP", "beads", "cl-mcp", "Mario Zechner"], "alternates": {"html": "https://wpnews.pro/news/pi-is-bad-or-the-positive-effects-of-friction-in-automated-development", "markdown": "https://wpnews.pro/news/pi-is-bad-or-the-positive-effects-of-friction-in-automated-development.md", "text": "https://wpnews.pro/news/pi-is-bad-or-the-positive-effects-of-friction-in-automated-development.txt", "jsonld": "https://wpnews.pro/news/pi-is-bad-or-the-positive-effects-of-friction-in-automated-development.jsonld"}}