mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-28 19:35:27 +08:00
A Workspace installs a plugin once, but that single installation is reused by several product objects: every processor for a Runner, every knowledge base for a KnowledgeEngine / Parser / Retriever, and many conversations or page requests for the other component kinds. The platform storage key carries no processor or knowledge-base dimension, so a plugin must fold that identity into its own keys. - certified-plugins: add "one installation, many usages" with the isolation dimensions per component kind, and "when an installation is revoked" documenting BasePlugin.on_installation_revoked, its trigger set, the absent invocation context and the no-op/failure semantics. - component pages (runner, knowledge-engine, knowledge-retriever, parser, tool, command, event-listener, page): add a short component-specific section with that component's own rules and a link to the contract page. - Align the background-work rule with the SDK contract: the SDK does not track ownership of detached work, so a plugin must keep its own binding-keyed registry and stop it in the revocation hook. All three locales carry the same sections.
190 lines
6.8 KiB
Plaintext
190 lines
6.8 KiB
Plaintext
---
|
||
title: "组件:工具"
|
||
---
|
||
|
||
LangBot 内置的 Local Agent 在执行期间会根据场景调用工具以与外界交互,目前支持通过插件和 MCP 两种方式添加工具。
|
||
|
||
## 添加工具组件
|
||
|
||
单个插件中能添加任意数量的工具,请在插件目录执行命令`lbp comp Tool`,并根据提示输入工具的配置。
|
||
|
||
```bash
|
||
➜ HelloPlugin > lbp comp Tool
|
||
Generating component Tool...
|
||
Tool name: get_weather_alerts
|
||
Tool description: Get weather alerts for a US state.
|
||
Component Tool generated successfully.
|
||
组件 Tool 生成成功。
|
||
```
|
||
|
||
现在即会在`components/tools/`目录下生成`get_weather_alerts.yaml`和`get_weather_alerts.py`文件,`.yaml`定义了工具的基础信息,`.py`是该工具的处理程序:
|
||
|
||
```bash
|
||
➜ HelloPlugin > tree
|
||
...
|
||
├── components
|
||
│ ├── __init__.py
|
||
│ └── tools
|
||
│ ├── __init__.py
|
||
│ ├── get_weather_alerts.py
|
||
│ └── get_weather_alerts.yaml
|
||
...
|
||
```
|
||
|
||
## 清单文件:工具
|
||
|
||
```yaml
|
||
apiVersion: v1 # 请勿修改
|
||
kind: Tool # 请勿修改
|
||
metadata:
|
||
name: get_weather_alerts # 工具名称,供 LLM 识别
|
||
label:
|
||
en_US: GetWeatherAlerts # 工具显示名称,用于显示在 LangBot 的 UI 上,支持多语言
|
||
zh_Hans: GetWeatherAlerts
|
||
description:
|
||
en_US: 'Get weather alerts for a US state.' # 工具描述,用于显示在 LangBot 的 UI 上,支持多语言。可选
|
||
zh_Hans: '获取美国某个州的天气预警'
|
||
spec:
|
||
parameters: [] # 工具参数,由 LLM 根据对话上下文生成值
|
||
llm_prompt: 'Get weather alerts for a US state.' # 工具提示词,供 LLM 判断是否调用该工具
|
||
execution:
|
||
python:
|
||
path: get_weather_alerts.py # 工具处理程序,请勿修改
|
||
attr: GetWeatherAlerts # 工具处理程序的类名,与 get_weather_alerts.py 中的类名一致
|
||
```
|
||
|
||
## 插件处理
|
||
|
||
默认会生成如下代码(`components/tools/<工具名称>.py`),您需要在`GetWeatherAlerts`类的`call`方法中实现此工具的调用和返回逻辑。
|
||
|
||
```python
|
||
# Auto generated by LangBot Plugin SDK.
|
||
# Please refer to https://langbot.app/docs/en/plugin/dev/tutor.html for more details.
|
||
from __future__ import annotations
|
||
|
||
from typing import Any
|
||
|
||
from langbot_plugin.api.definition.components.tool.tool import Tool
|
||
from langbot_plugin.api.entities.builtin.provider import session as provider_session
|
||
|
||
|
||
class GetWeatherAlerts(Tool):
|
||
|
||
async def call(self, params: dict[str, Any], session: provider_session.Session, query_id: int) -> str:
|
||
"""Fill your tool code here"""
|
||
return {}
|
||
```
|
||
|
||
在 `call` 方法中,实现该工具:
|
||
|
||
<Info>
|
||
天气获取工具用例来自 MCP 的 [Server 编写示例](https://modelcontextprotocol.io/quickstart/server)。
|
||
</Info>
|
||
|
||
```python
|
||
from __future__ import annotations
|
||
|
||
from typing import Any
|
||
|
||
from langbot_plugin.api.definition.components.tool.tool import Tool
|
||
from langbot_plugin.api.entities.builtin.provider import session as provider_session
|
||
|
||
import httpx
|
||
|
||
# Constants
|
||
NWS_API_BASE = "https://api.weather.gov"
|
||
USER_AGENT = "weather-app/1.0"
|
||
|
||
|
||
async def make_nws_request(url: str) -> dict[str, Any] | None:
|
||
"""Make a request to the NWS API with proper error handling."""
|
||
headers = {
|
||
"User-Agent": USER_AGENT,
|
||
"Accept": "application/geo+json"
|
||
}
|
||
async with httpx.AsyncClient() as client:
|
||
try:
|
||
response = await client.get(url, headers=headers, timeout=30.0)
|
||
response.raise_for_status()
|
||
return response.json()
|
||
except Exception:
|
||
return None
|
||
|
||
def format_alert(feature: dict) -> str:
|
||
"""Format an alert feature into a readable string."""
|
||
props = feature["properties"]
|
||
return f"""
|
||
Event: {props.get('event', 'Unknown')}
|
||
Area: {props.get('areaDesc', 'Unknown')}
|
||
Severity: {props.get('severity', 'Unknown')}
|
||
Description: {props.get('description', 'No description available')}
|
||
Instructions: {props.get('instruction', 'No specific instructions provided')}
|
||
"""
|
||
|
||
class GetWeatherAlerts(Tool):
|
||
|
||
async def call(self, params: dict[str, Any], session: provider_session.Session, query_id: int) -> str:
|
||
"""Fill your tool code here"""
|
||
state = params.get("state", "CA")
|
||
|
||
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
|
||
data = await make_nws_request(url)
|
||
|
||
if not data or "features" not in data:
|
||
return "Unable to fetch alerts or no alerts found."
|
||
|
||
if not data["features"]:
|
||
return "No active alerts for this state."
|
||
|
||
alerts = [format_alert(feature) for feature in data["features"]]
|
||
return "\n---\n".join(alerts)
|
||
```
|
||
|
||
在这个工具中,我们要从`params`中获取`state`参数,并调用 NWS API 获取该州的天气预警,故我们需要在清单文件的`parameters`中定义`state`参数。
|
||
|
||
`parameters` 的格式遵循 [JSON Schema](https://json-schema.org/docs),受 [OpenAI Function Calling 特性](https://platform.openai.com/docs/guides/function-calling#defining-functions)支持,且其根类型固定为`type: object`,请在`properties`中添加参数,并在`required`中添加必填参数说明。
|
||
|
||
```yaml
|
||
...
|
||
spec:
|
||
parameters:
|
||
type: object # 请勿修改
|
||
properties: # 请勿修改,在此处添加参数
|
||
state:
|
||
type: string
|
||
description: 'Two-letter US state code (e.g. CA, NY)'
|
||
required: # 在此添加必填参数说明
|
||
- state
|
||
...
|
||
```
|
||
|
||
本工具中还使用了`httpx`库,我们需要在插件目录的`requirements.txt`中添加`httpx`依赖。
|
||
|
||
```txt
|
||
# HelloPlugin/requirements.txt
|
||
langbot-plugin # 默认已存在
|
||
httpx
|
||
```
|
||
|
||
现在在插件目录执行命令`lbp run`,启动调试。在 LangBot 中配置支持工具调用的模型,并在对应流水线上选择使用该模型,即可使用该工具。
|
||
|
||
<img width="600" src="/images/zh/plugin/dev/components/tool_use_in_chat.png" />
|
||
|
||
## 一个安装,多份用法
|
||
|
||
一个 Tool 会被**多个处理器与会话**调用(同一事件可以触发多个插件处理器):
|
||
|
||
- 配置每次调用读取(`self.get_plugin_config()` 或 `ctx.config`),不要在 `initialize()` 中读取后缓存到实例。
|
||
- 不要把调用参数、返回结果或会话数据留在实例字段或模块级变量上;会话身份从当前调用的 `session` / `query_id` 取。
|
||
- 并发调用会共享同一个实例,实例字段会被交织写入;需要跨调用保留的数据放 Host 存储,键包含对应处理器或会话身份。
|
||
- 如果按安装维护了进程内缓存,请在 `on_installation_revoked(binding)` 中释放。
|
||
|
||
以上约束的完整说明见[认证插件与共享运行](/zh/plugin/certified-plugins)。
|
||
|
||
## 接下来做什么
|
||
|
||
您已经了解了工具的基本用法,接下来可以:
|
||
|
||
- 查看 Tool 的 [`session` 和 `query_id` 说明](/zh/plugin/dev/apis/agent-run#tool)
|
||
- 查看 [LangBot API](/zh/plugin/dev/apis/common)
|