Teleop example
Teleop example
⚠️ Not yet released: in-development v1.5.0-SNAPSHOT capability; interface and protocol may change. Do not use in production before the official release.
New in v1.5.0. End-to-end Python walkthrough of
enter → start_audio → append_audio_delta → done_audio → exit.
Minimum example
python
import time
from linksoul_agentsdk import (
AgentAuthCallback,
AgentParam,
AgentSdk,
IdGenerator,
TeleopEnterCallback,
TeleopExitCallback,
TeleopKeepaliveCallback,
TeleopRequest,
)
url = "wss://open.agibot.com/api/V1/open-portal/app/wss/agent-sdk"
app_id = "<appId from the LinkSoul open platform>"
app_key = "<appKey from the LinkSoul open platform>"
app_secret = "<appSecret from the LinkSoul open platform>"
agent_id = "<target robot agentId>"
# 1. Create the SDK instance
agent_sdk = AgentSdk.create(url, app_id, app_key, app_secret)
# 2. Register auth callback
class MyAuthCallback(AgentAuthCallback):
def on_auth_state(self, app_id: str, code: int, msg: str) -> None:
print(f"on_auth_state => app_id: {app_id}, code: {code}, msg: {msg}")
agent_sdk.register_auth(MyAuthCallback())
# 3. Open the WebSocket connection
agent_sdk.initialize()
time.sleep(2)
# 4. Register a teleop request
teleop_id = IdGenerator.generate_teleop_id()
teleop_request = TeleopRequest(agent_sdk, agent_id, teleop_id)
agent_sdk.register_teleop(teleop_request)
# 5. Enter the teleop session
class MyEnterCallback(TeleopEnterCallback):
def on_enter_ack(self, teleop_id: str, event_id: str, code: int, msg: str) -> None:
print(f"on_enter_ack => teleop_id={teleop_id}, event_id={event_id}, code={code}, msg={msg}")
enter_param = AgentParam.create()
teleop_request.enter(enter_param, MyEnterCallback(), 2000)
# 6. Push one audio segment (fire-and-forget)
start_param = (
AgentParam.create()
.set_string("role", "male") # male / female
.set_integer("threshold", 0) # -14 ~ 14
)
event_id = teleop_request.start_audio(start_param)
# real code should call append_audio_delta once per 20-40 ms PCM/Opus chunk (base64-encoded)
teleop_request.append_audio_delta(event_id, "")
teleop_request.done_audio(event_id)
# 7. Probe robot online (in real code drive this on a 10 s timer -- see "Periodic keepalive" below)
class MyKeepaliveCallback(TeleopKeepaliveCallback):
def on_keepalive_ack(self, teleop_id: str, event_id: str, code: int, msg: str) -> None:
print(f"on_keepalive_ack => teleop_id={teleop_id}, event_id={event_id}, code={code}, msg={msg}")
teleop_request.keepalive(MyKeepaliveCallback(), 2000)
# 8. Exit the teleop session
class MyExitCallback(TeleopExitCallback):
def on_exit_ack(self, teleop_id: str, event_id: str, code: int, msg: str) -> None:
print(f"on_exit_ack => teleop_id={teleop_id}, event_id={event_id}, code={code}, msg={msg}")
teleop_request.exit(MyExitCallback(), 2000)
# 9. Unregister and release (omitted here)
# agent_sdk.unregister_teleop(teleop_id)
# agent_sdk.release()
Periodic keepalive
After enter succeeds you should probe every 10 seconds. Any on_keepalive_ack with code != 0 means the robot is offline -- stop the timer, exit the session, unregister the request so no further audio is wasted on a dead peer.
python
import threading
from linksoul_agentsdk import TeleopKeepaliveCallback, TeleopExitCallback
def start_keepalive(teleop_request, agent_sdk, interval_sec: int = 10):
"""Call after enter succeeds; probes every interval_sec seconds"""
state = {"online": True}
def tick():
if not state["online"]:
return
class _Cb(TeleopKeepaliveCallback):
def on_keepalive_ack(self, teleop_id, event_id, code, msg):
if code != 0 and state["online"]:
state["online"] = False
print(f"robot offline => code={code}, msg={msg}")
class _ExitCb(TeleopExitCallback):
def on_exit_ack(self, teleop_id, event_id, code, msg):
agent_sdk.unregister_teleop(teleop_id)
teleop_request.exit(_ExitCb(), 2000)
teleop_request.keepalive(_Cb(), 2000)
if state["online"]:
threading.Timer(interval_sec, tick).start()
threading.Timer(interval_sec, tick).start()
return state # caller may set state["online"] = False to stop probing
Also set state["online"] = False when your business logic invokes exit, so probes stop as well.
Common tweaks
| Goal | Where to change |
|---|---|
| Multiple utterances in one session | Call start_audio(start_param) again for each utterance to get a fresh event_id; reuse that event_id for its append_audio_delta / done_audio. No need to exit/enter again. |
| Change voice / VAD threshold mid-session | Re-populate AgentParam.role / threshold on the next start_audio; previous segments are unaffected. |
| Abort teleop mid-flight | Call exit(...) directly, skipping any pending done_audio. |
| React to SDK auth / disconnect | Maintain an authed flag inside AgentAuthCallback.on_auth_state; double-check before enter, or drive reconnection when on_enter_ack returns code == 1000. |
| Teleop multiple robots concurrently | Create one TeleopRequest per agent_id; the SDK indexes by teleop_id so they don't collide. |