pinecallDocs
The wire / Commands

Commands

What an app may ask the gateway to do, over the socket.

What reaches the gateway: the commands an app sends over its socket, each with the event it lands in the log as, and the verbs a supervisor sends to POST /v1/calls/{call}/verbs. The frame around a command is in README.md.

type scope lands as what it does
agent.configure agent agent.configured Declare or change what the agent is: voice, models, language, greeting, the full tool list.
agent.drain agent agent.draining This socket is leaving: hand it no new call for the agent, move the live calls it holds to the newest other socket holding the agent, or park them until one registers.
agent.register agent agent.registered The app's first message: this socket speaks for this agent and answers these endpoints.
agent.reply call turn.agent Make the model speak now, guided by an instruction it reads and the caller never hears: 'tell them a slot at 10:15 just opened'.
agent.say call turn.agent Make the agent say this text now, verbatim, outside the model's turn: a greeting, a read-back, a system notice.
call.attention call attention.requested, call.line, attention.answered Ask for a person without sending the caller anywhere: the call waits on hold until a supervisor takes the line, or until wait_s passes with nobody taking it.
call.callback call callback.requested Write down that the caller wants to be called back.
call.claim call call.claimed The caller said the code a page shows: bind this call to it, so the page follows the call from here.
call.dial agent call.dialing Place an outbound call as this agent.
call.dtmf call nothing Send touch tones down the line, for an IVR on the far end.
call.event call event.received Hand the agent a fact from the tenant's backend: a slot freed, an order shipped, a payment confirmed.
call.hangup call call.ended End the call from the app's side.
call.hold call call.line Put the caller on hold: they hear hold audio, the agent hears nothing.
call.log call custom Write a line of the app's own into the call's log.
call.mute call call.line Mute the agent: it keeps listening and thinking, produces no audio.
call.opt_out call nothing The caller asked never to be called again: their number joins the org's do-not-call list.
call.transfer call call.transferred Send the caller to another number, or bring that number into the call.
call.unhold call call.line Take the caller off hold.
call.unmute call call.line Unmute the agent.
dev.answer agent nothing The app's answer to a dev.request: what the verb produced, or the refusal it ended in — a status and a sentence, which the gateway hands the console verbatim.
participant.mute call track.unpublished Silence a participant for the rest of the call: their audio leaves the room, for everyone in it.
participant.remove call participant.left Put a participant out of the room.
ping agent pong Is the socket alive? The gateway answers pong.
prompt.set call prompt.changed Rewrite one block of the prompt, whole, by name.
room.invite call participant.joined Bring somebody else into the call's room.
room.send call room.sent Push a payload to a browser in the room over the DataChannel: a card to render, a form to open.
session.configure call state.changed, agent.configured Set up this one call before the first turn: the app's initial state, and any config that differs from the agent's defaults for this caller.
state.set call state.changed The app's state changed and this is all of it.
supervisor.verb call supervisor.said, supervisor.whispered, supervisor.took_over, supervisor.released, supervisor.transferred, supervisor.ended One supervise verb, from the human the endpoint named.
tool.result call tool.result The app ran the tool the platform asked for in tool.call and this is what came back.
tools.set call tools.changed The tools the model may see now.

agent.configure#

Declare or change what the agent is: voice, models, language, greeting, the full tool list. Only the fields sent change.

Lands in the log as: agent.configured.

field type required meaning
config AgentConfig yes What an app declares about its agent: the prompt's layout, the language, the tools, whether it searches its bases itself, and who may see and send what.

agent.drain#

This socket is leaving: hand it no new call for the agent, move the live calls it holds to the newest other socket holding the agent, or park them until one registers. The gateway answers agent.draining; the socket closes once its tools in flight have answered.

Lands in the log as: agent.draining.

No fields.

agent.register#

The app's first message: this socket speaks for this agent and answers these endpoints. The gateway answers agent.registered, or error.

Lands in the log as: agent.registered.

field type required meaning
routes Route[] yes The endpoints this agent answers. A number may belong to one agent at a time.
sdk string no The SDK and version the app runs: pinecall/2.0.0.
host string no The machine the app runs on, as it names itself: what a person reading the org's live processes reads to tell a laptop from a server.
takes_unclaimed boolean no Whether this socket may be handed a call that named no app — every phone call, and every web call that did not ask for one. A console holds the agent to serve the call it opens itself and says false, so a real caller is never answered from somebody's terminal. Absent means yes.
answers_dev boolean no Whether this socket answers the console's dev verbs for the agent (POST /v1/agents/{slug}/dev/…): the companion pinecall start holds beside the process serving the class. view.render still goes to the socket serving the call, whose class draws the panel. Absent means no.

agent.reply#

Make the model speak now, guided by an instruction it reads and the caller never hears: 'tell them a slot at 10:15 just opened'. On livekit's session.generate_reply; the sibling of agent.say, which speaks verbatim. The reply lands as turn.agent.

