ExtSkill guide (extended skills)

ExtSkill guide (extended skills)

⚠️ 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. ExtSkill = extended skills: the application attaches custom skills to an agent, then at runtime first query the list of extended skills currently available on that agent, and invoke one of them to run. It sits alongside passive / active / teleop, using its own event family and the AgentPolicy.EXT_SKILL policy (wire value "extskill").

When to use

  • The application has configured extended skills for an agent on the LinkSoul platform (weather lookup, ticket creation, device control, etc.) and needs to discover the list at runtime and trigger them on demand.
  • You need to bypass the dialogue chain and call a deterministic capability directly (structured input, structured output) instead of LLM free-form generation.
  • One invoke returns in three stages: onInvokeAck first (gateway accepted the request), then onState for execution-time progress reports (optional), then onInvokeResult (the skill's actual execution output).

Flow

After registerExtSkill, call query to fetch the list and invoke to trigger execution any number of times; unregisterExtSkill to release when done.

text
   ┌─────────────────────────────┐
   │  ExtSkillRequest.query       │  fetch available extended-skill list
   │    (onQueryResult)           │
   └─────────────────────────────┘

   ┌─────────────────────────────┐
   │  ExtSkillRequest.invoke      │  trigger a skill to run
   │    (onInvokeAck)             │  ← stage 1: gateway accepted
   │    (onState)                 │  ← stage 2: execution-time state report (0..n)
   │    (onInvokeResult)          │  ← stage 3: execution output
   └─────────────────────────────┘
  • query returns once via onQueryResult; when code == 0, result carries the skill list and related content.
  • invoke returns in three stages: onInvokeAck (accept), then onState (execution-time progress reported via agentsdk.ext_skill.report_state, zero or more times), then onInvokeResult (output; param carries the result when code == 0).
  • If the SDK connection is already closed at send time, the query / invoke callback fires synchronously on the calling thread once with code == 1000 + msg == "Agentsdk connection is closed".

Event family & protocol

Event types live in com.agibot.aiem.sdk.enums.AgentEventType:

Enum memberEvent type stringMeaning
AGENTSDK_EXT_SKILL_QUERYagentsdk.ext_skill.queryQuery available extended skills (SDK → gateway)
AGENTSDK_EXT_SKILL_QUERY_RESULTagentsdk.ext_skill.query_resultQuery result (gateway → SDK)
AGENTSDK_EXT_SKILL_INVOKEagentsdk.ext_skill.invokeTrigger a skill (SDK → gateway)
AGENTSDK_EXT_SKILL_INVOKE_ACKagentsdk.ext_skill.invoke_ackAccept receipt (gateway → SDK)
AGENTSDK_EXT_SKILL_REPORT_STATEagentsdk.ext_skill.report_stateExecution-time state report (gateway → SDK)
AGENTSDK_EXT_SKILL_INVOKE_RESULTagentsdk.ext_skill.invoke_resultExecution result (gateway → SDK)

Wire structure of every ExtSkill message:

json
{
  "type": "<event type>",
  "agentId": "<target agent agentId>",
  "eventId": "event_xxxxxxxxxxxxxxxxxxxxx",
  "agentMode": "extskill",
  "requestId": "extskill_xxxxxxxxxxxxxxxxxxxxx"
}
  • Unlike Teleop (which uses sn), ExtSkill uses agentId as the agent identity field.
  • requestId comes from IdGenerator.generateExtSkillRequestId(); it is the identity of one extended-skill session and is reused by query / invoke.
  • invoke additionally carries extSkillId (the skill to trigger) and input (flat input key-values, matching input.getExtParam()).
  • agentMode is always "extskill" (matching AgentPolicy.EXT_SKILL).

invoke input

The input of invoke(extSkillId, input, callback, timeout) is an AgentParam carrying the skill's structured input; the exact keys are defined by the skill. Example:

java
AgentParam input = AgentParam.create()
        .setString("city", "shanghai")
        .setInteger("days", 3);
String eventId = extSkillRequest.invoke("skill_weather", input, invokeCallback, 2000);

It is sent as flat key-values on the wire (input.city / input.days), matching input.getExtParam().

Result codes

The code of query / invoke callbacks is uniform:

codeMeaning
0Success (result / param carries returned content)
-1Server returned failure; msg carries errorMsg
1000Local failure: LinkskyClient was closed at send time; the SDK invokes this code synchronously on the calling thread

When code != 0, both result (in onQueryResult) and param (in onInvokeResult) are null.

API at a glance

  • Request class: com.agibot.aiem.sdk.extskill.ExtSkillRequest
  • Callback base classes: ExtSkillQueryCallback (onQueryResult) / ExtSkillInvokeCallback (onInvokeAck + onState + onInvokeResult)
  • Registration: AgentSdk.registerExtSkill(ExtSkillRequest) / AgentSdk.unregisterExtSkill(requestId)
  • ID: IdGenerator.generateExtSkillRequestId()

Full signatures in ExtSkill API. Runnable example in ExtSkill examples.

Lifecycle & cleanup

  • AgentSdkExtSkillMgr tracks active requests by requestId; you must registerExtSkill(...) before calling query / invoke.
  • Each request method call refreshes the internal updateTs; a request idle for more than 7200s is reclaimed by the background cleanup thread.
  • When done, call agentSdk.unregisterExtSkill(requestId) to release explicitly.
  • AgentSdk.release() also clears all ExtSkill requests owned by that instance.

ExtSkill vs. Teleop

AspectTeleopExtSkill
PolicyAgentPolicy.TELEOP ("teleop")AgentPolicy.EXT_SKILL ("extskill")
Identity fieldssn + teleopIdagentId + requestId
Core actionsenter / audio / keepalive / exitquery / invoke
Result modelsingle ACKquery: single result; invoke: three stages (ack + state + result)