Don't give your agent a "run command" tool
- Agentic AI
- AI Security
The decision people regret most in agent systems usually gets made on day one: give the model shell access and let it work the rest out. In the short term it works beautifully. Six months later you notice nobody can answer "what can this system do" any more.
The difference between these two has nothing to do with how clever the model is:
run_command(host: string, command: string) -> string
restart_service(host: HostId, service: ServiceName) -> RestartResult
In the first, the answer to "what can the agent do" is "anything". Writing a permission check means parsing the text inside command - using natural language as a security boundary. It does not hold.
In the second the answer is finite. ServiceName comes from a known set, HostId is verified against inventory, and the call layer decides on those two parameters. It never reads prose.
The expected objection is that narrow tools kill flexibility. We found the opposite. With a broad tool the model constructs the right command from scratch on every call - a fresh chance to get it wrong each time. With a narrow one it picks a tool and two parameters. One mistake stays available, choosing the wrong target, and inventory catches that.
The cost is real: the tool count grows, and somewhere near thirty the model starts struggling to pick correctly. What worked was not reducing the number of tools but reducing how many the model sees at once. The set is narrowed by the context of the session; it never sees all thirty.
The rule we use: if you cannot say what a tool does in one sentence without the word "anything", it is too broad.
Whatever you put in the prompt, a model can be talked around. A signature cannot.