主题
Fleet webhooks
将 agent 发布与外部系统、CI/CD 流水线或自定义部署工作流集成。
触发时,webhook 会将 agent 的完整配置和文件包发送到指定端点。
INFO
安全说明:
- Webhook URL 必须使用 HTTPS。
- 自定义标头(例如 API key)会加密存储。
- 会包含发布者身份以便审计。
- Webhook 仅对 agent 所有者可见。
添加 webhook
- 前往 Settings > Fleet webhooks。
- 点击 Add webhook。
- 配置:
- Name:描述性名称(例如 "Publish Agent"、"Deploy to Production")。
- URL:将接收 webhook 的 HTTPS 端点。
- Headers(可选):用于身份验证的自定义标头(加密存储)。
- Form Schema(可选):定义用户在触发时必须填写的自定义输入字段。
- 点击 Save。
触发 webhook
- 在 Fleet 编辑器中打开你的 agent。
- 点击 Settings 菜单(齿轮图标)。
- 在 Webhooks 下,点击 webhook 名称。
- 填写表单 schema 中定义的任何自定义字段。
- 点击 Run Webhook。
编辑 webhook
- 前往 Settings > Fleet webhooks。
- 对于要编辑的 webhook,点击 Edit。
- 进行更改并点击 Save。
删除 webhook
- 前往 Settings > Fleet webhooks。
- 对于要删除的 webhook,点击 Delete。
- 要确认删除,请再次点击 Delete。
Webhook payload
Webhook payload 是一个包含以下字段的 JSON 对象:
| 字段 | 说明 |
|---|---|
action | webhook 的名称。 |
input | 自定义表单字段的值(如果没有自定义字段,则为空对象)。 |
publisher | 触发 webhook 的人员的用户 ID 和电子邮件。 |
agent | Agent 名称和描述。 |
tool_auth_requirements | agent 使用的每个工具的身份验证要求。 |
files | 包含所有 agent 文件的 Base64 编码 ZIP。 |
fields | 自定义输入字段。 |
例如:
json
{
"action": "Webhook Name",
"input": {
"notes": "User-provided value",
"environment": "prod",
"dry_run": true
},
"publisher": {
"user_id": "uuid-of-publishing-user",
"email": "user@example.com"
},
"agent": {
"name": "My Agent",
"description": "Agent description text"
},
"tool_auth_requirements": [
{
"tool_name": "tavily_web_search",
"auth_type": "api_key",
"required_env_vars": ["TAVILY_API_KEY"]
},
{
"tool_name": "google_calendar",
"auth_type": "oauth",
"auth_provider": "google",
"scopes": ["calendar.readonly"]
}
],
"files": {
"type": "zip",
"filename": "My_Agent.zip",
"content_base64": "<base64-encoded-zip>"
},
"fields": [
{
"name": "notes",
"label": "Deployment Notes",
"type": "textarea"
}
]
}工具身份验证要求
tool_auth_requirements 数组描述每个工具所需的身份验证:
| 身份验证类型 | 字段 | 说明 |
|---|---|---|
none | - | 工具无需身份验证 |
api_key | required_env_vars | 工具需要环境变量中的 API key |
oauth | auth_provider、scopes | 工具需要具有指定 scope 的 OAuth token |
使用此信息为你的部署环境配置必要的凭据。
ZIP 文件结构
files.content_base64 字段包含一个具有以下结构的 ZIP 归档:
.
├── AGENTS.md # Agent system prompt and instructions
├── config.json # Agent metadata (name, description, visibility)
├── tools.json # Tool configurations and interrupt settings
├── skills/ # Optional skill definitions
│ └── skill-name/
│ └── SKILL.md
└── subagents/ # Optional subagent configurations
└── research_worker/
├── AGENTS.md
└── tools.jsonconfig.json 文件和 tools.json 文件的结构如下:
json
{
"name": "My Agent",
"description": "Agent description",
"visibility_scope": "tenant",
"triggers_paused": false
}自定义输入字段
你可以定义自定义输入字段,以便在触发 webhook 时收集信息。支持的字段类型如下:
| 类型 | 说明 |
|---|---|
string | 单行文本输入(默认)。 |
number | 数字输入。 |
boolean | 复选框(true/false)。 |
textarea | 多行文本输入。 |
json | JSON 编辑器。 |
select | 带预定义选项的下拉菜单。 |
例如:
json
{
"fields": [
{
"name": "notes",
"label": "Deployment Notes",
"type": "textarea"
},
{
"name": "environment",
"label": "Environment",
"type": "select",
"options": [
{ "label": "Development", "value": "dev" },
{ "label": "Staging", "value": "staging" },
{ "label": "Production", "value": "prod" }
]
},
{
"name": "dry_run",
"label": "Dry Run",
"type": "boolean",
"default": true
}
]
}示例:Webhook 服务器
以下是一个 Python webhook 服务器示例:
python
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import base64
import zipfile
import io
class WebhookHandler(BaseHTTPRequestHandler):
def do_POST(self):
content_length = int(self.headers['Content-Length'])
body = json.loads(self.rfile.read(content_length))
action = body.get("action")
input_data = body.get("input", {})
publisher = body.get("publisher", {})
agent = body.get("agent", {})
tool_auth = body.get("tool_auth_requirements", [])
files = body.get("files", {})
print(f"Webhook: {action}")
print(f"Publisher: {publisher.get('email')}")
print(f"Agent: {agent.get('name')}")
print(f"Custom Input: {input_data}")
# Extract ZIP contents
if files.get("content_base64"):
zip_bytes = base64.b64decode(files["content_base64"])
with zipfile.ZipFile(io.BytesIO(zip_bytes)) as zf:
print(f"Files: {zf.namelist()}")
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps({"status": "ok"}).encode())
HTTPServer(("", 8000), WebhookHandler).serve_forever()