Skip to main content

Writing Tools

Knowing how to write tools is crucial for agent building.

Do not trash the context

Lets say you have a tool called book_appointment(phone_number) and a tool called get_phone_number().
  • book_appointment(phone_number) will book an appointment for the given phone number.
  • get_phone_number() will get the phone number of the customer.
Then naturally, you will write a system prompt that says:
Before booking an appointment, you need to get the phone number of the customer.
The model will in turn call the get_phone_number() tool to get the phone number of the customer and then book the appointment. How does the context look like in this case?
The ProblemThe phone number is not needed in the context window at all! The model uses it one time to call book_appointment() tool, and then it is not needed anymore. But it does stay in the context window for the whole duration of the call.It double-wastes space because its both the result of the get_phone_number() tool and the argument of the book_appointment() tool.
A much better solution would be to just call book_appointment() tool and inside book_appointment() tool call get_phone_number() tool.
Best PracticeWhat happens inside tools does not enter the context window. Only parameters and results enter the context window.Offload as much work as possible to tools.

Naming tools

This is so important. Some of you are not giving the model the chance to be right, you are setting it up to fail with bad tool names.
  1. Tool names should be short and use simple, common, english words.
  2. Tool names should be descriptive of the tool’s purpose.

Bad Examples

What do these even mean?
  • verify() - What does it verify?
  • isOpen() - Whats open?
  • get_context() - What context?
  • init() - ???

Good Examples

Clear and descriptive:
  • identify_customer()
  • book_appointment()
  • answer_question()

Namespacing by Skill

Tool names should be namespaced based on their “Skill”.

Inconsistent Naming

Hard to guess the pattern:
  • schedule_technician()
  • cancel()
  • re_schedule()

Consistent Naming

Grouped by domain:
  • service_schedule()
  • service_cancel()
  • service_rebook()

Tool parameters

Tool parameters should be also as simple as possible.
If you can fetch an argument inside a tool, do it. Don’t let the model pass something you can fetch from inside the tool.
Example: Instead of update_email(user_id, new_email), use update_email(new_email) and infer the user_id from the authenticated session context within the tool implementation. This saves tokens and reduces hallucination risk.

Prompting tools

Give your model examples in the prompt on how to use the tools. Make sure that the examples Match the actual signature of the tool.
User: "Book a meeting with John."
Assistant: tool_use(name="calendar_schedule", arguments={"participants": ["John"]})

Tool outputs

Return the minimal possible JSON object you can from the tool call. Don’t return irrelevant information that will trash the context. Return LLM-readable text inside JSON keys.

Avoid

  • Raw timestamps (e.g., 1678900000)
  • Complex nested objects irrelevant to the conversation

Prefer

  • Human-readable strings (e.g., "Monday, Dec 2nd")
  • Semantic status codes (e.g., "status": "active")