Skip to main content

Channel response judges

A channel Deployment whose attention_policy is participated or proactive asks a response judge whether the agent should answer an ordinary group message nobody addressed to it. Core decides which messages are candidates, freezes the policy with each message, collects the topic's context, records the decision and recovers it; the judge answers one question for one message.

Which messages are judged​

A direct message, mention or reply to the agent is answered without a judge. An ordinary message is judged as follows:

PolicyTopic the agent has not answeredTopic it has answered
participatedKept as context; the judge is not askedJudged
proactiveJudgedJudged

A topic is the message's conversation: its room or thread, or the reply chain it continues. "Answered" means the agent answered a message of that topic since the Deployment was last edited. The policy and instruction are frozen with each message, so an edit does not change how a recorded message is judged.

Each message is judged at most once. A message the judge declines creates no conversation and stays context for the next message the agent answers. A redelivered copy reads the recorded decision. A judge error is retried with backoff and is never read as an answer. A copy of the same message that mentions the agent makes it run even when the judge declines. A message a platform reports only as context (an observation signal) is never judged: the platform gave no permission to answer it.

The built-in judge​

Without an installed judge, AstraBox uses its own when the title model is enabled (ASTRABOX_TITLE_MODEL_ENABLED). It sends the message, the topic's last 50 unsubmitted messages (each cut to 2000 characters), whether the agent already answered in the topic, and the Deployment's response_instruction to the title model, and requires exactly {"respond": boolean, "reason": string} back. Silence is the default; the instruction says when the agent should speak. Any other output is an error, not an answer.

Set the policy and the instruction on the Deployment, in the console or the API:

{"attention_policy": "proactive",
"response_instruction": "Answer questions about deployments and incidents; stay silent otherwise."}

response_instruction (at most 4000 characters) applies only to these two policies; saving it with another policy is refused, and changing the policy away from them clears it. With neither a title model nor an installed judge, saving either policy is refused with CHANNEL_RESPONSE_JUDGE_UNAVAILABLE.

Installing a judge​

A deployment installs at most one judge, replacing the built-in one:

[project.entry-points."astrabox.providers.channel_response"]
enterprise = "my_deployment.judge:ResponseJudge"

The target subclasses astrabox.seams.channel_response.ChannelResponseJudge with a stable name and an async judge(*, context) that returns a ChannelResponseDecision(respond, reason).

ChannelResponseContext fieldMeaning
deployment_id, channel_nameThe binding and its provider
conversationThe topic: the conversation key or reply chain core resolved
messageThe candidate's participant, text and original timestamp
policy, instruction, binding_revisionFrozen when the message was first recorded
selection_reasonparticipated_topic or proactive_policy
participatedWhether a message of this topic and revision was already answered
contextThe topic's unsubmitted messages before this one, oldest first

The same message can be judged again after a host failure, so the judge must be side-effect free: do not post, record, dispatch, or start a consent flow. Raise when no decision can be made; core retries with backoff and never treats an exception as respond=true. The reason is kept on the message's record and must not contain secrets. A judge call is bounded at 30 seconds.