Lands in the log as: turn.agent.

field type required meaning
instructions string yes What the model is told before it speaks, in words the model reads. Not what it says.
allow_interruptions boolean no Whether the caller may cut it short. Default true.

agent.say#

Make the agent say this text now, verbatim, outside the model's turn: a greeting, a read-back, a system notice. The reply lands as turn.agent.

Lands in the log as: turn.agent.

field type required meaning
text string yes What to say, word for word.
allow_interruptions boolean no Whether the caller may cut it short. Default true; a legal notice sets false.

call.attention#

Ask for a person without sending the caller anywhere: the call waits on hold until a supervisor takes the line, or until wait_s passes with nobody taking it. attention.answered says which.

Lands in the log as: attention.requested, call.line, attention.answered.

field type required meaning
reason string yes Why a person is wanted, in the app's words: what the supervisor reads before taking the line.
wait_s number yes How long the caller waits for somebody to take the line before the agent has it back, above 0 and 900 at most (fifteen minutes). The app's to choose: there is no default.

call.callback#

Write down that the caller wants to be called back. Lands as callback.requested with via agent; placing the call is the app's.

Lands in the log as: callback.requested.

field type required meaning
number string yes The number to call back, E.164.
when string no When the caller asked to be called, in their words or as a date: tomorrow morning, 2026-09-23T10:00.
note string no What the call back is about, for whoever places it.

call.claim#

The caller said the code a page shows: bind this call to it, so the page follows the call from here. Refused with no_code when nobody issued that code for this agent, it expired, or another call already took it.

Lands in the log as: call.claimed.

field type required meaning
code string yes The four digits, as the page shows them. Matches ^[0-9]{4}$.

call.dial#

Place an outbound call as this agent. The new call's log opens with call.dialing; call.started follows when the far end answers.

Lands in the log as: call.dialing.

field type required meaning
to string yes The number to call, E.164.
from string no The number to show, E.164. Absent means the agent's first phone route.
caller Contact no Who is on the line, as far as the platform knows.
metadata object no Anything the app wants handed to the session at start, sealed by the platform, never seen by the far end.

call.dtmf#

Send touch tones down the line, for an IVR on the far end.

field type required meaning
digits string yes The tones to send, in order: 0-9, *, #. A comma is a short pause.

call.event#

Hand the agent a fact from the tenant's backend: a slot freed, an order shipped, a payment confirmed. Lands as event.received with source app. The agent must have declared the name in its events with app among the senders, or the gateway answers error and nothing touches the log.

Lands in the log as: event.received.

field type required meaning
name string yes The event's name, dotted, as the agent declared it: slot.released.
data object yes Whatever comes with it, as JSON, for the app's handler.

call.hangup#

End the call from the app's side. call.ended follows with reason agent_hung_up.

Lands in the log as: call.ended.

field type required meaning
reason string no Why, in the app's words, for the log.

call.hold#

Put the caller on hold: they hear hold audio, the agent hears nothing.

Lands in the log as: call.line.

No fields.

call.log#

Write a line of the app's own into the call's log. It gets a seq like everything else and lands as custom.

Lands in the log as: custom.

field type required meaning
name string yes The app's name for the line.
data object yes Whatever the app wants kept.

call.mute#

Mute the agent: it keeps listening and thinking, produces no audio.

Lands in the log as: call.line.

No fields.

call.opt_out#

The caller asked never to be called again: their number joins the org's do-not-call list. The gateway writes it, whichever process runs the call, as an opt-out of the org's environment with the call's id beside it (GET /v1/org/consents/{number}); no call of the org reaches the number again until a consent is recorded at POST /v1/org/consents. Nothing lands in the log: an SDK that predates the command would refuse an entry it has no shape for. Refused with no_session when the call is not running here, and with bad_shape on a call with no phone number at its far end (the widget, a chat).

Lands in the log as: nothing.

field type required meaning
note string no What the caller said, in their words, kept with the opt-out.

call.transfer#

Send the caller to another number, or bring that number into the call. call.transferred says whether it worked, and which mode it was.

Lands in the log as: call.transferred.

field type required meaning
to string yes The destination number in E.164 form, or a SIP URI.
mode TransferMode no Absent, the runtime picks: cold when the caller is on a SIP leg, warm when they are in a browser. A written conversation has no line and refuses both.

call.unhold#

Take the caller off hold.

Lands in the log as: call.line.

No fields.

call.unmute#

Unmute the agent.

Lands in the log as: call.line.

No fields.

dev.answer#

The app's answer to a dev.request: what the verb produced, or the refusal it ended in — a status and a sentence, which the gateway hands the console verbatim. One of the two, never both.

field type required meaning
id string yes The dev.request this answers.
result object no What the verb produced, as the verb's own answer: the call that opened, the run's id, the roster, the score.
refused DevRefusal no Why the verb did not run, in the words the console shows: the status it travels under, and the sentence.

