Most real problems aren't solved by one tool. they're solved by a chain. The agent decides to invoke a tool, reads its output, decides the next one, and so on.
Your job: design two tools that compose naturally.
A user tells the crew: "notify everyone on the night shift that the rendezvous moved to 23:00".
To solve it, the agent has to:
list_crewmates_on_shift(shift_id).notify_crewmate(alias, message, channel).If the two tools are well designed, the agent composes the solution alone. If they're badly designed (output of one doesn't fit the input of the other, descriptions that don't mention the pattern), the agent falls short or invents intermediate steps that break.
For two tools to chain without friction:
crewmates: ["Em", "Ly"] and notify accepts alias: string, the agent iterates with zero transformation.notify_crewmate's description, mention it's used after list_crewmates_on_shift when there are multiple recipients.shift_id, the other tool that returns shifts uses the same name, not id_de_turno.7 deterministic criteria + 2 llm-judge:
channel with enum.The mental test: if I, reading only your schema (without having read this text), could understand how to compose these two tools to solve the rendezvous case, you passed.