---
title: "Design tools like a small public API · Agent Wranglers"
url: https://agentwranglers.se/playbook/ai-features/structured-output-and-tools/tool-design
updated: 2026-10-20
licence: "All rights reserved"
---

# Design tools like a small public API

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Structured output and tools](https://agentwranglers.se/playbook/ai-features/structured-output-and-tools)
- Rule: Give each tool one clear job, a verb-noun name, a description of when to use it and a strict input schema. Validate every argument in code before the tool runs.
- How: Expose few tools, ideally 20 or fewer per request, because models choose worse among many. Name them like `find_order` and `create_return`, never `do_action`. Describe in one or two sentences what the tool does and when not to use it. Use enums and formats instead of free text. Set `strict: true` on each tool definition, as the OpenAI and Anthropic APIs both allow. Check the user's rights inside the tool, as [least power](https://agentwranglers.se/playbook/adversarial-testing/ai-agents-and-models/least-privilege-tools) requires.
- Check: A test loads every tool definition. Each has a name matching `^[a-z]+_[a-z_]+$`, a description of at least 40 characters, `additionalProperties: false` and no untyped parameter. A call with a wrong argument type is rejected before the tool body runs.

Example:

```ts
export const findOrder = {
  name: 'find_order',
  description: 'Look up one of the signed-in customer\'s orders by its number. Do not use it to search by product name.',
  input: z.object({ orderNumber: z.string().regex(/^[A-Z]-\d{4,}$/) }).strict(),
  run: async ({ orderNumber }: { orderNumber: string }, user: User) => orders.findForCustomer(orderNumber, user.id),
};
```

```python
class FindOrderInput(BaseModel):
    model_config = {"extra": "forbid"}
    order_number: str = Field(pattern=r"^[A-Z]-\d{4,}$")

def find_order(raw_args: dict, user: User) -> dict:
    args = FindOrderInput.model_validate(raw_args)
    return orders.find_for_customer(args.order_number, user.id)

find_order.description = "Look up one of the signed-in customer's orders by its number. Do not use it to search by product name."
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers ai features playbook: https://agentwranglers.se/playbook/ai-features/structured-output-and-tools/tool-design`.

- Previous: [Give the model a way to say it does not know](https://agentwranglers.se/playbook/ai-features/structured-output-and-tools/allow-unknown)
- Next: [Return errors the model can act on](https://agentwranglers.se/playbook/ai-features/structured-output-and-tools/tool-errors-for-models)
- [Structured output and tools](https://agentwranglers.se/playbook/ai-features/structured-output-and-tools)
