One Big update_task Tool or Three Small Ones? Your To-Do Agent Only Sees the Names and Descriptions

A to-do agent archived a task you meant to finish, and the tool was working fine. The model picks tools from a short menu of names and descriptions, so how you split that menu decides how often it picks wrong.

One Big update_task Tool or Three Small Ones? Your To-Do Agent Only Sees the Names and Descriptions

You tell your to-do agent "I finished the dentist booking," and the task vanishes. It wasn't marked done. It was archived, so it never shows up in your weekly "what I got done" summary. The tool did exactly what it was asked to do. The model asked for the wrong thing, because the way the tool was shaped made the wrong thing easy to ask for.

When you build your first agent, one of the earliest design calls is how to carve up its tools. Do you write one flexible tool that does everything to a task, or several small tools that each do one thing? This post gives you a way to decide, and it starts with what the model can actually see.

🌱 What the model sees when it picks a tool

When an agent decides which tool to call, it doesn't read your code. It reads three things:

  1. The tool's name
  2. The tool's description
  3. The parameter schema: field names, types, allowed values, and any per-field descriptions

That's the whole menu. Your function might have careful validation and a well-named enum deep inside it, but if the schema shows a field called status of type string, then from the model's point of view "archived", "done" and "closed" all look like reasonable values.

So the real question is not "how many tools should I have?" It's this: can the model tell, from the menu alone, which call matches what the user just said?

The two designs

Here's the to-do agent built both ways.

Option A: one general tool

{
  "name": "update_task",
  "description": "Update a task.",
  "parameters": {
    "task_id": "string",
    "status": "string",
    "title": "string (optional)",
    "due_date": "string (optional)"
  }
}

Option B: small, single-purpose tools

{
  "name": "complete_task",
  "description": "Mark a task as done because the user finished it. Done tasks appear in the weekly summary.",
  "parameters": { "task_id": "string" }
}
{
  "name": "archive_task",
  "description": "Hide a task the user no longer intends to do. Archived tasks do NOT count as completed.",
  "parameters": { "task_id": "string" }
}
{
  "name": "reschedule_task",
  "description": "Move a task's due date. Use when the user says later, next week, or postpones.",
  "parameters": { "task_id": "string", "new_due_date": "string, YYYY-MM-DD" }
}

In Option A, the model has to guess the right string for status. "I finished it" could reasonably become "done", "complete", "closed" or "archived", and nothing on the menu says which ones exist or what they mean. In Option B the choice sits in the tool name, and the description spells out the one difference that matters to you: archived tasks don't count as finished.

✅ When small tools win

Split a tool into several when any of these hold:

  • The actions have different consequences. Complete and archive both remove a task from your list, but only one shows up in your summary. If mixing two actions up would bother the user, give each its own name.
  • One action is hard to undo. Deleting, sending, paying and sharing should never be a value inside a general tool's parameter. A separate delete_task lets you require confirmation for that call alone, log it, or keep it away from some agents entirely.
  • The user's words map cleanly to verbs. People say "I finished", "push it to Friday", "drop that one". If each phrase points to one tool name, the model's job is mostly matching words.
  • The parameters differ. If rescheduling needs a date and completing needs nothing, one combined tool ends up with optional fields that are only valid in some combinations. That's a puzzle the model has to solve on every call.

When one general tool is fine

Small tools aren't free. Each one adds to the menu, and a long list of similar names makes choosing harder in a different way. Keep a single tool when:

  • The fields are independent edits with the same consequence. Renaming a task, changing its notes and setting its colour are all harmless edits. An edit_task_details tool with optional title, notes and colour fields works well, because no combination of them can surprise the user.
  • The values are closed and described. If you keep a general tool, swap the free-form string for an enum and describe every value:
"status": {
  "type": "string",
  "enum": ["open", "done", "archived"],
  "description": "done = user finished it (counts in weekly summary). archived = user dropped it (does not count)."
}

That one change closes most of the gap. The model can no longer make up "closed", and the difference between the two values is written right where the choice gets made.

🔍 A quick test before you ship

Before you settle on a tool layout, run this five-minute check:

  1. Write out ten things a real user would say to the agent: "done with the dentist thing", "forget the gym task", "move taxes to next month".
  2. For each one, read only the tool names, descriptions and schemas. Don't look at your code.
  3. Ask: is there exactly one obviously correct call?

If any phrase leaves you choosing between two reasonable calls, the model will face the same choice and sometimes pick the other one. Fix that by splitting the tool, adding an enum, or rewriting a description so it names the difference. Don't rely on the system prompt to explain it. Instructions in the system prompt sit far from the moment of choice, while the tool description sits right next to it.

⚠️ A common half-fix

Many first agents try to patch Option A with a line in the system prompt: "When the user finishes a task, set status to done, not archived." That works until the conversation gets long, or someone adds a second tool with a state field, or the user says "wrap up the dentist one." The rule lives in one place and the decision happens in another. Putting the distinction into the tool itself, through its name, its enum or its description, keeps them together.

The takeaway

Treat your tool list as a menu written for a reader who will never see the kitchen. If two actions have different consequences for the user, give them different names. If they're just different fields of the same harmless edit, one tool with a well-described schema is fine. And whichever layout you choose, test it the way the model meets it: by reading the menu, not the code.

Keep reading

Similar posts

Matched on shared tags and category — the more bars, the stronger the overlap with what you just read.