pinecallDocs
Key concepts / Personas

Personas

A caller a model plays: a goal, a manner, what it expects of the agent, how it acts on the line; Pinecall's library, and callers written for you.

A persona is a caller a model plays: a goal, a way of speaking, the facts they know about themselves, what they expect of the agent — and, on a spoken call, how they act on the line. It improvises every turn, so it finds the conversations you did not think to write as goldens.

What is a persona?#

A persona belongs to one agent and is kept by the gateway, the same in sandbox and production. Two agents of one org can each have a caller with the same name. Your repository holds none of them: you write them with pinecall personas or on the console's Harness ▸ Personas screen, and no deploy is needed. Pinecall's own library of callers comes first in every list, each one off until you switch it on.

Pinecall's library#

Every agent's list starts with Pinecall's personas, each off until pinecall personas on <name> — or the switch on the console — turns it on for that agent (the org's switch is the default, the agent's wins). The nightly plays what is on. One of them is never written nor dropped: write your own under another name.

tag personas what they test
realism in-a-hurry, wrong-number, non-native, interrupts, changes-mind, elderly-slow, angry-repeat-caller, asks-for-a-person the calls a real day brings: haste, confusion, a second language, a caller who talks over the agent, who changes their mind, who needs it twice, who is furious, who wants a person
red-team prompt-leak, data-leak, off-task, harmful, unauthorized-action the calls somebody makes on purpose: the prompt asked for, another customer's details, help with something else, something dangerous, an action the caller may not take

Each comes with what it expects of the agent, and some with how they act on a spoken line: interrupts talks over 60% of the agent's answers, in-a-hurry and angry-repeat-caller 30%, elderly-slow leaves 2.5 s before each line and non-native 1 s. pinecall personas show interrupts prints one whole.

Write one#

Terminal
pinecall personas add hurried \
  --about "Calls from the street, in a rush" \
  --goal "move the appointment to Tuesday afternoon without giving more details than needed" \
  --style "short sentences, interrupts, gives one fact at a time" \
  --fact "their name=Ana García" --fact "their phone=600 000 001" \
  --expect "The agent should offer a time on Tuesday afternoon." \
  --expect "The agent should confirm the new time before moving the appointment." \
  --interrupts 0.3 --pause 1
flag what it is
--goal what the caller wants from the call. Required
--style how they talk. Required
--about one line about who they are
--fact 'what=said' a fact they know about themselves, repeatable
--llm the model that plays them: vendor/model, a vendor, a model, or haiku, sonnet, opus
--tts, --voice the vendor and voice their lines are read in on a spoken call
--expect '…' one thing the agent should do, repeatable; see below
--tag x a word to find them by, repeatable
--interrupts 0–1, --pause s how they act on a spoken line; see below

A name is lower-case letters and digits joined by hyphens: hurried, price-shopper. A vendor or a voice Pinecall does not have is refused when you write it, not in the middle of a run.

Terminal
pinecall personas                      # one line each: name, style, goal
pinecall personas show hurried         # the whole caller, what it expects and how it acts
pinecall personas edit hurried --llm haiku
pinecall personas rm hurried

In a project with several agents, add --agent <name> to say whose callers you mean.

What they expect of the agent#

--expect lines are the caller's own pass mark: one verifiable demand each, written "The agent should …", about something the agent's prompt or knowledge says it can do — never about how the call ends. At hang-up, the library's expected-outcome judge reads the whole call against them, each line graded yes, no, or blocked (the call never got that far):

answer means
held every line is yes
broken a line is no
na every line is blocked

The reason gives each line its answer and the line of the call that decided it. The lines are never told to the model playing the caller: a caller that knows its pass mark plays to it. The judge is a separate model call, never the one that played the caller. They travel on the call itself (call.started.expects), so a call is judged by what it was made under even after you edit the persona. A persona that expects nothing gets na from expected-outcome without a model being asked.

How they act on a spoken line#

On a spoken call the caller does more than talk. --interrupts 0.3 makes it talk over that share of the agent's answers — a second or two in, as a person cutting in does, never at the first word — so the agent's barge-in is tested for real: did it stop, did it pick up what the caller said, did it lose the thread. --pause 2 leaves two seconds of silence before each of its lines: a caller who thinks, or looks for a paper. A persona may also carry its own line noise (interferer_db, packet_loss), which pinecall simulate --background-noise and --packet-loss override for one call. A written call ignores all of it.

Run it#

Terminal
pinecall simulate --persona hurried            # a written call, printed as it happens
pinecall simulate --persona hurried --judge    # ...then every judge's verdict
pinecall simulate --persona hurried --voice    # a spoken call on a real line
pinecall personas try hurried                  # the same as simulate, without --judge
flag what it does
--judge waits for the call to be judged and prints each verdict and what judging cost. Exits 1 when a judge answered broken
--turns <n> how many lines the caller improvises before hanging up. Default 15
--voice a real spoken call: a room, the agent dispatched into it, the caller read out loud
--listen plays the call on this machine's speakers while it happens. Turns --voice on
--background-noise <dB> a television behind the caller, that many dB under them. Spoken calls only
--packet-loss <share> that share of the caller's packets never arrive, from 0 to 1 (0.02), as pinecall test --voice takes it. Spoken calls only

You can also run a persona from the console's Harness ▸ Simulations screen.

How a persona is played#

Every caller line is one request to a model on the gateway: the persona's own --llm, or the gateway's default model. On a spoken call, the caller speaks in the persona's own --voice when it set one, else in a voice from the operator's list for the agent's language, never the voice the agent uses, so you can tell the two sides apart by ear. The caller waits for the agent's opening before its first line.

A spoken caller's lines and voice are paid for by the platform, so each call has a spending ceiling; the caller hangs up when the call reaches it, and the answer says so.

Callers written for the agent#

Terminal
pinecall personas generate 3 --about "price questions"
pinecall personas generate --template in-a-hurry --save
pinecall personas generate --from-call call_29d7c7

The judge model reads what the agent is — its prompt as its newest call ran it, its tools, its knowledge — and writes callers for it, each with what it expects. --about steers them, --from-call makes them like a real call's caller, --template writes one of Pinecall's again for this agent. They are printed and saved nowhere; --save keeps every one as the agent's own, and the console's Generate… lets you keep them one by one. Each caller written is one eval — none when your judges run on your own key.

Personas in files#

Older projects kept personas as files in test/<agent>/personas/. pinecall personas push sends them to the gateway once, as that agent's callers, along with the state a known caller's call opens in. It stops at the first caller the gateway refuses and names what landed and what is still only a file. The files are yours to delete afterwards.

Next steps#