Back to Blog
ai-agentsdesign-patternsreliabilityproduction

Tool Simplification Pattern: Reducing AI Cognitive Load

How we achieved a 71% reduction in AI decision-making burden by encoding intent in tool names instead of parameters.

by Viventhraa Rao6 min read

Tool Simplification Pattern: Reducing AI Cognitive Load

When building AI agents, we give them tools. The intuition is: more flexible tools = more capable agent.

This is wrong.

We found that flexible tools with many optional parameters actually hurt agent performance. The fix: encode decisions in tool names, not parameters.

Result: 71% reduction in decision-making burden and near-zero incorrect tool usage.

The Problem: Parameter Overload

AI agents face a hidden cost with powerful, flexible tools: every optional parameter is a decision point.

Consider this tool:

conversation_history_query({
  order?: "asc" | "desc",      // Decision 1
  limit?: number,               // Decision 2
  offset?: number,              // Decision 3
  role?: string,                // Decision 4
  afterDate?: string,           // Decision 5
  beforeDate?: string           // Decision 6
})

Every time the agent calls this tool, it must make 6 decisions. Multiply this across a conversation, and you get:

  • Cognitive overhead: Decisions compound
  • Incorrect usage: Agent copies parameters from history without understanding context
  • Unclear intent: Same tool serves multiple purposes
  • Self-reinforcing errors: Incorrect usage gets saved in history, agent mimics it

Real Example

We observed our agent copying subjectId from previous tool calls. User asks "Find discussions about authentication" → agent searches only one subject because it copied a subjectId from an earlier call.

The user wanted a full search. The agent's history poisoned its behavior.

The Solution: Tool Name = Decision

"The tool name is the decision, not the parameters."

Instead of one flexible tool, create multiple focused tools where the name expresses intent.

Before: One Flexible Tool

doThing({ mode?: "list" | "search" | "filter", ...options })

Agent thinks: "Which mode? Which options? What combination?"

After: Multiple Focused Tools

list_things()              // Clear: I want a list
search_things({ query })   // Clear: I want to search
filter_things({ criteria }) // Clear: I want to filter

Agent thinks: "I want to search" → uses search_things.

The hardest decision (what kind of operation?) is now encoded in the tool name.

This pattern solved our history-copying bug.

Before (5 Parameters)

conversation_semantic_search({
  query: string,
  subjectId?: string,   // Agent copies from history
  messageId?: string,   // Agent copies from history
  limit?: number,
  threshold?: number,
})

Agent sees subjectId in previous calls, copies it even when user wants full search.

After (2 Focused Tools)

// Default: search everything
search_messages({
  query: string,
  limit?: number = 5,
  threshold?: number = 0.3,
})

// Explicit: search specific subject
search_subject_messages({
  query: string,
  subjectId: string,    // Required, not optional
  limit?: number = 5,
  threshold?: number = 0.3,
})

Now:

  • Default is unscoped: Can't accidentally filter
  • Scoped version requires explicit ID: Forces intentionality
  • No parameter to copy: search_messages doesn't accept subjectId

Scenario Analysis

We measured decision reduction across 6 common scenarios:

ScenarioBeforeAfterReduction
Recent messages6 decisions183%
User messages yesterday6267%
Find discussions4175%
Search in subject5260%
Assistant last night7271%
Average5.61.571%

Design Guidelines

When to Split a Tool

1. Optional parameters change behavior

// Bad: mode changes what tool does
doThing({ mode?: "list" | "search" })

// Good: separate tools
list_things()
search_things({ query })

2. More than 3 optional parameters

  • 0-1 params: Perfect
  • 2-3 params: Good
  • 4-5 params: Warning
  • 6+ params: Split it

3. Parameters get copied from history

If you observe the agent copying values it shouldn't, split the tool so the problematic parameter doesn't exist in the default version.

How to Name Tools

Use action verb + scope + filter:

browse_messages()                    // No filter
browse_messages_by_role()            // Filter: role
browse_messages_by_date()            // Filter: date
browse_messages_by_role_and_date()   // Filter: both

The pattern:

  • do_thing() = base action
  • do_thing_by_X() = filtered by X
  • do_thing_by_X_and_Y() = filtered by both

Parameter Design

Make parameters required when:

  • Tool can't function without them
  • Value must be intentionally provided
  • You want to prevent accidental omission

Make parameters optional when:

  • There's a sensible default
  • It fine-tunes but isn't essential

Always provide sensible defaults:

// Bad: agent must decide every time
browse_messages({ limit: number, order: "asc" | "desc" })

// Good: sensible defaults
browse_messages({
  limit?: number = 5,
  order?: "asc" | "desc" = "asc"
})

Anti-Patterns

The Swiss Army Knife

// Bad: one tool does everything
manage_conversation({
  action: "list" | "search" | "filter" | "delete",
  target?: "messages" | "subjects",
  filters?: { ... },
  options?: { ... }
})

The Mode Parameter

// Bad: mode is manual tool selection
do_thing({ mode: "list" | "search" | "filter" })

// Good: mode IS the tool name
list_things()
search_things()
filter_things()

The Context Polluter

// Bad: optional IDs get copied
search({
  query: string,
  contextId?: string,  // Gets copied from history
})

// Good: scoped version is separate
search({ query })
search_in_context({ query, contextId })  // ID required

Results

On our conversation history system:

Before:

  • 5 complex tools
  • 3-6 parameters per tool
  • 5.6 decisions per call average
  • Frequent parameter copying bugs

After:

  • 9 focused tools
  • 0-3 parameters per tool
  • 1.5 decisions per call average
  • Zero parameter copying issues

Impact:

  • 71% reduction in decision burden
  • Zero accidental filtering
  • Self-documenting API (tool names explain themselves)

Quick Reference

Tool Naming

PatternExampleUse
action_things()list_subjects()Get all
action_things_by_X()browse_messages_by_role()Filter by one
action_scoped_thing()search_subject_messages()Specific scope

Red Flags

  • More than 3 optional parameters
  • Mode/type parameter that changes behavior
  • Boolean flags that change what tool does
  • Parameters frequently copied from history
  • Unclear what happens when parameter omitted

Takeaways

  1. Fewer decisions = better results
  2. Tool name = intent (not parameters)
  3. Required beats optional for intentional params
  4. Split when in doubt: Multiple simple > one complex
  5. Measure decision count as a design metric

The goal: tools that are easy to use correctly and hard to use incorrectly.


Building AI agents that need reliable tool use? Let's talk.

Share this post

Ready to ship reliable AI?

Book a discovery call to discuss your project.