pinecallDocs
Key concepts / Tools

Tools

A method the model may call: its docstring, its arguments, confirmation, masking and timeouts.

A tool is a method the model may call. You write its description as a docstring and its arguments as the method's parameters; Pinecall builds the schema, runs the call and logs it.

What is a tool?#

A method decorated with @tool(). When the model calls it, the method runs in your process with the arguments the model gave, and what it returns is what the model reads next.

agents/clinica-norte/agent.tsx
/** Free slots on one day, for one specialty. Always call it for a day the patient names. */
@tool({ stage: ["choose", "book"], preview: 2 })
async freeSlots(day: string, specialty: string): Promise<Slot[]> {
  const date = dayNamed(day, this.call.today ?? "");
  if (!date) throw new NotADay(day);
  this.slots = await this.agenda().free(date, specialty);
  this.stage = this.slots.length > 0 ? "book" : "choose";
  return this.slots;
}
agents/clinica-norte/agent.py
@tool(stage=("choose", "book"), preview=2)
def free_slots(self, day: str, specialty: str) -> list[dict]:
    """Free slots on one day, for one specialty. Always call it for a day the patient names."""
    date = day_named(day, self.call.today or "")
    if not date:
        raise NotADay(day)
    self.slots = self.agenda.free(date, specialty)
    self.stage = "book" if self.slots else "choose"
    return self.slots

The docstring is the description, an Args: section describes each parameter, and the annotations are the types: a Literal is an enum, a default makes a parameter optional. The options are the same, as keywords: when=, stage=, confirm=, announce=, preview=, pii=, timeout=. A def tool runs on a thread, an async def one on the event loop.

agents/clinica-norte/agent.rb
# Free slots on one day, for one specialty. Always call it for a day the patient names.
tool stage: %i[choose book], preview: 2
def free_slots(day:, specialty:)
  date = day_named(day, call.today.to_s)
  raise NotADay, day unless date
  self.slots = agenda.free(date, specialty)
  self.stage = slots.any? ? :book : :choose
  slots
end

The comment above tool is the description, and the keyword arguments are the parameters. The options are the same: when:, stage:, confirm:, announce:, preview:, pii:, timeout:, and params: for the types ({ day: String }).

How it works#

  • The docstring is the description, and it is required. Without one no model can choose the tool, so the class is refused before a call happens. It is read as one line: line breaks are joined, and the first @tag line ends it.
  • The signature is the schema. Parameter names and types become the JSON Schema the model fills. string, number, boolean and arrays of them are typed; an interface or a type declared in the same file is read field by field; any other type becomes an open object. An optional parameter is not required.
  • The arguments are checked before the method runs. A missing required argument, or a value of the wrong JSON type, fails the call without running the method.
  • Writes inside a tool are authored by the tool. The change log names it, and so does the console.

Options#

option what it does
when: (state) => boolean shows the tool only while this returns true for the current state
stage: "book" or ["choose", "book"] shows the tool only in these stages. See Stages
confirm: "Booked: {{result.when}}." a sentence read to the caller after the tool runs, and it marks the tool irreversible
announce: "Let me check the agenda." what the agent says as the tool starts, when the model's turn said nothing itself
preview: 2 how many items of an array result the model sees. The state keeps them all
pii: ["name", "phone"] parameters masked in the call's log
timeout: 8 seconds Pinecall waits for the method. 30 unless set, 300 at most
params: z.object({ … }) an explicit zod schema, when the signature is not enough

when and stage together must both hold.

Confirmation#

confirm is a receipt. Once the tool has run, Pinecall fills the sentence and says it, word for word, before the model replies. {{name}} is filled from an argument, and {{result.when}} from the tool's return value:

TypeScript
@tool({ stage: "book", confirm: "Booked: {{result.when}} with {{result.professional}}." })
async book(slot: string): Promise<Booking> { … }

confirm does not hold the tool until the caller agrees. The tool has already run when the sentence is said, so write it as a receipt, never as a question like "Shall I book it?". Make the model ask before it calls the tool: say so in the docstring and in the view.

Announcing a tool#

A tool that takes a second or two leaves the caller in silence, or on the hold melody. announce gives the agent a sentence to say as the tool starts:

TypeScript
@tool({ stage: "choose", announce: "Let me check the agenda." })
async freeSlots(day: string): Promise<Slot[]> { … }

It is said only when the model's turn said nothing itself. A model that answers "One moment, I will look at the agenda" and calls the tool in the same turn has already announced it, so the sentence stays unsaid: the caller never hears it twice. In a written chat it is a line of the agent's like any other.

A tool with confirm is declared irreversible to the gateway; every other tool is read. You do not set this yourself.

When a tool fails#

A tool that throws does not crash the call. The error's message becomes the tool's result, marked as an error, and the model reads it and can act on it. Throw a sentence a model can use, such as "Tuesday has no free slots", never a stack trace.

Ask the model for a word, not a record. book(slot: string), with the method looking the id up among the slots it offered, is safer than book(slot: Slot). Asked for a whole object, a model fills in one it was never offered.

Refused when the class loads#

Each of these stops the class before any call, with a message that says what to write:

mistake message
no docstring tool book: without a docstring no model can choose it; write a /** one line */ above the method
a name that is not one word a tool name is one word a model can call, not …
pii names a parameter the tool does not have tool book: pii names parameters the tool has; unknown: …
stage on a class with no stage field tool book: stage names a value of this agent's own stage field, and … declares none
@tool on something that is not a method @tool goes on a method; … is not one

Next steps#