The naming rules that hold my systems together
Every automation system I run eventually has more moving parts than I can hold in my head at once. Scripts call scripts. Agents call tools. Tools call other agents. The thing that keeps this from turning into a pile I can't debug at 2am isn't a clever architecture diagram. It's a naming convention, applied without exception, everywhere.
I didn't set out to write a naming standard. I backed into one after enough incidents where I opened a log file, saw a job called `run2_final_v3`, and had no idea what it did, which brand it touched, or whether it was safe to kill. That's the actual cost of a bad naming convention: not aesthetics, but time spent reconstructing context that should have been obvious from the name itself.
Why naming matters more once agents are involved
When you're the only one calling your own scripts, you can get away with sloppy names because you remember what you meant. That breaks the moment an AI agent is the one deciding which script or tool to call.
An agent reading a list of MCP tools doesn't have your memory of what `process.py` does. It has the tool name, the description string, and whatever context is in front of it. If two tools are named similarly, or a name doesn't describe what the function actually does, the agent will sometimes pick the wrong one. Not because the model is bad at reasoning, but because the name gave it bad information to reason from. A naming convention isn't just for humans anymore. It's part of the interface the agent uses to decide what to do.
This is the part people underestimate when they wire agents into real tools instead of demoing them in a sandbox. The description and name of a function is doing real interpretive work. Vague names produce vague behavior.
The rule I actually follow
My convention is boring on purpose: `verb_object_scope`. A script is named for what it does, what it does it to, and where that action is scoped.
`publish_article_smp.py` publishes an article, for the SMP brand. `render_video_queue.py` renders whatever is in the video queue. `reconcile_shop_ports.py` reconciles shop ports. No adjectives, no version numbers baked into the filename, no `_final`, no `_v2`. If a script needs a new version, it replaces the old one and git history holds the difference. A file called `_v2` is a confession that nobody deleted the old one, and now there are two sources of truth sitting next to each other waiting to be run by accident.
The scope part matters more than it looks. In a system with multiple brands, "publish the article" is not a complete instruction. Publish it where? For which brand? A script name that doesn't answer that is a script that will eventually get run against the wrong site.
Prefixes carry meaning, not decoration
Every brand and every environment gets a short, fixed prefix, and that prefix is load-bearing. It tells you, before you open the file, what blast radius you're dealing with.
A job prefixed with a brand name only touches that brand's content, queue, or credentials. A job with no brand prefix is either shared infrastructure or a mistake waiting to happen. When I'm scanning a crontab or a task scheduler list, the prefix is the first thing I read, because it tells me whether a failure is contained to one brand or is going to cascade across all of them.
The same logic applies to local versus cloud. If a job runs a model locally, on my own hardware, the name says so. If it calls out to a cloud API, the name says that too. This isn't cosmetic. Local and cloud runs fail differently, cost differently, and have different blast radii if something goes wrong at 3am while I'm asleep. A local render job stalling ties up a GPU I own. A cloud job stalling can quietly rack up usage against an account. I want to know which kind of problem I'm looking at from the job name alone, before I've read a single log line.
Agent and tool names are part of the prompt
This is the piece that's specific to running agents rather than just running scripts. When you register a tool for an agent to call, whether through MCP or any other interface, the tool's name and description function as part of the prompt. The model reads them the same way it reads your instructions.
That means a tool named `helper` or `process_data` is actively unhelpful. It tells the agent nothing about when to use it, so the agent either guesses or defaults to whichever tool has the most convincing description, regardless of whether it's the right one. I name tools the same way I name scripts: verb, object, scope. `get_thread` fetches a thread. `search_files` searches files. `apply_sensitive_message_label` applies a sensitive label to a message. None of that is exciting, and that's the point. Boring names are names an agent can act on correctly without extra clarification.
I've also learned to keep tool names distinct enough that an agent can't confuse two of them under time pressure or a long context window. If I have a tool that trashes a single message and another that trashes an entire thread, they need names that make the difference obvious on a skim, not just on a careful read. `apply_sensitive_message_label` versus `apply_sensitive_thread_label` isn't elegant, but it's unambiguous, and unambiguous beats elegant every time an agent is the one choosing.
Timestamps go in one place, one format
Every file, log, or output that needs a timestamp gets it in the same spot, in the same format, always in absolute date form rather than relative words like "yesterday" or "latest." Relative labels rot the moment a file is more than a day old, and they rot silently, because the filename still looks fine, it's just lying to you.
I standardized on `YYYY-MM-DD` for anything date related and dropped abbreviations like "yest" or "prev" entirely. It's a small thing, but it means I can sort a directory by name and get chronological order for free, and so can any script or agent that has to pick the most recent file out of a folder without additional logic to parse ambiguous dates.
What this actually protects against
None of this is about elegance. It's about the specific failure mode where a system has grown past the point where one person can hold all of it in working memory, and the only thing standing between "reasonable to operate" and "too risky to touch" is whether the names tell the truth.
A consistent naming convention means I can look at an unfamiliar job, in an unfamiliar log, at an unfamiliar hour, and know within a few seconds what it touches and how dangerous it is to interrupt. That's the whole value. It's not about looking organized. It's about not having to reconstruct context under pressure, whether the one reading the name is me or an agent deciding which tool to reach for next.
If you're running local models, cloud APIs, and agents wired into real tools in the same system, the naming convention is one of the few things that scales with you without needing to be redesigned every time you add a brand, a server, or a new tool. Get it wrong early and you'll be renaming things under pressure later, which is the worst time to do it.
If you want to see how this plays out in an actual multi-brand automation setup, [head back to the homepage](/) for more on how I run AI in production.
Get new guides and videos first — join the Telegram channel.