participant.mute#

Silence a participant for the rest of the call: their audio leaves the room, for everyone in it. Lands as track.unpublished for their microphone. There is no unmute; a leg that must speak again is invited again.

Lands in the log as: track.unpublished.

field type required meaning
identity string yes Whom to silence, by the identity participant.joined gave them.

participant.remove#

Put a participant out of the room. Lands as participant.left with reason participant_removed. Removing the caller ends the call.

Lands in the log as: participant.left.

field type required meaning
identity string yes Whom to remove, by the identity participant.joined gave them.

ping#

Is the socket alive? The gateway answers pong.

Lands in the log as: pong.

No fields.

prompt.set#

Rewrite one block of the prompt, whole, by name. The name must be one of the agent's declared blocks, or one of the default four; anything else is refused with the name.

Lands in the log as: prompt.changed.

field type required meaning
name string yes The block to rewrite, by the name its PromptBlockSpec declares.
text string yes The block's new text, whole.

room.invite#

Bring somebody else into the call's room. A second SIP leg dialed to a number is the warm path: the agent stays on with the caller while the other side answers. Lands as participant.joined when they arrive, or error when they do not.

Lands in the log as: participant.joined.

field type required meaning
to string yes A number in E.164 form for sip; an identity for participant.
kind `"sip" "participant"` yes

room.send#

Push a payload to a browser in the room over the DataChannel: a card to render, a form to open. Lands as room.sent with the size, never the payload. The widget listens on pinecall.ui; a topic of the tenant's own reaches the tenant's own page code.

Lands in the log as: room.sent.

field type required meaning
topic string yes The DataChannel topic: pinecall.ui, or the tenant's own.
data object yes The payload, as JSON. The browser gets it whole; the log keeps its size.
to string no One participant's identity. Absent: everyone in the room.

session.configure#

Set up this one call before the first turn: the app's initial state, and any config that differs from the agent's defaults for this caller.

Lands in the log as: state.changed, agent.configured.

field type required meaning
state object no The app's state at the start of the call, whole.
config AgentConfig no What an app declares about its agent: the prompt's layout, the language, the tools, whether it searches its bases itself, and who may see and send what.

state.set#

The app's state changed and this is all of it. The platform logs state.changed and re-renders.

Lands in the log as: state.changed.

field type required meaning
state object yes The whole state after the change.
changed string[] no The names of the fields that changed, when the app knows. Absent means: compare yourself.

supervisor.verb#

One supervise verb, from the human the endpoint named. Each verb lands in the caller's log as its own supervisor.* entry before the session acts on it.

Lands in the log as: supervisor.said, supervisor.whispered, supervisor.took_over, supervisor.released, supervisor.transferred, supervisor.ended.

field type required meaning
by Supervisor yes The human who sent a supervise verb, as the token that let them in names them.
verb Verb yes One supervise verb, told apart by its verb field.

tool.result#

The app ran the tool the platform asked for in tool.call and this is what came back. The model reads the output or the error.

Lands in the log as: tool.result.

Data: ToolResult, in Shapes.

tools.set#

The tools the model may see now. The full list was declared in agent.configure; this is the subset whose when allows them in this state.

Lands in the log as: tools.changed.

field type required meaning
tools ToolSpec[] yes The visible tools, whole specs, so a tool can change its description with the state.

Verbs#

SayVerb#

Make the agent say this, verbatim, to the caller. Logged as supervisor.said.

field type required meaning
verb "say" yes The verb.
text string yes What the agent will say, word for word.

WhisperVerb#

Tell the agent something the caller never hears. It reaches the agent as an instruction for its next reply; logged as supervisor.whispered.

field type required meaning
verb "whisper" yes The verb.
text string yes The instruction for the agent, in words the model reads.

TakeoverVerb#

The supervisor takes the line: the agent goes quiet and the supervisor's audio replaces it. Logged as supervisor.took_over.

field type required meaning
verb "takeover" yes The verb.

ReleaseVerb#

The supervisor hands the line back to the agent, which resumes with the history intact. Logged as supervisor.released.

field type required meaning
verb "release" yes The verb.

TransferVerb#

Send the caller to another number. Logged as supervisor.transferred, then call.transferred says whether it worked.

field type required meaning
verb "transfer" yes The verb.
to string yes The destination number in E.164 form, or a SIP URI.
mode TransferMode no Absent, the runtime picks, as call.transfer does.

EndVerb#

Hang up on the caller's behalf, at once: a sentence playing and a reply still being written are cut, not finished. Logged as supervisor.ended, then call.ended with reason supervisor_ended.

field type required meaning
verb "end" yes The verb.
reason string no Why, in the supervisor's words, for the log.

Verb#

One supervise verb, told apart by its verb field.

One of SayVerb, WhisperVerb, TakeoverVerb, ReleaseVerb, TransferVerb, EndVerb, told apart by verb.