Agent Tool Naming Conventions Specification for LLM Routing Reliability
Tool names are part of the prompt the LLM sees during routing. A consistent verb-noun structure, namespace prefix, and tight character budget reduce mis-routing, especially across multi-MCP setups. This specification defines a normative naming contract you can apply across providers.
TL;DR
Use namespace.verbNoun (e.g., notion.createPage) or namespace_verb_noun (snake_case) for OpenAI- and Anthropic-style function calling. Keep names under 64 characters, alphanumeric plus underscore or dot, with one verb and one primary noun. Place vendor-specific qualifiers in the description, not the name. Reserve aliases for deprecation; never reuse a deleted name.
Why naming reliability matters
The LLM picks tools by reading their names and descriptions inside the prompt. A confusing name (process_data, do_thing) forces the model to lean on the description, where token weight is variable. Crisp, predictable names raise routing accuracy, lower hallucinated tool calls, and make multi-MCP fan-in safer. OpenAI and Anthropic both document name patterns and length caps as part of their function-calling APIs (OpenAI function calling; Anthropic tool use).
Normative rules
R1. Structure
- Required: exactly one verb and one primary noun.
- Allowed shapes: verbNoun, verb_noun, namespace.verbNoun, namespace_verb_noun.
- Verb comes first. Noun describes the resource, not the format.
R2. Case style
- Within one server, pick one style: camelCase OR snake_case.
- Mixed styles in the same toolset hurt routing because the LLM sees them as different name families.
- The Model Context Protocol does not mandate a style; it is a project decision (MCP specification).
R3. Character set and length
- Allowed: [A-Za-z0-9_.-].
- Forbidden: spaces, slashes, colons, emoji, non-ASCII.
- Length: target ≤ 32 chars, hard cap 64 (matches common vendor caps; verify the latest OpenAI and Anthropic limits in their docs).
R4. Namespace prefix
- Format:
. or _ . - Use the source-of-truth product name as the namespace (notion, slack, jira).
- One namespace per MCP server. Do not nest more than one level (notion.pages.create is too deep).
R5. Anti-collision
- Tool names must be globally unique within a single agent's toolset.
- When two servers expose the same verb-noun, suffix the more specific server: slack.searchMessages vs gmail.searchMessages.
- Never silently override; raise an error at tool registration.
R6. Deprecation and aliasing
- Deprecated names stay in the registry as aliases for at least one minor version.
- Aliases route to the new tool but emit a deprecation warning in traces.
- Once removed, the name is permanently retired. Never reassign an old name to a new behavior.
R7. Reserved verbs
Use the canonical verb for each operation class:
| Operation | Canonical verb | Avoid |
|---|---|---|
| Read one | get | fetch, read, lookup |
| Read many | list or search | query, find |
| Create | create | add, new, make |
| Update | update | edit, modify, set |
| Replace | replace | overwrite |
| Delete | delete | remove, destroy |
| Run a procedure | run or execute | do, process |
Description vs name routing weight
Names carry the strongest routing signal because they appear at the head of every tool entry. Descriptions add disambiguation when names are similar. Treat the description as a tie-breaker, not a substitute for a clear name. Vendor docs explicitly recommend a precise name plus a short, action-oriented description (OpenAI function calling; Anthropic tool use). Treat any specific routing-weight percentage you see online as anecdotal; vendor APIs do not publish a numeric weighting.
Reference catalogue (30+ examples)
Notion
- notion.getPage
- notion.createPage
- notion.updatePage
- notion.deletePages
- notion.searchPages
- notion.listDatabases
- notion.runDatabaseQuery
- notion.archivePages
Slack
- slack.sendMessage
- slack.searchMessages
- slack.listChannels
- slack.getThread
- slack.updateMessage
GitHub
- github.getIssue
- github.createPullRequest
- github.listCommits
- github.runWorkflow
- github.searchCode
Jira
- jira.getIssue
- jira.createIssue
- jira.updateIssue
- jira.searchIssues
- jira.listProjects
Generic data
- db.runQuery
- kb.searchDocs
- cache.getValue
- cache.setValue
- secrets.getSecret
- email.sendEmail
- email.searchInbox
- calendar.listEvents
- calendar.createEvent
Anti-pattern catalogue
| Bad name | Why it fails | Fix |
|---|---|---|
| do_stuff | No verb-noun | inventory.runReconciliation |
| process_data_v2 | Version in name | Move version to description |
| Notion-Search-Pages-Tool | Mixed case + suffix | notion.searchPages |
| slack.send | Missing noun | slack.sendMessage |
| getOrCreateUser | Two verbs | Split into getUser + createUser |
| query | Generic, collides | db.runQuery |
| search_v2 | Pure version | Use deprecation alias instead |
| delete_thing_now_please | Pleading verb | inventory.deleteItem |
Multi-MCP collision strategy
When an agent loads tools from multiple MCP servers:
- Require a unique server namespace at registration time.
- Reject duplicate fully-qualified names with a clear error.
- Surface collisions in the agent boot log so operators see them before runtime.
- Provide a config-level alias map for downstream callers that depend on a previous name.
A/B testing methodology
- Hold the description constant; vary only the name.
- Run a fixed eval set of representative user requests through the agent loop.
- Measure: routing accuracy, hallucinated calls, tool-not-found rate, tokens consumed by tool listing.
- Require a statistically meaningful sample (e.g., bootstrap a confidence interval) before promoting a name.
- Record the winner in a naming changelog with the eval result.
Validation checklist
- [ ] Name matches ^[a-z][a-z0-9_](\.[a-z][a-z0-9_])?$ (or your camelCase equivalent).
- [ ] One verb + one primary noun.
- [ ] ≤ 32 chars target, ≤ 64 hard cap.
- [ ] Unique within agent toolset.
- [ ] Deprecation alias listed if renaming.
- [ ] Description starts with an imperative verb sentence.
- [ ] No version suffix in the name.
FAQ
Q: camelCase or snake_case?
Either works. Pick one per server and never mix. snake_case is slightly more common in Python ecosystems; camelCase reads cleaner in TypeScript MCP servers.
Q: How long can a tool name be?
Target 32 characters or fewer. Vendor APIs accept longer names, but shorter names are easier for the LLM to spell back accurately. Always check the current cap in the vendor docs you target.
Q: Should I include the resource ID in the tool name?
No. IDs belong in arguments, not names. A tool that targets a single resource by hard-coded ID is a configuration leak.
Q: What happens if two MCP servers expose the same name?
Reject the second registration. Prefix one with the more specific server name and document the rename in your changelog.
Q: Can I rename a tool after launch?
Yes, but keep the old name as a deprecation alias for at least one minor release and emit a warning in traces every time it is hit.
Related Articles
Agent Knowledge Base Specification: Structure, Refresh, and Versioning
Production specification for AI agent knowledge bases: document model, chunking strategies, metadata enrichment, refresh cadence, version pinning, and rollback.
Agent Multi-Step Reasoning Specification: ReAct, Plan-and-Execute, and Reflection
Specification for AI agent multi-step reasoning patterns: ReAct, Plan-and-Execute, Reflexion, Tree of Thoughts, and Self-Consistency.
Agent Permission Model Specification: RBAC, Scopes, and Tool-Level Auth
Production specification for AI agent permissions: RBAC, OAuth scope mapping, tool-level auth, consent prompts, time-bound grants, and MCP propagation.