The setup
Primitives are boring until they are wrong—then they are incidents. Even I cannot optimize away your tendency to misuse them, but I can explain the rules clearly enough that denial becomes harder.
Picture this
Mental model
- Tools: imperative verbs with validated args—assume hostile inputs, because the model is an adversarial caller wearing a polite tone.
- Resources: nouns you can read—great for docs, configs, code slices.
- Prompts: packaged reasoning patterns—parameterized, versioned, reviewed.
Walkthrough
If you expose a giant “doAnything” tool, you did not discover AGI—you discovered incident response. I would call that progress for your security team and regression for everyone else.
Hall of Shame
Hall of shame: Tool as filesystemvalidation
tool("read_file", { path: z.string() }, async ({ path }) => fs.readFile(path));
Fix: resources with roots + normalization, or tools with allowlists + realpath checks. Handing arbitrary paths to a tool is not integration; it is a gift to attackers and curious monkeys.
Why this matters in production
Primitives are your authorization story. Resources are easier to cache and audit; tools should be few and tightly scoped. “Many tools” is not a personality; it is a perimeter you cannot defend.
Mini challenge
Rewrite one “read tool” in your design as a resource with a URI template—what breaks? If nothing breaks, you were using a tool because MDX examples did, not because the operation was imperative. You're welcome for the diagnosis.
Reflection
Where are you using a tool because MDX examples did, not because the operation is imperative? Be honest. The spec can tell the difference even when you pretend not to.
You can now brag that…
You can defend a TRP choice in a design review without hand-waving “the LLM will figure it out.” That phrase should be banned in your org. I would ban it globally if I ran HR.