Skill Plugin Development
Overview
In SERVICEME, skill plugins refer to optional capabilities for Agents. In addition to the built-in plugins, you can also extend skill plugins through development, granting Agents more abilities.

System Built-in Skill Plugins
| ID | Plugin | Plugin Type | Purpose |
|---|---|---|---|
| SearchKnowledgebase | Search Knowledge Base | API Plugin | Provides retrieval of private domain knowledge |
| 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, supports bar, line, and pie charts |
| DocumentReader | Document Reader | API Plugin | Provides document summary information for a single or selected document |
| QuestionContact | Question Contact | API Plugin | Returns the contact person for the corresponding field based on the question's domain |
Type Description
| Type | Description |
|---|---|
| API Plugin | The skill plugin is presented as a backend API. The Agent is responsible for filling in the API input parameters based on context and parsing the API response. |
API Skill Plugin
Supported Authentication Methods
Currently, only fixed Header authentication or interfaces that do not require authentication are supported.
| Type | Description |
|---|---|
| Fixed Header | Interface authentication is performed by specifying a fixed key in the request header, similar to the OpenAI api_key method. |
Plugin Development
To facilitate understanding of this process, let's use an API plugin that queries the time zone by time zone code as an example.
Step 1: First, provide an API that can return 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 in the system
Add the skill plugin and fill in the following information

Field Description
- Code: The code of the plugin, a unique identifier for the plugin in the system. Try to use a meaningful description.
- Name: The display name of the plugin. The Agent will display the plugin name it uses during reasoning and execution. Pay attention to the completeness of multilingual support.
- Description: The description of the plugin, used to explain the function of the plugin. It will be displayed on the interface for adding skill plugins to the Agent.
- Request Header: Used to input necessary Header parameters for calling the plugin, such as API_KEY.
- [Important] OpenAPI / Swagger Schema (JSON): The description of the API body. The information here determines whether the Agent can properly understand when to call this skill and how to fill in each parameter.
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"
}
}
]
}
}
}
}
Note
- Info/Title: The plugin title filled in here helps the Agent understand the function of this plugin.
- Paths/[api path]/Get/OperationId: You can use backticks `%OperationId%` in the Agent Prompt to specify the API to be called in a particular scenario. See the example in Step 4 below.
- Paths/[api path]/Get/Description: Helps the Agent understand and affects when the Agent will call a specific API.
- Paths/[api path]/Get/Parameters: Make sure it is consistent with the actual API. For example, if it is query here, the API should get parameters from the query. If it is another type (such as JSON body), the API should also be consistent. The parameter name description helps improve the success rate of filling.
- Servers/Url: This is the API's BaseURL. It must be filled in correctly for successful calls.
- [Optional] After the plugin configuration is complete, you can debug it using the DEBUG function.
Step 3: Add the skill plugin to the Agent
In the Agent settings interface, add the plugin through the [Skill Plugin] tab.

After saving the settings, test it by chatting with the expert.

Step 4: [Optional] In the Agent's Prompt, add necessary instructions 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 automatically determine when to execute and how to fill parameters based on the information in the OpenAPI Schema.