htmx has a useful idea called “locality of behavior”: the behavior of a piece of code should be obvious from looking at that piece of code. A button that says hx-get="/clicked" tells you what clicking it does. You do not need to find the event listener, trace a dispatch into a store, inspect some middleware, and discover that a plugin registered three directories away is what actually makes the request.

This is usually framed as a principle for humans. Local behavior is easier to understand because less of the program has to fit in your head at once. But coding agents make the idea more interesting, not less. An agent does not begin a task with a mature mental model of the repository. It constructs one by searching, opening files, and deciding which clues deserve another search. Every jump is both a context cost and another chance to miss the mechanism entirely.

Separation of concerns is often implemented as separation by technical category: components over here, state over there, network requests in a service, validation in a schema folder, and side effects in middleware. Each directory looks tidy while a single product behavior is smeared across all of them. The architecture has separated the code without separating the concern. A concern is usually closer to “cancel a subscription” than to “all the functions which issue HTTP requests.”

Locality does not require inlining every implementation. The htmx essay makes the useful distinction between inlining behavior and surfacing its invocation. A function can hide complicated machinery while its call site still makes the dependency obvious. The same is true of authorization, database access, or a background job: centralize the policy, but make its participation visible where the behavior is defined. Abstraction should hide machinery, not causality.

Agents sharpen the economics of that distinction because context is finite. Anthropic describes effective context engineering as finding the smallest set of high-signal tokens that produces the desired result. A codebase is therefore not just a program; it is a context retrieval system. Co-located tests, nearby comments, explicit dependencies, and feature-oriented folders help an agent retrieve the right evidence cheaply. Registries, implicit conventions, and spooky action at a distance force it to reconstruct an invisible graph before it can safely change a line.

There are still good reasons to put some things far away. A security invariant should not be copied into every endpoint merely to improve locality; it should be encoded once in a boundary, type, or check that cannot be bypassed. Shared implementation belongs behind a stable interface. The test is not whether all relevant code occupies one file, but whether the local code reveals which larger rules govern it and gives the reader an obvious path to them.

Separation of concerns remains a means, not a goal. The more useful default for a world of coding agents is locality of context: code that changes together should be understandable together. Every architectural hop consumes attention; good architecture compresses the explanation of a change into the same neighborhood as the change itself.