Skill Plugin Development
Overview
In SERVICEME, skill plugins refer to optional capabilities for Agents. Besides the built-in system plugins, skill plugins can be extended through development to empower Agents with more abilities.

Built-in System Skill Plugins
| No. | Plugin | Plugin Type | Purpose |
|---|---|---|---|
| SearchKnowledgebase | Search Knowledgebase | API Plugin | Provides private domain knowledge retrieval functionality |
| ImageGeneration | Image Generation | API Plugin | Generates images based on text descriptions |
| Browsing | Web Browsing | API Plugin | Provides web browsing to search for real-time information |
| Charts | Charts | API Plugin | Generates corresponding charts based on provided data, supporting bar charts, line charts, and pie charts |
| DocumentReader | Document Reading | API Plugin | Provides document summary information for a single or selected document |
| QuestionContact | Question Contact | API Plugin | Returns the contact person for the domain related to the question |
Type Description
| Type | Description |
|---|---|
| API Plugin | Skill plugin manifests as a backend API, where the Agent is responsible for filling the API input parameters based on context and parsing the API return values |
API Skill Plugins
Supported Authentication Methods
Currently, only fixed Header authentication or no authentication is supported for interface calls.
| Type | Description |
|---|---|
| Fixed Header | Interface authentication via a fixed key specified in the request header, similar to OpenAI api_key |
Plugin Development
To facilitate understanding of this process, we take an API plugin that queries time zone information by time zone code as an example.
Step 1: Provide an API that returns time zone information based on the time zone code.
API Example
- .NET (Web API)
- Java (Spring Boot)
- Python (Fast API)
- Javascript (Next.js)
using Microsoft.AspNetCore.Mvc;
using System;
namespace WorldTimeApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class TimeController : ControllerBase
{
[HttpGet("current/zone")]
public IActionResult GetTimeByZone([FromQuery] string timeZone)
{
if (string.IsNullOrEmpty(timeZone))
{
return BadRequest("Missing required parameter: timeZone");
}
try
{
// 查找时区信息
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
// 获取指定时区的当前时间
var currentTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, timeZoneInfo);
// 返回结果
return Ok(new
{
TimeZone = timeZone,
CurrentTime = currentTime.ToString("yyyy-MM-ddTHH:mm:ss")
});
}
catch (TimeZoneNotFoundException)
{
return NotFound("Time zone not found");
}
catch (InvalidTimeZoneException)
{
return BadRequest("Invalid time zone");
}
catch (Exception ex)
{
return StatusCode(500, $"Internal server error: {ex.Message}");
}
}
}
}
package com.example.worldtime;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@RestController
public class TimeController {
@GetMapping("/api/Time/current/zone")
public Object getTimeByZone(@RequestParam String timeZone) {
try {
ZoneId zoneId = ZoneId.of(timeZone);
ZonedDateTime currentTime = ZonedDateTime.ofInstant(Instant.now(), zoneId);
return new TimeResponse(timeZone, currentTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
} catch (Exception e) {
return "Invalid time zone: " + e.getMessage();
}
}
static class TimeResponse {
public String timeZone;
public String currentTime;
public TimeResponse(String timeZone, String currentTime) {
this.timeZone = timeZone;
this.currentTime = currentTime;
}
}
}
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from datetime import datetime
import pytz
app = FastAPI()
class TimeResponse(BaseModel):
timeZone: str
currentTime: str
@app.get("/api/Time/current/zone", response_model=TimeResponse)
async def get_time_by_zone(timeZone: str):
if not timeZone:
raise HTTPException(status_code=400, detail="Missing required parameter: timeZone")
try:
tz = pytz.timezone(timeZone)
current_time = datetime.now(tz)
return TimeResponse(
timeZone=timeZone,
currentTime=current_time.strftime('%Y-%m-%dT%H:%M:%S')
)
except pytz.UnknownTimeZoneError:
raise HTTPException(status_code=404, detail="Time zone not found")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
import moment from 'moment-timezone';
export default function handler(req, res) {
const { timeZone } = req.query;
if (!timeZone) {
return res.status(400).json({ error: 'Missing required parameter: timeZone' });
}
try {
const currentTime = moment().tz(timeZone).format('YYYY-MM-DDTHH:mm:ss');
res.status(200).json({
timeZone: timeZone,
currentTime: currentTime,
});
} catch (e) {
res.status(404).json({ error: 'Time zone not found' });
}
}
Step 2: Register this plugin into the system
Add a skill plugin and fill in the following information

Field Description
- Code: The plugin code, a unique identifier for the plugin in the system, preferably a meaningful description.
- Name: The display name of the plugin, which the Agent will show during thinking and execution. Pay attention to multilingual completeness.
- Description: Description of the plugin, explaining its function, displayed in the Agent's skill plugin addition interface.
- Request Header: Used to input necessary Header parameters for calling the plugin, such as API_KEY
- 【Important】OpenAPI / Swagger Schema ( JSON ): Description of the API body. This information determines whether the Agent can properly understand when to call this skill and how each parameter should be filled.
OpenAPI Schema (JSON) Example
{
"Openapi": "3.0.0",
"Info": {
"Title": "World Time",
"Description": "Getting world time",
"Version": "v1.0.0"
},
"Servers": [
{
"Url": "https://www.timeapi.io"
}
],
"Paths": {
"/api/Time/current/zone": {
"Get": {
"OperationId": "zone",
"Description": "Get world time by timezone name",
"Deprecated": false,
"Parameters": [
{
"Name": "timeZone",
"In": "query",
"Required": true,
"Description": "Full IANA time zone names.",
"Schema": {
"Type": "string"
}
}
]
}
}
}
}
Notes
- Info/Title: The plugin title here helps the Agent understand the plugin's function.
- Paths/[api path]/Get/OperationId: Can be used in the Agent Prompt with backticks `%OperationId%` to specify API calls in particular scenarios, see the example in step four below.
- Paths/[api path]/Get/Description: Helps the Agent understand when to call this specific API.
- Paths/[api path]/Get/Parameters: Should be consistent with the actual API, e.g., if here is query, the API should get parameters from query. If it is another type (e.g., json body), the API should be consistent. Parameter descriptions help improve filling success.
- Servers/Url: The API BaseURL, must be correctly filled to successfully call.
- 【Optional】After plugin configuration, debugging can be done via the DEBUG feature.
Step 3: Add skill plugins to the Agent
In the Agent settings interface, add plugins via the [Skill Plugins] tab.

After saving the settings, test by conversing with the expert.

Step 4: 【Optional】Add necessary instructions in the Agent's Prompt to guide the Agent to better execute this skill.
Example
### Skill 3: Web Searching
- You can access web site by `Browsering` toolkit and looking for HR infomation from following sites: (site:*.linkedin.com; site:*.zhipin.com)
- Using result to fulfill users request and list up reference link at end of your response.
Note: In most cases, the Agent will determine the execution timing and parameter filling based on the information in the OpenAPI Schema.