Changelog
Changelog
v1.5.0-SNAPSHOT (Current Development)
⚠️ This is an in-development (SNAPSHOT) release. The v1.5.0 additions below (teleop / extended skills) are not yet released and the interfaces may change.
Release Date: In Development
🆕 New capability: beyond-line-of-sight teleop
v1.5.0 opens a third interaction path on top of passive / active — remote-operator teleop.
- New classes:
linksoul_agentsdk.TeleopRequest— session entity:enter/start_audio(param)/append_audio_delta/done_audio/keepalive/exitlinksoul_agentsdk.TeleopEnterCallback—on_enter_ack(teleop_id, event_id, code, msg)linksoul_agentsdk.TeleopKeepaliveCallback—on_keepalive_ack(teleop_id, event_id, code, msg); robot online probe, recommend calling every 10 seconds during the session,code != 0means the robot is offlinelinksoul_agentsdk.TeleopExitCallback—on_exit_ack(teleop_id, event_id, code, msg)linksoul_agentsdk.mgr.AgentSdkTeleopMgr— global request index, 7200 s idle sweeper
- New
AgentSdkpublic methods:register_teleop(TeleopRequest)unregister_teleop(teleop_id: str)
- New policy enum:
AgentPolicy.TELEOP(wire value"teleop") - Nine new event types under
AGENTSDK_TELEOP_*(includesagentsdk.teleop.keepalive/agentsdk.teleop.keepalive_ack) - New id-prefix generator:
IdGenerator.generate_teleop_id()→"teleop_<21 chars>" - New docs: Teleop guide · Teleop API · Teleop example
🆕 New capability: Extended Skills (ExtSkill)
v1.5.0 also introduces ExtSkill — query the robot's available skill list and remotely invoke a specific skill (three-phase acknowledgement: ack → state → result). During execution the skill side may report progress repeatedly via agentsdk.ext_skill.report_state (mapped to on_state). Uses agentId + requestId to identify each request.
- New classes:
linksoul_agentsdk.ExtSkillRequest— skill request entity:query/invokelinksoul_agentsdk.ExtSkillQueryCallback—on_query_result(request_id, event_id, code, msg, skills)linksoul_agentsdk.ExtSkillInvokeCallback—on_invoke_ack(request_id, event_id, code, msg)+on_state(agent_id, request_id, event_id, state_name, state_value)+on_invoke_result(request_id, event_id, code, msg, result)
- New
AgentSdkpublic methods:register_ext_skill(ExtSkillRequest)unregister_ext_skill(request_id: str)
- New policy enum:
AgentPolicy.EXT_SKILL(wire value"extskill") - Six new event types:
agentsdk.ext_skill.query/agentsdk.ext_skill.query_resultagentsdk.ext_skill.invoke/agentsdk.ext_skill.invoke_ack/agentsdk.ext_skill.report_state/agentsdk.ext_skill.invoke_result
- New id-prefix generator:
IdGenerator.generate_ext_skill_request_id()→"extskill_<21 chars>" - New docs: ExtSkill guide · ExtSkill API · ExtSkill example
⚠️ Breaking change: console "Skill Invocation Method = Agent Invocation" removed (v1.5.0 required)
With the introduction of Function Call + Arbiter in v1.5.0, the platform's skill-forwarding mode — setting Skill Invocation Method to Agent Invocation in the custom-agent configuration — has been removed:
- Before (≤ v1.4.0): with Skill Invocation Method set to Agent Invocation, the platform forwarded triggered skill requests to your agent (SDK) for custom handling.
- Now (v1.5.0): the platform no longer forwards skills. It surfaces pending skill requests as function calls to the SDK (
on_function_call), and your agent decides delegation explicitly via the Arbiter interface (response.on_arbiter(...)):ArbiterDecision.DELEGATE(hand off to the default chain) orArbiterDecision.OVERRIDE(agent takes over).
If your agent relies on the "Skill Invocation Method = Agent Invocation" forwarding behaviour, you must upgrade to v1.5.0 and reimplement skill delegation on top of Function Call + Arbiter, otherwise skills will no longer be handled.
Contract
register_teleop → enter → (start_audio(param) → append_audio_delta* → done_audio)+ → exit → unregister_teleop
Call keepalive at any frequency during the session (recommended every 10 seconds). If any on_keepalive_ack returns code != 0, treat the robot as offline and exit + unregister_teleop immediately.
enter/keepalive/exitare ack'd via callback (code == 0OK,code == 1000local close,code == -1server reject).start_audio/append_audio_delta/done_audioare fire-and-forget.start_audio(param)supports voice / VAD tuning per segment:role("male"/"female"),threshold(-14 ~ 14).timeoutis a placeholder (clamped to >=50 ms) — no timeout callback yet.
🆕 New capability: Function Call dispatch & Arbiter arbitration
v1.5.0 opens Function Call dispatch and Arbiter arbitration on the passive interaction path (in-development capability, not yet released).
- New callback (on all 8 passive callbacks):
on_function_call(agent_id, event_id, function_call, response)— the gateway forwards a pending function call - New response method (on all 8 Response classes):
on_arbiter(event_id, decision, arb_param)— returns the decision, emitsagentsdk.function_call.arbiter - New data class:
linksoul_agentsdk.FunctionCallInfo(source/policy/type/value/param) - New enum:
linksoul_agentsdk.ArbiterDecision(DELEGATE/OVERRIDE/ILLEGAL) - Two new event types:
agentsdk.function_call.expose/agentsdk.function_call.arbiter
🆕 New capability: conversation history passthrough (onHistories)
- New shared base callback:
on_histories(agent_id, event_id, histories)(default log-only impl onPassiveCallback; override as needed) - New data class:
linksoul_agentsdk.HistoryInfo(timestamp/query/answer/complete/event_id/skill) - One new event type:
agentsdk.histories.expose(gateway → SDK)
Compatibility
- API-level fully backward-compatible with v1.4.0: existing
register_auth, passive callbacks, and task-flow APIs are unchanged. Bump pip package version from1.4.0→1.5.0. - If you don't use teleop or Function Call, runtime behaviour is identical to v1.4.0.
- One breaking change applies: agents that relied on the console's "Skill Invocation Method = Agent Invocation" forwarding must be migrated to Function Call + Arbiter as described above.
Dependencies
Same as v1.4.0 — no third-party upgrades.
v1.4.0 (alpha)
Release date: in development
⚠️ Breaking change — auth/signing standardised (NOT compatible with v1.3.0 or earlier)
v1.4.0 standardises the AgentSDK signing scheme to align with the LinkSoul open-platform spec. The Python SDK ships the change together with the Java SDK; v1.3.0 (and earlier) clients cannot upgrade in place:
| Item | v1.3.0 and earlier | v1.4.0 |
|---|---|---|
| Gateway URL | wss://agentsdk.agibot.com/v1/agentsdk | wss://open.agibot.com/api/V1/open-portal/app/wss/agent-sdk |
| Credential source | Legacy custom-agent template | Application on the LinkSoul open platform (adds app_key) |
| Factory | AgentSdk.create(url, app_id, app_secret) | AgentSdk.create(url, app_id, app_key, app_secret) |
| Algorithm | JWT (HS256) sent via AGIBOT_AUTHORIZATION | HMAC-SHA256("GET\n{path}\n{timestamp}\n{nonce}"), delivered across five signed headers |
| Auth headers | 1 header: AGIBOT_AUTHORIZATION | 5 headers: X-App-Id / X-App-Key / X-Timestamp / X-Nonce / X-Signature |
callback_types transport | JWT payload field | Standalone header X-Callback-Types (JSON array string) |
| Implementation impact | LinkskyClient depends on jwt_util.py | LinkskyClient switches to hmac + hashlib; AgentSdk no longer exposes app_secret |
Migration checklist:
- Re-issue
app_id/app_key/app_secretfrom the open-platform application page; old credentials are not accepted. - Switch the WebSocket gateway URL to
wss://open.agibot.com/api/V1/open-portal/app/wss/agent-sdk. - Replace every
AgentSdk.create(url, app_id, app_secret)call withAgentSdk.create(url, app_id, app_key, app_secret). - If you proxy SDK traffic through a custom gateway, parse and propagate the new five-header
signature plus
X-Callback-Types, and stop relying onAGIBOT_AUTHORIZATION. - Make sure no code still reads
AgentSdk.app_secret— the attribute has been removed.
Equivalent to the Java SDK v1.4.0 — refer to the Java CHANGELOG for the complete protocol-level change list. This page only enumerates Python-specific notes.
Python-specific implementation
- Package name:
linksoul_agentsdk(PEP 8 snake_case), 1-to-1 mapped from the Java packages - Public modules:
linksoul_agentsdk.passive/.active/.client/.mgr - WebSocket client: built on
websocket-client>=1.7, synchronous blocking, runningrun_foreverin a dedicated daemon thread - Heartbeat: handled by
websocket-client(ping_interval=10s,ping_timeout=5s) - Reconnect: automatically scheduled by a
threading.Timer3 s after disconnect - Threading:
AgentThreadMgruses single-threadThreadPoolExecutorinstances, one peragent_id(matching JavaAgentThreadMgr) - Auth: built on
hmac+hashlib(HMAC-SHA256), matching JavaLinkskyClient.hmacSha256. The signature is delivered through five request headers —X-App-Id/X-App-Key/X-Timestamp/X-Nonce/X-Signature— and the set of registered callback types travels inX-Callback-Types
Public API naming
Java camelCase is translated to Python snake_case, with full typing annotations:
| Java | Python |
|---|---|
AgentSdk.create(url, appId, appKey, appSecret) | AgentSdk.create(url, app_id, app_key, app_secret) |
registerAuth(AgentAuthCallback) | register_auth(AgentAuthCallback) |
registerAsr2Llm(Asr2LlmCallback) | register_asr2_llm(Asr2LlmCallback) |
onRequest(agentId, eventId, ...) | on_request(agent_id, event_id, ...) |
response.onLlmItemDelta(...) | response.on_llm_item_delta(...) |
response.onInterrupt(...) | response.on_interrupt(...) |
response.onSkill(...) | response.on_skill(...) |
IdGenerator.generateEventId() | IdGenerator.generate_event_id() |
AgentParam.create().setString(k, v) | AgentParam.create().set_string(k, v) |
Dependencies
| Dependency | Version |
|---|---|
| Python | 3.9+ |
| websocket-client | ≥ 1.7.0 |
Tests
- 73+ unit tests using
pytest+ a mockLinkskyClient— no real WebSocket server required in CI - Run via
pip install -e ".[dev]" && pytest
Historical versions
Java & Python stay version-aligned — see the Java SDK v1.4.0 CHANGELOG for the protocol changes that landed in earlier releases (v1.0.0 / v1.1.0 / v1.3.0).