Where good ideas come from (for coding agents) A developer's essay argues that coding agents excel at 'adjacent possible' work but require users to supply constraints, context, an oracle, and a loop to become reliably useful, applying Steven Johnson's 'Where Good Ideas Come From' framework to AI-assisted coding. The author, who writes from personal experience, notes that large language models act as 'thought completers' and that effective prompting is more about steering than magic words. where good ideas come from for coding agents and the part where users have to level up I’ve been thinking about why some people absolutely cook with coding agents, and some people bounce off them hard. I had a thought last week: if llms are “next token predictors” in the small i.e., sentence finishers then in the large they’re closer to “thought completers.” you give them a few crumbs of context, they infer the genre, then they sprint down the most likely path in idea-space. which makes “good prompting” feel less like magic words and more like navigation : you’re steering the model toward a region of the space where the next steps are both plausible and useful. I wanted a better map for that, so i used steven johnson’s “where good ideas come from” as a rubric, the seven patterns that reliably produce interesting ideas, and tried applying it to coding agents: where they’re naturally strong, where they reliably drift, and what a user has to supply constraints, context, oracles, loops to make the whole thing converge. tl;dr: a plausible “week in the life” you can map onto your own codebase. the point is to make the user-adaptation story concrete: agents are excellent at adjacent-possible work, but they only become reliably useful when you supply constraints, context, an oracle, and a loop . the idea-space metaphor and what the seven ways add to it it’s tempting to picture an llm as navigating a huge multidimensional “idea-space”: your prompt lights up certain internal features, which reshapes the probability landscape of what comes next, and generation is basically a trajectory through that landscape. in that framing, context engineering is just steering - adding constraints, examples, and relevant artifacts so the model’s “next steps” stay in the neighborhood you care about. johnson’s seven ways are useful here because they explain which kinds of trajectories llms find naturally, and which ones require help: models are natively strong at smooth, local moves like the adjacent possible small diffs, incremental refinements and at platforms interfaces, scaffolds, reusable primitives , and they can do exaptation well when you explicitly state affordances and constraints. they’re weaker where progress depends on reality pushing back - error and serendipity - unless you give them feedback channels like tests, benchmarks, traces, and experiments that create a gradient toward truth. and they only approximate liquid networks and slow hunches when you supply diverse “voices” prior art, docs, debates and persist ideas long enough to recombine later. the point isn’t that llms can’t roam the space; it’s that they need mechanisms that select and validate the paths worth taking. quick sidequest: the seven ways steven johnson’s “where good ideas come from” https://www.amazon.com/Where-Good-Ideas-Come-Innovation/dp/1594487715/ is one of those lists that sounds like it belongs on a poster until you use it as a diagnostic tool. here’s the version that matters for engineering: the adjacent possible - most “new” ideas are the next reachable step from what already exists. stairs, not teleportation. liquid networks - ideas show up when partial thoughts collide: people, yes, but also artifacts docs, code, past debates . the slow hunch - many good ideas start half-baked. you keep them around until they meet the missing piece. serendipity - luck plus recognition; you notice the useful anomaly when it appears. error - failure is information; feedback turns wandering into convergence. exaptation - repurpose a thing built for one job into a different job. reuse as invention. platforms - stable primitives and standards let lots of people build lots of things faster and safer. now: drop an llm coding agent into this picture. what changes? my take: the seven patterns don’t go away. agents just amplify some of them and brutally expose where you’ve been relying on implicit human context for the others. let’s walk through that with one running example. the running example: “make webhook ingestion reliable” totally plausible, not actually shipped imagine a webhook ingestion service: - handler validates signature - stores event - enqueues downstream job and prod keeps reminding you that the world is adversarial: - partners retry aggressively → duplicates - downstream sometimes fails halfway → partial side effects - p99 latency is creeping up → every “fix” risks making tail worse the goal, as a human would say it: reliable ingestion with idempotency and bounded retries, without making latency worse. the goal, as an agent hears it: “write some code that sounds like reliability.” that mismatch is the whole story. so here’s the one-week simulation. day 1: I ask for “reliability.” the agent gives me plausible nonsense. the naive prompt is basically: make webhook ingestion reliable. handle duplicates and retries. keep latency reasonable. the agent does what continuation machines do when you hand them vibes: it fills in the blanks with the most likely reliability narrative it has seen before. so it might invent a new “reliability module,” add a retry helper even if your repo already has one , choose a payload-hash idempotency key because it sounds right, and sprinkle logging everywhere like it’s free. and the code might be clean which is the annoying part. because it can be clean and still wrong. in this simulation, you catch three problems quickly: - payload hashes aren’t stable identifiers for retries in the real world - retries in the request handler are a p99 tax and can trigger more retries, which is a fun kind of circular misery - duplicating retry logic is how you end up with a repo that has “one retry policy per mood” so you don’t merge it. you don’t argue with it. you just learn the lesson: if you ask an agent for a vibe, it will give you a vibe-shaped completion. day 2: adjacent possible - I stop asking for outcomes and start asking for stairs. this is the first user adaptation: take the big thing and turn it into rungs small enough to verify. the staircase looks like: - step 1: idempotency at ingestion no duplicate enqueue - step 2: bounded retries in the worker not the handler - step 3: dead-letter path + replay - step 4: metrics that tell us if it’s working then you create an oracle for step 1. not a paragraph. an actual check. maybe it’s a test that says: - same partner id, event id arrives twice → only one enqueue happens - second request returns quickly and doesn’t redo expensive work - storage failure behavior is explicit fail closed vs fail open is a choice, not an accident then the prompt becomes boring on purpose: implement step 1 only. keep the diff small. don’t invent new abstractions. make these tests pass. suddenly the agent looks competent again, because this is its strength: incremental diffs along a well-lit path. the “adjacent possible” isn’t just a creativity concept; it’s also a safety concept. small rungs are harder to misunderstand. day 3: liquid networks - I build a context packet so it stops inventing my codebase. even with good decomposition, agents have a habit: they’ll “helpfully” create new mini-frameworks unless you force them to collide with your existing ones. so you manufacture a liquid network. not by dumping the whole repo, but by curating the collision points. in this simulation, you assemble a tiny context packet: - the canonical retry policy already used elsewhere - your error taxonomy types - logging/metrics rules especially what not to log - the queue abstraction you must use - one prior PR that did retries correctly in your house style and you tell the agent, explicitly, to reuse what exists: for step 2, reuse