Small agent tools are easier to permission, review, and revoke.
A broad tool makes the prompt carry too much policy:
type ManageFilesArgs = {
action: "read" | "write" | "delete" | "move"
path: string
contents?: string
}
Prefer narrower capabilities:
type ReadWorkspaceFileArgs = { path: string }
type WriteGeneratedFileArgs = {
path: string
contents: string
reason: string
}
type DeleteGeneratedArtifactArgs = { artifactId: string }
The API list is less elegant. The permission boundary is easier to understand.
Small tools can still compose:
read file
inspect frontmatter
write draft
run markdown check
summarize result
Composition exposes intermediate state. Each call can be logged, denied, retried, or inspected. A higher-level wrapper is fine when the workflow is stable and safe, but it should preserve the receipt.
Logs benefit from the same granularity:
tool: read_workspace_file
path: src/content/blog/tool-calling-is-a-contract.mdx
result: ok
That is more useful than a generic task result that hides ten actions.
Tool shape should match risk. Read-only search can retry. Scoped writes can validate paths. Artifact tools can avoid user-authored files. Ticket tools can create drafts. Deploy tools can default to preview.
Names guide behavior too. run_project_check is narrower than run_command. count_open_incidents is narrower than query_database. Names do not enforce policy, but they make mismatches easier to see.
Small tools are narrow authority made visible.
Related posts

About Jeremy London
Engineering leader and builder in Denver. I write about AI platforms, agents, security, reliability, homelab infrastructure, and the parts of engineering work that have to survive production.