Passive Callback & Response API
Passive Callback & Response API
All *Callback classes live in linksoul_agentsdk.passive.
Callback / Response mapping
| Callback | Response | on_request signature |
|---|---|---|
Audio2LlmCallback | Audio2LlmResponse | (agent_id, event_id, flag, buf, param, response) |
Audio2TtsCallback | Audio2TtsResponse | (agent_id, event_id, item_id, flag, buf, param, response) |
Asr2LlmCallback | Asr2LlmResponse | (agent_id, event_id, text, param, response) |
Asr2TtsCallback | Asr2TtsResponse | (agent_id, event_id, text, param, response) |
AsrVideo2VlmCallback | AsrVideo2VlmResponse | (agent_id, event_id, flag, text, buf, param, response) |
AsrVideo2TtsCallback | AsrVideo2TtsResponse | (agent_id, event_id, flag, text, buf, param, response) |
AudioVideo2VlmCallback | AudioVideo2VlmResponse | (agent_id, event_id, flag, buf, param, response) |
AudioVideo2TtsCallback | AudioVideo2TtsResponse | (agent_id, event_id, flag, buf, param, response) |
Response capability matrix
| Response | ASR | LLM | VLM | TTS | Skill | Interrupt |
|---|---|---|---|---|---|---|
Audio2LlmResponse | ✓ | ✓ | ✓ | ✓ | ||
Audio2TtsResponse | ✓ | ✓ | ✓ | ✓ | ✓ | |
Asr2LlmResponse | ✓ | ✓ | ✓ | |||
Asr2TtsResponse | ✓ | ✓ | ✓ | ✓ | ||
AsrVideo2VlmResponse | ✓ | ✓ | ✓ | |||
AsrVideo2TtsResponse | ✓ | ✓ | ✓ | ✓ | ||
AudioVideo2VlmResponse | ✓ | ✓ | ✓ | ✓ | ||
AudioVideo2TtsResponse | ✓ | ✓ | ✓ | ✓ | ✓ |
Every response supports on_error(event_id, error_code, error_msg).
Function Call & Arbiter (new in v1.5.0)
⚠️ Not yet released: in-development v1.5.0-SNAPSHOT capability; interface and protocol may change. Do not use in production before the official release.
v1.5.0 adds Function Call dispatch and Arbiter arbitration on the passive interaction path; the interface is woven into the existing 8 callback / response classes. See Passive Callbacks Guide · Function Call exposure & Arbiter for the workflow.
Callback method (on all 8 callback classes)
def on_function_call(
self,
agent_id: str,
event_id: str,
function_call: FunctionCallInfo,
response: <XxxResponse>,
) -> None
Default no-op; override to receive a function call forwarded by the gateway. <XxxResponse> is the response type for that callback class.
FunctionCallInfo (linksoul_agentsdk.FunctionCallInfo)
| Field | Type | Description |
|---|---|---|
source | str | function call source |
policy | str | handling policy identifier |
type | str | function call type |
value | str | main value |
param | dict | extra parameters |
Response method (on all 8 Response classes)
def on_arbiter(self, event_id: str, decision: str, arb_param: AgentParam | None) -> None
Returns the arbitration decision; the SDK emits agentsdk.function_call.arbiter. decision comes from ArbiterDecision (pass ArbiterDecision.DELEGATE.value or the literal string):
Enum (linksoul_agentsdk.ArbiterDecision) | wire value | Meaning |
|---|---|---|
DELEGATE | delegate | delegate to the agent's default pipeline |
OVERRIDE | override | the application takes over, overriding the default behaviour |
ILLEGAL | illegal | illegal / fallback value |
Event types
agentsdk.function_call.expose (gateway → SDK, triggers on_function_call) / agentsdk.function_call.arbiter (SDK → gateway, emitted by on_arbiter). See the enums reference.
Shared base methods (PassiveCallback)
| Method | Trigger |
|---|---|
on_robot_online(agent_id, agent_meta) | Robot online |
on_robot_offline(agent_id) | Robot offline |
on_face_info(agent_id, event_id, param) | Face / voiceprint UID (opened in v1.4.0) |
on_video_frame(agent_id, event_id, flag, buf, is_key_frame, local_ts, param) | Video passthrough (flag=2 H264, flag=3 image) |
on_greet_signal(agent_id, event_id, param, response) | Greeting (merged in v1.4.0) |
on_state(agent_id, event_id, state_name, state_value) | Robot state push (merged in v1.4.0); see robot-side state modules for the full catalogue |
on_function_call(agent_id, event_id, function_call, response) | Function Call forwarded (new in v1.5.0); function_call is a FunctionCallInfo |
on_histories(agent_id, event_id, histories) | Conversation history forwarded (new in v1.5.0); histories is list[HistoryInfo] |
HistoryInfo (linksoul_agentsdk.HistoryInfo, v1.5.0)
| Field | Type | Description |
|---|---|---|
timestamp | int | timestamp, for sorting |
query | str | user-side input |
answer | str | agent-side reply |
complete | bool | whether this turn finished completely |
event_id | str | corresponding session event ID, for de-duplication |
skill | HistoryInfo.SkillInfo | skill info carried by this history entry (type / value), may be None |
GreetResponse methods
| Method | Description |
|---|---|
on_greet_vlm_delta(event_id, text) | VLM streaming chunk |
on_greet_vlm_done(event_id) | VLM done |
on_greet_tts_delta(event_id, audio_base64) | TTS audio chunk — audio_base64 is the base64-encoded chunk of synthesised audio bytes |
on_greet_tts_done(event_id) | TTS audio stream finished |
on_error(event_id, code, msg) | Error reply |
Type hints & async
All public classes carry full typing annotations. on_request is synchronous — the WebSocket
I/O runs in a dedicated worker thread per agent_id. Different agents process in parallel; the
same agent processes its messages serially.
If your downstream 语义理解/LLM call is async, bridge it inside
on_requestwithasyncio.run_coroutine_threadsafe(...)and wait for completion before invokingresponse.on_*so the "interrupt-first" ordering still holds.