跳到主要内容

🎬 动作函数:自定义交互按钮

⚠️ 关键安全警告

Action Functions 会在你的服务器上执行任意 Python 代码。 Function 创建权限仅限管理员。只应从可信来源安装,导入前必须审阅代码。恶意 Function 可能访问文件系统、外传数据,甚至接管整个系统。完整背景见 Plugin Security Warning

Action Function 允许你在聊天消息工具栏中添加自定义按钮。用户点击后,服务端就会执行对应逻辑。这适合做确认型操作、导出流程、可视化、外部工作流触发、文件处理等交互式功能。

为未来兼容性请始终使用 async

Action 函数应始终定义为 async。后端正在向全异步执行迁移;同步函数未来可能阻塞执行或触发兼容性问题。

Action 的结构

Action 是管理员管理的函数,会在配置了它的模型所生成的消息上显示为按钮。

class Action:
    def __init__(self):
        self.valves = self.Valves()

    class Valves(BaseModel):
        parameter_name: str = "default_value"
        priority: int = 0

    async def action(
        self,
        body: dict,
        __user__=None,
        __event_emitter__=None,
        __event_call__=None
    ):
        return {"content": "Modified message content"}

action() 方法可拿到的上下文

  • body:消息与上下文字典
  • __user__:当前用户
  • __event_emitter__:发送实时事件到前端
  • __event_call__:与用户双向交互
  • __model__:触发该 Action 的模型信息
  • __request__:FastAPI request 对象
  • __id__:当前 Action ID,适合多 Action 场景

事件系统集成

__event_emitter__

用于在执行过程中向前端发送状态、通知等实时更新:

async def action(self, body: dict, __event_emitter__=None):
    await __event_emitter__({
        "type": "status",
        "data": {"description": "Processing request..."}
    })

    await __event_emitter__({
        "type": "notification",
        "data": {"type": "info", "content": "Action completed successfully"}
    })

__event_call__

用于向用户请求确认或输入:

async def action(self, body: dict, __event_call__=None):
    response = await __event_call__({
        "type": "confirmation",
        "data": {
            "title": "Confirm Action",
            "message": "Are you sure you want to proceed?"
        }
    })

    user_input = await __event_call__({
        "type": "input",
        "data": {
            "title": "Enter Value",
            "message": "Please provide additional information:",
            "placeholder": "Type your input here..."
        }
    })

Action 形态

单一 Action

最常见的模式,类里只实现一个 action()

Multi-Action

也可以通过 actions 数组在一个 Function 中暴露多个子操作:

actions = [
    {
        "id": "summarize",
        "name": "Summarize",
        "icon_url": "https://example.com/icons/summarize.svg"
    },
    {
        "id": "translate",
        "name": "Translate",
        "icon_url": "https://example.com/icons/translate.svg"
    }
]

async def action(self, body: dict, __id__=None, **kwargs):
    if __id__ == "summarize":
        return {"content": "Summary: ..."}
    elif __id__ == "translate":
        return {"content": "Translation: ..."}

全局 Action 与模型级 Action

  • Global Action:在 Action 设置中开启全局开关,对所有用户和模型生效
  • Model-Specific Action:只在指定模型的设置中启用

按钮顺序:priority

消息下方的 Action 按钮会按 priority 从小到大排序。数值越小,越靠左、越先显示。

class Valves(BaseModel):
    priority: int = 0

如果多个 Action 都没有显式优先级,它们会默认使用 0,同优先级之间再按函数 ID 的字母顺序排序。

高级能力

长任务与后台执行

长任务通常会配合 status 事件,持续给用户反馈:

async def action(self, body: dict, __event_emitter__=None):
    await __event_emitter__({
        "type": "status",
        "data": {"description": "Starting background processing..."}
    })

    result = await some_long_running_function()
    return {"content": f"Processing completed: {result}"}

文件与媒体处理

Action 可以读取上传文件,也可以返回新文件:

async def action(self, body: dict):
    message = body

    if message.get("files"):
        for file in message["files"]:
            if file["type"] == "image":
                pass

    return {
        "content": "Analysis complete",
        "files": [
            {
                "type": "image",
                "url": "generated_chart.png",
                "name": "Analysis Chart"
            }
        ]
    }

用户上下文与权限

Action 可以基于当前用户角色和信息做权限判断:

async def action(self, body: dict, __user__=None):
    if __user__["role"] != "admin":
        return {"content": "This action requires admin privileges"}

    user_name = __user__["name"]
    return {"content": f"Hello {user_name}, admin action completed"}

Frontmatter

你可以在文件顶部 docstring 中定义 Action 元数据,例如:

  • title
  • author
  • version
  • required_open_webui_version
  • icon_url
不要使用 Base64 图标,优先使用 URL

不要把大块 base64 图片直接写进 icon_url。因为 Action 图标会随 /api/models 一起返回给前端,并在页面加载时反复传输。若一个 500KB 的 base64 图标挂在 20 个模型上,就会额外放大约 10MB 的返回体,只是为了这一张图标。

正确做法是:把图标托管成静态文件或公网 URL,再通过 URL 引用。

适合用 Action 的场景

  • 给消息增加“总结 / 翻译 / 导出”按钮
  • 触发审批、部署、Slack 通知等外部流程
  • 对某条消息做图表渲染、音频生成或文件分析
  • 需要用户显式确认后再执行的操作

如果你的能力需要“挂在消息上,被用户主动点击”,那通常就很适合做成 Action。*** End Patch