Speaking Turns¶
Whether an AI channel's agent speaks, offers or stays silent on an event. See the Speaking Turns guide for usage.
SpeakPolicy ¶
Bases: ABC
Decides, on every event an AI channel would answer, whether its agent speaks.
A policy that raises, or does not decide within the channel's bound, does
not silence the agent: the channel speaks and reports the reason
fallback. An instruction, a task's hand-back among them, never reaches
a policy: the application asked for that turn.
forget_room ¶
Drop what the policy keeps about room_id: the channel calls it when it joins or leaves the room, so a room that reuses an id inherits nothing (RFC §6.4).
SpeakTurn
dataclass
¶
What a policy judges: the event, and the conversation and people around it.
recent
class-attribute
instance-attribute
¶
The conversation before it, oldest first, the agent's own answers included: the room's messages, without tool records.
people
class-attribute
instance-attribute
¶
Who takes part besides the agent, by name: one name is a conversation between the agent and one person. The room's active participants that are neither agents nor bots, or the distinct speakers of the recent events when more (one microphone may carry several diarized voices).
channel_id
class-attribute
instance-attribute
¶
The agent's channel: its own answers in recent come from it.
speakers
class-attribute
instance-attribute
¶
Who said event and each of recent, by event id, by the label the
AI context gives them (RFC §6.4): the sender's name, the channel for a
sender with none (@sms1), and the rank of a sender whose name reads
like an earlier one's (ALICE (2), not Alice).
thought
class-attribute
instance-attribute
¶
What the agent has in mind, when its channel has a thinker.
cut
class-attribute
instance-attribute
¶
The agent's answer cut off just before event, when it has not spoken
since.
CutReply
dataclass
¶
SpeakDecision
dataclass
¶
Whether the agent speaks on a turn, and what it reads if it does.
reason
class-attribute
instance-attribute
¶
Why, in a few words, for logs and ON_SPEAK_DECISION.
judgments
class-attribute
instance-attribute
¶
What the policy weighed, by name: what makes a decision measurable.
notes
class-attribute
instance-attribute
¶
Blocks the turn's notes carry when the agent speaks or offers (RFC §6.4).
final
class-attribute
instance-attribute
¶
A silence the agent's thought will not change (a room that listens, a voice only listened to): the thinker thinks, and the channel neither waits for it nor asks again, so the next turn is not held back (RFC §6.4).
SpeakDecisionEvent
dataclass
¶
Carried to ON_SPEAK_DECISION hooks: one channel's decision on one event.
duration_ms
class-attribute
instance-attribute
¶
How long the policy took to decide: the channel's bound when it did not decide in time.
asked_again
class-attribute
instance-attribute
¶
The policy was asked again on the event once the agent thought, with the thought (RFC §6.4): not its first decision on it.
AlwaysSpeak ¶
Bases: SpeakPolicy
Answers every event. Unlike a channel without a policy, it reports each
decision to ON_SPEAK_DECISION: a baseline to measure another policy against.
AnswerOnly ¶
Bases: SpeakPolicy
Answers only people; everyone else is heard, never answered.
A turn whose speaker is not one of people, or whom the room does not
name, is decided silent with the reason :data:LISTENED_TO, without
asking policy: it is stored and the agent's thinker thinks about it, as
any turn left silent. A turn from one of people is policy's to decide,
with only people in SpeakTurn.people, the speaker among them: a voice
only listened to does not turn a conversation with one person into a group
one.
A speaker is matched by the name the room gives them (SpeakTurn.speakers,
without the rank a look-alike name carries: ALICE (2) is matched as
ALICE), ignoring case and spacing, so the person named is never
silenced by a sender who took their name first. It chooses whom the agent
answers; it is not an access control, since a participant may take any
display name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
SpeakPolicy
|
Decides on the turns of the people answered. |
required |
people
|
Iterable[str]
|
The names of the people the agent answers. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
people is one string rather than names. |
ValueError
|
people names no one. |
ClassifierSpeakPolicy ¶
ClassifierSpeakPolicy(classifier, *, agent_name, agent_role='', questions=None, languages=None, history=6, proactivity=0.5)
Bases: SpeakPolicy
Narrow judgments about the turn in one classifier call, composed in code.
The classifier stays the caller's: it may serve other components, and is closed by whoever made it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
classifier
|
Classifier
|
Answers the questions; Jev's calibrated probabilities are what the thresholds were measured on. |
required |
agent_name
|
str
|
The agent's name, as people call it. |
required |
agent_role
|
str
|
What the agent is there for, in a few words, when it helps to judge whether a turn is for it. |
''
|
questions
|
Mapping[str, Question] | None
|
Questions replacing :data: |
None
|
languages
|
Mapping[str, str] | None
|
The languages the agent answers in, each with the line its
turn's notes carry when the speaker speaks it, best written in that
language ( |
None
|
history
|
int
|
How many turns before the event the classifier reads. |
6
|
proactivity
|
float
|
How sure the policy must be that what the agent wants to say answers or corrects the turn before it offers unasked, in (0, 1]: lower is more eager. Only a thinker gives it something to say. |
0.5
|
A request to stay quiet or only listen from now on puts the room in a listening state the policy keeps (RFC §6.4): the agent is silent, a question put to it and addressing it directly is answered while the room goes on listening, and only a turn that lets it talk again ends it. A turn it cannot judge there (no text, a classifier that fails) stays silent.
questions ¶
The questions asked on turn: :data:QUESTIONS as replaced, those of
:data:THOUGHT_QUESTIONS when the agent has something to say, the
listening state's, and the language when the policy has languages.
state ¶
What the classifier reads: the agent (the request it was asked to only listen with, when it was), the people, the recent turns and the last one, each with its speaker, and the agent's thought when it has one.
decision ¶
The decision from the answers: in a listening room, as it listens; in an open one, a request to only listen sets the state, else as composed.
compose ¶
The mode, and why, from the judgments by question name (missing ones read 0).
directness is the expected level on 0 (not mentioned), 1 (tentatively),
2 (indirectly), 3 (directly); the others are probabilities of yes. alone:
one person talks with the agent, so a request is for it whatever the
directness says. In order: the speaker not done, postponing, or asking for
quiet on this turn keeps the agent silent; an answer to its question, or being
addressed, makes it speak; being
only wondered about makes it offer, or speak when what it wants to say answers
or corrects the turn (answers, corrects). Not addressed, it offers when
that reaches proactivity (lower is more eager), half of it when what it
wants to say is urgent: urgency alone made an agent ask the same question
four times over unrelated turns.
addressed ¶
Whether the agent was addressed: directly or indirectly, asked for something tentatively, or asked anything when it is the person's only listener.
0.75 rather than 0.5 opens the tentative band: an expected level near 0.5 is a split between "not mentioned" and "tentatively".
judgments_of ¶
The answers as judgments: a yes/no's probability, a score's level, and a
choice as name=choice with its probability.
listening ¶
Staying quiet when asked: a state of the room, not a judgment remade every turn (RFC §6.4).
A request to stay quiet or only listen from now on, re-judged from the recent turns
on every turn, faded as they passed and was lost once it left them (measured on a
live session: 0.63, then 0.33 two turns later). :class:ListeningRooms keeps it per
room; the classifier reads it with every turn and is asked, instead, whether the turn
puts a question to the agent and whether it lets the agent talk again.
LISTEN_REQUEST
module-attribute
¶
LISTEN_REQUEST = YesNoQuestion('Does `last_turn` ask the assistant to stop talking, to stay quiet or to only listen from now on, until told otherwise? Asking it not to answer this one turn only, or talking about someone else being quiet, does not count.')
Asked while the room is open: does the turn put it in the listening state?
ASKED_ME
module-attribute
¶
ASKED_ME = YesNoQuestion('The assistant was asked to only listen (`agent.listening_only`). Does `last_turn` put a question or a request to the assistant itself, expecting it to answer now? Thinking aloud, talking to someone else, or a question about the topic that is not put to the assistant does not count.')
Asked while the room listens: is the turn a question for the agent, to answer once?
LIFT
module-attribute
¶
LIFT = YesNoQuestion('The assistant was asked to only listen (`agent.listening_only`). Does `last_turn` tell the assistant it may talk or intervene again on its own, from now on? A question or a request put to it is not, by itself, letting it talk again: it answers that one and goes on listening.')
Asked while the room listens: does the turn end the listening state?
DIRECT_ADDRESS
module-attribute
¶
The directness from which a question breaks the silence of a listening room: the agent addressed indirectly (2) or directly (3), its name or "you". Below it, a question said aside and one put to the agent read alike ("What is the base URL?" was taken as put to the agent at 0.91, "What are we talking about?" at 0.26).
ASKED_LIMIT
module-attribute
¶
Characters of the request the classifier reads with every turn.
Listening
dataclass
¶
ListeningRooms ¶
The rooms in the listening state, in memory, by room id: not stored, so a
restart starts every room open, as it starts every thought empty; the channel
forgets a room it joins or leaves (SpeakPolicy.forget_room).
MockSpeakPolicy ¶
Bases: SpeakPolicy
Returns scripted decisions in order (the last one repeats) after delay seconds, or raises error; records the turns it was asked about.
Thought
dataclass
¶
What the agent thinks, in the first person.
text
class-attribute
instance-attribute
¶
What it makes of what is said, in a few short sentences.
want_to_say
class-attribute
instance-attribute
¶
What it would say if given the turn, most important first, three at most.
said ¶
The thought once the agent has spoken: what it wanted to say is on the table, so nothing is pending any more.
ThoughtEvent
dataclass
¶
ThoughtEvent(room_id, channel_id, thought, previous=Thought(), duration_ms=None)
Carried to ON_THOUGHT hooks: one channel's new thought in one room.
Thinker ¶
LLMThinker ¶
Bases: Thinker
A model answering through a JSON schema (RFC §6.7). It reads who the agent is from the context's system prompt, the agent's own: one description for both.
A small, fast model fits: the thought is a few sentences, rewritten on every turn the agent listens to. The provider stays the caller's.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
provider
|
AIProvider
|
An AI provider that supports |
required |
instructions
|
str | None
|
What the thinker is told, in place of :data: |
None
|
max_tokens
|
int
|
The thought's cap; a reasoning model needs room to reason. |
600
|
reasoning_effort
|
str | None
|
Passed to the provider; |
None
|
timeout
|
float
|
Seconds a call may take before it fails (the thought is kept). |
10.0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
provider does not support a response schema. |