first commit

This commit is contained in:
2026-02-28 23:01:30 +08:00
commit 3956ee4806
415 changed files with 74538 additions and 0 deletions

41
.gitignore vendored Normal file
View File

@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

36
README.md Normal file
View File

@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

View File

@@ -0,0 +1,48 @@
import { getDocBySlug, getAllDocSlugs } from "../../../lib/docs";
import { DocContent } from "../../../components/DocContent";
import { notFound } from "next/navigation";
import { Metadata } from "next";
export async function generateStaticParams() {
const slugs = getAllDocSlugs();
return slugs.map((slug) => ({
slug,
}));
}
export async function generateMetadata(
{ params }: { params: Promise<{ slug: string[] }> }
): Promise<Metadata> {
const resolvedParams = await params;
const slug = resolvedParams?.slug || [];
const doc = await getDocBySlug(slug);
if (!doc) {
return {
title: "Not Found",
};
}
return {
title: doc.meta.title,
description: doc.meta.description || doc.meta.summary,
};
}
export default async function DocPage({ params }: { params: Promise<{ slug: string[] }> }) {
const resolvedParams = await params;
const slug = resolvedParams?.slug || [];
const doc = await getDocBySlug(slug);
if (!doc) {
notFound();
}
return (
<article className="doc-page-container">
<h1 className="text-4xl font-bold mb-4">{doc.meta.title}</h1>
{doc.meta.description && (
<p className="text-xl text-gray-500 dark:text-gray-400 mb-8">{doc.meta.description}</p>
)}
<DocContent contentHtml={doc.contentHtml} />
</article>
);
}

19
app/docs/layout.tsx Normal file
View File

@@ -0,0 +1,19 @@
import { Sidebar } from "../../components/Sidebar";
import { getSidebarStructure } from "../../lib/docs";
export default function DocsLayout({
children,
}: {
children: React.ReactNode;
}) {
const sidebarData = getSidebarStructure();
return (
<>
<Sidebar sidebarData={sidebarData} />
<main className="doc-main">
{children}
</main>
</>
);
}

374
app/globals.css Normal file
View File

@@ -0,0 +1,374 @@
:root {
--bg-primary: #ffffff;
--bg-secondary: #f8fafc;
--bg-sidebar: #f1f5f9;
--text-primary: #1e293b;
--text-secondary: #475569;
--text-muted: #94a3b8;
--border-color: #e2e8f0;
--accent-primary: #3b82f6;
--accent-hover: #2563eb;
--accent-glow: rgba(59, 130, 246, 0.1);
--sidebar-width: 280px;
--header-height: 64px;
}
[data-theme="dark"] {
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--bg-sidebar: #0b1120;
--text-primary: #f8fafc;
--text-secondary: #cbd5e1;
--text-muted: #64748b;
--border-color: #334155;
--accent-primary: #60a5fa;
--accent-hover: #93c5fd;
--accent-glow: rgba(96, 165, 250, 0.15);
}
body {
margin: 0;
padding: 0;
background-color: var(--bg-primary);
color: var(--text-primary);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
transition: background-color 0.3s ease, color 0.3s ease;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* --- Layout --- */
.doc-main {
margin-left: var(--sidebar-width);
min-height: 100vh;
padding: 3rem 4rem;
background-color: var(--bg-primary);
transition: background-color 0.3s ease;
}
@media (max-width: 768px) {
.doc-main {
margin-left: 0;
padding: 2rem 1.5rem;
}
.sidebar {
transform: translateX(-100%);
}
}
/* --- Sidebar Styles --- */
.sidebar {
width: var(--sidebar-width);
height: 100vh;
position: fixed;
left: 0;
top: 0;
background-color: var(--bg-sidebar);
border-right: 1px solid var(--border-color);
display: flex;
flex-direction: column;
z-index: 50;
transition: background-color 0.3s ease, border-color 0.3s ease, transform 0.3s ease;
}
.sidebar-header {
height: var(--header-height);
padding: 0 1.5rem;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid var(--border-color);
background-color: var(--bg-sidebar);
}
.sidebar-logo {
display: flex;
align-items: center;
gap: 0.75rem;
text-decoration: none;
}
.sidebar-logo-icon {
font-size: 1.5rem;
}
.sidebar-logo-text {
display: flex;
flex-direction: column;
}
.sidebar-logo-title {
font-weight: 700;
color: var(--text-primary);
font-size: 1.125rem;
line-height: 1.2;
letter-spacing: -0.025em;
}
.sidebar-logo-subtitle {
font-size: 0.75rem;
color: var(--text-muted);
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.sidebar-nav {
flex: 1;
overflow-y: auto;
padding: 1.5rem 1rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
/* Scrollbar for sidebar */
.sidebar-nav::-webkit-scrollbar {
width: 4px;
}
.sidebar-nav::-webkit-scrollbar-track {
background: transparent;
}
.sidebar-nav::-webkit-scrollbar-thumb {
background-color: var(--border-color);
border-radius: 4px;
}
.sidebar-section {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.sidebar-section-title {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.5rem 0.75rem;
font-weight: 600;
font-size: 0.9rem;
color: var(--text-primary);
cursor: pointer;
border-radius: 0.375rem;
transition: background-color 0.2s;
user-select: none;
}
.sidebar-section-title:hover {
background-color: var(--bg-secondary);
}
.sidebar-section-title.active {
color: var(--accent-primary);
}
.sidebar-section-arrow {
font-size: 0.6rem;
color: var(--text-muted);
transition: transform 0.2s ease;
}
.sidebar-section-arrow.open {
transform: rotate(90deg);
}
.sidebar-section-children {
display: flex;
flex-direction: column;
margin-left: 1rem;
border-left: 1px solid var(--border-color);
padding-left: 0.5rem;
gap: 0.15rem;
margin-top: 0.25rem;
}
.sidebar-link,
.sidebar-root-link {
display: block;
padding: 0.4rem 0.75rem;
font-size: 0.9rem;
color: var(--text-secondary);
text-decoration: none;
border-radius: 0.375rem;
transition: all 0.2s ease;
line-height: 1.5;
}
.sidebar-link:hover,
.sidebar-root-link:hover {
background-color: var(--bg-secondary);
color: var(--text-primary);
}
.sidebar-link.active,
.sidebar-root-link.active {
color: var(--accent-primary);
background-color: var(--accent-glow);
font-weight: 500;
}
/* --- DocContent (Markdown) Styles --- */
.doc-article {
color: var(--text-primary);
line-height: 1.75;
font-size: 1.05rem;
max-width: 800px;
margin: 0 auto;
}
.doc-article h1,
.doc-article h2,
.doc-article h3,
.doc-article h4,
.doc-article h5,
.doc-article h6 {
color: var(--text-primary);
font-weight: 700;
margin-top: 2.5rem;
margin-bottom: 1rem;
line-height: 1.3;
}
.doc-article h1 {
font-size: 2.5rem;
letter-spacing: -0.025em;
}
.doc-article h2 {
font-size: 1.875rem;
border-bottom: 1px solid var(--border-color);
padding-bottom: 0.5rem;
margin-top: 3rem;
}
.doc-article h3 {
font-size: 1.5rem;
}
.doc-article h4 {
font-size: 1.25rem;
}
.doc-article p {
margin-bottom: 1.5rem;
color: var(--text-secondary);
}
.doc-article a {
color: var(--accent-primary);
text-decoration: none;
font-weight: 500;
transition: all 0.2s;
border-bottom: 1px transparent;
}
.doc-article a:hover {
color: var(--accent-hover);
text-decoration: underline;
text-underline-offset: 2px;
}
.doc-article ul,
.doc-article ol {
margin-bottom: 1.5rem;
padding-left: 1.5rem;
color: var(--text-secondary);
}
.doc-article li {
margin-bottom: 0.5rem;
}
.doc-article li::marker {
color: var(--text-muted);
}
.doc-article img {
max-width: 100%;
height: auto;
border-radius: 0.5rem;
margin: 1.5rem 0;
border: 1px solid var(--border-color);
}
.doc-article code {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
background-color: var(--bg-secondary);
padding: 0.2rem 0.4rem;
border-radius: 0.25rem;
font-size: 0.875em;
color: var(--accent-primary);
border: 1px solid var(--border-color);
}
.doc-article pre {
background-color: #0f172a;
color: #f8fafc;
padding: 1.25rem;
border-radius: 0.5rem;
overflow-x: auto;
margin: 1.5rem 0;
border: 1px solid var(--border-color);
}
/* Ignore nested code styling inside pre */
.doc-article pre code {
background-color: transparent;
padding: 0;
color: inherit;
font-size: 0.9em;
border: none;
}
.doc-article blockquote {
border-left: 4px solid var(--accent-primary);
padding: 1rem 1.25rem;
margin: 1.5rem 0;
color: var(--text-muted);
font-style: italic;
background-color: var(--bg-secondary);
border-radius: 0 0.5rem 0.5rem 0;
}
.doc-article blockquote p:last-child {
margin-bottom: 0;
}
.doc-article table {
width: 100%;
border-collapse: collapse;
margin: 2rem 0;
font-size: 0.95rem;
}
.doc-article th,
.doc-article td {
padding: 0.75rem 1rem;
border: 1px solid var(--border-color);
text-align: left;
}
.doc-article th {
background-color: var(--bg-secondary);
font-weight: 600;
color: var(--text-primary);
}
.doc-article td {
color: var(--text-secondary);
}
.doc-article hr {
border: 0;
border-top: 1px solid var(--border-color);
margin: 3rem 0;
}
/* Title container wrapper inside article to strip Tailwind prose max-width constraint */
article {
max-width: 800px;
margin: 0 auto;
}

24
app/layout.tsx Normal file
View File

@@ -0,0 +1,24 @@
import type { Metadata } from "next";
import { ThemeProvider } from "../components/ThemeProvider";
import "./globals.css";
export const metadata: Metadata = {
title: "OpenClaw Documentation",
description: "OpenClaw 中文文档",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="zh-CN" suppressHydrationWarning>
<body>
<ThemeProvider>
{children}
</ThemeProvider>
</body>
</html>
);
}

5
app/page.tsx Normal file
View File

@@ -0,0 +1,5 @@
import { redirect } from "next/navigation";
export default function Home() {
redirect("/docs/start/getting-started");
}

35
components/DocContent.tsx Normal file
View File

@@ -0,0 +1,35 @@
'use client';
import { useRouter } from 'next/navigation';
import { MouseEvent } from 'react';
interface DocContentProps {
contentHtml: string;
}
export function DocContent({ contentHtml }: DocContentProps) {
const router = useRouter();
const handleLinkClick = (e: MouseEvent<HTMLElement>) => {
const target = e.target as HTMLElement;
const anchor = target.closest('a');
if (anchor && anchor.href) {
const url = new URL(anchor.href);
// If it's an internal link on the same origin
if (url.origin === window.location.origin) {
e.preventDefault();
router.push(url.pathname + url.search + url.hash);
}
}
};
return (
<div
className="doc-article"
onClick={handleLinkClick}
dangerouslySetInnerHTML={{ __html: contentHtml }}
/>
);
}

94
components/Sidebar.tsx Normal file
View File

@@ -0,0 +1,94 @@
'use client';
import Link from 'next/link';
import { useState, useEffect } from 'react';
import { ThemeToggle } from './ThemeToggle';
interface SidebarItem {
title: string;
slug: string;
children?: SidebarItem[];
}
interface SidebarProps {
sidebarData: SidebarItem[];
currentSlug?: string;
}
export function Sidebar({ sidebarData, currentSlug }: SidebarProps) {
// Use a map to track open state of each section (by slug)
const [openSections, setOpenSections] = useState<Record<string, boolean>>({});
useEffect(() => {
// Automatically open the section that contains the current slug
if (currentSlug) {
const parentSection = sidebarData.find(item =>
item.children?.some(child => child.slug === currentSlug)
);
if (parentSection) {
setOpenSections(prev => ({ ...prev, [parentSection.slug]: true }));
}
}
}, [currentSlug, sidebarData]);
const toggleSection = (slug: string) => {
setOpenSections(prev => ({ ...prev, [slug]: !prev[slug] }));
};
return (
<aside className="sidebar">
<div className="sidebar-header">
<Link href="/" className="sidebar-logo">
<div className="sidebar-logo-icon">🦞</div>
<div className="sidebar-logo-text">
<span className="sidebar-logo-title">OpenClaw</span>
<span className="sidebar-logo-subtitle"></span>
</div>
</Link>
<ThemeToggle />
</div>
<nav className="sidebar-nav">
{sidebarData.map(item => {
if (item.children && item.children.length > 0) {
const isOpen = !!openSections[item.slug];
const hasActiveChild = item.children.some(c => c.slug === currentSlug);
return (
<div key={item.slug} className="sidebar-section">
<div
className={`sidebar-section-title ${hasActiveChild ? 'active' : ''}`}
onClick={() => toggleSection(item.slug)}
>
{item.title}
<span className={`sidebar-section-arrow ${isOpen ? 'open' : ''}`}></span>
</div>
{isOpen && (
<div className="sidebar-section-children">
{item.children.map(child => (
<Link
key={child.slug}
href={child.slug}
className={`sidebar-link ${child.slug === currentSlug ? 'active' : ''}`}
>
{child.title}
</Link>
))}
</div>
)}
</div>
);
}
return (
<Link
key={item.slug}
href={item.slug}
className={`sidebar-root-link ${item.slug === currentSlug ? 'active' : ''}`}
>
{item.title}
</Link>
);
})}
</nav>
</aside>
);
}

View File

@@ -0,0 +1,49 @@
'use client';
import React, { createContext, useContext, useEffect, useState } from 'react';
type Theme = 'light' | 'dark';
interface ThemeContextType {
theme: Theme;
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<Theme>('dark'); // Default to dark as requested earlier
const [mounted, setMounted] = useState(false);
useEffect(() => {
const savedTheme = localStorage.getItem('theme') as Theme | null;
if (savedTheme) {
setTheme(savedTheme);
document.documentElement.setAttribute('data-theme', savedTheme);
} else {
document.documentElement.setAttribute('data-theme', 'dark');
}
setMounted(true);
}, []);
const toggleTheme = () => {
const newTheme = theme === 'light' ? 'dark' : 'light';
setTheme(newTheme);
localStorage.setItem('theme', newTheme);
document.documentElement.setAttribute('data-theme', newTheme);
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}

View File

@@ -0,0 +1,29 @@
'use client';
import { useTheme } from './ThemeProvider';
import { useEffect, useState } from 'react';
export function ThemeToggle() {
const { theme, toggleTheme } = useTheme();
const [mounted, setMounted] = useState(false);
// Avoid hydration mismatch by only rendering icon after mount
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
return <button className="theme-toggle" style={{ visibility: 'hidden' }}></button>;
}
return (
<button
onClick={toggleTheme}
className="theme-toggle"
title={theme === 'light' ? '切换到深色模式' : '切换到亮色模式'}
aria-label="Toggle theme"
>
{theme === 'light' ? '🌙' : '☀️'}
</button>
);
}

View File

@@ -0,0 +1,47 @@
---
read_when:
- 设置认证过期监控或告警
- 自动化 Claude Code / Codex OAuth 刷新检查
summary: 监控模型提供商的 OAuth 过期状态
title: 认证监控
x-i18n:
generated_at: "2026-02-03T10:03:53Z"
model: claude-opus-4-5
provider: pi
source_hash: eef179af9545ed7ab881f3ccbef998869437fb50cdb4088de8da7223b614fa2b
source_path: automation/auth-monitoring.md
workflow: 15
---
# 认证监控
OpenClaw 通过 `openclaw models status` 提供 OAuth 过期健康状态。请使用该命令进行自动化和告警;脚本是为手机工作流程提供的可选附加功能。
## 推荐方式CLI 检查(可移植)
```bash
openclaw models status --check
```
退出码:
- `0`:正常
- `1`:凭证过期或缺失
- `2`即将过期24 小时内)
此方式适用于 cron/systemd无需额外脚本。
## 可选脚本(运维 / 手机工作流程)
这些脚本位于 `scripts/` 目录下,属于**可选**内容。它们假定你可以通过 SSH 访问 Gateway 网关主机,并针对 systemd + Termux 进行了调优。
- `scripts/claude-auth-status.sh` 现在使用 `openclaw models status --json` 作为数据来源(如果 CLI 不可用则回退到直接读取文件),因此请确保 `openclaw` 在定时器的 `PATH` 中。
- `scripts/auth-monitor.sh`cron/systemd 定时器目标发送告警ntfy 或手机)。
- `scripts/systemd/openclaw-auth-monitor.{service,timer}`systemd 用户定时器。
- `scripts/claude-auth-status.sh`Claude Code + OpenClaw 认证检查器(完整/json/简洁模式)。
- `scripts/mobile-reauth.sh`:通过 SSH 引导的重新认证流程。
- `scripts/termux-quick-auth.sh`:一键小部件状态查看 + 打开认证 URL。
- `scripts/termux-auth-widget.sh`:完整的引导式小部件流程。
- `scripts/termux-sync-widget.sh`:同步 Claude Code 凭证 → OpenClaw。
如果你不需要手机自动化或 systemd 定时器,可以跳过这些脚本。

View File

@@ -0,0 +1,424 @@
---
read_when:
- 调度后台任务或唤醒
- 配置需要与心跳一起或并行运行的自动化
- 在心跳和定时任务之间做选择
summary: Gateway网关调度器的定时任务与唤醒
title: 定时任务
x-i18n:
generated_at: "2026-02-01T19:37:32Z"
model: claude-opus-4-5
provider: pi
source_hash: d43268b0029f1b13d0825ddcc9c06a354987ea17ce02f3b5428a9c68bf936676
source_path: automation/cron-jobs.md
workflow: 14
---
# 定时任务Gateway网关调度器
> **定时任务还是心跳?** 请参阅[定时任务与心跳对比](/automation/cron-vs-heartbeat)了解何时使用哪种方式。
定时任务是 Gateway网关内置的调度器。它持久化任务、在合适的时间唤醒智能体并可选择将输出发送回聊天。
如果你想要 _"每天早上运行"__"20 分钟后提醒智能体"_,定时任务就是对应的机制。
## 简要概述
- 定时任务运行在 **Gateway网关内部**(而非模型内部)。
- 任务持久化存储在 `~/.openclaw/cron/` 下,因此重启不会丢失计划。
- 两种执行方式:
- **主会话**:入队一个系统事件,然后在下一次心跳时运行。
- **隔离式**:在 `cron:<jobId>` 中运行专用智能体轮次,可投递摘要(默认 announce或不投递。
- 唤醒是一等功能:任务可以请求"立即唤醒"或"下次心跳时"。
## 快速开始(可操作)
创建一个一次性提醒,验证其存在,然后立即运行:
```bash
openclaw cron add \
--name "Reminder" \
--at "2026-02-01T16:00:00Z" \
--session main \
--system-event "Reminder: check the cron docs draft" \
--wake now \
--delete-after-run
openclaw cron list
openclaw cron run <job-id> --force
openclaw cron runs --id <job-id>
```
调度一个带投递功能的周期性隔离任务:
```bash
openclaw cron add \
--name "Morning brief" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize overnight updates." \
--announce \
--channel slack \
--to "channel:C1234567890"
```
## 工具调用等价形式Gateway网关定时任务工具
有关规范的 JSON 结构和示例,请参阅[工具调用的 JSON 模式](/automation/cron-jobs#json-schema-for-tool-calls)。
## 定时任务的存储位置
定时任务默认持久化存储在 Gateway网关主机的 `~/.openclaw/cron/jobs.json` 中。Gateway网关将文件加载到内存中并在更改时写回因此仅在 Gateway网关停止时手动编辑才是安全的。请优先使用 `openclaw cron add/edit` 或定时任务工具调用 API 进行更改。
## 新手友好概述
将定时任务理解为:**何时**运行 + **做什么**
1. **选择调度计划**
- 一次性提醒 → `schedule.kind = "at"`CLI`--at`
- 重复任务 → `schedule.kind = "every"``schedule.kind = "cron"`
- 如果你的 ISO 时间戳省略了时区,将被视为 **UTC**
2. **选择运行位置**
- `sessionTarget: "main"` → 在下一次心跳时使用主会话上下文运行。
- `sessionTarget: "isolated"` → 在 `cron:<jobId>` 中运行专用智能体轮次。
3. **选择负载**
- 主会话 → `payload.kind = "systemEvent"`
- 隔离会话 → `payload.kind = "agentTurn"`
可选:一次性任务(`schedule.kind = "at"`)默认会在成功运行后删除。设置
`deleteAfterRun: false` 可保留它(成功后会禁用)。
## 概念
### 任务
定时任务是一条存储记录,包含:
- 一个**调度计划**(何时运行),
- 一个**负载**(做什么),
- 可选的**投递**(输出发送到哪里)。
- 可选的**智能体绑定**`agentId`在指定智能体下运行任务如果缺失或未知Gateway网关会回退到默认智能体。
任务通过稳定的 `jobId` 标识(用于 CLI/Gateway网关 API
在智能体工具调用中,`jobId` 是规范字段;旧版 `id` 仍可兼容使用。
一次性任务默认会在成功运行后自动删除;设置 `deleteAfterRun: false` 可保留它。
### 调度计划
定时任务支持三种调度类型:
- `at`一次性时间戳ISO 8601 字符串)。
- `every`:固定间隔(毫秒)。
- `cron`5 字段 cron 表达式,可选 IANA 时区。
Cron 表达式使用 `croner`。如果省略时区,将使用 Gateway网关主机的本地时区。
### 主会话与隔离式执行
#### 主会话任务(系统事件)
主会话任务入队一个系统事件,并可选择唤醒心跳运行器。它们必须使用 `payload.kind = "systemEvent"`
- `wakeMode: "next-heartbeat"`(默认):事件等待下一次计划心跳。
- `wakeMode: "now"`:事件触发立即心跳运行。
当你需要正常的心跳提示 + 主会话上下文时,这是最佳选择。参见[心跳](/gateway/heartbeat)。
#### 隔离任务(专用定时会话)
隔离任务在会话 `cron:<jobId>` 中运行专用智能体轮次。
关键行为:
- 提示以 `[cron:<jobId> <任务名称>]` 为前缀,便于追踪。
- 每次运行都会启动一个**全新的会话 ID**(不继承之前的对话)。
- 如果未指定 `delivery`隔离任务会默认以“announce”方式投递摘要。
- `delivery.mode` 可选 `announce`(投递摘要)或 `none`(内部运行)。
对于嘈杂、频繁或"后台杂务"类任务,使用隔离任务可以避免污染你的主聊天记录。
### 负载结构(运行内容)
支持两种负载类型:
- `systemEvent`:仅限主会话,通过心跳提示路由。
- `agentTurn`:仅限隔离会话,运行专用智能体轮次。
常用 `agentTurn` 字段:
- `message`:必填文本提示。
- `model` / `thinking`:可选覆盖(见下文)。
- `timeoutSeconds`:可选超时覆盖。
### 模型和思维覆盖
隔离任务(`agentTurn`)可以覆盖模型和思维级别:
- `model`:提供商/模型字符串(例如 `anthropic/claude-sonnet-4-20250514`)或别名(例如 `opus`
- `thinking`:思维级别(`off``minimal``low``medium``high``xhigh`;仅限 GPT-5.2 + Codex 模型)
注意:你也可以在主会话任务上设置 `model`,但这会更改共享的主会话模型。我们建议仅对隔离任务使用模型覆盖,以避免意外的上下文切换。
优先级解析顺序:
1. 任务负载覆盖(最高优先级)
2. 钩子特定默认值(例如 `hooks.gmail.model`
3. 智能体配置默认值
### 投递(渠道 + 目标)
隔离任务可以通过顶层 `delivery` 配置投递输出:
- `delivery.mode``announce`(投递摘要)或 `none`
- `delivery.channel``whatsapp` / `telegram` / `discord` / `slack` / `mattermost`(插件)/ `signal` / `imessage` / `last`
- `delivery.to`:渠道特定的接收目标
- `delivery.bestEffort`:投递失败时避免任务失败
当启用 announce 投递时,该轮次会抑制消息工具发送;请使用 `delivery.channel`/`delivery.to` 来指定目标。
如果省略 `delivery.channel``delivery.to`,定时任务会回退到主会话的“最后路由”(智能体最后回复的位置)。
目标格式提醒:
- Slack/Discord/Mattermost插件目标应使用明确前缀例如 `channel:<id>``user:<id>`)以避免歧义。
- Telegram 主题应使用 `:topic:` 格式(见下文)。
#### Telegram 投递目标(主题/论坛帖子)
Telegram 通过 `message_thread_id` 支持论坛主题。对于定时任务投递,你可以将主题/帖子编码到 `to` 字段中:
- `-1001234567890`(仅聊天 ID
- `-1001234567890:topic:123`(推荐:明确的主题标记)
- `-1001234567890:123`(简写:数字后缀)
带前缀的目标如 `telegram:...` / `telegram:group:...` 也可接受:
- `telegram:group:-1001234567890:topic:123`
## 工具调用的 JSON 模式
直接调用 Gateway网关 `cron.*` 工具(智能体工具调用或 RPC时使用这些结构。CLI 标志接受人类可读的时间格式如 `20m`,但工具调用应使用 ISO 8601 字符串作为 `schedule.at`,并使用毫秒作为 `schedule.everyMs`
### cron.add 参数
一次性主会话任务(系统事件):
```json
{
"name": "Reminder",
"schedule": { "kind": "at", "at": "2026-02-01T16:00:00Z" },
"sessionTarget": "main",
"wakeMode": "now",
"payload": { "kind": "systemEvent", "text": "Reminder text" },
"deleteAfterRun": true
}
```
带投递的周期性隔离任务:
```json
{
"name": "Morning brief",
"schedule": { "kind": "cron", "expr": "0 7 * * *", "tz": "America/Los_Angeles" },
"sessionTarget": "isolated",
"wakeMode": "next-heartbeat",
"payload": {
"kind": "agentTurn",
"message": "Summarize overnight updates."
},
"delivery": {
"mode": "announce",
"channel": "slack",
"to": "channel:C1234567890",
"bestEffort": true
}
}
```
说明:
- `schedule.kind``at``at`)、`every``everyMs`)或 `cron``expr`,可选 `tz`)。
- `schedule.at` 接受 ISO 8601可省略时区省略时按 UTC 处理)。
- `everyMs` 为毫秒数。
- `sessionTarget` 必须为 `"main"``"isolated"`,且必须与 `payload.kind` 匹配。
- 可选字段:`agentId``description``enabled``deleteAfterRun``delivery`
- `wakeMode` 省略时默认为 `"next-heartbeat"`
### cron.update 参数
```json
{
"jobId": "job-123",
"patch": {
"enabled": false,
"schedule": { "kind": "every", "everyMs": 3600000 }
}
}
```
说明:
- `jobId` 是规范字段;`id` 可兼容使用。
- 在补丁中使用 `agentId: null` 可清除智能体绑定。
### cron.run 和 cron.remove 参数
```json
{ "jobId": "job-123", "mode": "force" }
```
```json
{ "jobId": "job-123" }
```
## 存储与历史
- 任务存储:`~/.openclaw/cron/jobs.json`Gateway网关管理的 JSON
- 运行历史:`~/.openclaw/cron/runs/<jobId>.jsonl`JSONL自动清理
- 覆盖存储路径:配置中的 `cron.store`
## 配置
```json5
{
cron: {
enabled: true, // 默认 true
store: "~/.openclaw/cron/jobs.json",
maxConcurrentRuns: 1, // 默认 1
},
}
```
完全禁用定时任务:
- `cron.enabled: false`(配置)
- `OPENCLAW_SKIP_CRON=1`(环境变量)
## CLI 快速开始
一次性提醒UTC ISO成功后自动删除
```bash
openclaw cron add \
--name "Send reminder" \
--at "2026-01-12T18:00:00Z" \
--session main \
--system-event "Reminder: submit expense report." \
--wake now \
--delete-after-run
```
一次性提醒(主会话,立即唤醒):
```bash
openclaw cron add \
--name "Calendar check" \
--at "20m" \
--session main \
--system-event "Next heartbeat: check calendar." \
--wake now
```
周期性隔离任务(投递到 WhatsApp
```bash
openclaw cron add \
--name "Morning status" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize inbox + calendar for today." \
--announce \
--channel whatsapp \
--to "+15551234567"
```
周期性隔离任务(投递到 Telegram 主题):
```bash
openclaw cron add \
--name "Nightly summary (topic)" \
--cron "0 22 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize today; send to the nightly topic." \
--announce \
--channel telegram \
--to "-1001234567890:topic:123"
```
带模型和思维覆盖的隔离任务:
```bash
openclaw cron add \
--name "Deep analysis" \
--cron "0 6 * * 1" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Weekly deep analysis of project progress." \
--model "opus" \
--thinking high \
--announce \
--channel whatsapp \
--to "+15551234567"
```
智能体选择(多智能体配置):
```bash
# 将任务绑定到智能体 "ops"(如果该智能体不存在则回退到默认智能体)
openclaw cron add --name "Ops sweep" --cron "0 6 * * *" --session isolated --message "Check ops queue" --agent ops
# 切换或清除现有任务的智能体
openclaw cron edit <jobId> --agent ops
openclaw cron edit <jobId> --clear-agent
```
手动运行(调试):
```bash
openclaw cron run <jobId> --force
```
编辑现有任务(补丁字段):
```bash
openclaw cron edit <jobId> \
--message "Updated prompt" \
--model "opus" \
--thinking low
```
运行历史:
```bash
openclaw cron runs --id <jobId> --limit 50
```
不创建任务直接发送系统事件:
```bash
openclaw system event --mode now --text "Next heartbeat: check battery."
```
## Gateway网关 API 接口
- `cron.list``cron.status``cron.add``cron.update``cron.remove`
- `cron.run`(强制或到期)、`cron.runs`
如需不创建任务直接发送系统事件,请使用 [`openclaw system event`](/cli/system)。
## 故障排除
### "没有任何任务运行"
- 检查定时任务是否已启用:`cron.enabled``OPENCLAW_SKIP_CRON`
- 检查 Gateway网关是否持续运行定时任务运行在 Gateway网关进程内部
- 对于 `cron` 调度:确认时区(`--tz`)与主机时区的关系。
### Telegram 投递到了错误的位置
- 对于论坛主题,使用 `-100…:topic:<id>` 以确保明确无歧义。
- 如果你在日志或存储的"最后路由"目标中看到 `telegram:...` 前缀,这是正常的;定时任务投递接受这些前缀并仍能正确解析主题 ID。

View File

@@ -0,0 +1,286 @@
---
read_when:
- 决定如何调度周期性任务
- 设置后台监控或通知
- 优化定期检查的 token 用量
summary: 选择心跳还是定时任务进行自动化的指南
title: 定时任务与心跳对比
x-i18n:
generated_at: "2026-02-01T19:38:18Z"
model: claude-opus-4-5
provider: pi
source_hash: 5f71a63181baa41b1c307eb7bfac561df7943d4627077dfa2861eb9f76ab086b
source_path: automation/cron-vs-heartbeat.md
workflow: 14
---
# 定时任务与心跳:何时使用哪种方式
心跳和定时任务都可以按计划运行任务。本指南帮助你根据使用场景选择合适的机制。
## 快速决策指南
| 使用场景 | 推荐方式 | 原因 |
| ------------------------- | -------------------------- | ---------------------------------------- |
| 每 30 分钟检查收件箱 | 心跳 | 可与其他检查批量处理,具备上下文感知能力 |
| 每天上午 9 点准时发送报告 | 定时任务(隔离式) | 需要精确定时 |
| 监控日历中即将到来的事件 | 心跳 | 天然适合周期性感知 |
| 运行每周深度分析 | 定时任务(隔离式) | 独立任务,可使用不同模型 |
| 20 分钟后提醒我 | 定时任务(主会话,`--at` | 精确定时的一次性任务 |
| 后台项目健康检查 | 心跳 | 搭载在现有周期上 |
## 心跳:周期性感知
心跳在**主会话**中以固定间隔运行默认30 分钟)。它的设计目的是让智能体检查各种事项并呈现重要信息。
### 何时使用心跳
- **多个周期性检查**:与其设置 5 个独立的定时任务分别检查收件箱、日历、天气、通知和项目状态,不如用一次心跳批量处理所有内容。
- **上下文感知决策**:智能体拥有完整的主会话上下文,因此可以智能判断哪些紧急、哪些可以等待。
- **对话连续性**:心跳运行共享同一会话,因此智能体记得最近的对话,可以自然地进行后续跟进。
- **低开销监控**:一次心跳替代多个小型轮询任务。
### 心跳优势
- **批量处理多项检查**:一次智能体轮次可以同时审查收件箱、日历和通知。
- **减少 API 调用**:一次心跳比 5 个隔离式定时任务更经济。
- **上下文感知**:智能体了解你一直在做什么,可以据此排定优先级。
- **智能抑制**:如果没有需要关注的事项,智能体回复 `HEARTBEAT_OK`,不会投递任何消息。
- **自然定时**:会根据队列负载略有漂移,但对大多数监控来说没有问题。
### 心跳示例HEARTBEAT.md 检查清单
```md
# Heartbeat checklist
- Check email for urgent messages
- Review calendar for events in next 2 hours
- If a background task finished, summarize results
- If idle for 8+ hours, send a brief check-in
```
智能体在每次心跳时读取此清单,并在一次轮次中处理所有项目。
### 配置心跳
```json5
{
agents: {
defaults: {
heartbeat: {
every: "30m", // 间隔
target: "last", // 告警投递目标
activeHours: { start: "08:00", end: "22:00" }, // 可选
},
},
},
}
```
完整配置请参阅[心跳](/gateway/heartbeat)。
## 定时任务:精确调度
定时任务在**精确时间**运行,可以在隔离会话中运行而不影响主会话上下文。
### 何时使用定时任务
- **需要精确定时**"每周一上午 9:00 发送"(而不是"大约 9 点左右")。
- **独立任务**:不需要对话上下文的任务。
- **不同的模型/思维级别**:需要更强大模型的深度分析。
- **一次性提醒**:使用 `--at` 实现"20 分钟后提醒我"。
- **嘈杂/频繁的任务**:会把主会话历史搞得杂乱的任务。
- **外部触发器**:无论智能体是否处于活跃状态都应独立运行的任务。
### 定时任务优势
- **精确定时**:支持带时区的 5 字段 cron 表达式。
- **会话隔离**:在 `cron:<jobId>` 中运行,不会污染主会话历史。
- **模型覆盖**:可按任务使用更便宜或更强大的模型。
- **投递控制**:隔离任务默认以 `announce` 投递摘要,可选 `none` 仅内部运行。
- **无需智能体上下文**:即使主会话空闲或已压缩,也能运行。
- **一次性支持**`--at` 用于精确的未来时间戳。
### 定时任务示例:每日早间简报
```bash
openclaw cron add \
--name "Morning briefing" \
--cron "0 7 * * *" \
--tz "America/New_York" \
--session isolated \
--message "Generate today's briefing: weather, calendar, top emails, news summary." \
--model opus \
--announce \
--channel whatsapp \
--to "+15551234567"
```
这会在纽约时间每天早上 7:00 准时运行,使用 Opus 保证质量,并直接投递到 WhatsApp。
### 定时任务示例:一次性提醒
```bash
openclaw cron add \
--name "Meeting reminder" \
--at "20m" \
--session main \
--system-event "Reminder: standup meeting starts in 10 minutes." \
--wake now \
--delete-after-run
```
完整 CLI 参考请参阅[定时任务](/automation/cron-jobs)。
## 决策流程图
```
任务是否需要在精确时间运行?
是 -> 使用定时任务
否 -> 继续...
任务是否需要与主会话隔离?
是 -> 使用定时任务(隔离式)
否 -> 继续...
此任务能否与其他周期性检查批量处理?
是 -> 使用心跳(添加到 HEARTBEAT.md
否 -> 使用定时任务
这是一次性提醒吗?
是 -> 使用定时任务配合 --at
否 -> 继续...
是否需要不同的模型或思维级别?
是 -> 使用定时任务(隔离式)配合 --model/--thinking
否 -> 使用心跳
```
## 组合使用
最高效的配置是**两者结合**
1. **心跳**处理常规监控(收件箱、日历、通知),每 30 分钟批量处理一次。
2. **定时任务**处理精确调度(每日报告、每周回顾)和一次性提醒。
### 示例:高效自动化配置
**HEARTBEAT.md**(每 30 分钟检查一次):
```md
# Heartbeat checklist
- Scan inbox for urgent emails
- Check calendar for events in next 2h
- Review any pending tasks
- Light check-in if quiet for 8+ hours
```
**定时任务**(精确定时):
```bash
# 每天早上 7 点的早间简报
openclaw cron add --name "Morning brief" --cron "0 7 * * *" --session isolated --message "..." --announce
# 每周一上午 9 点的项目回顾
openclaw cron add --name "Weekly review" --cron "0 9 * * 1" --session isolated --message "..." --model opus
# 一次性提醒
openclaw cron add --name "Call back" --at "2h" --session main --system-event "Call back the client" --wake now
```
## Lobster带审批的确定性工作流
Lobster 是用于**多步骤工具管道**的工作流运行时,适用于需要确定性执行和明确审批的场景。当任务不只是单次智能体轮次,且你需要可恢复的带人工检查点的工作流时,使用它。
### 何时适合使用 Lobster
- **多步骤自动化**:你需要一个固定的工具调用管道,而不是一次性提示。
- **审批关卡**:副作用应暂停直到你批准,然后继续执行。
- **可恢复运行**:继续暂停的工作流而无需重新运行之前的步骤。
### 如何与心跳和定时任务配合
- **心跳/定时任务**决定*何时*运行。
- **Lobster** 定义运行开始后*执行哪些步骤*。
对于计划性工作流,使用定时任务或心跳触发一次调用 Lobster 的智能体轮次。对于临时工作流,直接调用 Lobster。
### 操作说明(来自代码)
- Lobster 以**本地子进程**`lobster` CLI在工具模式下运行并返回 **JSON 信封**
- 如果工具返回 `needs_approval`,你需要使用 `resumeToken``approve` 标志来恢复。
- 该工具是**可选插件**;建议通过 `tools.alsoAllow: ["lobster"]` 附加启用。
- 如果传入 `lobsterPath`,必须是**绝对路径**。
完整用法和示例请参阅 [Lobster](/tools/lobster)。
## 主会话与隔离会话
心跳和定时任务都可以与主会话交互,但方式不同:
| | 心跳 | 定时任务(主会话) | 定时任务(隔离式) |
| ------ | ------------------------ | ---------------------- | --------------------- |
| 会话 | 主会话 | 主会话(通过系统事件) | `cron:<jobId>` |
| 历史 | 共享 | 共享 | 每次运行全新 |
| 上下文 | 完整 | 完整 | 无(从零开始) |
| 模型 | 主会话模型 | 主会话模型 | 可覆盖 |
| 输出 | 非 `HEARTBEAT_OK` 时投递 | 心跳提示 + 事件 | announce 摘要(默认) |
### 何时使用主会话定时任务
当你需要以下场景时,使用 `--session main` 配合 `--system-event`
- 提醒/事件出现在主会话上下文中
- 智能体在下一次心跳时带着完整上下文处理它
- 不需要单独的隔离运行
```bash
openclaw cron add \
--name "Check project" \
--every "4h" \
--session main \
--system-event "Time for a project health check" \
--wake now
```
### 何时使用隔离式定时任务
当你需要以下场景时,使用 `--session isolated`
- 无先前上下文的全新环境
- 不同的模型或思维设置
- 输出可通过 `announce` 直接投递摘要(或用 `none` 仅内部运行)
- 不会把主会话搞得杂乱的历史记录
```bash
openclaw cron add \
--name "Deep analysis" \
--cron "0 6 * * 0" \
--session isolated \
--message "Weekly codebase analysis..." \
--model opus \
--thinking high \
--announce
```
## 成本考量
| 机制 | 成本特征 |
| ------------------ | ---------------------------------------------- |
| 心跳 | 每 N 分钟一次轮次;随 HEARTBEAT.md 大小扩展 |
| 定时任务(主会话) | 将事件添加到下一次心跳(无隔离轮次) |
| 定时任务(隔离式) | 每个任务一次完整智能体轮次;可使用更便宜的模型 |
**建议**
- 保持 `HEARTBEAT.md` 精简以减少 token 开销。
- 将类似的检查批量放入心跳,而不是创建多个定时任务。
- 如果只需要内部处理,在心跳上使用 `target: "none"`
- 对常规任务使用隔离式定时任务配合更便宜的模型。
## 相关内容
- [心跳](/gateway/heartbeat) - 完整的心跳配置
- [定时任务](/automation/cron-jobs) - 完整的定时任务 CLI 和 API 参考
- [系统](/cli/system) - 系统事件 + 心跳控制

View File

@@ -0,0 +1,249 @@
---
read_when:
- 将 Gmail 收件箱触发器接入 OpenClaw
- 为智能体唤醒设置 Pub/Sub 推送
summary: 通过 gogcli 将 Gmail Pub/Sub 推送接入 OpenClaw webhooks
title: Gmail PubSub
x-i18n:
generated_at: "2026-02-03T07:43:25Z"
model: claude-opus-4-5
provider: pi
source_hash: dfb92133b69177e4e984b7d072f5dc28aa53a9e0cf984a018145ed811aa96195
source_path: automation/gmail-pubsub.md
workflow: 15
---
# Gmail Pub/Sub -> OpenClaw
目标Gmail watch -> Pub/Sub 推送 -> `gog gmail watch serve` -> OpenClaw webhook。
## 前置条件
- 已安装并登录 `gcloud`[安装指南](https://docs.cloud.google.com/sdk/docs/install-sdk))。
- 已安装 `gog` (gogcli) 并为 Gmail 账户授权([gogcli.sh](https://gogcli.sh/))。
- 已启用 OpenClaw hooks参见 [Webhooks](/automation/webhook))。
- 已登录 `tailscale`[tailscale.com](https://tailscale.com/))。支持的设置使用 Tailscale Funnel 作为公共 HTTPS 端点。
其他隧道服务也可以使用,但需要自行配置/不受支持,需要手动接入。
目前,我们支持的是 Tailscale。
示例 hook 配置(启用 Gmail 预设映射):
```json5
{
hooks: {
enabled: true,
token: "OPENCLAW_HOOK_TOKEN",
path: "/hooks",
presets: ["gmail"],
},
}
```
要将 Gmail 摘要投递到聊天界面,请用设置了 `deliver` 以及可选的 `channel`/`to` 的映射覆盖预设:
```json5
{
hooks: {
enabled: true,
token: "OPENCLAW_HOOK_TOKEN",
presets: ["gmail"],
mappings: [
{
match: { path: "gmail" },
action: "agent",
wakeMode: "now",
name: "Gmail",
sessionKey: "hook:gmail:{{messages[0].id}}",
messageTemplate: "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
model: "openai/gpt-5.2-mini",
deliver: true,
channel: "last",
// to: "+15551234567"
},
],
},
}
```
如果你想使用固定渠道,请设置 `channel` + `to`。否则 `channel: "last"` 会使用上次的投递路由(默认回退到 WhatsApp
要为 Gmail 运行强制使用更便宜的模型,请在映射中设置 `model``provider/model` 或别名)。如果你强制启用了 `agents.defaults.models`,请将其包含在内。
要专门为 Gmail hooks 设置默认模型和思考级别,请在配置中添加 `hooks.gmail.model` / `hooks.gmail.thinking`
```json5
{
hooks: {
gmail: {
model: "openrouter/meta-llama/llama-3.3-70b-instruct:free",
thinking: "off",
},
},
}
```
注意事项:
- 映射中的每个 hook 的 `model`/`thinking` 仍会覆盖这些默认值。
- 回退顺序:`hooks.gmail.model``agents.defaults.model.fallbacks` → 主模型(认证/速率限制/超时)。
- 如果设置了 `agents.defaults.models`Gmail 模型必须在允许列表中。
- Gmail hook 内容默认使用外部内容安全边界包装。
要禁用(危险),请设置 `hooks.gmail.allowUnsafeExternalContent: true`
要进一步自定义负载处理,请添加 `hooks.mappings` 或在 `hooks.transformsDir` 下添加 JS/TS 转换模块(参见 [Webhooks](/automation/webhook))。
## 向导(推荐)
使用 OpenClaw 助手将所有内容接入在一起(在 macOS 上通过 brew 安装依赖):
```bash
openclaw webhooks gmail setup \
--account openclaw@gmail.com
```
默认设置:
- 使用 Tailscale Funnel 作为公共推送端点。
-`openclaw webhooks gmail run` 写入 `hooks.gmail` 配置。
- 启用 Gmail hook 预设(`hooks.presets: ["gmail"]`)。
路径说明:当启用 `tailscale.mode`OpenClaw 会自动将 `hooks.gmail.serve.path` 设置为 `/`,并将公共路径保持在 `hooks.gmail.tailscale.path`(默认 `/gmail-pubsub`),因为 Tailscale 在代理之前会剥离设置的路径前缀。
如果你需要后端接收带前缀的路径,请将 `hooks.gmail.tailscale.target`(或 `--tailscale-target`)设置为完整 URL`http://127.0.0.1:8788/gmail-pubsub`,并匹配 `hooks.gmail.serve.path`
想要自定义端点?使用 `--push-endpoint <url>``--tailscale off`
平台说明:在 macOS 上,向导通过 Homebrew 安装 `gcloud``gogcli``tailscale`;在 Linux 上请先手动安装它们。
Gateway 网关自动启动(推荐):
-`hooks.enabled=true` 且设置了 `hooks.gmail.account`Gateway 网关会在启动时运行 `gog gmail watch serve` 并自动续期 watch。
- 设置 `OPENCLAW_SKIP_GMAIL_WATCHER=1` 可退出(如果你自己运行守护进程则很有用)。
- 不要同时运行手动守护进程,否则会遇到 `listen tcp 127.0.0.1:8788: bind: address already in use`
手动守护进程(启动 `gog gmail watch serve` + 自动续期):
```bash
openclaw webhooks gmail run
```
## 一次性设置
1. 选择**拥有 `gog` 使用的 OAuth 客户端**的 GCP 项目。
```bash
gcloud auth login
gcloud config set project <project-id>
```
注意Gmail watch 要求 Pub/Sub 主题与 OAuth 客户端位于同一项目中。
2. 启用 API
```bash
gcloud services enable gmail.googleapis.com pubsub.googleapis.com
```
3. 创建主题:
```bash
gcloud pubsub topics create gog-gmail-watch
```
4. 允许 Gmail push 发布:
```bash
gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \
--member=serviceAccount:gmail-api-push@system.gserviceaccount.com \
--role=roles/pubsub.publisher
```
## 启动 watch
```bash
gog gmail watch start \
--account openclaw@gmail.com \
--label INBOX \
--topic projects/<project-id>/topics/gog-gmail-watch
```
保存输出中的 `history_id`(用于调试)。
## 运行推送处理程序
本地示例(共享 token 认证):
```bash
gog gmail watch serve \
--account openclaw@gmail.com \
--bind 127.0.0.1 \
--port 8788 \
--path /gmail-pubsub \
--token <shared> \
--hook-url http://127.0.0.1:18789/hooks/gmail \
--hook-token OPENCLAW_HOOK_TOKEN \
--include-body \
--max-bytes 20000
```
注意事项:
- `--token` 保护推送端点(`x-gog-token``?token=`)。
- `--hook-url` 指向 OpenClaw `/hooks/gmail`(已映射;隔离运行 + 摘要发送到主线程)。
- `--include-body``--max-bytes` 控制发送到 OpenClaw 的正文片段。
推荐:`openclaw webhooks gmail run` 封装了相同的流程并自动续期 watch。
## 暴露处理程序(高级,不受支持)
如果你需要非 Tailscale 隧道,请手动接入并在推送订阅中使用公共 URL不受支持无保护措施
```bash
cloudflared tunnel --url http://127.0.0.1:8788 --no-autoupdate
```
使用生成的 URL 作为推送端点:
```bash
gcloud pubsub subscriptions create gog-gmail-watch-push \
--topic gog-gmail-watch \
--push-endpoint "https://<public-url>/gmail-pubsub?token=<shared>"
```
生产环境:使用稳定的 HTTPS 端点并配置 Pub/Sub OIDC JWT然后运行
```bash
gog gmail watch serve --verify-oidc --oidc-email <svc@...>
```
## 测试
向被监视的收件箱发送一条消息:
```bash
gog gmail send \
--account openclaw@gmail.com \
--to openclaw@gmail.com \
--subject "watch test" \
--body "ping"
```
检查 watch 状态和历史记录:
```bash
gog gmail watch status --account openclaw@gmail.com
gog gmail history --account openclaw@gmail.com --since <historyId>
```
## 故障排除
- `Invalid topicName`:项目不匹配(主题不在 OAuth 客户端项目中)。
- `User not authorized`:主题缺少 `roles/pubsub.publisher`
- 空消息Gmail push 仅提供 `historyId`;通过 `gog gmail history` 获取。
## 清理
```bash
gog gmail watch stop --account openclaw@gmail.com
gcloud pubsub subscriptions delete gog-gmail-watch-push
gcloud pubsub topics delete gog-gmail-watch
```

882
content/automation/hooks.md Normal file
View File

@@ -0,0 +1,882 @@
---
read_when:
- 你想为 /new、/reset、/stop 和智能体生命周期事件实现事件驱动自动化
- 你想构建、安装或调试 hooks
summary: Hooks用于命令和生命周期事件的事件驱动自动化
title: Hooks
x-i18n:
generated_at: "2026-02-03T07:50:59Z"
model: claude-opus-4-5
provider: pi
source_hash: 853227a0f1abd20790b425fa64dda60efc6b5f93c1b13ecd2dcb788268f71d79
source_path: automation/hooks.md
workflow: 15
---
# Hooks
Hooks 提供了一个可扩展的事件驱动系统用于响应智能体命令和事件自动执行操作。Hooks 从目录中自动发现,可以通过 CLI 命令管理,类似于 OpenClaw 中 Skills 的工作方式。
## 入门指南
Hooks 是在事件发生时运行的小脚本。有两种类型:
- **Hooks**(本页):当智能体事件触发时在 Gateway 网关内运行,如 `/new``/reset``/stop` 或生命周期事件。
- **Webhooks**:外部 HTTP webhooks让其他系统触发 OpenClaw 中的工作。参见 [Webhook Hooks](/automation/webhook) 或使用 `openclaw webhooks` 获取 Gmail 助手命令。
Hooks 也可以捆绑在插件中;参见 [插件](/tools/plugin#plugin-hooks)。
常见用途:
- 重置会话时保存记忆快照
- 保留命令审计跟踪用于故障排除或合规
- 会话开始或结束时触发后续自动化
- 事件触发时向智能体工作区写入文件或调用外部 API
如果你能写一个小的 TypeScript 函数,你就能写一个 hook。Hooks 会自动发现,你可以通过 CLI 启用或禁用它们。
## 概述
hooks 系统允许你:
- 在发出 `/new` 时将会话上下文保存到记忆
- 记录所有命令以供审计
- 在智能体生命周期事件上触发自定义自动化
- 在不修改核心代码的情况下扩展 OpenClaw 的行为
## 入门
### 捆绑的 Hooks
OpenClaw 附带三个自动发现的捆绑 hooks
- **💾 session-memory**:当你发出 `/new` 时将会话上下文保存到智能体工作区(默认 `~/.openclaw/workspace/memory/`
- **📝 command-logger**:将所有命令事件记录到 `~/.openclaw/logs/commands.log`
- **🚀 boot-md**:当 Gateway 网关启动时运行 `BOOT.md`(需要启用内部 hooks
列出可用的 hooks
```bash
openclaw hooks list
```
启用一个 hook
```bash
openclaw hooks enable session-memory
```
检查 hook 状态:
```bash
openclaw hooks check
```
获取详细信息:
```bash
openclaw hooks info session-memory
```
### 新手引导
在新手引导期间(`openclaw onboard`),你将被提示启用推荐的 hooks。向导会自动发现符合条件的 hooks 并呈现供选择。
## Hook 发现
Hooks 从三个目录自动发现(按优先级顺序):
1. **工作区 hooks**`<workspace>/hooks/`(每智能体,最高优先级)
2. **托管 hooks**`~/.openclaw/hooks/`(用户安装,跨工作区共享)
3. **捆绑 hooks**`<openclaw>/dist/hooks/bundled/`(随 OpenClaw 附带)
托管 hook 目录可以是**单个 hook** 或 **hook 包**(包目录)。
每个 hook 是一个包含以下内容的目录:
```
my-hook/
├── HOOK.md # 元数据 + 文档
└── handler.ts # 处理程序实现
```
## Hook 包npm/archives
Hook 包是标准的 npm 包,通过 `package.json` 中的 `openclaw.hooks` 导出一个或多个 hooks。使用以下命令安装
```bash
openclaw hooks install <path-or-spec>
```
示例 `package.json`
```json
{
"name": "@acme/my-hooks",
"version": "0.1.0",
"openclaw": {
"hooks": ["./hooks/my-hook", "./hooks/other-hook"]
}
}
```
每个条目指向包含 `HOOK.md``handler.ts`(或 `index.ts`)的 hook 目录。
Hook 包可以附带依赖;它们将安装在 `~/.openclaw/hooks/<id>` 下。
## Hook 结构
### HOOK.md 格式
`HOOK.md` 文件在 YAML frontmatter 中包含元数据,加上 Markdown 文档:
```markdown
---
name: my-hook
description: "Short description of what this hook does"
homepage: https://docs.openclaw.ai/automation/hooks#my-hook
metadata:
{ "openclaw": { "emoji": "🔗", "events": ["command:new"], "requires": { "bins": ["node"] } } }
---
# My Hook
Detailed documentation goes here...
## What It Does
- Listens for `/new` commands
- Performs some action
- Logs the result
## Requirements
- Node.js must be installed
## Configuration
No configuration needed.
```
### 元数据字段
`metadata.openclaw` 对象支持:
- **`emoji`**CLI 的显示表情符号(例如 `"💾"`
- **`events`**:要监听的事件数组(例如 `["command:new", "command:reset"]`
- **`export`**:要使用的命名导出(默认为 `"default"`
- **`homepage`**:文档 URL
- **`requires`**:可选要求
- **`bins`**PATH 中需要的二进制文件(例如 `["git", "node"]`
- **`anyBins`**:这些二进制文件中至少有一个必须存在
- **`env`**:需要的环境变量
- **`config`**:需要的配置路径(例如 `["workspace.dir"]`
- **`os`**:需要的平台(例如 `["darwin", "linux"]`
- **`always`**:绕过资格检查(布尔值)
- **`install`**:安装方法(对于捆绑 hooks`[{"id":"bundled","kind":"bundled"}]`
### 处理程序实现
`handler.ts` 文件导出一个 `HookHandler` 函数:
```typescript
import type { HookHandler } from "../../src/hooks/hooks.js";
const myHandler: HookHandler = async (event) => {
// Only trigger on 'new' command
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log(`[my-hook] New command triggered`);
console.log(` Session: ${event.sessionKey}`);
console.log(` Timestamp: ${event.timestamp.toISOString()}`);
// Your custom logic here
// Optionally send message to user
event.messages.push("✨ My hook executed!");
};
export default myHandler;
```
#### 事件上下文
每个事件包含:
```typescript
{
type: 'command' | 'session' | 'agent' | 'gateway',
action: string, // e.g., 'new', 'reset', 'stop'
sessionKey: string, // Session identifier
timestamp: Date, // When the event occurred
messages: string[], // Push messages here to send to user
context: {
sessionEntry?: SessionEntry,
sessionId?: string,
sessionFile?: string,
commandSource?: string, // e.g., 'whatsapp', 'telegram'
senderId?: string,
workspaceDir?: string,
bootstrapFiles?: WorkspaceBootstrapFile[],
cfg?: OpenClawConfig
}
}
```
## 事件类型
### 命令事件
当发出智能体命令时触发:
- **`command`**:所有命令事件(通用监听器)
- **`command:new`**:当发出 `/new` 命令时
- **`command:reset`**:当发出 `/reset` 命令时
- **`command:stop`**:当发出 `/stop` 命令时
### 智能体事件
- **`agent:bootstrap`**在注入工作区引导文件之前hooks 可以修改 `context.bootstrapFiles`
### Gateway 网关事件
当 Gateway 网关启动时触发:
- **`gateway:startup`**:在渠道启动和 hooks 加载之后
### 工具结果 Hooks插件 API
这些 hooks 不是事件流监听器;它们让插件在 OpenClaw 持久化工具结果之前同步调整它们。
- **`tool_result_persist`**:在工具结果写入会话记录之前转换它们。必须是同步的;返回更新后的工具结果负载或 `undefined` 保持原样。参见 [智能体循环](/concepts/agent-loop)。
### 未来事件
计划中的事件类型:
- **`session:start`**:当新会话开始时
- **`session:end`**:当会话结束时
- **`agent:error`**:当智能体遇到错误时
- **`message:sent`**:当消息被发送时
- **`message:received`**:当消息被接收时
## 创建自定义 Hooks
### 1. 选择位置
- **工作区 hooks**`<workspace>/hooks/`):每智能体,最高优先级
- **托管 hooks**`~/.openclaw/hooks/`):跨工作区共享
### 2. 创建目录结构
```bash
mkdir -p ~/.openclaw/hooks/my-hook
cd ~/.openclaw/hooks/my-hook
```
### 3. 创建 HOOK.md
```markdown
---
name: my-hook
description: "Does something useful"
metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
---
# My Custom Hook
This hook does something useful when you issue `/new`.
```
### 4. 创建 handler.ts
```typescript
import type { HookHandler } from "../../src/hooks/hooks.js";
const handler: HookHandler = async (event) => {
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log("[my-hook] Running!");
// Your logic here
};
export default handler;
```
### 5. 启用并测试
```bash
# Verify hook is discovered
openclaw hooks list
# Enable it
openclaw hooks enable my-hook
# Restart your gateway process (menu bar app restart on macOS, or restart your dev process)
# Trigger the event
# Send /new via your messaging channel
```
## 配置
### 新配置格式(推荐)
```json
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"session-memory": { "enabled": true },
"command-logger": { "enabled": false }
}
}
}
}
```
### 每 Hook 配置
Hooks 可以有自定义配置:
```json
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"my-hook": {
"enabled": true,
"env": {
"MY_CUSTOM_VAR": "value"
}
}
}
}
}
}
```
### 额外目录
从额外目录加载 hooks
```json
{
"hooks": {
"internal": {
"enabled": true,
"load": {
"extraDirs": ["/path/to/more/hooks"]
}
}
}
}
```
### 遗留配置格式(仍然支持)
旧配置格式仍然有效以保持向后兼容:
```json
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts",
"export": "default"
}
]
}
}
}
```
**迁移**:对新 hooks 使用基于发现的新系统。遗留处理程序在基于目录的 hooks 之后加载。
## CLI 命令
### 列出 Hooks
```bash
# List all hooks
openclaw hooks list
# Show only eligible hooks
openclaw hooks list --eligible
# Verbose output (show missing requirements)
openclaw hooks list --verbose
# JSON output
openclaw hooks list --json
```
### Hook 信息
```bash
# Show detailed info about a hook
openclaw hooks info session-memory
# JSON output
openclaw hooks info session-memory --json
```
### 检查资格
```bash
# Show eligibility summary
openclaw hooks check
# JSON output
openclaw hooks check --json
```
### 启用/禁用
```bash
# Enable a hook
openclaw hooks enable session-memory
# Disable a hook
openclaw hooks disable command-logger
```
## 捆绑的 Hooks
### session-memory
当你发出 `/new` 时将会话上下文保存到记忆。
**事件**`command:new`
**要求**:必须配置 `workspace.dir`
**输出**`<workspace>/memory/YYYY-MM-DD-slug.md`(默认为 `~/.openclaw/workspace`
**功能**
1. 使用预重置会话条目定位正确的记录
2. 提取最后 15 行对话
3. 使用 LLM 生成描述性文件名 slug
4. 将会话元数据保存到带日期的记忆文件
**示例输出**
```markdown
# Session: 2026-01-16 14:30:00 UTC
- **Session Key**: agent:main:main
- **Session ID**: abc123def456
- **Source**: telegram
```
**文件名示例**
- `2026-01-16-vendor-pitch.md`
- `2026-01-16-api-design.md`
- `2026-01-16-1430.md`(如果 slug 生成失败则回退到时间戳)
**启用**
```bash
openclaw hooks enable session-memory
```
### command-logger
将所有命令事件记录到集中审计文件。
**事件**`command`
**要求**:无
**输出**`~/.openclaw/logs/commands.log`
**功能**
1. 捕获事件详情(命令操作、时间戳、会话键、发送者 ID、来源
2. 以 JSONL 格式追加到日志文件
3. 在后台静默运行
**示例日志条目**
```jsonl
{"timestamp":"2026-01-16T14:30:00.000Z","action":"new","sessionKey":"agent:main:main","senderId":"+1234567890","source":"telegram"}
{"timestamp":"2026-01-16T15:45:22.000Z","action":"stop","sessionKey":"agent:main:main","senderId":"user@example.com","source":"whatsapp"}
```
**查看日志**
```bash
# View recent commands
tail -n 20 ~/.openclaw/logs/commands.log
# Pretty-print with jq
cat ~/.openclaw/logs/commands.log | jq .
# Filter by action
grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .
```
**启用**
```bash
openclaw hooks enable command-logger
```
### boot-md
当 Gateway 网关启动时运行 `BOOT.md`(在渠道启动之后)。
必须启用内部 hooks 才能运行。
**事件**`gateway:startup`
**要求**:必须配置 `workspace.dir`
**功能**
1. 从你的工作区读取 `BOOT.md`
2. 通过智能体运行器运行指令
3. 通过 message 工具发送任何请求的出站消息
**启用**
```bash
openclaw hooks enable boot-md
```
## 最佳实践
### 保持处理程序快速
Hooks 在命令处理期间运行。保持它们轻量:
```typescript
// ✓ Good - async work, returns immediately
const handler: HookHandler = async (event) => {
void processInBackground(event); // Fire and forget
};
// ✗ Bad - blocks command processing
const handler: HookHandler = async (event) => {
await slowDatabaseQuery(event);
await evenSlowerAPICall(event);
};
```
### 优雅处理错误
始终包装有风险的操作:
```typescript
const handler: HookHandler = async (event) => {
try {
await riskyOperation(event);
} catch (err) {
console.error("[my-handler] Failed:", err instanceof Error ? err.message : String(err));
// Don't throw - let other handlers run
}
};
```
### 尽早过滤事件
如果事件不相关则尽早返回:
```typescript
const handler: HookHandler = async (event) => {
// Only handle 'new' commands
if (event.type !== "command" || event.action !== "new") {
return;
}
// Your logic here
};
```
### 使用特定事件键
尽可能在元数据中指定确切事件:
```yaml
metadata: { "openclaw": { "events": ["command:new"] } } # Specific
```
而不是:
```yaml
metadata: { "openclaw": { "events": ["command"] } } # General - more overhead
```
## 调试
### 启用 Hook 日志
Gateway 网关在启动时记录 hook 加载:
```
Registered hook: session-memory -> command:new
Registered hook: command-logger -> command
Registered hook: boot-md -> gateway:startup
```
### 检查发现
列出所有发现的 hooks
```bash
openclaw hooks list --verbose
```
### 检查注册
在你的处理程序中,记录它被调用的时间:
```typescript
const handler: HookHandler = async (event) => {
console.log("[my-handler] Triggered:", event.type, event.action);
// Your logic
};
```
### 验证资格
检查为什么 hook 不符合条件:
```bash
openclaw hooks info my-hook
```
在输出中查找缺失的要求。
## 测试
### Gateway 网关日志
监控 Gateway 网关日志以查看 hook 执行:
```bash
# macOS
./scripts/clawlog.sh -f
# Other platforms
tail -f ~/.openclaw/gateway.log
```
### 直接测试 Hooks
隔离测试你的处理程序:
```typescript
import { test } from "vitest";
import { createHookEvent } from "./src/hooks/hooks.js";
import myHandler from "./hooks/my-hook/handler.js";
test("my handler works", async () => {
const event = createHookEvent("command", "new", "test-session", {
foo: "bar",
});
await myHandler(event);
// Assert side effects
});
```
## 架构
### 核心组件
- **`src/hooks/types.ts`**:类型定义
- **`src/hooks/workspace.ts`**:目录扫描和加载
- **`src/hooks/frontmatter.ts`**HOOK.md 元数据解析
- **`src/hooks/config.ts`**:资格检查
- **`src/hooks/hooks-status.ts`**:状态报告
- **`src/hooks/loader.ts`**:动态模块加载器
- **`src/cli/hooks-cli.ts`**CLI 命令
- **`src/gateway/server-startup.ts`**:在 Gateway 网关启动时加载 hooks
- **`src/auto-reply/reply/commands-core.ts`**:触发命令事件
### 发现流程
```
Gateway 网关启动
扫描目录(工作区 → 托管 → 捆绑)
解析 HOOK.md 文件
检查资格bins、env、config、os
从符合条件的 hooks 加载处理程序
为事件注册处理程序
```
### 事件流程
```
用户发送 /new
命令验证
创建 hook 事件
触发 hook所有注册的处理程序
命令处理继续
会话重置
```
## 故障排除
### Hook 未被发现
1. 检查目录结构:
```bash
ls -la ~/.openclaw/hooks/my-hook/
# Should show: HOOK.md, handler.ts
```
2. 验证 HOOK.md 格式:
```bash
cat ~/.openclaw/hooks/my-hook/HOOK.md
# Should have YAML frontmatter with name and metadata
```
3. 列出所有发现的 hooks
```bash
openclaw hooks list
```
### Hook 不符合条件
检查要求:
```bash
openclaw hooks info my-hook
```
查找缺失的:
- 二进制文件(检查 PATH
- 环境变量
- 配置值
- 操作系统兼容性
### Hook 未执行
1. 验证 hook 已启用:
```bash
openclaw hooks list
# Should show ✓ next to enabled hooks
```
2. 重启你的 Gateway 网关进程以重新加载 hooks。
3. 检查 Gateway 网关日志中的错误:
```bash
./scripts/clawlog.sh | grep hook
```
### 处理程序错误
检查 TypeScript/import 错误:
```bash
# Test import directly
node -e "import('./path/to/handler.ts').then(console.log)"
```
## 迁移指南
### 从遗留配置到发现
**之前**
```json
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts"
}
]
}
}
}
```
**之后**
1. 创建 hook 目录:
```bash
mkdir -p ~/.openclaw/hooks/my-hook
mv ./hooks/handlers/my-handler.ts ~/.openclaw/hooks/my-hook/handler.ts
```
2. 创建 HOOK.md
```markdown
---
name: my-hook
description: "My custom hook"
metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
---
# My Hook
Does something useful.
```
3. 更新配置:
```json
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"my-hook": { "enabled": true }
}
}
}
}
```
4. 验证并重启你的 Gateway 网关进程:
```bash
openclaw hooks list
# Should show: 🎯 my-hook ✓
```
**迁移的好处**
- 自动发现
- CLI 管理
- 资格检查
- 更好的文档
- 一致的结构
## 另请参阅
- [CLI 参考hooks](/cli/hooks)
- [捆绑 Hooks README](https://github.com/openclaw/openclaw/tree/main/src/hooks/bundled)
- [Webhook Hooks](/automation/webhook)
- [配置](/gateway/configuration#hooks)

View File

@@ -0,0 +1,76 @@
---
read_when:
- 添加或修改投票支持
- 调试从 CLI 或 Gateway 网关发送的投票
summary: 通过 Gateway 网关 + CLI 发送投票
title: 投票
x-i18n:
generated_at: "2026-02-03T07:43:12Z"
model: claude-opus-4-5
provider: pi
source_hash: 760339865d27ec40def7996cac1d294d58ab580748ad6b32cc34d285d0314eaf
source_path: automation/poll.md
workflow: 15
---
# 投票
## 支持的渠道
- WhatsAppWeb 渠道)
- Discord
- MS TeamsAdaptive Cards
## CLI
```bash
# WhatsApp
openclaw message poll --target +15555550123 \
--poll-question "Lunch today?" --poll-option "Yes" --poll-option "No" --poll-option "Maybe"
openclaw message poll --target 123456789@g.us \
--poll-question "Meeting time?" --poll-option "10am" --poll-option "2pm" --poll-option "4pm" --poll-multi
# Discord
openclaw message poll --channel discord --target channel:123456789 \
--poll-question "Snack?" --poll-option "Pizza" --poll-option "Sushi"
openclaw message poll --channel discord --target channel:123456789 \
--poll-question "Plan?" --poll-option "A" --poll-option "B" --poll-duration-hours 48
# MS Teams
openclaw message poll --channel msteams --target conversation:19:abc@thread.tacv2 \
--poll-question "Lunch?" --poll-option "Pizza" --poll-option "Sushi"
```
选项:
- `--channel``whatsapp`(默认)、`discord``msteams`
- `--poll-multi`:允许选择多个选项
- `--poll-duration-hours`:仅限 Discord省略时默认为 24
## Gateway 网关 RPC
方法:`poll`
参数:
- `to`(字符串,必需)
- `question`(字符串,必需)
- `options`(字符串数组,必需)
- `maxSelections`(数字,可选)
- `durationHours`(数字,可选)
- `channel`(字符串,可选,默认:`whatsapp`
- `idempotencyKey`(字符串,必需)
## 渠道差异
- WhatsApp2-12 个选项,`maxSelections` 必须在选项数量范围内,忽略 `durationHours`
- Discord2-10 个选项,`durationHours` 限制在 1-768 小时之间(默认 24`maxSelections > 1` 启用多选Discord 不支持严格的选择数量限制。
- MS TeamsAdaptive Card 投票(由 OpenClaw 管理)。无原生投票 API`durationHours` 被忽略。
## 智能体工具Message
使用 `message` 工具的 `poll` 操作(`to``pollQuestion``pollOption`,可选 `pollMulti``pollDurationHours``channel`)。
注意Discord 没有"恰好选择 N 个"模式;`pollMulti` 映射为多选。
Teams 投票以 Adaptive Cards 形式渲染,需要 Gateway 网关保持在线
以将投票记录到 `~/.openclaw/msteams-polls.json`

View File

@@ -0,0 +1,8 @@
---
summary: 自动化故障排查:排查 cron 和 heartbeat 调度与投递问题
title: 自动化故障排查
---
# 自动化故障排查
该页面是英文文档的中文占位版本,完整内容请先参考英文版:[Automation Troubleshooting](/automation/troubleshooting)。

View File

@@ -0,0 +1,163 @@
---
read_when:
- 添加或更改 webhook 端点
- 将外部系统接入 OpenClaw
summary: 用于唤醒和隔离智能体运行的 Webhook 入口
title: Webhooks
x-i18n:
generated_at: "2026-02-03T07:43:23Z"
model: claude-opus-4-5
provider: pi
source_hash: f26b88864567be82366b1f66a4772ef2813c7846110c62fce6caf7313568265e
source_path: automation/webhook.md
workflow: 15
---
# Webhooks
Gateway 网关可以暴露一个小型 HTTP webhook 端点用于外部触发。
## 启用
```json5
{
hooks: {
enabled: true,
token: "shared-secret",
path: "/hooks",
},
}
```
注意事项:
-`hooks.enabled=true` 时,`hooks.token` 为必填项。
- `hooks.path` 默认为 `/hooks`
## 认证
每个请求必须包含 hook 令牌。推荐使用请求头:
- `Authorization: Bearer <token>`(推荐)
- `x-openclaw-token: <token>`
- `?token=<token>`(已弃用;会记录警告日志,将在未来的主要版本中移除)
## 端点
### `POST /hooks/wake`
请求体:
```json
{ "text": "System line", "mode": "now" }
```
- `text` **必填**(字符串):事件描述(例如"收到新邮件")。
- `mode` 可选(`now` | `next-heartbeat`):是否立即触发心跳(默认 `now`)或等待下一次定期检查。
效果:
- 为**主**会话加入一个系统事件队列
- 如果 `mode=now`,则立即触发心跳
### `POST /hooks/agent`
请求体:
```json
{
"message": "Run this",
"name": "Email",
"sessionKey": "hook:email:msg-123",
"wakeMode": "now",
"deliver": true,
"channel": "last",
"to": "+15551234567",
"model": "openai/gpt-5.2-mini",
"thinking": "low",
"timeoutSeconds": 120
}
```
- `message` **必填**(字符串):智能体要处理的提示或消息。
- `name` 可选字符串hook 的可读名称(例如"GitHub"),用作会话摘要的前缀。
- `sessionKey` 可选(字符串):用于标识智能体会话的键。默认为随机的 `hook:<uuid>`。使用一致的键可以在 hook 上下文中进行多轮对话。
- `wakeMode` 可选(`now` | `next-heartbeat`):是否立即触发心跳(默认 `now`)或等待下一次定期检查。
- `deliver` 可选(布尔值):如果为 `true`,智能体的响应将发送到消息渠道。默认为 `true`。仅为心跳确认的响应会自动跳过。
- `channel` 可选(字符串):用于投递的消息渠道。可选值:`last``whatsapp``telegram``discord``slack``mattermost`(插件)、`signal``imessage``msteams`。默认为 `last`
- `to` 可选(字符串):渠道的接收者标识符(例如 WhatsApp/Signal 的电话号码、Telegram 的聊天 ID、Discord/Slack/Mattermost插件的频道 ID、MS Teams 的会话 ID。默认为主会话中的最后一个接收者。
- `model` 可选(字符串):模型覆盖(例如 `anthropic/claude-3-5-sonnet` 或别名)。如果有限制,必须在允许的模型列表中。
- `thinking` 可选(字符串):思考级别覆盖(例如 `low``medium``high`)。
- `timeoutSeconds` 可选(数字):智能体运行的最大持续时间(秒)。
效果:
- 运行一个**隔离的**智能体回合(独立的会话键)
- 始终在**主**会话中发布摘要
- 如果 `wakeMode=now`,则立即触发心跳
### `POST /hooks/<name>`(映射)
自定义 hook 名称通过 `hooks.mappings` 解析(见配置)。映射可以将任意请求体转换为 `wake``agent` 操作,支持可选的模板或代码转换。
映射选项(摘要):
- `hooks.presets: ["gmail"]` 启用内置的 Gmail 映射。
- `hooks.mappings` 允许你在配置中定义 `match``action` 和模板。
- `hooks.transformsDir` + `transform.module` 加载 JS/TS 模块用于自定义逻辑。
- 使用 `match.source` 保持通用的接收端点(基于请求体的路由)。
- TS 转换需要 TS 加载器(例如 `bun``tsx`)或运行时预编译的 `.js`
- 在映射上设置 `deliver: true` + `channel`/`to` 可将回复路由到聊天界面(`channel` 默认为 `last`,回退到 WhatsApp
- `allowUnsafeExternalContent: true` 禁用该 hook 的外部内容安全包装(危险;仅用于受信任的内部来源)。
- `openclaw webhooks gmail setup``openclaw webhooks gmail run` 写入 `hooks.gmail` 配置。完整的 Gmail 监听流程请参阅 [Gmail Pub/Sub](/automation/gmail-pubsub)。
## 响应
- `200` 用于 `/hooks/wake`
- `202` 用于 `/hooks/agent`(异步运行已启动)
- `401` 认证失败
- `400` 请求体无效
- `413` 请求体过大
## 示例
```bash
curl -X POST http://127.0.0.1:18789/hooks/wake \
-H 'Authorization: Bearer SECRET' \
-H 'Content-Type: application/json' \
-d '{"text":"New email received","mode":"now"}'
```
```bash
curl -X POST http://127.0.0.1:18789/hooks/agent \
-H 'x-openclaw-token: SECRET' \
-H 'Content-Type: application/json' \
-d '{"message":"Summarize inbox","name":"Email","wakeMode":"next-heartbeat"}'
```
### 使用不同的模型
在智能体请求体(或映射)中添加 `model` 以覆盖该次运行的模型:
```bash
curl -X POST http://127.0.0.1:18789/hooks/agent \
-H 'x-openclaw-token: SECRET' \
-H 'Content-Type: application/json' \
-d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.2-mini"}'
```
如果你启用了 `agents.defaults.models` 限制,请确保覆盖的模型包含在其中。
```bash
curl -X POST http://127.0.0.1:18789/hooks/gmail \
-H 'Authorization: Bearer SECRET' \
-H 'Content-Type: application/json' \
-d '{"source":"gmail","messages":[{"from":"Ada","subject":"Hello","snippet":"Hi"}]}'
```
## 安全
- 将 hook 端点保持在 loopback、tailnet 或受信任的反向代理之后。
- 使用专用的 hook 令牌;不要复用 Gateway 网关认证令牌。
- 避免在 webhook 日志中包含敏感的原始请求体。
- Hook 请求体默认被视为不受信任并使用安全边界包装。如果你必须为特定 hook 禁用此功能,请在该 hook 的映射中设置 `allowUnsafeExternalContent: true`(危险)。

View File

@@ -0,0 +1,271 @@
---
read_when:
- 设置 BlueBubbles 渠道
- 排查 webhook 配对问题
- 在 macOS 上配置 iMessage
summary: 通过 BlueBubbles macOS 服务器使用 iMessageREST 发送/接收、输入状态、回应、配对、高级操作)。
title: BlueBubbles
x-i18n:
generated_at: "2026-02-03T10:04:52Z"
model: claude-opus-4-5
provider: pi
source_hash: 3aae277a8bec479800a7f6268bfbca912c65a4aadc6e513694057fb873597b69
source_path: channels/bluebubbles.md
workflow: 15
---
# BlueBubblesmacOS REST
状态:内置插件,通过 HTTP 与 BlueBubbles macOS 服务器通信。由于其更丰富的 API 和更简便的设置,**推荐用于 iMessage 集成**,优于旧版 imsg 渠道。
## 概述
- 通过 BlueBubbles 辅助应用在 macOS 上运行([bluebubbles.app](https://bluebubbles.app))。
- 推荐/已测试版本macOS Sequoia (15)。macOS Tahoe (26) 可用;但在 Tahoe 上编辑功能目前不可用,群组图标更新可能显示成功但实际未同步。
- OpenClaw 通过其 REST API 与之通信(`GET /api/v1/ping``POST /message/text``POST /chat/:id/*`)。
- 传入消息通过 webhook 到达;发出的回复、输入指示器、已读回执和 tapback 均为 REST 调用。
- 附件和贴纸作为入站媒体被接收(并在可能时呈现给智能体)。
- 配对/白名单的工作方式与其他渠道相同(`/channels/pairing` 等),使用 `channels.bluebubbles.allowFrom` + 配对码。
- 回应作为系统事件呈现,与 Slack/Telegram 类似,智能体可以在回复前"提及"它们。
- 高级功能:编辑、撤回、回复线程、消息效果、群组管理。
## 快速开始
1. 在你的 Mac 上安装 BlueBubbles 服务器(按照 [bluebubbles.app/install](https://bluebubbles.app/install) 的说明操作)。
2. 在 BlueBubbles 配置中,启用 web API 并设置密码。
3. 运行 `openclaw onboard` 并选择 BlueBubbles或手动配置
```json5
{
channels: {
bluebubbles: {
enabled: true,
serverUrl: "http://192.168.1.100:1234",
password: "example-password",
webhookPath: "/bluebubbles-webhook",
},
},
}
```
4. 将 BlueBubbles webhook 指向你的 Gateway 网关(示例:`https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)。
5. 启动 Gateway 网关;它将注册 webhook 处理程序并开始配对。
## 新手引导
BlueBubbles 可在交互式设置向导中使用:
```
openclaw onboard
```
向导会提示输入:
- **服务器 URL**必填BlueBubbles 服务器地址(例如 `http://192.168.1.100:1234`
- **密码**(必填):来自 BlueBubbles 服务器设置的 API 密码
- **Webhook 路径**(可选):默认为 `/bluebubbles-webhook`
- **私信策略**:配对、白名单、开放或禁用
- **白名单**:电话号码、电子邮件或聊天目标
你也可以通过 CLI 添加 BlueBubbles
```
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
```
## 访问控制(私信 + 群组)
私信:
- 默认:`channels.bluebubbles.dmPolicy = "pairing"`。
- 未知发送者会收到配对码;在批准之前消息会被忽略(配对码 1 小时后过期)。
- 批准方式:
- `openclaw pairing list bluebubbles`
- `openclaw pairing approve bluebubbles <CODE>`
- 配对是默认的令牌交换方式。详情:[配对](/channels/pairing)
群组:
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled`(默认:`allowlist`)。
- 当设置为 `allowlist` 时,`channels.bluebubbles.groupAllowFrom` 控制谁可以在群组中触发。
### 提及门控(群组)
BlueBubbles 支持群聊的提及门控,与 iMessage/WhatsApp 行为一致:
- 使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)检测提及。
- 当群组启用 `requireMention` 时,智能体仅在被提及时响应。
- 来自授权发送者的控制命令会绕过提及门控。
单群组配置:
```json5
{
channels: {
bluebubbles: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: {
"*": { requireMention: true }, // 所有群组的默认设置
"iMessage;-;chat123": { requireMention: false }, // 特定群组的覆盖设置
},
},
},
}
```
### 命令门控
- 控制命令(例如 `/config`、`/model`)需要授权。
- 使用 `allowFrom` 和 `groupAllowFrom` 确定命令授权。
- 授权发送者即使在群组中未被提及也可以运行控制命令。
## 输入状态 + 已读回执
- **输入指示器**:在响应生成前和生成期间自动发送。
- **已读回执**:由 `channels.bluebubbles.sendReadReceipts` 控制(默认:`true`)。
- **输入指示器**OpenClaw 发送输入开始事件BlueBubbles 在发送或超时时自动清除输入状态(通过 DELETE 手动停止不可靠)。
```json5
{
channels: {
bluebubbles: {
sendReadReceipts: false, // 禁用已读回执
},
},
}
```
## 高级操作
BlueBubbles 在配置中启用时支持高级消息操作:
```json5
{
channels: {
bluebubbles: {
actions: {
reactions: true, // tapback默认true
edit: true, // 编辑已发送消息macOS 13+,在 macOS 26 Tahoe 上不可用)
unsend: true, // 撤回消息macOS 13+
reply: true, // 通过消息 GUID 进行回复线程
sendWithEffect: true, // 消息效果slam、loud 等)
renameGroup: true, // 重命名群聊
setGroupIcon: true, // 设置群聊图标/照片(在 macOS 26 Tahoe 上不稳定)
addParticipant: true, // 将参与者添加到群组
removeParticipant: true, // 从群组移除参与者
leaveGroup: true, // 离开群聊
sendAttachment: true, // 发送附件/媒体
},
},
},
}
```
可用操作:
- **react**:添加/移除 tapback 回应(`messageId`、`emoji`、`remove`
- **edit**:编辑已发送的消息(`messageId`、`text`
- **unsend**:撤回消息(`messageId`
- **reply**:回复特定消息(`messageId`、`text`、`to`
- **sendWithEffect**:带 iMessage 效果发送(`text`、`to`、`effectId`
- **renameGroup**:重命名群聊(`chatGuid`、`displayName`
- **setGroupIcon**:设置群聊图标/照片(`chatGuid`、`media`)— 在 macOS 26 Tahoe 上不稳定API 可能返回成功但图标未同步)。
- **addParticipant**:将某人添加到群组(`chatGuid`、`address`
- **removeParticipant**:将某人从群组移除(`chatGuid`、`address`
- **leaveGroup**:离开群聊(`chatGuid`
- **sendAttachment**:发送媒体/文件(`to`、`buffer`、`filename`、`asVoice`
- 语音备忘录:将 `asVoice: true` 与 **MP3** 或 **CAF** 音频一起设置,以 iMessage 语音消息形式发送。BlueBubbles 在发送语音备忘录时会将 MP3 转换为 CAF。
### 消息 ID短格式 vs 完整格式)
OpenClaw 可能会显示*短*消息 ID例如 `1`、`2`)以节省 token。
- `MessageSid` / `ReplyToId` 可以是短 ID。
- `MessageSidFull` / `ReplyToIdFull` 包含提供商的完整 ID。
- 短 ID 存储在内存中;它们可能在重启或缓存清除后过期。
- 操作接受短或完整的 `messageId`,但如果短 ID 不再可用将会报错。
对于持久化自动化和存储,请使用完整 ID
- 模板:`{{MessageSidFull}}`、`{{ReplyToIdFull}}`
- 上下文:入站负载中的 `MessageSidFull` / `ReplyToIdFull`
参见[配置](/gateway/configuration)了解模板变量。
## 分块流式传输
控制响应是作为单条消息发送还是分块流式传输:
```json5
{
channels: {
bluebubbles: {
blockStreaming: true, // 启用分块流式传输(默认关闭)
},
},
}
```
## 媒体 + 限制
- 入站附件会被下载并存储在媒体缓存中。
- 媒体上限通过 `channels.bluebubbles.mediaMaxMb` 设置默认8 MB
- 出站文本按 `channels.bluebubbles.textChunkLimit` 分块默认4000 字符)。
## 配置参考
完整配置:[配置](/gateway/configuration)
提供商选项:
- `channels.bluebubbles.enabled`:启用/禁用渠道。
- `channels.bluebubbles.serverUrl`BlueBubbles REST API 基础 URL。
- `channels.bluebubbles.password`API 密码。
- `channels.bluebubbles.webhookPath`Webhook 端点路径(默认:`/bluebubbles-webhook`)。
- `channels.bluebubbles.dmPolicy``pairing | allowlist | open | disabled`(默认:`pairing`)。
- `channels.bluebubbles.allowFrom`私信白名单句柄、电子邮件、E.164 号码、`chat_id:*`、`chat_guid:*`)。
- `channels.bluebubbles.groupPolicy``open | allowlist | disabled`(默认:`allowlist`)。
- `channels.bluebubbles.groupAllowFrom`:群组发送者白名单。
- `channels.bluebubbles.groups`:单群组配置(`requireMention` 等)。
- `channels.bluebubbles.sendReadReceipts`:发送已读回执(默认:`true`)。
- `channels.bluebubbles.blockStreaming`:启用分块流式传输(默认:`false`;流式回复必需)。
- `channels.bluebubbles.textChunkLimit`出站分块大小字符默认4000
- `channels.bluebubbles.chunkMode``length`(默认)仅在超过 `textChunkLimit` 时分割;`newline` 在长度分块前先按空行(段落边界)分割。
- `channels.bluebubbles.mediaMaxMb`入站媒体上限MB默认8
- `channels.bluebubbles.historyLimit`上下文的最大群组消息数0 表示禁用)。
- `channels.bluebubbles.dmHistoryLimit`:私信历史限制。
- `channels.bluebubbles.actions`:启用/禁用特定操作。
- `channels.bluebubbles.accounts`:多账户配置。
相关全局选项:
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)。
- `messages.responsePrefix`。
## 地址 / 投递目标
优先使用 `chat_guid` 以获得稳定的路由:
- `chat_guid:iMessage;-;+15555550123`(群组推荐)
- `chat_id:123`
- `chat_identifier:...`
- 直接句柄:`+15555550123`、`user@example.com`
- 如果直接句柄没有现有的私信聊天OpenClaw 将通过 `POST /api/v1/chat/new` 创建一个。这需要启用 BlueBubbles Private API。
## 安全性
- Webhook 请求通过比较 `guid`/`password` 查询参数或头部与 `channels.bluebubbles.password` 进行身份验证。来自 `localhost` 的请求也会被接受。
- 保持 API 密码和 webhook 端点的机密性(将它们视为凭证)。
- localhost 信任意味着同主机的反向代理可能无意中绕过密码验证。如果你使用代理 Gateway 网关,请在代理处要求身份验证并配置 `gateway.trustedProxies`。参见 [Gateway 网关安全性](/gateway/security#reverse-proxy-configuration)。
- 如果将 BlueBubbles 服务器暴露在局域网之外,请启用 HTTPS + 防火墙规则。
## 故障排除
- 如果输入/已读事件停止工作,请检查 BlueBubbles webhook 日志并验证 Gateway 网关路径是否与 `channels.bluebubbles.webhookPath` 匹配。
- 配对码在一小时后过期;使用 `openclaw pairing list bluebubbles` 和 `openclaw pairing approve bluebubbles <code>`。
- 回应需要 BlueBubbles private API`POST /api/v1/message/react`);确保服务器版本支持它。
- 编辑/撤回需要 macOS 13+ 和兼容的 BlueBubbles 服务器版本。在 macOS 26Tahoe由于 private API 变更,编辑功能目前不可用。
- 在 macOS 26Tahoe上群组图标更新可能不稳定API 可能返回成功但新图标未同步。
- OpenClaw 会根据 BlueBubbles 服务器的 macOS 版本自动隐藏已知不可用的操作。如果在 macOS 26Tahoe上编辑仍然显示请使用 `channels.bluebubbles.actions.edit=false` 手动禁用。
- 查看状态/健康信息:`openclaw status --all` 或 `openclaw status --deep`。
有关通用渠道工作流参考,请参阅[渠道](/channels)和[插件](/tools/plugin)指南。

View File

@@ -0,0 +1,449 @@
---
read_when:
- 配置广播群组
- 调试 WhatsApp 中的多智能体回复
status: experimental
summary: 向多个智能体广播 WhatsApp 消息
title: 广播群组
x-i18n:
generated_at: "2026-02-03T07:43:43Z"
model: claude-opus-4-5
provider: pi
source_hash: eaeb4035912c49413e012177cf0bd28b348130d30d3317674418dca728229b70
source_path: channels/broadcast-groups.md
workflow: 15
---
# 广播群组
**状态:** 实验性功能
**版本:** 于 2026.1.9 版本新增
## 概述
广播群组允许多个智能体同时处理并响应同一条消息。这使你能够在单个 WhatsApp 群组或私信中创建协同工作的专业智能体团队——全部使用同一个手机号码。
当前范围:**仅限 WhatsApp**web 渠道)。
广播群组在渠道白名单和群组激活规则之后进行评估。在 WhatsApp 群组中,这意味着广播会在 OpenClaw 正常回复时发生(例如:被提及时,具体取决于你的群组设置)。
## 使用场景
### 1. 专业智能体团队
部署多个具有原子化、专注职责的智能体:
```
Group: "Development Team"
Agents:
- CodeReviewer (reviews code snippets)
- DocumentationBot (generates docs)
- SecurityAuditor (checks for vulnerabilities)
- TestGenerator (suggests test cases)
```
每个智能体处理相同的消息并提供其专业视角。
### 2. 多语言支持
```
Group: "International Support"
Agents:
- Agent_EN (responds in English)
- Agent_DE (responds in German)
- Agent_ES (responds in Spanish)
```
### 3. 质量保证工作流
```
Group: "Customer Support"
Agents:
- SupportAgent (provides answer)
- QAAgent (reviews quality, only responds if issues found)
```
### 4. 任务自动化
```
Group: "Project Management"
Agents:
- TaskTracker (updates task database)
- TimeLogger (logs time spent)
- ReportGenerator (creates summaries)
```
## 配置
### 基本设置
添加一个顶层 `broadcast` 部分(与 `bindings` 同级)。键为 WhatsApp peer id
- 群聊:群组 JID例如 `120363403215116621@g.us`
- 私信E.164 格式的电话号码(例如 `+15551234567`
```json
{
"broadcast": {
"120363403215116621@g.us": ["alfred", "baerbel", "assistant3"]
}
}
```
**结果:** 当 OpenClaw 在此聊天中回复时,将运行所有三个智能体。
### 处理策略
控制智能体如何处理消息:
#### 并行(默认)
所有智能体同时处理:
```json
{
"broadcast": {
"strategy": "parallel",
"120363403215116621@g.us": ["alfred", "baerbel"]
}
}
```
#### 顺序
智能体按顺序处理(后一个等待前一个完成):
```json
{
"broadcast": {
"strategy": "sequential",
"120363403215116621@g.us": ["alfred", "baerbel"]
}
}
```
### 完整示例
```json
{
"agents": {
"list": [
{
"id": "code-reviewer",
"name": "Code Reviewer",
"workspace": "/path/to/code-reviewer",
"sandbox": { "mode": "all" }
},
{
"id": "security-auditor",
"name": "Security Auditor",
"workspace": "/path/to/security-auditor",
"sandbox": { "mode": "all" }
},
{
"id": "docs-generator",
"name": "Documentation Generator",
"workspace": "/path/to/docs-generator",
"sandbox": { "mode": "all" }
}
]
},
"broadcast": {
"strategy": "parallel",
"120363403215116621@g.us": ["code-reviewer", "security-auditor", "docs-generator"],
"120363424282127706@g.us": ["support-en", "support-de"],
"+15555550123": ["assistant", "logger"]
}
}
```
## 工作原理
### 消息流程
1. **接收消息** 到达 WhatsApp 群组
2. **广播检查**:系统检查 peer ID 是否在 `broadcast`
3. **如果在广播列表中**
- 所有列出的智能体处理该消息
- 每个智能体有自己的会话键和隔离的上下文
- 智能体并行处理(默认)或顺序处理
4. **如果不在广播列表中**
- 应用正常路由(第一个匹配的绑定)
注意:广播群组不会绕过渠道白名单或群组激活规则(提及/命令等)。它们只改变消息符合处理条件时*运行哪些智能体*。
### 会话隔离
广播群组中的每个智能体完全独立维护:
- **会话键**`agent:alfred:whatsapp:group:120363...` vs `agent:baerbel:whatsapp:group:120363...`
- **对话历史**(智能体看不到其他智能体的消息)
- **工作空间**(如果配置了则使用独立的沙箱)
- **工具访问权限**(不同的允许/拒绝列表)
- **记忆/上下文**(独立的 IDENTITY.md、SOUL.md 等)
- **群组上下文缓冲区**(用于上下文的最近群组消息)按 peer 共享,因此所有广播智能体在被触发时看到相同的上下文
这允许每个智能体拥有:
- 不同的个性
- 不同的工具访问权限(例如只读 vs 读写)
- 不同的模型(例如 opus vs sonnet
- 不同的已安装 Skills
### 示例:隔离的会话
在群组 `120363403215116621@g.us` 中,智能体为 `["alfred", "baerbel"]`
**Alfred 的上下文:**
```
Session: agent:alfred:whatsapp:group:120363403215116621@g.us
History: [user message, alfred's previous responses]
Workspace: /Users/pascal/openclaw-alfred/
Tools: read, write, exec
```
**Bärbel 的上下文:**
```
Session: agent:baerbel:whatsapp:group:120363403215116621@g.us
History: [user message, baerbel's previous responses]
Workspace: /Users/pascal/openclaw-baerbel/
Tools: read only
```
## 最佳实践
### 1. 保持智能体专注
将每个智能体设计为具有单一、明确的职责:
```json
{
"broadcast": {
"DEV_GROUP": ["formatter", "linter", "tester"]
}
}
```
**好的做法:** 每个智能体只有一个任务
**不好的做法:** 一个通用的"dev-helper"智能体
### 2. 使用描述性名称
明确每个智能体的功能:
```json
{
"agents": {
"security-scanner": { "name": "Security Scanner" },
"code-formatter": { "name": "Code Formatter" },
"test-generator": { "name": "Test Generator" }
}
}
```
### 3. 配置不同的工具访问权限
只给智能体提供它们需要的工具:
```json
{
"agents": {
"reviewer": {
"tools": { "allow": ["read", "exec"] } // Read-only
},
"fixer": {
"tools": { "allow": ["read", "write", "edit", "exec"] } // Read-write
}
}
}
```
### 4. 监控性能
当有多个智能体时,请考虑:
- 使用 `"strategy": "parallel"`(默认)以提高速度
- 将广播群组限制在 5-10 个智能体
- 为较简单的智能体使用较快的模型
### 5. 优雅地处理失败
智能体独立失败。一个智能体的错误不会阻塞其他智能体:
```
Message → [Agent A ✓, Agent B ✗ error, Agent C ✓]
Result: Agent A and C respond, Agent B logs error
```
## 兼容性
### 提供商
广播群组目前支持:
- ✅ WhatsApp已实现
- 🚧 Telegram计划中
- 🚧 Discord计划中
- 🚧 Slack计划中
### 路由
广播群组与现有路由一起工作:
```json
{
"bindings": [
{
"match": { "channel": "whatsapp", "peer": { "kind": "group", "id": "GROUP_A" } },
"agentId": "alfred"
}
],
"broadcast": {
"GROUP_B": ["agent1", "agent2"]
}
}
```
- `GROUP_A`:只有 alfred 响应(正常路由)
- `GROUP_B`agent1 和 agent2 都响应(广播)
**优先级:** `broadcast` 优先于 `bindings`
## 故障排除
### 智能体不响应
**检查:**
1. 智能体 ID 存在于 `agents.list`
2. Peer ID 格式正确(例如 `120363403215116621@g.us`
3. 智能体不在拒绝列表中
**调试:**
```bash
tail -f ~/.openclaw/logs/gateway.log | grep broadcast
```
### 只有一个智能体响应
**原因:** Peer ID 可能在 `bindings` 中但不在 `broadcast` 中。
**修复:** 添加到广播配置或从绑定中移除。
### 性能问题
**如果智能体较多时速度较慢:**
- 减少每个群组的智能体数量
- 使用较轻的模型sonnet 而非 opus
- 检查沙箱启动时间
## 示例
### 示例 1代码审查团队
```json
{
"broadcast": {
"strategy": "parallel",
"120363403215116621@g.us": [
"code-formatter",
"security-scanner",
"test-coverage",
"docs-checker"
]
},
"agents": {
"list": [
{
"id": "code-formatter",
"workspace": "~/agents/formatter",
"tools": { "allow": ["read", "write"] }
},
{
"id": "security-scanner",
"workspace": "~/agents/security",
"tools": { "allow": ["read", "exec"] }
},
{
"id": "test-coverage",
"workspace": "~/agents/testing",
"tools": { "allow": ["read", "exec"] }
},
{ "id": "docs-checker", "workspace": "~/agents/docs", "tools": { "allow": ["read"] } }
]
}
}
```
**用户发送:** 代码片段
**响应:**
- code-formatter"修复了缩进并添加了类型提示"
- security-scanner"⚠️ 第 12 行存在 SQL 注入漏洞"
- test-coverage"覆盖率为 45%,缺少错误情况的测试"
- docs-checker"函数 `process_data` 缺少文档字符串"
### 示例 2多语言支持
```json
{
"broadcast": {
"strategy": "sequential",
"+15555550123": ["detect-language", "translator-en", "translator-de"]
},
"agents": {
"list": [
{ "id": "detect-language", "workspace": "~/agents/lang-detect" },
{ "id": "translator-en", "workspace": "~/agents/translate-en" },
{ "id": "translator-de", "workspace": "~/agents/translate-de" }
]
}
}
```
## API 参考
### 配置模式
```typescript
interface OpenClawConfig {
broadcast?: {
strategy?: "parallel" | "sequential";
[peerId: string]: string[];
};
}
```
### 字段
- `strategy`(可选):如何处理智能体
- `"parallel"`(默认):所有智能体同时处理
- `"sequential"`:智能体按数组顺序处理
- `[peerId]`WhatsApp 群组 JID、E.164 号码或其他 peer ID
- 值:应处理消息的智能体 ID 数组
## 限制
1. **最大智能体数:** 无硬性限制,但 10 个以上智能体可能会较慢
2. **共享上下文:** 智能体看不到彼此的响应(设计如此)
3. **消息顺序:** 并行响应可能以任意顺序到达
4. **速率限制:** 所有智能体都计入 WhatsApp 速率限制
## 未来增强
计划中的功能:
- [ ] 共享上下文模式(智能体可以看到彼此的响应)
- [ ] 智能体协调(智能体可以相互发信号)
- [ ] 动态智能体选择(根据消息内容选择智能体)
- [ ] 智能体优先级(某些智能体先于其他智能体响应)
## 另请参阅
- [多智能体配置](/tools/multi-agent-sandbox-tools)
- [路由配置](/channels/channel-routing)
- [会话管理](/concepts/sessions)

View File

@@ -0,0 +1,117 @@
---
read_when:
- 更改渠道路由或收件箱行为
summary: 每个渠道WhatsApp、Telegram、Discord、Slack的路由规则及共享上下文
title: 渠道路由
x-i18n:
generated_at: "2026-02-01T20:22:21Z"
model: claude-opus-4-5
provider: pi
source_hash: 1a322b5187e32c82fc1e8aac02437e2eeb7ba84e7b3a1db89feeab1dcf7dbbab
source_path: channels/channel-routing.md
workflow: 14
---
# 渠道与路由
OpenClaw 将回复**路由回消息来源的渠道**。模型不会选择渠道;路由是确定性的,由主机配置控制。
## 关键术语
- **渠道**`whatsapp``telegram``discord``slack``signal``imessage``webchat`
- **AccountId**:每个渠道的账户实例(在支持的情况下)。
- **AgentId**:隔离的工作区 + 会话存储("大脑")。
- **SessionKey**:用于存储上下文和控制并发的桶键。
## 会话键格式(示例)
私信会折叠到智能体的**主**会话:
- `agent:<agentId>:<mainKey>`(默认:`agent:main:main`
群组和渠道按渠道隔离:
- 群组:`agent:<agentId>:<channel>:group:<id>`
- 渠道/房间:`agent:<agentId>:<channel>:channel:<id>`
线程:
- Slack/Discord 线程会在基础键后追加 `:thread:<threadId>`
- Telegram 论坛主题在群组键中嵌入 `:topic:<topicId>`
示例:
- `agent:main:telegram:group:-1001234567890:topic:42`
- `agent:main:discord:channel:123456:thread:987654`
## 路由规则(如何选择智能体)
路由为每条入站消息选择**一个智能体**
1. **精确对端匹配**`bindings` 中的 `peer.kind` + `peer.id`)。
2. **Guild 匹配**Discord通过 `guildId`
3. **Team 匹配**Slack通过 `teamId`
4. **账户匹配**(渠道上的 `accountId`)。
5. **渠道匹配**(该渠道上的任意账户)。
6. **默认智能体**`agents.list[].default`,否则取列表第一项,兜底为 `main`)。
匹配到的智能体决定使用哪个工作区和会话存储。
## 广播组(运行多个智能体)
广播组允许你为同一对端运行**多个智能体****在 OpenClaw 正常回复时**触发(例如:在 WhatsApp 群组中,经过提及/激活门控之后)。
配置:
```json5
{
broadcast: {
strategy: "parallel",
"120363403215116621@g.us": ["alfred", "baerbel"],
"+15555550123": ["support", "logger"],
},
}
```
参见:[广播组](/channels/broadcast-groups)。
## 配置概览
- `agents.list`:命名的智能体定义(工作区、模型等)。
- `bindings`:将入站渠道/账户/对端映射到智能体。
示例:
```json5
{
agents: {
list: [{ id: "support", name: "Support", workspace: "~/.openclaw/workspace-support" }],
},
bindings: [
{ match: { channel: "slack", teamId: "T123" }, agentId: "support" },
{ match: { channel: "telegram", peer: { kind: "group", id: "-100123" } }, agentId: "support" },
],
}
```
## 会话存储
会话存储位于状态目录下(默认 `~/.openclaw`
- `~/.openclaw/agents/<agentId>/sessions/sessions.json`
- JSONL 记录文件与存储位于同一目录
你可以通过 `session.store``{agentId}` 模板来覆盖存储路径。
## WebChat 行为
WebChat 连接到**所选智能体**并默认使用该智能体的主会话。因此WebChat 让你可以在一个地方查看该智能体的跨渠道上下文。
## 回复上下文
入站回复包含:
- `ReplyToId``ReplyToBody``ReplyToSender`(在可用时)。
- 引用的上下文会以 `[Replying to ...]` 块的形式追加到 `Body` 中。
这在所有渠道中保持一致。

468
content/channels/discord.md Normal file
View File

@@ -0,0 +1,468 @@
---
read_when:
- 开发 Discord 渠道功能时
summary: Discord 机器人支持状态、功能和配置
title: Discord
x-i18n:
generated_at: "2026-02-03T07:45:45Z"
model: claude-opus-4-5
provider: pi
source_hash: 2f0083b55648f9158668b80d078353421e7dc310135fdc43f2d280b242bf8459
source_path: channels/discord.md
workflow: 15
---
# DiscordBot API
状态:已支持通过官方 Discord 机器人网关进行私信和服务器文字频道通信。
## 快速设置(新手)
1. 创建 Discord 机器人并复制机器人令牌。
2. 在 Discord 应用设置中启用 **Message Content Intent**(如果你计划使用允许列表或名称查找,还需启用 **Server Members Intent**)。
3. 为 OpenClaw 设置令牌:
- 环境变量:`DISCORD_BOT_TOKEN=...`
- 或配置:`channels.discord.token: "..."`
- 如果两者都设置,配置优先(环境变量回退仅适用于默认账户)。
4. 使用消息权限邀请机器人到你的服务器(如果你只想使用私信,可以创建一个私人服务器)。
5. 启动 Gateway 网关。
6. 私信访问默认采用配对模式;首次联系时需批准配对码。
最小配置:
```json5
{
channels: {
discord: {
enabled: true,
token: "YOUR_BOT_TOKEN",
},
},
}
```
## 目标
- 通过 Discord 私信或服务器频道与 OpenClaw 对话。
- 直接聊天会合并到智能体的主会话(默认 `agent:main:main`);服务器频道保持隔离为 `agent:<agentId>:discord:channel:<channelId>`(显示名称使用 `discord:<guildSlug>#<channelSlug>`)。
- 群组私信默认被忽略;通过 `channels.discord.dm.groupEnabled` 启用,并可选择通过 `channels.discord.dm.groupChannels` 进行限制。
- 保持路由确定性:回复始终返回到消息来源的渠道。
## 工作原理
1. 创建 Discord 应用程序 → Bot启用你需要的意图私信 + 服务器消息 + 消息内容),并获取机器人令牌。
2. 使用所需权限邀请机器人到你的服务器,以便在你想使用的地方读取/发送消息。
3. 使用 `channels.discord.token` 配置 OpenClaw或使用 `DISCORD_BOT_TOKEN` 作为回退)。
4. 运行 Gateway 网关;当令牌可用(配置优先,环境变量回退)且 `channels.discord.enabled` 不为 `false` 时,它会自动启动 Discord 渠道。
- 如果你更喜欢使用环境变量,设置 `DISCORD_BOT_TOKEN`(配置块是可选的)。
5. 直接聊天:发送时使用 `user:<id>`(或 `<@id>` 提及);所有对话都进入共享的 `main` 会话。纯数字 ID 是模糊的,会被拒绝。
6. 服务器频道:发送时使用 `channel:<channelId>`。默认需要提及,可以按服务器或按频道设置。
7. 直接聊天:默认通过 `channels.discord.dm.policy` 进行安全保护(默认:`"pairing"`。未知发送者会收到配对码1 小时后过期);通过 `openclaw pairing approve discord <code>` 批准。
- 要保持旧的"对任何人开放"行为:设置 `channels.discord.dm.policy="open"``channels.discord.dm.allowFrom=["*"]`
- 要使用硬编码允许列表:设置 `channels.discord.dm.policy="allowlist"` 并在 `channels.discord.dm.allowFrom` 中列出发送者。
- 要忽略所有私信:设置 `channels.discord.dm.enabled=false``channels.discord.dm.policy="disabled"`
8. 群组私信默认被忽略;通过 `channels.discord.dm.groupEnabled` 启用,并可选择通过 `channels.discord.dm.groupChannels` 进行限制。
9. 可选服务器规则:设置 `channels.discord.guilds`,以服务器 ID首选或 slug 为键,并包含每个频道的规则。
10. 可选原生命令:`commands.native` 默认为 `"auto"`Discord/Telegram 开启Slack 关闭)。使用 `channels.discord.commands.native: true|false|"auto"` 覆盖;`false` 会清除之前注册的命令。文本命令由 `commands.text` 控制,必须作为独立的 `/...` 消息发送。使用 `commands.useAccessGroups: false` 可跳过命令的访问组检查。
- 完整命令列表 + 配置:[斜杠命令](/tools/slash-commands)
11. 可选服务器上下文历史:设置 `channels.discord.historyLimit`(默认 20回退到 `messages.groupChat.historyLimit`)以在回复提及时包含最近 N 条服务器消息作为上下文。设置 `0` 禁用。
12. 表情反应:智能体可以通过 `discord` 工具触发表情反应(受 `channels.discord.actions.*` 控制)。
- 表情反应移除语义:参见 [/tools/reactions](/tools/reactions)。
- `discord` 工具仅在当前渠道是 Discord 时暴露。
13. 原生命令使用隔离的会话键(`agent:<agentId>:discord:slash:<userId>`)而不是共享的 `main` 会话。
注意:名称 → ID 解析使用服务器成员搜索,需要 Server Members Intent如果机器人无法搜索成员请使用 ID 或 `<@id>` 提及。
注意Slug 为小写,空格替换为 `-`。频道名称的 slug 不包含前导 `#`
注意:服务器上下文 `[from:]` 行包含 `author.tag` + `id`,便于进行可提及的回复。
## 配置写入
默认情况下,允许 Discord 写入由 `/config set|unset` 触发的配置更新(需要 `commands.config: true`)。
禁用方式:
```json5
{
channels: { discord: { configWrites: false } },
}
```
## 如何创建自己的机器人
这是在服务器guild频道`#help`)中运行 OpenClaw 的"Discord 开发者门户"设置。
### 1创建 Discord 应用 + 机器人用户
1. Discord 开发者门户 → **Applications****New Application**
2. 在你的应用中:
- **Bot** → **Add Bot**
- 复制 **Bot Token**(这是你放入 `DISCORD_BOT_TOKEN` 的内容)
### 2启用 OpenClaw 需要的网关意图
Discord 会阻止"特权意图",除非你明确启用它们。
**Bot****Privileged Gateway Intents** 中启用:
- **Message Content Intent**(在大多数服务器中读取消息文本所必需;没有它你会看到"Used disallowed intents"或机器人会连接但不响应消息)
- **Server Members Intent**(推荐;服务器中的某些成员/用户查找和允许列表匹配需要)
你通常**不需要** **Presence Intent**
### 3生成邀请 URLOAuth2 URL Generator
在你的应用中:**OAuth2** → **URL Generator**
**Scopes**
-`bot`
-`applications.commands`(原生命令所需)
**Bot Permissions**(最小基线)
- ✅ View Channels
- ✅ Send Messages
- ✅ Read Message History
- ✅ Embed Links
- ✅ Attach Files
- ✅ Add Reactions可选但推荐
- ✅ Use External Emojis / Stickers可选仅当你需要时
除非你在调试并完全信任机器人,否则避免使用 **Administrator**
复制生成的 URL打开它选择你的服务器然后安装机器人。
### 4获取 ID服务器/用户/频道)
Discord 到处使用数字 IDOpenClaw 配置优先使用 ID。
1. Discord桌面/网页)→ **用户设置****高级** → 启用 **开发者模式**
2. 右键点击:
- 服务器名称 → **复制服务器 ID**(服务器 ID
- 频道(例如 `#help`)→ **复制频道 ID**
- 你的用户 → **复制用户 ID**
### 5配置 OpenClaw
#### 令牌
通过环境变量设置机器人令牌(服务器上推荐):
- `DISCORD_BOT_TOKEN=...`
或通过配置:
```json5
{
channels: {
discord: {
enabled: true,
token: "YOUR_BOT_TOKEN",
},
},
}
```
多账户支持:使用 `channels.discord.accounts`,每个账户有自己的令牌和可选的 `name`。参见 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) 了解通用模式。
#### 允许列表 + 频道路由
示例"单服务器,只允许我,只允许 #help"
```json5
{
channels: {
discord: {
enabled: true,
dm: { enabled: false },
guilds: {
YOUR_GUILD_ID: {
users: ["YOUR_USER_ID"],
requireMention: true,
channels: {
help: { allow: true, requireMention: true },
},
},
},
retry: {
attempts: 3,
minDelayMs: 500,
maxDelayMs: 30000,
jitter: 0.1,
},
},
},
}
```
注意:
- `requireMention: true` 意味着机器人只在被提及时回复(推荐用于共享频道)。
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)对于服务器消息也算作提及。
- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每个智能体的模式。
- 如果存在 `channels`,任何未列出的频道默认被拒绝。
- 使用 `"*"` 频道条目在所有频道应用默认值;显式频道条目覆盖通配符。
- 话题继承父频道配置(允许列表、`requireMention`、Skills、提示词等除非你显式添加话题频道 ID。
- 机器人发送的消息默认被忽略;设置 `channels.discord.allowBots=true` 允许它们(自己的消息仍被过滤)。
- 警告:如果你允许回复其他机器人(`channels.discord.allowBots=true`),请使用 `requireMention``channels.discord.guilds.*.channels.<id>.users` 允许列表和/或在 `AGENTS.md``SOUL.md` 中设置明确的防护措施来防止机器人之间的回复循环。
### 6验证是否工作
1. 启动 Gateway 网关。
2. 在你的服务器频道中发送:`@Krill hello`(或你的机器人名称)。
3. 如果没有反应:查看下面的**故障排除**。
### 故障排除
- 首先:运行 `openclaw doctor``openclaw channels status --probe`(可操作的警告 + 快速审计)。
- **"Used disallowed intents"**:在开发者门户中启用 **Message Content Intent**(可能还需要 **Server Members Intent**),然后重启 Gateway 网关。
- **机器人连接但从不在服务器频道回复**
- 缺少 **Message Content Intent**,或
- 机器人缺少频道权限View/Send/Read History
- 你的配置需要提及但你没有提及它,或
- 你的服务器/频道允许列表拒绝了该频道/用户。
- **`requireMention: false` 但仍然没有回复**
- `channels.discord.groupPolicy` 默认为 **allowlist**;将其设置为 `"open"` 或在 `channels.discord.guilds` 下添加服务器条目(可选择在 `channels.discord.guilds.<id>.channels` 下列出频道以进行限制)。
- 如果你只设置了 `DISCORD_BOT_TOKEN` 而从未创建 `channels.discord` 部分,运行时会将 `groupPolicy` 默认为 `open`。添加 `channels.discord.groupPolicy``channels.defaults.groupPolicy` 或服务器/频道允许列表来锁定它。
- `requireMention` 必须位于 `channels.discord.guilds`(或特定频道)下。顶层的 `channels.discord.requireMention` 会被忽略。
- **权限审计**`channels status --probe`)只检查数字频道 ID。如果你使用 slug/名称作为 `channels.discord.guilds.*.channels` 键,审计无法验证权限。
- **私信不工作**`channels.discord.dm.enabled=false``channels.discord.dm.policy="disabled"`,或者你尚未被批准(`channels.discord.dm.policy="pairing"`)。
- **Discord 中的执行审批**Discord 支持私信中执行审批的**按钮 UI**(允许一次 / 始终允许 / 拒绝)。`/approve <id> ...` 仅用于转发的审批,不会解析 Discord 的按钮提示。如果你看到 `❌ Failed to submit approval: Error: unknown approval id` 或 UI 从未出现,请检查:
- 你的配置中有 `channels.discord.execApprovals.enabled: true`
- 你的 Discord 用户 ID 在 `channels.discord.execApprovals.approvers` 中列出UI 仅发送给审批者)。
- 使用私信提示中的按钮(**Allow once**、**Always allow**、**Deny**)。
- 参见[执行审批](/tools/exec-approvals)和[斜杠命令](/tools/slash-commands)了解更广泛的审批和命令流程。
## 功能和限制
- 支持私信和服务器文字频道(话题被视为独立频道;不支持语音)。
- 打字指示器尽力发送;消息分块使用 `channels.discord.textChunkLimit`(默认 2000并按行数分割长回复`channels.discord.maxLinesPerMessage`,默认 17
- 可选换行分块:设置 `channels.discord.chunkMode="newline"` 以在空行(段落边界)处分割,然后再进行长度分块。
- 支持文件上传,最大 `channels.discord.mediaMaxMb`(默认 8 MB
- 默认服务器回复需要提及,以避免嘈杂的机器人。
- 当消息引用另一条消息时,会注入回复上下文(引用内容 + ID
- 原生回复线程**默认关闭**;使用 `channels.discord.replyToMode` 和回复标签启用。
## 重试策略
出站 Discord API 调用在速率限制429时使用 Discord `retry_after`(如果可用)进行重试,采用指数退避和抖动。通过 `channels.discord.retry` 配置。参见[重试策略](/concepts/retry)。
## 配置
```json5
{
channels: {
discord: {
enabled: true,
token: "abc.123",
groupPolicy: "allowlist",
guilds: {
"*": {
channels: {
general: { allow: true },
},
},
},
mediaMaxMb: 8,
actions: {
reactions: true,
stickers: true,
emojiUploads: true,
stickerUploads: true,
polls: true,
permissions: true,
messages: true,
threads: true,
pins: true,
search: true,
memberInfo: true,
roleInfo: true,
roles: false,
channelInfo: true,
channels: true,
voiceStatus: true,
events: true,
moderation: false,
},
replyToMode: "off",
dm: {
enabled: true,
policy: "pairing", // pairing | allowlist | open | disabled
allowFrom: ["123456789012345678", "steipete"],
groupEnabled: false,
groupChannels: ["openclaw-dm"],
},
guilds: {
"*": { requireMention: true },
"123456789012345678": {
slug: "friends-of-openclaw",
requireMention: false,
reactionNotifications: "own",
users: ["987654321098765432", "steipete"],
channels: {
general: { allow: true },
help: {
allow: true,
requireMention: true,
users: ["987654321098765432"],
skills: ["search", "docs"],
systemPrompt: "Keep answers short.",
},
},
},
},
},
},
}
```
确认表情反应通过 `messages.ackReaction` + `messages.ackReactionScope` 全局控制。使用 `messages.removeAckAfterReply` 在机器人回复后清除确认表情反应。
- `dm.enabled`:设置 `false` 忽略所有私信(默认 `true`)。
- `dm.policy`:私信访问控制(推荐 `pairing`)。`"open"` 需要 `dm.allowFrom=["*"]`
- `dm.allowFrom`:私信允许列表(用户 ID 或名称)。用于 `dm.policy="allowlist"``dm.policy="open"` 验证。向导接受用户名,并在机器人可以搜索成员时将其解析为 ID。
- `dm.groupEnabled`:启用群组私信(默认 `false`)。
- `dm.groupChannels`:群组私信频道 ID 或 slug 的可选允许列表。
- `groupPolicy`:控制服务器频道处理(`open|disabled|allowlist``allowlist` 需要频道允许列表。
- `guilds`:按服务器规则,以服务器 ID首选或 slug 为键。
- `guilds."*"`:当没有显式条目时应用的默认每服务器设置。
- `guilds.<id>.slug`:用于显示名称的可选友好 slug。
- `guilds.<id>.users`可选的每服务器用户允许列表ID 或名称)。
- `guilds.<id>.tools`:可选的每服务器工具策略覆盖(`allow`/`deny`/`alsoAllow`),在频道覆盖缺失时使用。
- `guilds.<id>.toolsBySender`:服务器级别的可选每发送者工具策略覆盖(在频道覆盖缺失时应用;支持 `"*"` 通配符)。
- `guilds.<id>.channels.<channel>.allow`:当 `groupPolicy="allowlist"` 时允许/拒绝频道。
- `guilds.<id>.channels.<channel>.requireMention`:频道的提及限制。
- `guilds.<id>.channels.<channel>.tools`:可选的每频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `guilds.<id>.channels.<channel>.toolsBySender`:频道内的可选每发送者工具策略覆盖(支持 `"*"` 通配符)。
- `guilds.<id>.channels.<channel>.users`:可选的每频道用户允许列表。
- `guilds.<id>.channels.<channel>.skills`Skills 过滤器(省略 = 所有 Skills空 = 无)。
- `guilds.<id>.channels.<channel>.systemPrompt`:频道的额外系统提示词(与频道主题组合)。
- `guilds.<id>.channels.<channel>.enabled`:设置 `false` 禁用频道。
- `guilds.<id>.channels`:频道规则(键为频道 slug 或 ID
- `guilds.<id>.requireMention`:每服务器提及要求(可按频道覆盖)。
- `guilds.<id>.reactionNotifications`:表情反应系统事件模式(`off``own``all``allowlist`)。
- `textChunkLimit`出站文本块大小字符。默认2000。
- `chunkMode``length`(默认)仅在超过 `textChunkLimit` 时分割;`newline` 在空行(段落边界)处分割,然后再进行长度分块。
- `maxLinesPerMessage`每条消息的软最大行数。默认17。
- `mediaMaxMb`:限制保存到磁盘的入站媒体大小。
- `historyLimit`:回复提及时作为上下文包含的最近服务器消息数量(默认 20回退到 `messages.groupChat.historyLimit``0` 禁用)。
- `dmHistoryLimit`:私信历史限制(用户轮次)。每用户覆盖:`dms["<user_id>"].historyLimit`
- `retry`:出站 Discord API 调用的重试策略attempts、minDelayMs、maxDelayMs、jitter
- `pluralkit`:解析 PluralKit 代理消息,使系统成员显示为不同的发送者。
- `actions`:每操作工具门控;省略允许所有(设置 `false` 禁用)。
- `reactions`(涵盖表情反应 + 读取表情反应)
- `stickers``emojiUploads``stickerUploads``polls``permissions``messages``threads``pins``search`
- `memberInfo``roleInfo``channelInfo``voiceStatus``events`
- `channels`(创建/编辑/删除频道 + 类别 + 权限)
- `roles`(角色添加/移除,默认 `false`
- `moderation`(超时/踢出/封禁,默认 `false`
- `execApprovals`Discord 专用执行审批私信(按钮 UI。支持 `enabled``approvers``agentFilter``sessionFilter`
表情反应通知使用 `guilds.<id>.reactionNotifications`
- `off`:无表情反应事件。
- `own`:机器人自己消息上的表情反应(默认)。
- `all`:所有消息上的所有表情反应。
- `allowlist`:来自 `guilds.<id>.users` 的用户在所有消息上的表情反应(空列表禁用)。
### PluralKitPK支持
启用 PK 查找,以便代理消息解析到底层系统 + 成员。启用后OpenClaw 使用成员身份进行允许列表匹配,并将发送者标记为 `Member (PK:System)` 以避免意外的 Discord 提及。
```json5
{
channels: {
discord: {
pluralkit: {
enabled: true,
token: "pk_live_...", // 可选;私有系统需要
},
},
},
}
```
允许列表注意事项(启用 PK 时):
-`dm.allowFrom``guilds.<id>.users` 或每频道 `users` 中使用 `pk:<memberId>`
- 成员显示名称也按名称/slug 匹配。
- 查找使用**原始** Discord 消息 ID代理前的消息因此 PK API 只在其 30 分钟窗口内解析它。
- 如果 PK 查找失败(例如,没有令牌的私有系统),代理消息会被视为机器人消息并被丢弃,除非 `channels.discord.allowBots=true`
### 工具操作默认值
| 操作组 | 默认 | 说明 |
| -------------- | ---- | ----------------------------------- |
| reactions | 启用 | 表情反应 + 列出表情反应 + emojiList |
| stickers | 启用 | 发送贴纸 |
| emojiUploads | 启用 | 上传表情 |
| stickerUploads | 启用 | 上传贴纸 |
| polls | 启用 | 创建投票 |
| permissions | 启用 | 频道权限快照 |
| messages | 启用 | 读取/发送/编辑/删除 |
| threads | 启用 | 创建/列出/回复 |
| pins | 启用 | 置顶/取消置顶/列出 |
| search | 启用 | 消息搜索(预览功能) |
| memberInfo | 启用 | 成员信息 |
| roleInfo | 启用 | 角色列表 |
| channelInfo | 启用 | 频道信息 + 列表 |
| channels | 启用 | 频道/类别管理 |
| voiceStatus | 启用 | 语音状态查询 |
| events | 启用 | 列出/创建预定事件 |
| roles | 禁用 | 角色添加/移除 |
| moderation | 禁用 | 超时/踢出/封禁 |
- `replyToMode``off`(默认)、`first``all`。仅在模型包含回复标签时适用。
## 回复标签
要请求线程回复,模型可以在其输出中包含一个标签:
- `[[reply_to_current]]` — 回复触发的 Discord 消息。
- `[[reply_to:<id>]]` — 回复上下文/历史中的特定消息 ID。当前消息 ID 作为 `[message_id: …]` 附加到提示词;历史条目已包含 ID。
行为由 `channels.discord.replyToMode` 控制:
- `off`:忽略标签。
- `first`:只有第一个出站块/附件是回复。
- `all`:每个出站块/附件都是回复。
允许列表匹配注意事项:
- `allowFrom`/`users`/`groupChannels` 接受 ID、名称、标签或像 `<@id>` 这样的提及。
- 支持 `discord:`/`user:`(用户)和 `channel:`(群组私信)等前缀。
- 使用 `*` 允许任何发送者/频道。
- 当存在 `guilds.<id>.channels` 时,未列出的频道默认被拒绝。
- 当省略 `guilds.<id>.channels` 时,允许列表中服务器的所有频道都被允许。
- 要**不允许任何频道**,设置 `channels.discord.groupPolicy: "disabled"`(或保持空允许列表)。
- 配置向导接受 `Guild/Channel` 名称(公开 + 私有)并在可能时将其解析为 ID。
- 启动时OpenClaw 将允许列表中的频道/用户名称解析为 ID当机器人可以搜索成员时并记录映射未解析的条目保持原样。
原生命令注意事项:
- 注册的命令镜像 OpenClaw 的聊天命令。
- 原生命令遵循与私信/服务器消息相同的允许列表(`channels.discord.dm.allowFrom``channels.discord.guilds`、每频道规则)。
- 斜杠命令可能在 Discord UI 中对未在允许列表中的用户仍然可见OpenClaw 在执行时强制执行允许列表并回复"未授权"。
## 工具操作
智能体可以使用以下操作调用 `discord`
- `react` / `reactions`(添加或列出表情反应)
- `sticker``poll``permissions`
- `readMessages``sendMessage``editMessage``deleteMessage`
- 读取/搜索/置顶工具负载包含规范化的 `timestampMs`UTC 纪元毫秒)和 `timestampUtc` 以及原始 Discord `timestamp`
- `threadCreate``threadList``threadReply`
- `pinMessage``unpinMessage``listPins`
- `searchMessages``memberInfo``roleInfo``roleAdd``roleRemove``emojiList`
- `channelInfo``channelList``voiceStatus``eventList``eventCreate`
- `timeout``kick``ban`
Discord 消息 ID 在注入的上下文中显示(`[discord message id: …]` 和历史行),以便智能体可以定位它们。
表情可以是 unicode例如 `✅`)或自定义表情语法如 `<:party_blob:1234567890>`
## 安全与运维
- 像对待密码一样对待机器人令牌;在受监督的主机上优先使用 `DISCORD_BOT_TOKEN` 环境变量,或锁定配置文件权限。
- 只授予机器人所需的权限(通常是读取/发送消息)。
- 如果机器人卡住或受到速率限制,在确认没有其他进程拥有 Discord 会话后重启 Gateway 网关(`openclaw gateway --force`)。

629
content/channels/feishu.md Normal file
View File

@@ -0,0 +1,629 @@
---
summary: "飞书机器人支持状态、功能和配置"
read_when:
- 您想要连接飞书机器人
- 您正在配置飞书渠道
title: 飞书
---
# 飞书机器人
状态:生产就绪,支持机器人私聊和群组。使用 WebSocket 长连接模式接收消息。
---
## 需要插件
安装 Feishu 插件:
```bash
openclaw plugins install @openclaw/feishu
```
本地 checkout在 git 仓库内运行):
```bash
openclaw plugins install ./extensions/feishu
```
---
## 快速开始
添加飞书渠道有两种方式:
### 方式一:通过安装向导添加(推荐)
如果您刚安装完 OpenClaw可以直接运行向导根据提示添加飞书
```bash
openclaw onboard
```
向导会引导您完成:
1. 创建飞书应用并获取凭证
2. 配置应用凭证
3. 启动网关
**完成配置后**,您可以使用以下命令检查网关状态:
- `openclaw gateway status` - 查看网关运行状态
- `openclaw logs --follow` - 查看实时日志
### 方式二:通过命令行添加
如果您已经完成了初始安装,可以用以下命令添加飞书渠道:
```bash
openclaw channels add
```
然后根据交互式提示选择 Feishu输入 App ID 和 App Secret 即可。
**完成配置后**,您可以使用以下命令管理网关:
- `openclaw gateway status` - 查看网关运行状态
- `openclaw gateway restart` - 重启网关以应用新配置
- `openclaw logs --follow` - 查看实时日志
---
## 第一步:创建飞书应用
### 1. 打开飞书开放平台
访问 [飞书开放平台](https://open.feishu.cn/app),使用飞书账号登录。
Lark国际版请使用 https://open.larksuite.com/app并在配置中设置 `domain: "lark"`
### 2. 创建应用
1. 点击 **创建企业自建应用**
2. 填写应用名称和描述
3. 选择应用图标
![创建企业自建应用](/images/feishu-step2-create-app.png)
### 3. 获取应用凭证
在应用的 **凭证与基础信息** 页面,复制:
- **App ID**(格式如 `cli_xxx`
- **App Secret**
**重要**:请妥善保管 App Secret不要分享给他人。
![获取应用凭证](/images/feishu-step3-credentials.png)
### 4. 配置应用权限
**权限管理** 页面,点击 **批量导入** 按钮,粘贴以下 JSON 配置一键导入所需权限:
```json
{
"scopes": {
"tenant": [
"aily:file:read",
"aily:file:write",
"application:application.app_message_stats.overview:readonly",
"application:application:self_manage",
"application:bot.menu:write",
"cardkit:card:write",
"contact:user.employee_id:readonly",
"corehr:file:download",
"docs:document.content:read",
"event:ip_list",
"im:chat",
"im:chat.access_event.bot_p2p_chat:read",
"im:chat.members:bot_access",
"im:message",
"im:message.group_at_msg:readonly",
"im:message.group_msg",
"im:message.p2p_msg:readonly",
"im:message:readonly",
"im:message:send_as_bot",
"im:resource",
"sheets:spreadsheet",
"wiki:wiki:readonly"
],
"user": ["aily:file:read", "aily:file:write", "im:chat.access_event.bot_p2p_chat:read"]
}
}
```
![配置应用权限](/images/feishu-step4-permissions.png)
### 5. 启用机器人能力
**应用能力** > **机器人** 页面:
1. 开启机器人能力
2. 配置机器人名称
![启用机器人能力](/images/feishu-step5-bot-capability.png)
### 6. 配置事件订阅
⚠️ **重要提醒**:在配置事件订阅前,请务必确保已完成以下步骤:
1. 运行 `openclaw channels add` 添加了 Feishu 渠道
2. 网关处于启动状态(可通过 `openclaw gateway status` 检查状态)
**事件订阅** 页面:
1. 选择 **使用长连接接收事件**WebSocket 模式)
2. 添加事件:`im.message.receive_v1`(接收消息)
⚠️ **注意**:如果网关未启动或渠道未添加,长连接设置将保存失败。
![配置事件订阅](/images/feishu-step6-event-subscription.png)
### 7. 发布应用
1.**版本管理与发布** 页面创建版本
2. 提交审核并发布
3. 等待管理员审批(企业自建应用通常自动通过)
---
## 第二步:配置 OpenClaw
### 通过向导配置(推荐)
运行以下命令,根据提示粘贴 App ID 和 App Secret
```bash
openclaw channels add
```
选择 **Feishu**,然后输入您在第一步获取的凭证即可。
### 通过配置文件配置
编辑 `~/.openclaw/openclaw.json`
```json5
{
channels: {
feishu: {
enabled: true,
dmPolicy: "pairing",
accounts: {
main: {
appId: "cli_xxx",
appSecret: "xxx",
botName: "我的AI助手",
},
},
},
},
}
```
### 通过环境变量配置
```bash
export FEISHU_APP_ID="cli_xxx"
export FEISHU_APP_SECRET="xxx"
```
### Lark国际版域名
如果您的租户在 Lark国际版请设置域名为 `lark`(或完整域名),可配置 `channels.feishu.domain``channels.feishu.accounts.<id>.domain`
```json5
{
channels: {
feishu: {
domain: "lark",
accounts: {
main: {
appId: "cli_xxx",
appSecret: "xxx",
},
},
},
},
}
```
---
## 第三步:启动并测试
### 1. 启动网关
```bash
openclaw gateway
```
### 2. 发送测试消息
在飞书中找到您创建的机器人,发送一条消息。
### 3. 配对授权
默认情况下,机器人会回复一个 **配对码**。您需要批准此代码:
```bash
openclaw pairing approve feishu <配对码>
```
批准后即可正常对话。
---
## 介绍
- **飞书机器人渠道**:由网关管理的飞书机器人
- **确定性路由**:回复始终返回飞书,模型不会选择渠道
- **会话隔离**:私聊共享主会话;群组独立隔离
- **WebSocket 连接**:使用飞书 SDK 的长连接模式,无需公网 URL
---
## 访问控制
### 私聊访问
- **默认**`dmPolicy: "pairing"`,陌生用户会收到配对码
- **批准配对**
```bash
openclaw pairing list feishu # 查看待审批列表
openclaw pairing approve feishu <CODE> # 批准
```
- **白名单模式**:通过 `channels.feishu.allowFrom` 配置允许的用户 Open ID
### 群组访问
**1. 群组策略**`channels.feishu.groupPolicy`
- `"open"` = 允许群组中所有人(默认)
- `"allowlist"` = 仅允许 `groupAllowFrom` 中的用户
- `"disabled"` = 禁用群组消息
**2. @提及要求**`channels.feishu.groups.<chat_id>.requireMention`
- `true` = 需要 @机器人才响应(默认)
- `false` = 无需 @也响应
---
## 群组配置示例
### 允许所有群组,需要 @提及(默认行为)
```json5
{
channels: {
feishu: {
groupPolicy: "open",
// 默认 requireMention: true
},
},
}
```
### 允许所有群组,无需 @提及
需要为特定群组配置:
```json5
{
channels: {
feishu: {
groups: {
oc_xxx: { requireMention: false },
},
},
},
}
```
### 仅允许特定用户在群组中使用
```json5
{
channels: {
feishu: {
groupPolicy: "allowlist",
groupAllowFrom: ["ou_xxx", "ou_yyy"],
},
},
}
```
---
## 获取群组/用户 ID
### 获取群组 IDchat_id
群组 ID 格式为 `oc_xxx`,可以通过以下方式获取:
**方法一**(推荐):
1. 启动网关并在群组中 @机器人发消息
2. 运行 `openclaw logs --follow` 查看日志中的 `chat_id`
**方法二**
使用飞书 API 调试工具获取机器人所在群组列表。
### 获取用户 IDopen_id
用户 ID 格式为 `ou_xxx`,可以通过以下方式获取:
**方法一**(推荐):
1. 启动网关并给机器人发消息
2. 运行 `openclaw logs --follow` 查看日志中的 `open_id`
**方法二**
查看配对请求列表,其中包含用户的 Open ID
```bash
openclaw pairing list feishu
```
---
## 常用命令
| 命令 | 说明 |
| --------- | -------------- |
| `/status` | 查看机器人状态 |
| `/reset` | 重置对话会话 |
| `/model` | 查看/切换模型 |
> 注意:飞书目前不支持原生命令菜单,命令需要以文本形式发送。
## 网关管理命令
在配置和使用飞书渠道时,您可能需要使用以下网关管理命令:
| 命令 | 说明 |
| -------------------------- | ----------------- |
| `openclaw gateway status` | 查看网关运行状态 |
| `openclaw gateway install` | 安装/启动网关服务 |
| `openclaw gateway stop` | 停止网关服务 |
| `openclaw gateway restart` | 重启网关服务 |
| `openclaw logs --follow` | 实时查看日志输出 |
---
## 故障排除
### 机器人在群组中不响应
1. 检查机器人是否已添加到群组
2. 检查是否 @了机器人(默认需要 @提及)
3. 检查 `groupPolicy` 是否为 `"disabled"`
4. 查看日志:`openclaw logs --follow`
### 机器人收不到消息
1. 检查应用是否已发布并审批通过
2. 检查事件订阅是否配置正确(`im.message.receive_v1`
3. 检查是否选择了 **长连接** 模式
4. 检查应用权限是否完整
5. 检查网关是否正在运行:`openclaw gateway status`
6. 查看实时日志:`openclaw logs --follow`
### App Secret 泄露怎么办
1. 在飞书开放平台重置 App Secret
2. 更新配置文件中的 App Secret
3. 重启网关
### 发送消息失败
1. 检查应用是否有 `im:message:send_as_bot` 权限
2. 检查应用是否已发布
3. 查看日志获取详细错误信息
---
## 高级配置
### 多账号配置
如果需要管理多个飞书机器人:
```json5
{
channels: {
feishu: {
accounts: {
main: {
appId: "cli_xxx",
appSecret: "xxx",
botName: "主机器人",
},
backup: {
appId: "cli_yyy",
appSecret: "yyy",
botName: "备用机器人",
enabled: false, // 暂时禁用
},
},
},
},
}
```
### 消息限制
- `textChunkLimit`:出站文本分块大小(默认 2000 字符)
- `mediaMaxMb`:媒体上传/下载限制(默认 30MB
### 流式输出
飞书支持通过交互式卡片实现流式输出,机器人会实时更新卡片内容显示生成进度。默认配置:
```json5
{
channels: {
feishu: {
streaming: true, // 启用流式卡片输出(默认 true
blockStreaming: true, // 启用块级流式(默认 true
},
},
}
```
如需禁用流式输出(等待完整回复后一次性发送),可设置 `streaming: false`。
### 消息引用
在群聊中,机器人的回复可以引用用户发送的原始消息,让对话上下文更加清晰。
配置选项:
```json5
{
channels: {
feishu: {
// 账户级别配置(默认 "all"
replyToMode: "all",
groups: {
oc_xxx: {
// 特定群组可以覆盖
replyToMode: "first",
},
},
},
},
}
```
`replyToMode` 值说明:
| 值 | 行为 |
| --------- | ---------------------------------- |
| `"off"` | 不引用原消息(私聊默认值) |
| `"first"` | 仅在第一条回复时引用原消息 |
| `"all"` | 所有回复都引用原消息(群聊默认值) |
> 注意:消息引用功能与流式卡片输出(`streaming: true`)不能同时使用。当启用流式输出时,回复会以卡片形式呈现,不会显示引用。
### 多 Agent 路由
通过 `bindings` 配置,您可以用一个飞书机器人对接多个不同功能或性格的 Agent。系统会根据用户 ID 或群组 ID 自动将对话分发到对应的 Agent。
配置示例:
```json5
{
agents: {
list: [
{ id: "main" },
{
id: "clawd-fan",
workspace: "/home/user/clawd-fan",
agentDir: "/home/user/.openclaw/agents/clawd-fan/agent",
},
{
id: "clawd-xi",
workspace: "/home/user/clawd-xi",
agentDir: "/home/user/.openclaw/agents/clawd-xi/agent",
},
],
},
bindings: [
{
// 用户 A 的私聊 → main agent
agentId: "main",
match: {
channel: "feishu",
peer: { kind: "dm", id: "ou_28b31a88..." },
},
},
{
// 用户 B 的私聊 → clawd-fan agent
agentId: "clawd-fan",
match: {
channel: "feishu",
peer: { kind: "dm", id: "ou_0fe6b1c9..." },
},
},
{
// 某个群组 → clawd-xi agent
agentId: "clawd-xi",
match: {
channel: "feishu",
peer: { kind: "group", id: "oc_xxx..." },
},
},
],
}
```
匹配规则说明:
| 字段 | 说明 |
| ----------------- | --------------------------------------------- |
| `agentId` | 目标 Agent 的 ID需要在 `agents.list` 中定义 |
| `match.channel` | 渠道类型,这里固定为 `"feishu"` |
| `match.peer.kind` | 对话类型:`"dm"`(私聊)或 `"group"`(群组) |
| `match.peer.id` | 用户 Open ID`ou_xxx`)或群组 ID`oc_xxx` |
> 获取 ID 的方法:参见上文 [获取群组/用户 ID](#获取群组用户-id) 章节。
---
## 配置参考
完整配置请参考:[网关配置](/gateway/configuration)
主要选项:
| 配置项 | 说明 | 默认值 |
| ------------------------------------------------- | ------------------------------ | --------- |
| `channels.feishu.enabled` | 启用/禁用渠道 | `true` |
| `channels.feishu.domain` | API 域名(`feishu` 或 `lark` | `feishu` |
| `channels.feishu.accounts.<id>.appId` | 应用 App ID | - |
| `channels.feishu.accounts.<id>.appSecret` | 应用 App Secret | - |
| `channels.feishu.accounts.<id>.domain` | 单账号 API 域名覆盖 | `feishu` |
| `channels.feishu.dmPolicy` | 私聊策略 | `pairing` |
| `channels.feishu.allowFrom` | 私聊白名单open_id 列表) | - |
| `channels.feishu.groupPolicy` | 群组策略 | `open` |
| `channels.feishu.groupAllowFrom` | 群组白名单 | - |
| `channels.feishu.groups.<chat_id>.requireMention` | 是否需要 @提及 | `true` |
| `channels.feishu.groups.<chat_id>.enabled` | 是否启用该群组 | `true` |
| `channels.feishu.textChunkLimit` | 消息分块大小 | `2000` |
| `channels.feishu.mediaMaxMb` | 媒体大小限制 | `30` |
| `channels.feishu.streaming` | 启用流式卡片输出 | `true` |
| `channels.feishu.blockStreaming` | 启用块级流式 | `true` |
---
## dmPolicy 策略说明
| 值 | 行为 |
| ------------- | -------------------------------------------------- |
| `"pairing"` | **默认**。未知用户收到配对码,管理员批准后才能对话 |
| `"allowlist"` | 仅 `allowFrom` 列表中的用户可对话,其他静默忽略 |
| `"open"` | 允许所有人对话(需在 allowFrom 中加 `"*"` |
| `"disabled"` | 完全禁止私聊 |
---
## 支持的消息类型
### 接收
- ✅ 文本消息
- ✅ 图片
- ✅ 文件
- ✅ 音频
- ✅ 视频
- ✅ 表情包
### 发送
- ✅ 文本消息
- ✅ 图片
- ✅ 文件
- ✅ 音频
- ⚠️ 富文本(部分支持)

View File

@@ -0,0 +1,257 @@
---
read_when:
- 开发 Google Chat 渠道功能时
summary: Google Chat 应用支持状态、功能和配置
title: Google Chat
x-i18n:
generated_at: "2026-02-03T07:43:39Z"
model: claude-opus-4-5
provider: pi
source_hash: 3b2bb116cdd12614c3d5afddd0879e9deb05c3606e3a2385cbc07f23552b357e
source_path: channels/googlechat.md
workflow: 15
---
# Google ChatChat API
状态:已支持通过 Google Chat API webhooks仅 HTTP使用私信和空间。
## 快速设置(新手)
1. 创建一个 Google Cloud 项目并启用 **Google Chat API**
- 前往:[Google Chat API Credentials](https://console.cloud.google.com/apis/api/chat.googleapis.com/credentials)
- 如果 API 尚未启用,请启用它。
2. 创建一个**服务账号**
- 点击 **Create Credentials** > **Service Account**
- 随意命名(例如 `openclaw-chat`)。
- 权限留空(点击 **Continue**)。
- 有访问权限的主账号留空(点击 **Done**)。
3. 创建并下载 **JSON 密钥**
- 在服务账号列表中,点击刚刚创建的账号。
- 前往 **Keys** 标签页。
- 点击 **Add Key** > **Create new key**
- 选择 **JSON** 并点击 **Create**
4. 将下载的 JSON 文件存储在 Gateway 网关主机上(例如 `~/.openclaw/googlechat-service-account.json`)。
5. 在 [Google Cloud Console Chat Configuration](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat) 中创建一个 Google Chat 应用:
- 填写 **Application info**
- **App name**:(例如 `OpenClaw`
- **Avatar URL**:(例如 `https://openclaw.ai/logo.png`
- **Description**:(例如 `Personal AI Assistant`
- 启用 **Interactive features**
-**Functionality** 下,勾选 **Join spaces and group conversations**
-**Connection settings** 下,选择 **HTTP endpoint URL**
-**Triggers** 下,选择 **Use a common HTTP endpoint URL for all triggers** 并将其设置为你的 Gateway 网关公网 URL 后加 `/googlechat`
- _提示运行 `openclaw status` 查看你的 Gateway 网关公网 URL。_
-**Visibility** 下,勾选 **Make this Chat app available to specific people and groups in &lt;Your Domain&gt;**
- 在文本框中输入你的邮箱地址(例如 `user@example.com`)。
- 点击底部的 **Save**
6. **启用应用状态**
- 保存后,**刷新页面**。
- 找到 **App status** 部分(通常在保存后位于顶部或底部附近)。
- 将状态更改为 **Live - available to users**
- 再次点击 **Save**
7. 使用服务账号路径和 webhook audience 配置 OpenClaw
- 环境变量:`GOOGLE_CHAT_SERVICE_ACCOUNT_FILE=/path/to/service-account.json`
- 或配置:`channels.googlechat.serviceAccountFile: "/path/to/service-account.json"`
8. 设置 webhook audience 类型和值(与你的 Chat 应用配置匹配)。
9. 启动 Gateway 网关。Google Chat 将向你的 webhook 路径发送 POST 请求。
## 添加到 Google Chat
Gateway 网关运行后,且你的邮箱已添加到可见性列表中:
1. 前往 [Google Chat](https://chat.google.com/)。
2. 点击 **Direct Messages** 旁边的 **+**(加号)图标。
3. 在搜索栏(通常用于添加联系人的位置)中,输入你在 Google Cloud Console 中配置的 **App name**
- **注意**:该机器人*不会*出现在"Marketplace"浏览列表中,因为它是私有应用。你必须按名称搜索。
4. 从结果中选择你的机器人。
5. 点击 **Add****Chat** 开始一对一对话。
6. 发送"Hello"来触发助手!
## 公网 URL仅 Webhook
Google Chat webhooks 需要一个公网 HTTPS 端点。为了安全起见,**只将 `/googlechat` 路径暴露到互联网**。将 OpenClaw 仪表板和其他敏感端点保留在你的私有网络上。
### 方案 ATailscale Funnel推荐
使用 Tailscale Serve 提供私有仪表板,使用 Funnel 提供公网 webhook 路径。这样可以保持 `/` 私有,同时只暴露 `/googlechat`
1. **检查你的 Gateway 网关绑定的地址:**
```bash
ss -tlnp | grep 18789
```
记下 IP 地址(例如 `127.0.0.1`、`0.0.0.0` 或你的 Tailscale IP 如 `100.x.x.x`)。
2. **仅将仪表板暴露给 tailnet端口 8443**
```bash
# 如果绑定到 localhost127.0.0.1 或 0.0.0.0
tailscale serve --bg --https 8443 http://127.0.0.1:18789
# 如果仅绑定到 Tailscale IP例如 100.106.161.80
tailscale serve --bg --https 8443 http://100.106.161.80:18789
```
3. **仅公开暴露 webhook 路径:**
```bash
# 如果绑定到 localhost127.0.0.1 或 0.0.0.0
tailscale funnel --bg --set-path /googlechat http://127.0.0.1:18789/googlechat
# 如果仅绑定到 Tailscale IP例如 100.106.161.80
tailscale funnel --bg --set-path /googlechat http://100.106.161.80:18789/googlechat
```
4. **授权节点访问 Funnel**
如果出现提示,请访问输出中显示的授权 URL以在你的 tailnet 策略中为此节点启用 Funnel。
5. **验证配置:**
```bash
tailscale serve status
tailscale funnel status
```
你的公网 webhook URL 将是:
`https://<node-name>.<tailnet>.ts.net/googlechat`
你的私有仪表板仅限 tailnet 访问:
`https://<node-name>.<tailnet>.ts.net:8443/`
在 Google Chat 应用配置中使用公网 URL不带 `:8443`)。
> 注意:此配置在重启后会保留。如需稍后移除,请运行 `tailscale funnel reset` 和 `tailscale serve reset`。
### 方案 B反向代理Caddy
如果你使用像 Caddy 这样的反向代理,只代理特定路径:
```caddy
your-domain.com {
reverse_proxy /googlechat* localhost:18789
}
```
使用此配置,任何发往 `your-domain.com/` 的请求将被忽略或返回 404而 `your-domain.com/googlechat` 会安全地路由到 OpenClaw。
### 方案 CCloudflare Tunnel
配置你的隧道入口规则,只路由 webhook 路径:
- **路径**`/googlechat` -> `http://localhost:18789/googlechat`
- **默认规则**HTTP 404未找到
## 工作原理
1. Google Chat 向 Gateway 网关发送 webhook POST 请求。每个请求都包含一个 `Authorization: Bearer <token>` 头。
2. OpenClaw 根据配置的 `audienceType` + `audience` 验证令牌:
- `audienceType: "app-url"` → audience 是你的 HTTPS webhook URL。
- `audienceType: "project-number"` → audience 是 Cloud 项目编号。
3. 消息按空间路由:
- 私信使用会话键 `agent:<agentId>:googlechat:dm:<spaceId>`。
- 空间使用会话键 `agent:<agentId>:googlechat:group:<spaceId>`。
4. 私信访问默认为配对模式。未知发送者会收到配对码;使用以下命令批准:
- `openclaw pairing approve googlechat <code>`
5. 群组空间默认需要 @提及。如果提及检测需要应用的用户名,请使用 `botUser`。
## 目标标识符
使用这些标识符进行消息投递和允许列表:
- 私信:`users/<userId>` 或 `users/<email>`(接受邮箱地址)。
- 空间:`spaces/<spaceId>`。
## 配置要点
```json5
{
channels: {
googlechat: {
enabled: true,
serviceAccountFile: "/path/to/service-account.json",
audienceType: "app-url",
audience: "https://gateway.example.com/googlechat",
webhookPath: "/googlechat",
botUser: "users/1234567890", // 可选;帮助提及检测
dm: {
policy: "pairing",
allowFrom: ["users/1234567890", "name@example.com"],
},
groupPolicy: "allowlist",
groups: {
"spaces/AAAA": {
allow: true,
requireMention: true,
users: ["users/1234567890"],
systemPrompt: "Short answers only.",
},
},
actions: { reactions: true },
typingIndicator: "message",
mediaMaxMb: 20,
},
},
}
```
注意事项:
- 服务账号凭证也可以通过 `serviceAccount`JSON 字符串)内联传递。
- 如果未设置 `webhookPath`,默认 webhook 路径为 `/googlechat`。
- 当 `actions.reactions` 启用时,可通过 `reactions` 工具和 `channels action` 使用表情回应。
- `typingIndicator` 支持 `none`、`message`(默认)和 `reaction`reaction 需要用户 OAuth
- 附件通过 Chat API 下载并存储在媒体管道中(大小受 `mediaMaxMb` 限制)。
## 故障排除
### 405 Method Not Allowed
如果 Google Cloud Logs Explorer 显示如下错误:
```
status code: 405, reason phrase: HTTP error response: HTTP/1.1 405 Method Not Allowed
```
这意味着 webhook 处理程序未注册。常见原因:
1. **渠道未配置**:配置中缺少 `channels.googlechat` 部分。使用以下命令验证:
```bash
openclaw config get channels.googlechat
```
如果返回"Config path not found",请添加配置(参见[配置要点](#配置要点))。
2. **插件未启用**:检查插件状态:
```bash
openclaw plugins list | grep googlechat
```
如果显示"disabled",请在配置中添加 `plugins.entries.googlechat.enabled: true`。
3. **Gateway 网关未重启**:添加配置后,重启 Gateway 网关:
```bash
openclaw gateway restart
```
验证渠道是否正在运行:
```bash
openclaw channels status
# 应显示Google Chat default: enabled, configured, ...
```
### 其他问题
- 检查 `openclaw channels status --probe` 以查看认证错误或缺少 audience 配置。
- 如果没有收到消息,请确认 Chat 应用的 webhook URL 和事件订阅。
- 如果提及门控阻止了回复,请将 `botUser` 设置为应用的用户资源名称并验证 `requireMention`。
- 在发送测试消息时使用 `openclaw logs --follow` 查看请求是否到达 Gateway 网关。
相关文档:
- [Gateway 网关配置](/gateway/configuration)
- [安全](/gateway/security)
- [表情回应](/tools/reactions)

View File

@@ -0,0 +1,38 @@
---
read_when:
- 开发 Telegram 或 grammY 相关功能时
summary: 通过 grammY 集成 Telegram Bot API附设置说明
title: grammY
x-i18n:
generated_at: "2026-02-03T10:03:55Z"
model: claude-opus-4-5
provider: pi
source_hash: ea7ef23e6d77801f4ef5fc56685ef4470f79f5aecab448d644a72cbab53521b7
source_path: channels/grammy.md
workflow: 15
---
# grammY 集成Telegram Bot API
# 为什么选择 grammY
- 以 TS 为核心的 Bot API 客户端,内置长轮询 + webhook 辅助工具、中间件、错误处理和速率限制器。
- 媒体处理辅助工具比手动编写 fetch + FormData 更简洁;支持所有 Bot API 方法。
- 可扩展:通过自定义 fetch 支持代理,可选的会话中间件,类型安全的上下文。
# 我们发布的内容
- **单一客户端路径:** 移除了基于 fetch 的实现grammY 现在是唯一的 Telegram 客户端(发送 + Gateway 网关),默认启用 grammY throttler。
- **Gateway 网关:** `monitorTelegramProvider` 构建 grammY `Bot`,接入 mention/allowlist 网关控制,通过 `getFile`/`download` 下载媒体,并使用 `sendMessage/sendPhoto/sendVideo/sendAudio/sendDocument` 发送回复。通过 `webhookCallback` 支持长轮询或 webhook。
- **代理:** 可选的 `channels.telegram.proxy` 通过 grammY 的 `client.baseFetch` 使用 `undici.ProxyAgent`
- **Webhook 支持:** `webhook-set.ts` 封装了 `setWebhook/deleteWebhook``webhook.ts` 托管回调,支持健康检查和优雅关闭。当设置了 `channels.telegram.webhookUrl` + `channels.telegram.webhookSecret`Gateway 网关启用 webhook 模式(否则使用长轮询)。
- **会话:** 私聊折叠到智能体主会话(`agent:<agentId>:<mainKey>`);群组使用 `agent:<agentId>:telegram:group:<chatId>`;回复路由回同一渠道。
- **配置选项:** `channels.telegram.botToken``channels.telegram.dmPolicy``channels.telegram.groups`allowlist + mention 默认值)、`channels.telegram.allowFrom``channels.telegram.groupAllowFrom``channels.telegram.groupPolicy``channels.telegram.mediaMaxMb``channels.telegram.linkPreview``channels.telegram.proxy``channels.telegram.webhookSecret``channels.telegram.webhookUrl`
- **草稿流式传输:** 可选的 `channels.telegram.streamMode` 在私有话题聊天中使用 `sendMessageDraft`Bot API 9.3+)。这与渠道分块流式传输是分开的。
- **测试:** grammY mock 覆盖了私信 + 群组 mention 网关控制和出站发送;欢迎添加更多媒体/webhook 测试用例。
待解决问题
- 如果遇到 Bot API 429 错误,考虑使用可选的 grammY 插件throttler
- 添加更多结构化媒体测试(贴纸、语音消息)。
- 使 webhook 监听端口可配置(目前固定为 8787除非通过 Gateway 网关配置)。

View File

@@ -0,0 +1,91 @@
---
read_when:
- 更改群组消息规则或提及设置时
summary: WhatsApp 群组消息处理的行为和配置mentionPatterns 在各平台间共享)
title: 群组消息
x-i18n:
generated_at: "2026-02-03T10:05:00Z"
model: claude-opus-4-5
provider: pi
source_hash: 181a72f12f5021af77c2e4c913120f711e0c0bc271d218d75cb6fe80dab675bb
source_path: channels/group-messages.md
workflow: 15
---
# 群组消息WhatsApp 网页渠道)
目标:让 Clawd 留在 WhatsApp 群组中,仅在被提及时唤醒,并将该对话线程与个人私信会话分开。
注意:`agents.list[].groupChat.mentionPatterns` 现在也被 Telegram/Discord/Slack/iMessage 使用;本文档重点介绍 WhatsApp 特定的行为。对于多智能体设置,为每个智能体设置 `agents.list[].groupChat.mentionPatterns`(或使用 `messages.groupChat.mentionPatterns` 作为全局回退)。
## 已实现的功能2025-12-03
- 激活模式:`mention`(默认)或 `always``mention` 需要被提及(通过 `mentionedJids` 的真实 WhatsApp @提及、正则表达式模式,或文本中任意位置的机器人 E.164 号码)。`always` 会在每条消息时唤醒智能体,但它应该只在能提供有意义价值时才回复;否则返回静默令牌 `NO_REPLY`。默认值可在配置中设置(`channels.whatsapp.groups`),并可通过 `/activation` 为每个群组单独覆盖。当设置了 `channels.whatsapp.groups` 时,它同时充当群组允许列表(包含 `"*"` 以允许所有群组)。
- 群组策略:`channels.whatsapp.groupPolicy` 控制是否接受群组消息(`open|disabled|allowlist`)。`allowlist` 使用 `channels.whatsapp.groupAllowFrom`(回退:显式的 `channels.whatsapp.allowFrom`)。默认为 `allowlist`(在你添加发送者之前被阻止)。
- 独立群组会话:会话键格式为 `agent:<agentId>:whatsapp:group:<jid>`,因此 `/verbose on``/think high`(作为独立消息发送)等命令仅作用于该群组;个人私信状态不受影响。群组线程会跳过心跳。
- 上下文注入:**仅待处理**的群组消息(默认 50 条),即*未*触发运行的消息,会以 `[Chat messages since your last reply - for context]` 为前缀注入,触发行在 `[Current message - respond to this]` 下。已在会话中的消息不会重复注入。
- 发送者显示:每个群组批次现在以 `[from: Sender Name (+E164)]` 结尾,让 Pi 知道是谁在说话。
- 阅后即焚/一次性查看:我们在提取文本/提及之前会先解包这些消息,因此其中的提及仍会触发。
- 群组系统提示:在群组会话的第一轮(以及每当 `/activation` 更改模式时),我们会向系统提示注入一段简短说明,如 `You are replying inside the WhatsApp group "<subject>". Group members: Alice (+44...), Bob (+43...), … Activation: trigger-only … Address the specific sender noted in the message context.` 如果元数据不可用,我们仍会告知智能体这是一个群聊。
## 配置示例WhatsApp
`~/.openclaw/openclaw.json` 中添加 `groupChat` 块,以便在 WhatsApp 剥离文本正文中的可视 `@` 时,显示名称提及仍能正常工作:
```json5
{
channels: {
whatsapp: {
groups: {
"*": { requireMention: true },
},
},
},
agents: {
list: [
{
id: "main",
groupChat: {
historyLimit: 50,
mentionPatterns: ["@?openclaw", "\\+?15555550123"],
},
},
],
},
}
```
注意:
- 正则表达式不区分大小写;它们涵盖了像 `@openclaw` 这样的显示名称提及,以及带或不带 `+`/空格的原始号码。
- 当有人点击联系人时WhatsApp 仍会通过 `mentionedJids` 发送规范的提及,因此号码回退很少需要,但作为安全网很有用。
### 激活命令(仅所有者)
使用群聊命令:
- `/activation mention`
- `/activation always`
只有所有者号码(来自 `channels.whatsapp.allowFrom`,或未设置时使用机器人自己的 E.164)可以更改此设置。在群组中发送 `/status` 作为独立消息以查看当前激活模式。
## 使用方法
1. 将你的 WhatsApp 账号(运行 OpenClaw 的账号)添加到群组。
2.`@openclaw …`(或包含号码)。只有允许列表中的发送者才能触发,除非你设置 `groupPolicy: "open"`
3. 智能体提示将包含最近的群组上下文以及尾部的 `[from: …]` 标记,以便它能够回应正确的人。
4. 会话级指令(`/verbose on``/think high``/new``/reset``/compact`)仅适用于该群组的会话;将它们作为独立消息发送以使其生效。你的个人私信会话保持独立。
## 测试/验证
- 手动冒烟测试:
- 在群组中发送 `@openclaw` 提及,确认收到引用发送者名称的回复。
- 发送第二次提及,验证历史记录块被包含,然后在下一轮清除。
- 检查 Gateway 网关日志(使用 `--verbose` 运行)以查看 `inbound web message` 条目,显示 `from: <groupJid>``[from: …]` 后缀。
## 已知注意事项
- 群组有意跳过心跳以避免嘈杂的广播。
- 回声抑制使用组合的批次字符串;如果你发送两次相同的文本但没有提及,只有第一次会得到响应。
- 会话存储条目将在会话存储中显示为 `agent:<agentId>:whatsapp:group:<jid>`(默认为 `~/.openclaw/agents/<agentId>/sessions/sessions.json`);缺失条目只是意味着该群组尚未触发运行。
- 群组中的输入指示器遵循 `agents.defaults.typingMode`(默认:未被提及时为 `message`)。

379
content/channels/groups.md Normal file
View File

@@ -0,0 +1,379 @@
---
read_when:
- 更改群聊行为或提及限制
summary: 跨平台的群聊行为WhatsApp/Telegram/Discord/Slack/Signal/iMessage/Microsoft Teams
title: 群组
x-i18n:
generated_at: "2026-02-03T07:47:08Z"
model: claude-opus-4-5
provider: pi
source_hash: b727a053edf51f6e7b5c0c324c2fc9c9789a9796c37f622418bd555e8b5a0ec4
source_path: channels/groups.md
workflow: 15
---
# 群组
OpenClaw 在各平台上统一处理群聊WhatsApp、Telegram、Discord、Slack、Signal、iMessage、Microsoft Teams。
## 新手入门2 分钟)
OpenClaw"运行"在你自己的消息账户上。没有单独的 WhatsApp 机器人用户。如果**你**在一个群组中OpenClaw 就可以看到该群组并在其中回复。
默认行为:
- 群组受限(`groupPolicy: "allowlist"`)。
- 除非你明确禁用提及限制,否则回复需要 @ 提及。
解释:允许列表中的发送者可以通过提及来触发 OpenClaw。
> 简而言之
>
> - **私信访问**由 `*.allowFrom` 控制。
> - **群组访问**由 `*.groupPolicy` + 允许列表(`*.groups`、`*.groupAllowFrom`)控制。
> - **回复触发**由提及限制(`requireMention`、`/activation`)控制。
快速流程(群消息会发生什么):
```
groupPolicy? disabled -> 丢弃
groupPolicy? allowlist -> 群组允许? 否 -> 丢弃
requireMention? 是 -> 被提及? 否 -> 仅存储为上下文
否则 -> 回复
```
![群消息流程](/images/groups-flow.svg)
如果你想...
| 目标 | 设置什么 |
|------|-------------|
| 允许所有群组但仅在 @ 提及时回复 | `groups: { "*": { requireMention: true } }` |
| 禁用所有群组回复 | `groupPolicy: "disabled"` |
| 仅特定群组 | `groups: { "<group-id>": { ... } }`(无 `"*"` 键) |
| 仅你可以在群组中触发 | `groupPolicy: "allowlist"``groupAllowFrom: ["+1555..."]` |
## 会话键
- 群组会话使用 `agent:<agentId>:<channel>:group:<id>` 会话键(房间/频道使用 `agent:<agentId>:<channel>:channel:<id>`)。
- Telegram 论坛话题在群组 ID 后添加 `:topic:<threadId>`,因此每个话题都有自己的会话。
- 私聊使用主会话(或按发送者配置时使用各自的会话)。
- 群组会话跳过心跳。
## 模式:个人私信 + 公开群组(单智能体)
是的——如果你的"个人"流量是**私信**而"公开"流量是**群组**,这种方式效果很好。
原因:在单智能体模式下,私信通常落在**主**会话键(`agent:main:main`)中,而群组始终使用**非主**会话键(`agent:main:<channel>:group:<id>`)。如果你启用 `mode: "non-main"` 的沙箱隔离,这些群组会话在 Docker 中运行,而你的主私信会话保持在主机上。
这给你一个智能体"大脑"(共享工作区 + 记忆),但两种执行姿态:
- **私信**:完整工具(主机)
- **群组**:沙箱 + 受限工具Docker
> 如果你需要真正独立的工作区/角色("个人"和"公开"绝不能混合),请使用第二个智能体 + 绑定。参见[多智能体路由](/concepts/multi-agent)。
示例(私信在主机上,群组沙箱隔离 + 仅消息工具):
```json5
{
agents: {
defaults: {
sandbox: {
mode: "non-main", // 群组/频道是非主 -> 沙箱隔离
scope: "session", // 最强隔离(每个群组/频道一个容器)
workspaceAccess: "none",
},
},
},
tools: {
sandbox: {
tools: {
// 如果 allow 非空其他所有工具都被阻止deny 仍然优先)。
allow: ["group:messaging", "group:sessions"],
deny: ["group:runtime", "group:fs", "group:ui", "nodes", "cron", "gateway"],
},
},
},
}
```
想要"群组只能看到文件夹 X"而不是"无主机访问"?保持 `workspaceAccess: "none"` 并仅将允许的路径挂载到沙箱中:
```json5
{
agents: {
defaults: {
sandbox: {
mode: "non-main",
scope: "session",
workspaceAccess: "none",
docker: {
binds: [
// hostPath:containerPath:mode
"~/FriendsShared:/data:ro",
],
},
},
},
},
}
```
相关:
- 配置键和默认值:[Gateway 网关配置](/gateway/configuration#agentsdefaultssandbox)
- 调试为什么工具被阻止:[沙箱 vs 工具策略 vs 提权](/gateway/sandbox-vs-tool-policy-vs-elevated)
- 绑定挂载详情:[沙箱隔离](/gateway/sandboxing#custom-bind-mounts)
## 显示标签
- UI 标签在可用时使用 `displayName`,格式为 `<channel>:<token>`
- `#room` 保留用于房间/频道;群聊使用 `g-<slug>`(小写,空格 -> `-`,保留 `#@+._-`)。
## 群组策略
控制每个渠道如何处理群组/房间消息:
```json5
{
channels: {
whatsapp: {
groupPolicy: "disabled", // "open" | "disabled" | "allowlist"
groupAllowFrom: ["+15551234567"],
},
telegram: {
groupPolicy: "disabled",
groupAllowFrom: ["123456789", "@username"],
},
signal: {
groupPolicy: "disabled",
groupAllowFrom: ["+15551234567"],
},
imessage: {
groupPolicy: "disabled",
groupAllowFrom: ["chat_id:123"],
},
msteams: {
groupPolicy: "disabled",
groupAllowFrom: ["user@org.com"],
},
discord: {
groupPolicy: "allowlist",
guilds: {
GUILD_ID: { channels: { help: { allow: true } } },
},
},
slack: {
groupPolicy: "allowlist",
channels: { "#general": { allow: true } },
},
matrix: {
groupPolicy: "allowlist",
groupAllowFrom: ["@owner:example.org"],
groups: {
"!roomId:example.org": { allow: true },
"#alias:example.org": { allow: true },
},
},
},
}
```
| 策略 | 行为 |
| ------------- | --------------------------------------- |
| `"open"` | 群组绕过允许列表;提及限制仍然适用。 |
| `"disabled"` | 完全阻止所有群组消息。 |
| `"allowlist"` | 仅允许与配置的允许列表匹配的群组/房间。 |
注意事项:
- `groupPolicy` 与提及限制(需要 @ 提及)是分开的。
- WhatsApp/Telegram/Signal/iMessage/Microsoft Teams使用 `groupAllowFrom`(回退:显式 `allowFrom`)。
- Discord允许列表使用 `channels.discord.guilds.<id>.channels`
- Slack允许列表使用 `channels.slack.channels`
- Matrix允许列表使用 `channels.matrix.groups`(房间 ID、别名或名称。使用 `channels.matrix.groupAllowFrom` 限制发送者;也支持每个房间的 `users` 允许列表。
- 群组私信单独控制(`channels.discord.dm.*``channels.slack.dm.*`)。
- Telegram 允许列表可以匹配用户 ID`"123456789"``"telegram:123456789"``"tg:123456789"`)或用户名(`"@alice"``"alice"`);前缀不区分大小写。
- 默认为 `groupPolicy: "allowlist"`;如果你的群组允许列表为空,群组消息将被阻止。
快速心智模型(群组消息的评估顺序):
1. `groupPolicy`open/disabled/allowlist
2. 群组允许列表(`*.groups``*.groupAllowFrom`、渠道特定允许列表)
3. 提及限制(`requireMention``/activation`
## 提及限制(默认)
群组消息需要提及,除非按群组覆盖。默认值位于 `*.groups."*"` 下的每个子系统中。
回复机器人消息被视为隐式提及(当渠道支持回复元数据时)。这适用于 Telegram、WhatsApp、Slack、Discord 和 Microsoft Teams。
```json5
{
channels: {
whatsapp: {
groups: {
"*": { requireMention: true },
"123@g.us": { requireMention: false },
},
},
telegram: {
groups: {
"*": { requireMention: true },
"123456789": { requireMention: false },
},
},
imessage: {
groups: {
"*": { requireMention: true },
"123": { requireMention: false },
},
},
},
agents: {
list: [
{
id: "main",
groupChat: {
mentionPatterns: ["@openclaw", "openclaw", "\\+15555550123"],
historyLimit: 50,
},
},
],
},
}
```
注意事项:
- `mentionPatterns` 是不区分大小写的正则表达式。
- 提供显式提及的平台仍然通过;模式是回退。
- 每个智能体覆盖:`agents.list[].groupChat.mentionPatterns`(当多个智能体共享一个群组时有用)。
- 提及限制仅在提及检测可行时强制执行(原生提及或 `mentionPatterns` 已配置)。
- Discord 默认值位于 `channels.discord.guilds."*"`(可按服务器/频道覆盖)。
- 群组历史上下文在渠道间统一包装,并且是**仅待处理**(由于提及限制而跳过的消息);使用 `messages.groupChat.historyLimit` 作为全局默认值,使用 `channels.<channel>.historyLimit`(或 `channels.<channel>.accounts.*.historyLimit`)进行覆盖。设置 `0` 以禁用。
## 群组/频道工具限制(可选)
某些渠道配置支持限制**特定群组/房间/频道内**可用的工具。
- `tools`:为整个群组允许/拒绝工具。
- `toolsBySender`:群组内的按发送者覆盖(键是发送者 ID/用户名/邮箱/电话号码,取决于渠道)。使用 `"*"` 作为通配符。
解析顺序(最具体的优先):
1. 群组/频道 `toolsBySender` 匹配
2. 群组/频道 `tools`
3. 默认(`"*"``toolsBySender` 匹配
4. 默认(`"*"``tools`
示例Telegram
```json5
{
channels: {
telegram: {
groups: {
"*": { tools: { deny: ["exec"] } },
"-1001234567890": {
tools: { deny: ["exec", "read", "write"] },
toolsBySender: {
"123456789": { alsoAllow: ["exec"] },
},
},
},
},
},
}
```
注意事项:
- 群组/频道工具限制在全局/智能体工具策略之外额外应用deny 仍然优先)。
- 某些渠道对房间/频道使用不同的嵌套结构例如Discord `guilds.*.channels.*`、Slack `channels.*`、MS Teams `teams.*.channels.*`)。
## 群组允许列表
当配置了 `channels.whatsapp.groups``channels.telegram.groups``channels.imessage.groups` 时,键作为群组允许列表。使用 `"*"` 允许所有群组,同时仍设置默认提及行为。
常见意图(复制/粘贴):
1. 禁用所有群组回复
```json5
{
channels: { whatsapp: { groupPolicy: "disabled" } },
}
```
2. 仅允许特定群组WhatsApp
```json5
{
channels: {
whatsapp: {
groups: {
"123@g.us": { requireMention: true },
"456@g.us": { requireMention: false },
},
},
},
}
```
3. 允许所有群组但需要提及(显式)
```json5
{
channels: {
whatsapp: {
groups: { "*": { requireMention: true } },
},
},
}
```
4. 仅所有者可以在群组中触发WhatsApp
```json5
{
channels: {
whatsapp: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15551234567"],
groups: { "*": { requireMention: true } },
},
},
}
```
## 激活(仅所有者)
群组所有者可以切换每个群组的激活状态:
- `/activation mention`
- `/activation always`
所有者由 `channels.whatsapp.allowFrom` 确定(未设置时为机器人自身的 E.164)。将命令作为独立消息发送。其他平台目前忽略 `/activation`
## 上下文字段
群组入站负载设置:
- `ChatType=group`
- `GroupSubject`(如果已知)
- `GroupMembers`(如果已知)
- `WasMentioned`(提及限制结果)
- Telegram 论坛话题还包括 `MessageThreadId``IsForum`
智能体系统提示在新群组会话的第一轮包含群组介绍。它提醒模型像人类一样回复,避免 Markdown 表格,避免输入字面量 `\n` 序列。
## iMessage 特定内容
- 路由或允许列表时优先使用 `chat_id:<id>`
- 列出聊天:`imsg chats --limit 20`
- 群组回复始终返回到相同的 `chat_id`
## WhatsApp 特定内容
参见[群消息](/channels/group-messages)了解 WhatsApp 专有行为(历史注入、提及处理详情)。

View File

@@ -0,0 +1,302 @@
---
read_when:
- 设置 iMessage 支持
- 调试 iMessage 发送/接收
summary: 通过 imsg基于 stdio 的 JSON-RPC实现 iMessage 支持、设置及 chat_id 路由
title: iMessage
x-i18n:
generated_at: "2026-02-03T07:44:18Z"
model: claude-opus-4-5
provider: pi
source_hash: bc19756a42ead80a0845f18c4830c3f1f40948f69b2b016a4026598cfb8fef0d
source_path: channels/imessage.md
workflow: 15
---
# iMessage (imsg)
状态:外部 CLI 集成。Gateway 网关生成 `imsg rpc`(基于 stdio 的 JSON-RPC
## 快速设置(新手)
1. 确保在此 Mac 上已登录"信息"。
2. 安装 `imsg`
- `brew install steipete/tap/imsg`
3. 配置 OpenClaw 的 `channels.imessage.cliPath``channels.imessage.dbPath`
4. 启动 Gateway 网关并批准所有 macOS 提示(自动化 + 完全磁盘访问权限)。
最小配置:
```json5
{
channels: {
imessage: {
enabled: true,
cliPath: "/usr/local/bin/imsg",
dbPath: "/Users/<you>/Library/Messages/chat.db",
},
},
}
```
## 简介
- 基于 macOS 上 `imsg` 的 iMessage 渠道。
- 确定性路由:回复始终返回到 iMessage。
- 私信共享智能体的主会话;群组是隔离的(`agent:<agentId>:imessage:group:<chat_id>`)。
- 如果多参与者会话以 `is_group=false` 到达,你仍可使用 `channels.imessage.groups``chat_id` 隔离(参见下方"类群组会话")。
## 配置写入
默认情况下iMessage 允许写入由 `/config set|unset` 触发的配置更新(需要 `commands.config: true`)。
禁用方式:
```json5
{
channels: { imessage: { configWrites: false } },
}
```
## 要求
- 已登录"信息"的 macOS。
- OpenClaw + `imsg` 的完全磁盘访问权限(访问"信息"数据库)。
- 发送时需要自动化权限。
- `channels.imessage.cliPath` 可以指向任何代理 stdin/stdout 的命令(例如,通过 SSH 连接到另一台 Mac 并运行 `imsg rpc` 的包装脚本)。
## 设置(快速路径)
1. 确保在此 Mac 上已登录"信息"。
2. 配置 iMessage 并启动 Gateway 网关。
### 专用机器人 macOS 用户(用于隔离身份)
如果你希望机器人从**独立的 iMessage 身份**发送(并保持你的个人"信息"整洁),请使用专用 Apple ID + 专用 macOS 用户。
1. 创建专用 Apple ID例如`my-cool-bot@icloud.com`)。
- Apple 可能需要电话号码进行验证 / 2FA。
2. 创建 macOS 用户(例如:`openclawhome`)并登录。
3. 在该 macOS 用户中打开"信息"并使用机器人 Apple ID 登录 iMessage。
4. 启用远程登录(系统设置 → 通用 → 共享 → 远程登录)。
5. 安装 `imsg`
- `brew install steipete/tap/imsg`
6. 设置 SSH 使 `ssh <bot-macos-user>@localhost true` 无需密码即可工作。
7.`channels.imessage.accounts.bot.cliPath` 指向以机器人用户身份运行 `imsg` 的 SSH 包装脚本。
首次运行注意事项:发送/接收可能需要在*机器人 macOS 用户*中进行 GUI 批准(自动化 + 完全磁盘访问权限)。如果 `imsg rpc` 看起来卡住或退出,请登录该用户(屏幕共享很有帮助),运行一次 `imsg chats --limit 1` / `imsg send ...`,批准提示,然后重试。
示例包装脚本(`chmod +x`)。将 `<bot-macos-user>` 替换为你的实际 macOS 用户名:
```bash
#!/usr/bin/env bash
set -euo pipefail
# Run an interactive SSH once first to accept host keys:
# ssh <bot-macos-user>@localhost true
exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T <bot-macos-user>@localhost \
"/usr/local/bin/imsg" "$@"
```
示例配置:
```json5
{
channels: {
imessage: {
enabled: true,
accounts: {
bot: {
name: "Bot",
enabled: true,
cliPath: "/path/to/imsg-bot",
dbPath: "/Users/<bot-macos-user>/Library/Messages/chat.db",
},
},
},
},
}
```
对于单账户设置,使用扁平选项(`channels.imessage.cliPath``channels.imessage.dbPath`)而不是 `accounts` 映射。
### 远程/SSH 变体(可选)
如果你想在另一台 Mac 上使用 iMessage请将 `channels.imessage.cliPath` 设置为通过 SSH 在远程 macOS 主机上运行 `imsg` 的包装脚本。OpenClaw 只需要 stdio。
示例包装脚本:
```bash
#!/usr/bin/env bash
exec ssh -T gateway-host imsg "$@"
```
**远程附件:**`cliPath` 通过 SSH 指向远程主机时,"信息"数据库中的附件路径引用的是远程机器上的文件。OpenClaw 可以通过设置 `channels.imessage.remoteHost` 自动通过 SCP 获取这些文件:
```json5
{
channels: {
imessage: {
cliPath: "~/imsg-ssh", // SSH wrapper to remote Mac
remoteHost: "user@gateway-host", // for SCP file transfer
includeAttachments: true,
},
},
}
```
如果未设置 `remoteHost`OpenClaw 会尝试通过解析包装脚本中的 SSH 命令自动检测。建议显式配置以提高可靠性。
#### 通过 Tailscale 连接远程 Mac示例
如果 Gateway 网关运行在 Linux 主机/虚拟机上但 iMessage 必须运行在 Mac 上Tailscale 是最简单的桥接方式Gateway 网关通过 tailnet 与 Mac 通信,通过 SSH 运行 `imsg`,并通过 SCP 获取附件。
架构:
```
┌──────────────────────────────┐ SSH (imsg rpc) ┌──────────────────────────┐
│ Gateway host (Linux/VM) │──────────────────────────────────▶│ Mac with Messages + imsg │
│ - openclaw gateway │ SCP (attachments) │ - Messages signed in │
│ - channels.imessage.cliPath │◀──────────────────────────────────│ - Remote Login enabled │
└──────────────────────────────┘ └──────────────────────────┘
│ Tailscale tailnet (hostname or 100.x.y.z)
user@gateway-host
```
具体配置示例Tailscale 主机名):
```json5
{
channels: {
imessage: {
enabled: true,
cliPath: "~/.openclaw/scripts/imsg-ssh",
remoteHost: "bot@mac-mini.tailnet-1234.ts.net",
includeAttachments: true,
dbPath: "/Users/bot/Library/Messages/chat.db",
},
},
}
```
示例包装脚本(`~/.openclaw/scripts/imsg-ssh`
```bash
#!/usr/bin/env bash
exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"
```
注意事项:
- 确保 Mac 已登录"信息",并已启用远程登录。
- 使用 SSH 密钥使 `ssh bot@mac-mini.tailnet-1234.ts.net` 无需提示即可工作。
- `remoteHost` 应与 SSH 目标匹配,以便 SCP 可以获取附件。
多账户支持:使用 `channels.imessage.accounts` 配置每个账户及可选的 `name`。参见 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) 了解共享模式。不要提交 `~/.openclaw/openclaw.json`(它通常包含令牌)。
## 访问控制(私信 + 群组)
私信:
- 默认:`channels.imessage.dmPolicy = "pairing"`
- 未知发送者会收到配对码;消息在批准前会被忽略(配对码在 1 小时后过期)。
- 批准方式:
- `openclaw pairing list imessage`
- `openclaw pairing approve imessage <CODE>`
- 配对是 iMessage 私信的默认令牌交换方式。详情:[配对](/channels/pairing)
群组:
- `channels.imessage.groupPolicy = open | allowlist | disabled`
- 设置 `allowlist` 时,`channels.imessage.groupAllowFrom` 控制谁可以在群组中触发。
- 提及检测使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`),因为 iMessage 没有原生提及元数据。
- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每个智能体的模式。
## 工作原理(行为)
- `imsg` 流式传输消息事件Gateway 网关将它们规范化为共享渠道信封。
- 回复始终路由回相同的 chat id 或 handle。
## 类群组会话(`is_group=false`
某些 iMessage 会话可能有多个参与者,但根据"信息"存储聊天标识符的方式,仍以 `is_group=false` 到达。
如果你在 `channels.imessage.groups` 下显式配置了 `chat_id`OpenClaw 会将该会话视为"群组"用于:
- 会话隔离(独立的 `agent:<agentId>:imessage:group:<chat_id>` 会话键)
- 群组允许列表 / 提及检测行为
示例:
```json5
{
channels: {
imessage: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: {
"42": { requireMention: false },
},
},
},
}
```
当你想为特定会话使用隔离的个性/模型时这很有用(参见[多智能体路由](/concepts/multi-agent))。关于文件系统隔离,参见[沙箱隔离](/gateway/sandboxing)。
## 媒体 + 限制
- 通过 `channels.imessage.includeAttachments` 可选附件摄取。
- 通过 `channels.imessage.mediaMaxMb` 设置媒体上限。
## 限制
- 出站文本按 `channels.imessage.textChunkLimit` 分块(默认 4000
- 可选换行分块:设置 `channels.imessage.chunkMode="newline"` 在长度分块前按空行(段落边界)分割。
- 媒体上传受 `channels.imessage.mediaMaxMb` 限制(默认 16
## 寻址 / 投递目标
优先使用 `chat_id` 进行稳定路由:
- `chat_id:123`(推荐)
- `chat_guid:...`
- `chat_identifier:...`
- 直接 handle`imessage:+1555` / `sms:+1555` / `user@example.com`
列出聊天:
```
imsg chats --limit 20
```
## 配置参考iMessage
完整配置:[配置](/gateway/configuration)
提供商选项:
- `channels.imessage.enabled`:启用/禁用渠道启动。
- `channels.imessage.cliPath``imsg` 路径。
- `channels.imessage.dbPath`"信息"数据库路径。
- `channels.imessage.remoteHost`:当 `cliPath` 指向远程 Mac 时用于 SCP 附件传输的 SSH 主机(例如 `user@gateway-host`)。如未设置则从 SSH 包装脚本自动检测。
- `channels.imessage.service``imessage | sms | auto`
- `channels.imessage.region`:短信区域。
- `channels.imessage.dmPolicy``pairing | allowlist | open | disabled`默认pairing
- `channels.imessage.allowFrom`私信允许列表handle、邮箱、E.164 号码或 `chat_id:*`)。`open` 需要 `"*"`。iMessage 没有用户名;使用 handle 或聊天目标。
- `channels.imessage.groupPolicy``open | allowlist | disabled`默认allowlist
- `channels.imessage.groupAllowFrom`:群组发送者允许列表。
- `channels.imessage.historyLimit` / `channels.imessage.accounts.*.historyLimit`作为上下文包含的最大群组消息数0 禁用)。
- `channels.imessage.dmHistoryLimit`:私信历史限制(用户轮次)。每用户覆盖:`channels.imessage.dms["<handle>"].historyLimit`
- `channels.imessage.groups`:每群组默认值 + 允许列表(使用 `"*"` 作为全局默认值)。
- `channels.imessage.includeAttachments`:将附件摄取到上下文。
- `channels.imessage.mediaMaxMb`:入站/出站媒体上限MB
- `channels.imessage.textChunkLimit`:出站分块大小(字符)。
- `channels.imessage.chunkMode``length`(默认)或 `newline` 在长度分块前按空行(段落边界)分割。
相关全局选项:
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)。
- `messages.responsePrefix`

53
content/channels/index.md Normal file
View File

@@ -0,0 +1,53 @@
---
read_when:
- 你想为 OpenClaw 选择一个聊天渠道
- 你需要快速了解支持的消息平台
summary: OpenClaw 可连接的消息平台
title: 聊天渠道
x-i18n:
generated_at: "2026-02-03T07:43:27Z"
model: claude-opus-4-5
provider: pi
source_hash: 2632863def6dee97e0fa8b931762f0969174fd4fb22303a00dcd46527fe4a141
source_path: channels/index.md
workflow: 15
---
# 聊天渠道
OpenClaw 可以在你已经使用的任何聊天应用上与你交流。每个渠道通过 Gateway 网关连接。
所有渠道都支持文本;媒体和表情回应的支持因渠道而异。
## 支持的渠道
- [WhatsApp](/channels/whatsapp) — 最受欢迎;使用 Baileys需要二维码配对。
- [Telegram](/channels/telegram) — 通过 grammY 使用 Bot API支持群组。
- [Discord](/channels/discord) — Discord Bot API + Gateway支持服务器、频道和私信。
- [Slack](/channels/slack) — Bolt SDK工作区应用。
- [飞书](/channels/feishu) — 飞书Lark机器人插件需单独安装
- [Google Chat](/channels/googlechat) — 通过 HTTP webhook 的 Google Chat API 应用。
- [Mattermost](/channels/mattermost) — Bot API + WebSocket频道、群组、私信插件需单独安装
- [Signal](/channels/signal) — signal-cli注重隐私。
- [BlueBubbles](/channels/bluebubbles) — **推荐用于 iMessage**;使用 BlueBubbles macOS 服务器 REST API功能完整编辑、撤回、特效、回应、群组管理——编辑功能在 macOS 26 Tahoe 上目前不可用)。
- [iMessage旧版](/channels/imessage) — 通过 imsg CLI 的旧版 macOS 集成(已弃用,新设置请使用 BlueBubbles
- [Microsoft Teams](/channels/msteams) — Bot Framework企业支持插件需单独安装
- [LINE](/channels/line) — LINE Messaging API 机器人(插件,需单独安装)。
- [Nextcloud Talk](/channels/nextcloud-talk) — 通过 Nextcloud Talk 的自托管聊天(插件,需单独安装)。
- [Matrix](/channels/matrix) — Matrix 协议(插件,需单独安装)。
- [Nostr](/channels/nostr) — 通过 NIP-04 的去中心化私信(插件,需单独安装)。
- [Tlon](/channels/tlon) — 基于 Urbit 的消息应用(插件,需单独安装)。
- [Twitch](/channels/twitch) — 通过 IRC 连接的 Twitch 聊天(插件,需单独安装)。
- [Zalo](/channels/zalo) — Zalo Bot API越南流行的消息应用插件需单独安装
- [Zalo Personal](/channels/zalouser) — 通过二维码登录的 Zalo 个人账号(插件,需单独安装)。
- [WebChat](/web/webchat) — 基于 WebSocket 的 Gateway 网关 WebChat 界面。
## 注意事项
- 渠道可以同时运行配置多个渠道后OpenClaw 会按聊天进行路由。
- 最快的设置方式通常是 **Telegram**简单的机器人令牌。WhatsApp 需要二维码配对,
并在磁盘上存储更多状态。
- 群组行为因渠道而异;参见[群组](/channels/groups)。
- 为安全起见,私信配对和允许列表会被强制执行;参见[安全](/gateway/security)。
- Telegram 内部机制:[grammY 说明](/channels/grammy)。
- 故障排除:[渠道故障排除](/channels/troubleshooting)。
- 模型提供商单独记录;参见[模型提供商](/providers/models)。

241
content/channels/irc.md Normal file
View File

@@ -0,0 +1,241 @@
---
title: IRC
description: Connect OpenClaw to IRC channels and direct messages.
summary: "IRC plugin setup, access controls, and troubleshooting"
read_when:
- You want to connect OpenClaw to IRC channels or DMs
- You are configuring IRC allowlists, group policy, or mention gating
---
Use IRC when you want OpenClaw in classic channels (`#room`) and direct messages.
IRC ships as an extension plugin, but it is configured in the main config under `channels.irc`.
## Quick start
1. Enable IRC config in `~/.openclaw/openclaw.json`.
2. Set at least:
```json
{
"channels": {
"irc": {
"enabled": true,
"host": "irc.libera.chat",
"port": 6697,
"tls": true,
"nick": "openclaw-bot",
"channels": ["#openclaw"]
}
}
}
```
3. Start/restart gateway:
```bash
openclaw gateway run
```
## Security defaults
- `channels.irc.dmPolicy` defaults to `"pairing"`.
- `channels.irc.groupPolicy` defaults to `"allowlist"`.
- With `groupPolicy="allowlist"`, set `channels.irc.groups` to define allowed channels.
- Use TLS (`channels.irc.tls=true`) unless you intentionally accept plaintext transport.
## Access control
There are two separate “gates” for IRC channels:
1. **Channel access** (`groupPolicy` + `groups`): whether the bot accepts messages from a channel at all.
2. **Sender access** (`groupAllowFrom` / per-channel `groups["#channel"].allowFrom`): who is allowed to trigger the bot inside that channel.
Config keys:
- DM allowlist (DM sender access): `channels.irc.allowFrom`
- Group sender allowlist (channel sender access): `channels.irc.groupAllowFrom`
- Per-channel controls (channel + sender + mention rules): `channels.irc.groups["#channel"]`
- `channels.irc.groupPolicy="open"` allows unconfigured channels (**still mention-gated by default**)
Allowlist entries should use stable sender identities (`nick!user@host`).
Bare nick matching is mutable and only enabled when `channels.irc.dangerouslyAllowNameMatching: true`.
### Common gotcha: `allowFrom` is for DMs, not channels
If you see logs like:
- `irc: drop group sender alice!ident@host (policy=allowlist)`
…it means the sender wasnt allowed for **group/channel** messages. Fix it by either:
- setting `channels.irc.groupAllowFrom` (global for all channels), or
- setting per-channel sender allowlists: `channels.irc.groups["#channel"].allowFrom`
Example (allow anyone in `#tuirc-dev` to talk to the bot):
```json5
{
channels: {
irc: {
groupPolicy: "allowlist",
groups: {
"#tuirc-dev": { allowFrom: ["*"] },
},
},
},
}
```
## Reply triggering (mentions)
Even if a channel is allowed (via `groupPolicy` + `groups`) and the sender is allowed, OpenClaw defaults to **mention-gating** in group contexts.
That means you may see logs like `drop channel … (missing-mention)` unless the message includes a mention pattern that matches the bot.
To make the bot reply in an IRC channel **without needing a mention**, disable mention gating for that channel:
```json5
{
channels: {
irc: {
groupPolicy: "allowlist",
groups: {
"#tuirc-dev": {
requireMention: false,
allowFrom: ["*"],
},
},
},
},
}
```
Or to allow **all** IRC channels (no per-channel allowlist) and still reply without mentions:
```json5
{
channels: {
irc: {
groupPolicy: "open",
groups: {
"*": { requireMention: false, allowFrom: ["*"] },
},
},
},
}
```
## Security note (recommended for public channels)
If you allow `allowFrom: ["*"]` in a public channel, anyone can prompt the bot.
To reduce risk, restrict tools for that channel.
### Same tools for everyone in the channel
```json5
{
channels: {
irc: {
groups: {
"#tuirc-dev": {
allowFrom: ["*"],
tools: {
deny: ["group:runtime", "group:fs", "gateway", "nodes", "cron", "browser"],
},
},
},
},
},
}
```
### Different tools per sender (owner gets more power)
Use `toolsBySender` to apply a stricter policy to `"*"` and a looser one to your nick:
```json5
{
channels: {
irc: {
groups: {
"#tuirc-dev": {
allowFrom: ["*"],
toolsBySender: {
"*": {
deny: ["group:runtime", "group:fs", "gateway", "nodes", "cron", "browser"],
},
"id:eigen": {
deny: ["gateway", "nodes", "cron"],
},
},
},
},
},
},
}
```
注意事项:
- `toolsBySender` keys should use `id:` for IRC sender identity values:
`id:eigen` or `id:eigen!~eigen@174.127.248.171` for stronger matching.
- Legacy unprefixed keys are still accepted and matched as `id:` only.
- The first matching sender policy wins; `"*"` is the wildcard fallback.
For more on group access vs mention-gating (and how they interact), see: [/channels/groups](/channels/groups).
## NickServ
To identify with NickServ after connect:
```json
{
"channels": {
"irc": {
"nickserv": {
"enabled": true,
"service": "NickServ",
"password": "your-nickserv-password"
}
}
}
}
```
Optional one-time registration on connect:
```json
{
"channels": {
"irc": {
"nickserv": {
"register": true,
"registerEmail": "bot@example.com"
}
}
}
}
```
Disable `register` after the nick is registered to avoid repeated REGISTER attempts.
## Environment variables
Default account supports:
- `IRC_HOST`
- `IRC_PORT`
- `IRC_TLS`
- `IRC_NICK`
- `IRC_USERNAME`
- `IRC_REALNAME`
- `IRC_PASSWORD`
- `IRC_CHANNELS` (comma-separated)
- `IRC_NICKSERV_PASSWORD`
- `IRC_NICKSERV_REGISTER_EMAIL`
## Troubleshooting
- If the bot connects but never replies in channels, verify `channels.irc.groups` **and** whether mention-gating is dropping messages (`missing-mention`). If you want it to reply without pings, set `requireMention:false` for the channel.
- If login fails, verify nick availability and server password.
- If TLS fails on a custom network, verify host/port and certificate setup.

180
content/channels/line.md Normal file
View File

@@ -0,0 +1,180 @@
---
read_when:
- 你想将 OpenClaw 连接到 LINE
- 你需要配置 LINE webhook + 凭证
- 你想了解 LINE 特有的消息选项
summary: LINE Messaging API 插件的配置、设置和使用方法
title: LINE
x-i18n:
generated_at: "2026-02-03T07:43:38Z"
model: claude-opus-4-5
provider: pi
source_hash: 8fbac126786f95b9454f3cc61906c2798393a8d7914e787d3755c020c7ab2da6
source_path: channels/line.md
workflow: 15
---
# LINE插件
LINE 通过 LINE Messaging API 连接到 OpenClaw。该插件作为 webhook 接收器在 Gateway 网关上运行,使用你的 channel access token + channel secret 进行身份验证。
状态通过插件支持。支持私信、群聊、媒体、位置、Flex 消息、模板消息和快捷回复。不支持表情回应和话题回复。
## 需要安装插件
安装 LINE 插件:
```bash
openclaw plugins install @openclaw/line
```
本地检出(从 git 仓库运行时):
```bash
openclaw plugins install ./extensions/line
```
## 配置步骤
1. 创建 LINE Developers 账户并打开控制台:
https://developers.line.biz/console/
2. 创建(或选择)一个 Provider 并添加 **Messaging API** 渠道。
3. 从渠道设置中复制 **Channel access token****Channel secret**
4. 在 Messaging API 设置中启用 **Use webhook**
5. 将 webhook URL 设置为你的 Gateway 网关端点(必须使用 HTTPS
```
https://gateway-host/line/webhook
```
Gateway 网关会响应 LINE 的 webhook 验证GET和入站事件POST。如果你需要自定义路径请设置 `channels.line.webhookPath``channels.line.accounts.<id>.webhookPath` 并相应更新 URL。
## 配置
最小配置:
```json5
{
channels: {
line: {
enabled: true,
channelAccessToken: "LINE_CHANNEL_ACCESS_TOKEN",
channelSecret: "LINE_CHANNEL_SECRET",
dmPolicy: "pairing",
},
},
}
```
环境变量(仅限默认账户):
- `LINE_CHANNEL_ACCESS_TOKEN`
- `LINE_CHANNEL_SECRET`
Token/secret 文件:
```json5
{
channels: {
line: {
tokenFile: "/path/to/line-token.txt",
secretFile: "/path/to/line-secret.txt",
},
},
}
```
多账户配置:
```json5
{
channels: {
line: {
accounts: {
marketing: {
channelAccessToken: "...",
channelSecret: "...",
webhookPath: "/line/marketing",
},
},
},
},
}
```
## 访问控制
私信默认使用配对模式。未知发送者会收到配对码,其消息在获得批准前会被忽略。
```bash
openclaw pairing list line
openclaw pairing approve line <CODE>
```
允许列表和策略:
- `channels.line.dmPolicy``pairing | allowlist | open | disabled`
- `channels.line.allowFrom`:私信的允许列表 LINE 用户 ID
- `channels.line.groupPolicy``allowlist | open | disabled`
- `channels.line.groupAllowFrom`:群组的允许列表 LINE 用户 ID
- 单群组覆盖:`channels.line.groups.<groupId>.allowFrom`
LINE ID 区分大小写。有效 ID 格式如下:
- 用户:`U` + 32 位十六进制字符
- 群组:`C` + 32 位十六进制字符
- 房间:`R` + 32 位十六进制字符
## 消息行为
- 文本按 5000 字符分块。
- Markdown 格式会被移除;代码块和表格会尽可能转换为 Flex 卡片。
- 流式响应会被缓冲智能体处理时LINE 会收到完整分块并显示加载动画。
- 媒体下载受 `channels.line.mediaMaxMb` 限制(默认 10
## 渠道数据(富消息)
使用 `channelData.line` 发送快捷回复、位置、Flex 卡片或模板消息。
```json5
{
text: "Here you go",
channelData: {
line: {
quickReplies: ["Status", "Help"],
location: {
title: "Office",
address: "123 Main St",
latitude: 35.681236,
longitude: 139.767125,
},
flexMessage: {
altText: "Status card",
contents: {
/* Flex payload */
},
},
templateMessage: {
type: "confirm",
text: "Proceed?",
confirmLabel: "Yes",
confirmData: "yes",
cancelLabel: "No",
cancelData: "no",
},
},
},
}
```
LINE 插件还提供 `/card` 命令用于 Flex 消息预设:
```
/card info "Welcome" "Thanks for joining!"
```
## 故障排除
- **Webhook 验证失败:** 确保 webhook URL 使用 HTTPS 且 `channelSecret` 与 LINE 控制台中的一致。
- **没有入站事件:** 确认 webhook 路径与 `channels.line.webhookPath` 匹配,且 Gateway 网关可从 LINE 访问。
- **媒体下载错误:** 如果媒体超过默认限制,请提高 `channels.line.mediaMaxMb`

View File

@@ -0,0 +1,63 @@
---
read_when:
- 添加或修改渠道位置解析
- 在智能体提示或工具中使用位置上下文字段
summary: 入站渠道位置解析Telegram + WhatsApp及上下文字段
title: 渠道位置解析
x-i18n:
generated_at: "2026-02-01T19:21:46Z"
model: claude-opus-4-5
provider: pi
source_hash: 5602ef105c3da7e47497bfed8fc343dd8d7f3c019ff7e423a08b25092c5a1837
source_path: channels/location.md
workflow: 14
---
# 渠道位置解析
OpenClaw 将聊天渠道中分享的位置标准化为:
- 附加到入站消息体的可读文本,以及
- 自动回复上下文负载中的结构化字段。
目前支持:
- **Telegram**(位置图钉 + 地点 + 实时位置)
- **WhatsApp**locationMessage + liveLocationMessage
- **Matrix**`m.location` 配合 `geo_uri`
## 文本格式
位置以友好的行格式呈现,不带括号:
- 图钉:
- `📍 48.858844, 2.294351 ±12m`
- 命名地点:
- `📍 Eiffel Tower — Champ de Mars, Paris (48.858844, 2.294351 ±12m)`
- 实时分享:
- `🛰 Live location: 48.858844, 2.294351 ±12m`
如果渠道包含标题/评论,会附加在下一行:
```
📍 48.858844, 2.294351 ±12m
Meet here
```
## 上下文字段
当存在位置信息时,以下字段会被添加到 `ctx` 中:
- `LocationLat`(数字)
- `LocationLon`(数字)
- `LocationAccuracy`(数字,米;可选)
- `LocationName`(字符串;可选)
- `LocationAddress`(字符串;可选)
- `LocationSource``pin | place | live`
- `LocationIsLive`(布尔值)
## 渠道说明
- **Telegram**:地点映射到 `LocationName/LocationAddress`;实时位置使用 `live_period`
- **WhatsApp**`locationMessage.comment``liveLocationMessage.caption` 作为标题行附加。
- **Matrix**`geo_uri` 解析为图钉位置;忽略海拔高度,`LocationIsLive` 始终为 false。

221
content/channels/matrix.md Normal file
View File

@@ -0,0 +1,221 @@
---
read_when:
- 开发 Matrix 渠道功能
summary: Matrix 支持状态、功能和配置
title: Matrix
x-i18n:
generated_at: "2026-02-03T07:44:02Z"
model: claude-opus-4-5
provider: pi
source_hash: b276b5263593c766e7be6549abbb27927177e7b51cfd297b4825965372513ee4
source_path: channels/matrix.md
workflow: 15
---
# Matrix插件
Matrix 是一个开放的去中心化消息协议。OpenClaw 以 Matrix **用户**身份连接到任意主服务器,因此你需要为机器人创建一个 Matrix 账户。登录后你可以直接私信机器人或邀请它加入房间Matrix"群组"。Beeper 也是一个有效的客户端选项,但它需要启用 E2EE。
状态:通过插件(@vector-im/matrix-bot-sdk支持。支持私信、房间、话题、媒体、表情回应、投票发送 + poll-start 作为文本)、位置和 E2EE需要加密支持
## 需要插件
Matrix 作为插件提供,不包含在核心安装中。
通过 CLI 安装npm 仓库):
```bash
openclaw plugins install @openclaw/matrix
```
本地检出(从 git 仓库运行时):
```bash
openclaw plugins install ./extensions/matrix
```
如果你在配置/新手引导期间选择 Matrix 并检测到 git 检出OpenClaw 将自动提供本地安装路径。
详情:[插件](/tools/plugin)
## 设置
1. 安装 Matrix 插件:
- 从 npm`openclaw plugins install @openclaw/matrix`
- 从本地检出:`openclaw plugins install ./extensions/matrix`
2. 在主服务器上创建 Matrix 账户:
- 在 [https://matrix.org/ecosystem/hosting/](https://matrix.org/ecosystem/hosting/) 浏览托管选项
- 或自行托管。
3. 获取机器人账户的访问令牌:
- 在你的主服务器上使用 `curl` 调用 Matrix 登录 API
```bash
curl --request POST \
--url https://matrix.example.org/_matrix/client/v3/login \
--header 'Content-Type: application/json' \
--data '{
"type": "m.login.password",
"identifier": {
"type": "m.id.user",
"user": "your-user-name"
},
"password": "your-password"
}'
```
- 将 `matrix.example.org` 替换为你的主服务器 URL。
- 或设置 `channels.matrix.userId` + `channels.matrix.password`OpenClaw 会调用相同的登录端点,将访问令牌存储在 `~/.openclaw/credentials/matrix/credentials.json`,并在下次启动时重用。
4. 配置凭证:
- 环境变量:`MATRIX_HOMESERVER`、`MATRIX_ACCESS_TOKEN`(或 `MATRIX_USER_ID` + `MATRIX_PASSWORD`
- 或配置:`channels.matrix.*`
- 如果两者都设置,配置优先。
- 使用访问令牌时:用户 ID 通过 `/whoami` 自动获取。
- 设置时,`channels.matrix.userId` 应为完整的 Matrix ID示例`@bot:example.org`)。
5. 重启 Gateway 网关(或完成新手引导)。
6. 从任何 Matrix 客户端Element、Beeper 等;参见 https://matrix.org/ecosystem/clients/与机器人开始私信或邀请它加入房间。Beeper 需要 E2EE因此请设置 `channels.matrix.encryption: true` 并验证设备。
最小配置(访问令牌,用户 ID 自动获取):
```json5
{
channels: {
matrix: {
enabled: true,
homeserver: "https://matrix.example.org",
accessToken: "syt_***",
dm: { policy: "pairing" },
},
},
}
```
E2EE 配置(启用端到端加密):
```json5
{
channels: {
matrix: {
enabled: true,
homeserver: "https://matrix.example.org",
accessToken: "syt_***",
encryption: true,
dm: { policy: "pairing" },
},
},
}
```
## 加密E2EE
通过 Rust 加密 SDK **支持**端到端加密。
使用 `channels.matrix.encryption: true` 启用:
- 如果加密模块加载成功,加密房间会自动解密。
- 发送到加密房间时,出站媒体会被加密。
- 首次连接时OpenClaw 会向你的其他会话请求设备验证。
- 在另一个 Matrix 客户端Element 等)中验证设备以启用密钥共享。
- 如果无法加载加密模块E2EE 将被禁用加密房间将无法解密OpenClaw 会记录警告。
- 如果你看到缺少加密模块的错误(例如 `@matrix-org/matrix-sdk-crypto-nodejs-*`),请允许 `@matrix-org/matrix-sdk-crypto-nodejs` 的构建脚本并运行 `pnpm rebuild @matrix-org/matrix-sdk-crypto-nodejs`,或使用 `node node_modules/@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js` 获取二进制文件。
加密状态按账户 + 访问令牌存储在 `~/.openclaw/matrix/accounts/<account>/<homeserver>__<user>/<token-hash>/crypto/`SQLite 数据库)。同步状态存储在同目录的 `bot-storage.json` 中。如果访问令牌(设备)更改,将创建新的存储,机器人必须重新验证才能访问加密房间。
**设备验证:**
启用 E2EE 时,机器人将在启动时向你的其他会话请求验证。打开 Element或其他客户端并批准验证请求以建立信任。验证后机器人可以解密加密房间中的消息。
## 路由模型
- 回复始终返回到 Matrix。
- 私信共享智能体的主会话;房间映射到群组会话。
## 访问控制(私信)
- 默认:`channels.matrix.dm.policy = "pairing"`。未知发送者会收到配对码。
- 通过以下方式批准:
- `openclaw pairing list matrix`
- `openclaw pairing approve matrix <CODE>`
- 公开私信:`channels.matrix.dm.policy="open"` 加上 `channels.matrix.dm.allowFrom=["*"]`。
- `channels.matrix.dm.allowFrom` 仅接受完整 Matrix 用户 ID例如 `@user:server`)。向导仅在目录搜索得到唯一精确匹配时将显示名称解析为用户 ID。
## 房间(群组)
- 默认:`channels.matrix.groupPolicy = "allowlist"`(提及门控)。使用 `channels.defaults.groupPolicy` 在未设置时覆盖默认值。
- 使用 `channels.matrix.groups` 配置房间允许列表(房间 ID 或别名;名称仅在目录搜索得到唯一精确匹配时解析为 ID
```json5
{
channels: {
matrix: {
groupPolicy: "allowlist",
groups: {
"!roomId:example.org": { allow: true },
"#alias:example.org": { allow: true },
},
groupAllowFrom: ["@owner:example.org"],
},
},
}
```
- `requireMention: false` 启用该房间的自动回复。
- `groups."*"` 可以设置跨房间的提及门控默认值。
- `groupAllowFrom` 限制哪些发送者可以在房间中触发机器人(需完整 Matrix 用户 ID
- 每个房间的 `users` 允许列表可以进一步限制特定房间内的发送者(需完整 Matrix 用户 ID
- 配置向导会提示输入房间允许列表(房间 ID、别名或名称仅在精确且唯一匹配时解析名称。
- 启动时OpenClaw 将允许列表中的房间/用户名称解析为 ID 并记录映射;未解析的条目不会参与允许列表匹配。
- 默认自动加入邀请;使用 `channels.matrix.autoJoin` 和 `channels.matrix.autoJoinAllowlist` 控制。
- 要**禁止所有房间**,设置 `channels.matrix.groupPolicy: "disabled"`(或保持空的允许列表)。
- 旧版键名:`channels.matrix.rooms`(与 `groups` 相同的结构)。
## 话题
- 支持回复话题。
- `channels.matrix.threadReplies` 控制回复是否保持在话题中:
- `off`、`inbound`(默认)、`always`
- `channels.matrix.replyToMode` 控制不在话题中回复时的 reply-to 元数据:
- `off`(默认)、`first`、`all`
## 功能
| 功能 | 状态 |
| -------- | ------------------------------------------------------ |
| 私信 | ✅ 支持 |
| 房间 | ✅ 支持 |
| 话题 | ✅ 支持 |
| 媒体 | ✅ 支持 |
| E2EE | ✅ 支持(需要加密模块) |
| 表情回应 | ✅ 支持(通过工具发送/读取) |
| 投票 | ✅ 支持发送;入站投票开始转换为文本(响应/结束被忽略) |
| 位置 | ✅ 支持geo URI忽略海拔 |
| 原生命令 | ✅ 支持 |
## 配置参考Matrix
完整配置:[配置](/gateway/configuration)
提供商选项:
- `channels.matrix.enabled`:启用/禁用渠道启动。
- `channels.matrix.homeserver`:主服务器 URL。
- `channels.matrix.userId`Matrix 用户 ID使用访问令牌时可选
- `channels.matrix.accessToken`:访问令牌。
- `channels.matrix.password`:登录密码(令牌会被存储)。
- `channels.matrix.deviceName`:设备显示名称。
- `channels.matrix.encryption`:启用 E2EE默认false
- `channels.matrix.initialSyncLimit`:初始同步限制。
- `channels.matrix.threadReplies``off | inbound | always`默认inbound
- `channels.matrix.textChunkLimit`:出站文本分块大小(字符)。
- `channels.matrix.chunkMode``length`(默认)或 `newline` 在长度分块前按空行(段落边界)分割。
- `channels.matrix.dm.policy``pairing | allowlist | open | disabled`默认pairing
- `channels.matrix.dm.allowFrom`:私信允许列表(需完整 Matrix 用户 ID。`open` 需要 `"*"`。向导在可能时将名称解析为 ID。
- `channels.matrix.groupPolicy``allowlist | open | disabled`默认allowlist
- `channels.matrix.groupAllowFrom`:群组消息的允许发送者列表(需完整 Matrix 用户 ID
- `channels.matrix.allowlistOnly`:强制私信 + 房间使用允许列表规则。
- `channels.matrix.groups`:群组允许列表 + 每个房间的设置映射。
- `channels.matrix.rooms`:旧版群组允许列表/配置。
- `channels.matrix.replyToMode`:话题/标签的 reply-to 模式。
- `channels.matrix.mediaMaxMb`:入站/出站媒体上限MB
- `channels.matrix.autoJoin`:邀请处理(`always | allowlist | off`默认always
- `channels.matrix.autoJoinAllowlist`:自动加入的允许房间 ID/别名。
- `channels.matrix.actions`每个操作的工具限制reactions/messages/pins/memberInfo/channelInfo

View File

@@ -0,0 +1,144 @@
---
read_when:
- 设置 Mattermost
- 调试 Mattermost 路由
summary: Mattermost 机器人设置和 OpenClaw 配置
title: Mattermost
x-i18n:
generated_at: "2026-02-03T07:43:43Z"
model: claude-opus-4-5
provider: pi
source_hash: 57fabe5eb0efbcb885f4178b317b2fa99a41daf609e3a471de2b44db9def4ad7
source_path: channels/mattermost.md
workflow: 15
---
# Mattermost插件
状态通过插件支持bot token + WebSocket 事件)。支持频道、群组和私信。
Mattermost 是一个可自托管的团队消息平台;有关产品详情和下载,请访问官方网站
[mattermost.com](https://mattermost.com)。
## 需要插件
Mattermost 以插件形式提供,不包含在核心安装中。
通过 CLI 安装npm 注册表):
```bash
openclaw plugins install @openclaw/mattermost
```
本地检出(从 git 仓库运行时):
```bash
openclaw plugins install ./extensions/mattermost
```
如果你在配置/新手引导期间选择 Mattermost 并检测到 git 检出OpenClaw 会自动提供本地安装路径。
详情:[插件](/tools/plugin)
## 快速设置
1. 安装 Mattermost 插件。
2. 创建 Mattermost bot 账户并复制 **bot token**
3. 复制 Mattermost **基础 URL**(例如 `https://chat.example.com`)。
4. 配置 OpenClaw 并启动 Gateway 网关。
最小配置:
```json5
{
channels: {
mattermost: {
enabled: true,
botToken: "mm-token",
baseUrl: "https://chat.example.com",
dmPolicy: "pairing",
},
},
}
```
## 环境变量(默认账户)
如果你偏好使用环境变量,请在 Gateway 网关主机上设置:
- `MATTERMOST_BOT_TOKEN=...`
- `MATTERMOST_URL=https://chat.example.com`
环境变量仅适用于**默认**账户(`default`)。其他账户必须使用配置值。
## 聊天模式
Mattermost 自动响应私信。频道行为由 `chatmode` 控制:
- `oncall`(默认):仅在频道中被 @提及时响应
- `onmessage`:响应每条频道消息。
- `onchar`:当消息以触发前缀开头时响应。
配置示例:
```json5
{
channels: {
mattermost: {
chatmode: "onchar",
oncharPrefixes: [">", "!"],
},
},
}
```
注意事项:
- `onchar` 仍会响应显式 @提及
- `channels.mattermost.requireMention` 对旧配置仍然有效,但推荐使用 `chatmode`
## 访问控制(私信)
- 默认:`channels.mattermost.dmPolicy = "pairing"`(未知发送者会收到配对码)。
- 通过以下方式批准:
- `openclaw pairing list mattermost`
- `openclaw pairing approve mattermost <CODE>`
- 公开私信:`channels.mattermost.dmPolicy="open"` 加上 `channels.mattermost.allowFrom=["*"]`
## 频道(群组)
- 默认:`channels.mattermost.groupPolicy = "allowlist"`(提及限制)。
- 使用 `channels.mattermost.groupAllowFrom` 将发送者加入允许列表(用户 ID 或 `@username`)。
- 开放频道:`channels.mattermost.groupPolicy="open"`(提及限制)。
## 出站投递目标
`openclaw message send` 或 cron/webhooks 中使用这些目标格式:
- `channel:<id>` 用于频道
- `user:<id>` 用于私信
- `@username` 用于私信(通过 Mattermost API 解析)
裸 ID 被视为频道。
## 多账户
Mattermost 支持在 `channels.mattermost.accounts` 下配置多个账户:
```json5
{
channels: {
mattermost: {
accounts: {
default: { name: "Primary", botToken: "mm-token", baseUrl: "https://chat.example.com" },
alerts: { name: "Alerts", botToken: "mm-token-2", baseUrl: "https://alerts.example.com" },
},
},
},
}
```
## 故障排除
- 频道中无回复:确保 bot 在频道中并提及它oncall使用触发前缀onchar或设置 `chatmode: "onmessage"`
- 认证错误:检查 bot token、基础 URL 以及账户是否已启用。
- 多账户问题:环境变量仅适用于 `default` 账户。

775
content/channels/msteams.md Normal file
View File

@@ -0,0 +1,775 @@
---
read_when:
- 开发 MS Teams 渠道功能
summary: Microsoft Teams 机器人支持状态、功能和配置
title: Microsoft Teams
x-i18n:
generated_at: "2026-02-03T07:46:52Z"
model: claude-opus-4-5
provider: pi
source_hash: 2046cb8fa3dd349f4b25a40c013a87188af8f75c1886a782698bff2bb9f70971
source_path: channels/msteams.md
workflow: 15
---
# Microsoft Teams插件
> "进入此地者,放弃一切希望。"
更新时间2026-01-21
状态:支持文本 + 私信附件;频道/群组文件发送需要 `sharePointSiteId` + Graph 权限(参见[在群聊中发送文件](#sending-files-in-group-chats))。投票通过 Adaptive Cards 发送。
## 需要插件
Microsoft Teams 作为插件提供,不包含在核心安装中。
**破坏性变更2026.1.15** MS Teams 已从核心移出。如果你使用它,必须安装插件。
原因说明:保持核心安装更轻量,并让 MS Teams 依赖项可以独立更新。
通过 CLI 安装npm 注册表):
```bash
openclaw plugins install @openclaw/msteams
```
本地检出(从 git 仓库运行时):
```bash
openclaw plugins install ./extensions/msteams
```
如果你在配置/新手引导过程中选择 Teams 并检测到 git 检出,
OpenClaw 将自动提供本地安装路径。
详情:[插件](/tools/plugin)
## 快速设置(初学者)
1. 安装 Microsoft Teams 插件。
2. 创建一个 **Azure Bot**App ID + 客户端密钥 + 租户 ID
3. 使用这些凭证配置 OpenClaw。
4. 通过公共 URL 或隧道暴露 `/api/messages`(默认端口 3978
5. 安装 Teams 应用包并启动 Gateway 网关。
最小配置:
```json5
{
channels: {
msteams: {
enabled: true,
appId: "<APP_ID>",
appPassword: "<APP_PASSWORD>",
tenantId: "<TENANT_ID>",
webhook: { port: 3978, path: "/api/messages" },
},
},
}
```
注意:群聊默认被阻止(`channels.msteams.groupPolicy: "allowlist"`)。要允许群组回复,请设置 `channels.msteams.groupAllowFrom`(或使用 `groupPolicy: "open"` 允许任何成员,需要提及才能触发)。
## 目标
- 通过 Teams 私信、群聊或频道与 OpenClaw 交流。
- 保持路由确定性:回复始终返回到消息到达的渠道。
- 默认使用安全的渠道行为(除非另有配置,否则需要提及)。
## 配置写入
默认情况下Microsoft Teams 允许通过 `/config set|unset` 触发的配置更新写入(需要 `commands.config: true`)。
禁用方式:
```json5
{
channels: { msteams: { configWrites: false } },
}
```
## 访问控制(私信 + 群组)
**私信访问**
- 默认:`channels.msteams.dmPolicy = "pairing"`。未知发送者在获得批准之前将被忽略。
- `channels.msteams.allowFrom` 接受 AAD 对象 ID、UPN 或显示名称。当凭证允许时,向导会通过 Microsoft Graph 将名称解析为 ID。
**群组访问**
- 默认:`channels.msteams.groupPolicy = "allowlist"`(除非添加 `groupAllowFrom`,否则被阻止)。使用 `channels.defaults.groupPolicy` 在未设置时覆盖默认值。
- `channels.msteams.groupAllowFrom` 控制哪些发送者可以在群聊/频道中触发(回退到 `channels.msteams.allowFrom`)。
- 设置 `groupPolicy: "open"` 允许任何成员(默认仍需提及才能触发)。
- 要**不允许任何频道**,设置 `channels.msteams.groupPolicy: "disabled"`
示例:
```json5
{
channels: {
msteams: {
groupPolicy: "allowlist",
groupAllowFrom: ["user@org.com"],
},
},
}
```
**团队 + 频道允许列表**
- 通过在 `channels.msteams.teams` 下列出团队和频道来限定群组/频道回复的范围。
- 键可以是团队 ID 或名称;频道键可以是会话 ID 或名称。
-`groupPolicy="allowlist"` 且存在团队允许列表时,仅接受列出的团队/频道(需要提及才能触发)。
- 配置向导接受 `Team/Channel` 条目并为你存储。
- 启动时OpenClaw 将团队/频道和用户允许列表名称解析为 ID当 Graph 权限允许时)
并记录映射;未解析的条目保持原样。
示例:
```json5
{
channels: {
msteams: {
groupPolicy: "allowlist",
teams: {
"My Team": {
channels: {
General: { requireMention: true },
},
},
},
},
},
}
```
## 工作原理
1. 安装 Microsoft Teams 插件。
2. 创建一个 **Azure Bot**App ID + 密钥 + 租户 ID
3. 构建一个引用机器人并包含以下 RSC 权限的 **Teams 应用包**
4. 将 Teams 应用上传/安装到团队中(或用于私信的个人范围)。
5.`~/.openclaw/openclaw.json`(或环境变量)中配置 `msteams` 并启动 Gateway 网关。
6. Gateway 网关默认在 `/api/messages` 上监听 Bot Framework webhook 流量。
## Azure Bot 设置(前提条件)
在配置 OpenClaw 之前,你需要创建一个 Azure Bot 资源。
### 步骤 1创建 Azure Bot
1. 前往[创建 Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot)
2. 填写**基本信息**选项卡:
| 字段 | 值 |
| ------------------ | --------------------------------------------------- |
| **Bot handle** | 你的机器人名称,例如 `openclaw-msteams`(必须唯一) |
| **Subscription** | 选择你的 Azure 订阅 |
| **Resource group** | 新建或使用现有 |
| **Pricing tier** | **Free** 用于开发/测试 |
| **Type of App** | **Single Tenant**(推荐 - 见下方说明) |
| **Creation type** | **Create new Microsoft App ID** |
> **弃用通知:** 2025-07-31 之后已弃用创建新的多租户机器人。新机器人请使用 **Single Tenant**。
3. 点击 **Review + create****Create**(等待约 1-2 分钟)
### 步骤 2获取凭证
1. 前往你的 Azure Bot 资源 → **Configuration**
2. 复制 **Microsoft App ID** → 这是你的 `appId`
3. 点击 **Manage Password** → 前往应用注册
4.**Certificates & secrets****New client secret** → 复制 **Value** → 这是你的 `appPassword`
5. 前往 **Overview** → 复制 **Directory (tenant) ID** → 这是你的 `tenantId`
### 步骤 3配置消息端点
1. 在 Azure Bot → **Configuration**
2.**Messaging endpoint** 设置为你的 webhook URL
- 生产环境:`https://your-domain.com/api/messages`
- 本地开发:使用隧道(见下方[本地开发](#local-development-tunneling)
### 步骤 4启用 Teams 渠道
1. 在 Azure Bot → **Channels**
2. 点击 **Microsoft Teams** → Configure → Save
3. 接受服务条款
## 本地开发(隧道)
Teams 无法访问 `localhost`。本地开发请使用隧道:
**选项 Angrok**
```bash
ngrok http 3978
# 复制 https URL例如 https://abc123.ngrok.io
# 将消息端点设置为https://abc123.ngrok.io/api/messages
```
**选项 BTailscale Funnel**
```bash
tailscale funnel 3978
# 使用你的 Tailscale funnel URL 作为消息端点
```
## Teams 开发者门户(替代方案)
除了手动创建清单 ZIP你可以使用 [Teams 开发者门户](https://dev.teams.microsoft.com/apps)
1. 点击 **+ New app**
2. 填写基本信息(名称、描述、开发者信息)
3. 前往 **App features****Bot**
4. 选择 **Enter a bot ID manually** 并粘贴你的 Azure Bot App ID
5. 勾选范围:**Personal**、**Team**、**Group Chat**
6. 点击 **Distribute****Download app package**
7. 在 Teams 中:**Apps** → **Manage your apps****Upload a custom app** → 选择 ZIP
这通常比手动编辑 JSON 清单更容易。
## 测试机器人
**选项 AAzure Web Chat先验证 webhook**
1. 在 Azure 门户 → 你的 Azure Bot 资源 → **Test in Web Chat**
2. 发送一条消息 - 你应该看到响应
3. 这确认你的 webhook 端点在 Teams 设置之前正常工作
**选项 BTeams应用安装后**
1. 安装 Teams 应用(侧载或组织目录)
2. 在 Teams 中找到机器人并发送私信
3. 检查 Gateway 网关日志中的传入活动
## 设置(最小纯文本)
1. **安装 Microsoft Teams 插件**
- 从 npm`openclaw plugins install @openclaw/msteams`
- 从本地检出:`openclaw plugins install ./extensions/msteams`
2. **机器人注册**
- 创建一个 Azure Bot见上文并记录
- App ID
- 客户端密钥App password
- 租户 ID单租户
3. **Teams 应用清单**
- 包含一个 `bot` 条目,其中 `botId = <App ID>`
- 范围:`personal``team``groupChat`
- `supportsFiles: true`(个人范围文件处理所需)。
- 添加 RSC 权限(见下文)。
- 创建图标:`outline.png`32x32`color.png`192x192
- 将三个文件一起打包:`manifest.json``outline.png``color.png`
4. **配置 OpenClaw**
```json
{
"msteams": {
"enabled": true,
"appId": "<APP_ID>",
"appPassword": "<APP_PASSWORD>",
"tenantId": "<TENANT_ID>",
"webhook": { "port": 3978, "path": "/api/messages" }
}
}
```
你也可以使用环境变量代替配置键:
- `MSTEAMS_APP_ID`
- `MSTEAMS_APP_PASSWORD`
- `MSTEAMS_TENANT_ID`
5. **机器人端点**
- 将 Azure Bot Messaging Endpoint 设置为:
- `https://<host>:3978/api/messages`(或你选择的路径/端口)。
6. **运行 Gateway 网关**
- 当插件已安装且 `msteams` 配置存在并有凭证时Teams 渠道会自动启动。
## 历史上下文
- `channels.msteams.historyLimit` 控制将多少条最近的频道/群组消息包含到提示中。
- 回退到 `messages.groupChat.historyLimit`。设置 `0` 禁用(默认 50
- 私信历史可以通过 `channels.msteams.dmHistoryLimit`(用户轮次)限制。每用户覆盖:`channels.msteams.dms["<user_id>"].historyLimit`。
## 当前 Teams RSC 权限(清单)
这些是我们 Teams 应用清单中**现有的 resourceSpecific 权限**。它们仅适用于安装了应用的团队/聊天内部。
**对于频道(团队范围):**
- `ChannelMessage.Read.Group`Application- 无需 @提及即可接收所有频道消息
- `ChannelMessage.Send.Group`Application
- `Member.Read.Group`Application
- `Owner.Read.Group`Application
- `ChannelSettings.Read.Group`Application
- `TeamMember.Read.Group`Application
- `TeamSettings.Read.Group`Application
**对于群聊:**
- `ChatMessage.Read.Chat`Application- 无需 @提及即可接收所有群聊消息
## Teams 清单示例(已脱敏)
包含必需字段的最小有效示例。请替换 ID 和 URL。
```json
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json",
"manifestVersion": "1.23",
"version": "1.0.0",
"id": "00000000-0000-0000-0000-000000000000",
"name": { "short": "OpenClaw" },
"developer": {
"name": "Your Org",
"websiteUrl": "https://example.com",
"privacyUrl": "https://example.com/privacy",
"termsOfUseUrl": "https://example.com/terms"
},
"description": { "short": "OpenClaw in Teams", "full": "OpenClaw in Teams" },
"icons": { "outline": "outline.png", "color": "color.png" },
"accentColor": "#5B6DEF",
"bots": [
{
"botId": "11111111-1111-1111-1111-111111111111",
"scopes": ["personal", "team", "groupChat"],
"isNotificationOnly": false,
"supportsCalling": false,
"supportsVideo": false,
"supportsFiles": true
}
],
"webApplicationInfo": {
"id": "11111111-1111-1111-1111-111111111111"
},
"authorization": {
"permissions": {
"resourceSpecific": [
{ "name": "ChannelMessage.Read.Group", "type": "Application" },
{ "name": "ChannelMessage.Send.Group", "type": "Application" },
{ "name": "Member.Read.Group", "type": "Application" },
{ "name": "Owner.Read.Group", "type": "Application" },
{ "name": "ChannelSettings.Read.Group", "type": "Application" },
{ "name": "TeamMember.Read.Group", "type": "Application" },
{ "name": "TeamSettings.Read.Group", "type": "Application" },
{ "name": "ChatMessage.Read.Chat", "type": "Application" }
]
}
}
}
```
### 清单注意事项(必填字段)
- `bots[].botId` **必须**与 Azure Bot App ID 匹配。
- `webApplicationInfo.id` **必须**与 Azure Bot App ID 匹配。
- `bots[].scopes` 必须包含你计划使用的界面(`personal`、`team`、`groupChat`)。
- `bots[].supportsFiles: true` 是个人范围文件处理所需的。
- `authorization.permissions.resourceSpecific` 如果你需要频道流量,必须包含频道读取/发送权限。
### 更新现有应用
要更新已安装的 Teams 应用(例如,添加 RSC 权限):
1. 使用新设置更新你的 `manifest.json`
2. **增加 `version` 字段**(例如,`1.0.0` → `1.1.0`
3. **重新打包**清单和图标(`manifest.json`、`outline.png`、`color.png`
4. 上传新的 zip
- **选项 ATeams 管理中心):** Teams 管理中心 → Teams apps → Manage apps → 找到你的应用 → Upload new version
- **选项 B侧载** 在 Teams 中 → Apps → Manage your apps → Upload a custom app
5. **对于团队频道:** 在每个团队中重新安装应用以使新权限生效
6. **完全退出并重新启动 Teams**(不仅仅是关闭窗口)以清除缓存的应用元数据
## 功能:仅 RSC 与 Graph
### 仅使用 **Teams RSC**(应用已安装,无 Graph API 权限)
可用:
- 读取频道消息**文本**内容。
- 发送频道消息**文本**内容。
- 接收**个人(私信)**文件附件。
不可用:
- 频道/群组**图片或文件内容**(负载仅包含 HTML 存根)。
- 下载存储在 SharePoint/OneDrive 中的附件。
- 读取消息历史(超出实时 webhook 事件)。
### 使用 **Teams RSC + Microsoft Graph Application 权限**
增加:
- 下载托管内容(粘贴到消息中的图片)。
- 下载存储在 SharePoint/OneDrive 中的文件附件。
- 通过 Graph 读取频道/聊天消息历史。
### RSC 与 Graph API 对比
| 功能 | RSC 权限 | Graph API |
| -------------- | ------------------ | ------------------------- |
| **实时消息** | 是(通过 webhook | 否(仅轮询) |
| **历史消息** | 否 | 是(可查询历史) |
| **设置复杂度** | 仅应用清单 | 需要管理员同意 + 令牌流程 |
| **离线工作** | 否(必须运行) | 是(随时查询) |
**结论:** RSC 用于实时监听Graph API 用于历史访问。要在离线时补上错过的消息,你需要带有 `ChannelMessage.Read.All` 的 Graph API需要管理员同意
## 启用 Graph 的媒体 + 历史(频道所需)
如果你需要**频道**中的图片/文件或想要获取**消息历史**,你必须启用 Microsoft Graph 权限并授予管理员同意。
1. 在 Entra IDAzure AD**App Registration** 中,添加 Microsoft Graph **Application 权限**
- `ChannelMessage.Read.All`(频道附件 + 历史)
- `Chat.Read.All` 或 `ChatMessage.Read.All`(群聊)
2. 为租户**授予管理员同意**。
3. 提升 Teams 应用**清单版本**,重新上传,并**在 Teams 中重新安装应用**。
4. **完全退出并重新启动 Teams** 以清除缓存的应用元数据。
## 已知限制
### Webhook 超时
Teams 通过 HTTP webhook 传递消息。如果处理时间过长例如LLM 响应缓慢),你可能会看到:
- Gateway 网关超时
- Teams 重试消息(导致重复)
- 丢失的回复
OpenClaw 通过快速返回并主动发送回复来处理这个问题,但非常慢的响应仍可能导致问题。
### 格式化
Teams markdown 比 Slack 或 Discord 更有限:
- 基本格式化有效:**粗体**、_斜体_、`代码`、链接
- 复杂的 markdown表格、嵌套列表可能无法正确渲染
- 支持 Adaptive Cards 用于投票和任意卡片发送(见下文)
## 配置
关键设置(共享渠道模式见 `/gateway/configuration`
- `channels.msteams.enabled`:启用/禁用渠道。
- `channels.msteams.appId`、`channels.msteams.appPassword`、`channels.msteams.tenantId`:机器人凭证。
- `channels.msteams.webhook.port`(默认 `3978`
- `channels.msteams.webhook.path`(默认 `/api/messages`
- `channels.msteams.dmPolicy``pairing | allowlist | open | disabled`默认pairing
- `channels.msteams.allowFrom`私信允许列表AAD 对象 ID、UPN 或显示名称)。当 Graph 访问可用时,向导在设置期间将名称解析为 ID。
- `channels.msteams.textChunkLimit`:出站文本分块大小。
- `channels.msteams.chunkMode``length`(默认)或 `newline` 在长度分块之前按空行(段落边界)分割。
- `channels.msteams.mediaAllowHosts`:入站附件主机允许列表(默认为 Microsoft/Teams 域名)。
- `channels.msteams.mediaAuthAllowHosts`:在媒体重试时附加 Authorization 头的允许列表(默认为 Graph + Bot Framework 主机)。
- `channels.msteams.requireMention`:在频道/群组中需要 @提及(默认 true
- `channels.msteams.replyStyle``thread | top-level`(见[回复样式](#reply-style-threads-vs-posts))。
- `channels.msteams.teams.<teamId>.replyStyle`:每团队覆盖。
- `channels.msteams.teams.<teamId>.requireMention`:每团队覆盖。
- `channels.msteams.teams.<teamId>.tools`:当缺少频道覆盖时使用的默认每团队工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `channels.msteams.teams.<teamId>.toolsBySender`:默认每团队每发送者工具策略覆盖(支持 `"*"` 通配符)。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle`:每频道覆盖。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention`:每频道覆盖。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.tools`:每频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender`:每频道每发送者工具策略覆盖(支持 `"*"` 通配符)。
- `channels.msteams.sharePointSiteId`:用于群聊/频道文件上传的 SharePoint 站点 ID见[在群聊中发送文件](#sending-files-in-group-chats))。
## 路由和会话
- 会话键遵循标准智能体格式(见 [/concepts/session](/concepts/session)
- 私信共享主会话(`agent:<agentId>:<mainKey>`)。
- 频道/群组消息使用会话 ID
- `agent:<agentId>:msteams:channel:<conversationId>`
- `agent:<agentId>:msteams:group:<conversationId>`
## 回复样式:话题 vs 帖子
Teams 最近在相同的底层数据模型上引入了两种频道 UI 样式:
| 样式 | 描述 | 推荐的 `replyStyle` |
| ----------------------- | ------------------------------ | ------------------- |
| **Posts**(经典) | 消息显示为卡片,下方有话题回复 | `thread`(默认) |
| **Threads**(类 Slack | 消息线性流动,更像 Slack | `top-level` |
**问题:** Teams API 不暴露频道使用的 UI 样式。如果你使用错误的 `replyStyle`
- 在 Threads 样式频道中使用 `thread` → 回复嵌套显示很别扭
- 在 Posts 样式频道中使用 `top-level` → 回复显示为单独的顶级帖子而不是在话题中
**解决方案:** 根据频道的设置方式为每个频道配置 `replyStyle`
```json
{
"msteams": {
"replyStyle": "thread",
"teams": {
"19:abc...@thread.tacv2": {
"channels": {
"19:xyz...@thread.tacv2": {
"replyStyle": "top-level"
}
}
}
}
}
}
```
## 附件和图片
**当前限制:**
- **私信:** 图片和文件附件通过 Teams bot file API 工作。
- **频道/群组:** 附件存储在 M365 存储SharePoint/OneDrive中。webhook 负载仅包含 HTML 存根,而非实际文件字节。**需要 Graph API 权限**才能下载频道附件。
没有 Graph 权限,带图片的频道消息将作为纯文本接收(机器人无法访问图片内容)。
默认情况下OpenClaw 仅从 Microsoft/Teams 主机名下载媒体。使用 `channels.msteams.mediaAllowHosts` 覆盖(使用 `["*"]` 允许任何主机)。
Authorization 头仅附加到 `channels.msteams.mediaAuthAllowHosts` 中的主机(默认为 Graph + Bot Framework 主机)。保持此列表严格(避免多租户后缀)。
## 在群聊中发送文件
机器人可以使用 FileConsentCard 流程在私信中发送文件(内置)。但是,**在群聊/频道中发送文件**需要额外设置:
| 上下文 | 文件发送方式 | 所需设置 |
| ---------------------- | --------------------------------------- | ------------------------------------ |
| **私信** | FileConsentCard → 用户接受 → 机器人上传 | 开箱即用 |
| **群聊/频道** | 上传到 SharePoint → 共享链接 | 需要 `sharePointSiteId` + Graph 权限 |
| **图片(任何上下文)** | Base64 编码内联 | 开箱即用 |
### 为什么群聊需要 SharePoint
机器人没有个人 OneDrive 驱动器(`/me/drive` Graph API 端点对应用程序身份不起作用)。要在群聊/频道中发送文件,机器人上传到 **SharePoint 站点**并创建共享链接。
### 设置
1. **在 Entra IDAzure AD→ App Registration 中添加 Graph API 权限**
- `Sites.ReadWrite.All`Application- 上传文件到 SharePoint
- `Chat.Read.All`Application- 可选,启用每用户共享链接
2. 为租户**授予管理员同意**。
3. **获取你的 SharePoint 站点 ID**
```bash
# 通过 Graph Explorer 或带有效令牌的 curl
curl -H "Authorization: Bearer $TOKEN" \
"https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}"
# 示例:对于 "contoso.sharepoint.com/sites/BotFiles" 的站点
curl -H "Authorization: Bearer $TOKEN" \
"https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles"
# 响应包含:"id": "contoso.sharepoint.com,guid1,guid2"
```
4. **配置 OpenClaw**
```json5
{
channels: {
msteams: {
// ... 其他配置 ...
sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",
},
},
}
```
### 共享行为
| 权限 | 共享行为 |
| --------------------------------------- | ------------------------------------------ |
| 仅 `Sites.ReadWrite.All` | 组织范围共享链接(组织中任何人都可以访问) |
| `Sites.ReadWrite.All` + `Chat.Read.All` | 每用户共享链接(仅聊天成员可以访问) |
每用户共享更安全,因为只有聊天参与者才能访问文件。如果缺少 `Chat.Read.All` 权限,机器人回退到组织范围共享。
### 回退行为
| 场景 | 结果 |
| --------------------------------------- | ------------------------------------------------ |
| 群聊 + 文件 + 已配置 `sharePointSiteId` | 上传到 SharePoint发送共享链接 |
| 群聊 + 文件 + 无 `sharePointSiteId` | 尝试 OneDrive 上传(可能失败),仅发送文本 |
| 个人聊天 + 文件 | FileConsentCard 流程(无需 SharePoint 即可工作) |
| 任何上下文 + 图片 | Base64 编码内联(无需 SharePoint 即可工作) |
### 文件存储位置
上传的文件存储在配置的 SharePoint 站点默认文档库中的 `/OpenClawShared/` 文件夹中。
## 投票Adaptive Cards
OpenClaw 将 Teams 投票作为 Adaptive Cards 发送(没有原生 Teams 投票 API
- CLI`openclaw message poll --channel msteams --target conversation:<id> ...`
- 投票由 Gateway 网关记录在 `~/.openclaw/msteams-polls.json` 中。
- Gateway 网关必须保持在线才能记录投票。
- 投票尚不自动发布结果摘要(如需要请检查存储文件)。
## Adaptive Cards任意
使用 `message` 工具或 CLI 向 Teams 用户或会话发送任意 Adaptive Card JSON。
`card` 参数接受 Adaptive Card JSON 对象。当提供 `card` 时,消息文本是可选的。
**智能体工具:**
```json
{
"action": "send",
"channel": "msteams",
"target": "user:<id>",
"card": {
"type": "AdaptiveCard",
"version": "1.5",
"body": [{ "type": "TextBlock", "text": "Hello!" }]
}
}
```
**CLI**
```bash
openclaw message send --channel msteams \
--target "conversation:19:abc...@thread.tacv2" \
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}'
```
参见 [Adaptive Cards 文档](https://adaptivecards.io/)了解卡片模式和示例。目标格式详情见下方[目标格式](#target-formats)。
## 目标格式
MSTeams 目标使用前缀来区分用户和会话:
| 目标类型 | 格式 | 示例 |
| ----------------- | -------------------------------- | ------------------------------------------------- |
| 用户(按 ID | `user:<aad-object-id>` | `user:40a1a0ed-4ff2-4164-a219-55518990c197` |
| 用户(按名称) | `user:<display-name>` | `user:John Smith`(需要 Graph API |
| 群组/频道 | `conversation:<conversation-id>` | `conversation:19:abc123...@thread.tacv2` |
| 群组/频道(原始) | `<conversation-id>` | `19:abc123...@thread.tacv2`(如果包含 `@thread` |
**CLI 示例:**
```bash
# 按 ID 发送给用户
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"
# 按显示名称发送给用户(触发 Graph API 查找)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"
# 发送到群聊或频道
openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello"
# 向会话发送 Adaptive Card
openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" \
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello"}]}'
```
**智能体工具示例:**
```json
{
"action": "send",
"channel": "msteams",
"target": "user:John Smith",
"message": "Hello!"
}
```
```json
{
"action": "send",
"channel": "msteams",
"target": "conversation:19:abc...@thread.tacv2",
"card": {
"type": "AdaptiveCard",
"version": "1.5",
"body": [{ "type": "TextBlock", "text": "Hello" }]
}
}
```
注意:没有 `user:` 前缀时,名称默认解析为群组/团队。按显示名称定位人员时始终使用 `user:`。
## 主动消息
- 主动消息仅在用户交互**之后**才可能,因为我们在那时存储会话引用。
- 有关 `dmPolicy` 和允许列表控制,请参见 `/gateway/configuration`。
## 团队和频道 ID常见陷阱
Teams URL 中的 `groupId` 查询参数**不是**用于配置的团队 ID。请从 URL 路径中提取 ID
**团队 URL**
```
https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
└────────────────────────────┘
团队 IDURL 解码此部分)
```
**频道 URL**
```
https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
└─────────────────────────┘
频道 IDURL 解码此部分)
```
**用于配置:**
- 团队 ID = `/team/` 后的路径段URL 解码,例如 `19:Bk4j...@thread.tacv2`
- 频道 ID = `/channel/` 后的路径段URL 解码)
- **忽略** `groupId` 查询参数
## 私有频道
机器人在私有频道中的支持有限:
| 功能 | 标准频道 | 私有频道 |
| ------------------- | -------- | ---------------- |
| 机器人安装 | 是 | 有限 |
| 实时消息webhook | 是 | 可能不工作 |
| RSC 权限 | 是 | 行为可能不同 |
| @提及 | 是 | 如果机器人可访问 |
| Graph API 历史 | 是 | 是(有权限) |
**如果私有频道不工作的变通方法:**
1. 使用标准频道进行机器人交互
2. 使用私信 - 用户始终可以直接给机器人发消息
3. 使用 Graph API 进行历史访问(需要 `ChannelMessage.Read.All`
## 故障排除
### 常见问题
- **频道中图片不显示:** 缺少 Graph 权限或管理员同意。重新安装 Teams 应用并完全退出/重新打开 Teams。
- **频道中无响应:** 默认需要提及;设置 `channels.msteams.requireMention=false` 或按团队/频道配置。
- **版本不匹配Teams 仍显示旧清单):** 移除 + 重新添加应用并完全退出 Teams 以刷新。
- **来自 webhook 的 401 Unauthorized** 在没有 Azure JWT 的情况下手动测试时属于预期情况 - 意味着端点可达但认证失败。使用 Azure Web Chat 正确测试。
### 清单上传错误
- **"Icon file cannot be empty"** 清单引用的图标文件为 0 字节。创建有效的 PNG 图标(`outline.png` 为 32x32`color.png` 为 192x192
- **"webApplicationInfo.Id already in use"** 应用仍安装在另一个团队/聊天中。先找到并卸载它,或等待 5-10 分钟让其传播。
- **上传时"Something went wrong"** 改为通过 https://admin.teams.microsoft.com 上传,打开浏览器 DevToolsF12→ Network 选项卡,检查响应正文中的实际错误。
- **侧载失败:** 尝试"Upload an app to your org's app catalog"而不是"Upload a custom app" - 这通常可以绕过侧载限制。
### RSC 权限不工作
1. 验证 `webApplicationInfo.id` 与你的机器人 App ID 完全匹配
2. 重新上传应用并在团队/聊天中重新安装
3. 检查你的组织管理员是否阻止了 RSC 权限
4. 确认你使用的是正确的范围:团队使用 `ChannelMessage.Read.Group`,群聊使用 `ChatMessage.Read.Chat`
## 参考资料
- [创建 Azure Bot](https://learn.microsoft.com/en-us/azure/bot-service/bot-service-quickstart-registration) - Azure Bot 设置指南
- [Teams 开发者门户](https://dev.teams.microsoft.com/apps) - 创建/管理 Teams 应用
- [Teams 应用清单模式](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema)
- [使用 RSC 接收频道消息](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/channel-messages-with-rsc)
- [RSC 权限参考](https://learn.microsoft.com/en-us/microsoftteams/platform/graph-api/rsc/resource-specific-consent)
- [Teams 机器人文件处理](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4)(频道/群组需要 Graph
- [主动消息](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages)

View File

@@ -0,0 +1,142 @@
---
read_when:
- 开发 Nextcloud Talk 渠道功能时
summary: Nextcloud Talk 支持状态、功能和配置
title: Nextcloud Talk
x-i18n:
generated_at: "2026-02-03T10:04:00Z"
model: claude-opus-4-5
provider: pi
source_hash: 21b7b9756c4356a76dc0f14c10e44ed74a284cf3badf87e2df75eb88d8a90c31
source_path: channels/nextcloud-talk.md
workflow: 15
---
# Nextcloud Talk插件
状态通过插件支持webhook 机器人)。支持私信、房间、表情回应和 Markdown 消息。
## 需要插件
Nextcloud Talk 以插件形式提供,不包含在核心安装包中。
通过 CLI 安装npm 仓库):
```bash
openclaw plugins install @openclaw/nextcloud-talk
```
本地检出安装(从 git 仓库运行时):
```bash
openclaw plugins install ./extensions/nextcloud-talk
```
如果你在配置/新手引导过程中选择了 Nextcloud Talk并且检测到 git 检出,
OpenClaw 将自动提供本地安装路径。
详情:[插件](/tools/plugin)
## 快速设置(新手)
1. 安装 Nextcloud Talk 插件。
2. 在你的 Nextcloud 服务器上创建机器人:
```bash
./occ talk:bot:install "OpenClaw" "<shared-secret>" "<webhook-url>" --feature reaction
```
3. 在目标房间设置中启用机器人。
4. 配置 OpenClaw
- 配置项:`channels.nextcloud-talk.baseUrl` + `channels.nextcloud-talk.botSecret`
- 或环境变量:`NEXTCLOUD_TALK_BOT_SECRET`(仅默认账户)
5. 重启 Gateway 网关(或完成新手引导)。
最小配置:
```json5
{
channels: {
"nextcloud-talk": {
enabled: true,
baseUrl: "https://cloud.example.com",
botSecret: "shared-secret",
dmPolicy: "pairing",
},
},
}
```
## 注意事项
- 机器人无法主动发起私信。用户必须先向机器人发送消息。
- Webhook URL 必须可被 Gateway 网关访问;如果在代理后面,请设置 `webhookPublicUrl`。
- 机器人 API 不支持媒体上传;媒体以 URL 形式发送。
- Webhook 载荷无法区分私信和房间;设置 `apiUser` + `apiPassword` 以启用房间类型查询(否则私信将被视为房间)。
## 访问控制(私信)
- 默认:`channels.nextcloud-talk.dmPolicy = "pairing"`。未知发送者将收到配对码。
- 批准方式:
- `openclaw pairing list nextcloud-talk`
- `openclaw pairing approve nextcloud-talk <CODE>`
- 公开私信:`channels.nextcloud-talk.dmPolicy="open"` 加上 `channels.nextcloud-talk.allowFrom=["*"]`。
## 房间(群组)
- 默认:`channels.nextcloud-talk.groupPolicy = "allowlist"`(需要提及触发)。
- 使用 `channels.nextcloud-talk.rooms` 设置房间白名单:
```json5
{
channels: {
"nextcloud-talk": {
rooms: {
"room-token": { requireMention: true },
},
},
},
}
```
- 如需禁止所有房间,保持白名单为空或设置 `channels.nextcloud-talk.groupPolicy="disabled"`。
## 功能支持
| 功能 | 状态 |
| -------- | ------ |
| 私信 | 支持 |
| 房间 | 支持 |
| 话题 | 不支持 |
| 媒体 | 仅 URL |
| 表情回应 | 支持 |
| 原生命令 | 不支持 |
## 配置参考Nextcloud Talk
完整配置:[配置](/gateway/configuration)
提供商选项:
- `channels.nextcloud-talk.enabled`:启用/禁用渠道启动。
- `channels.nextcloud-talk.baseUrl`Nextcloud 实例 URL。
- `channels.nextcloud-talk.botSecret`:机器人共享密钥。
- `channels.nextcloud-talk.botSecretFile`:密钥文件路径。
- `channels.nextcloud-talk.apiUser`:用于房间查询的 API 用户(私信检测)。
- `channels.nextcloud-talk.apiPassword`:用于房间查询的 API/应用密码。
- `channels.nextcloud-talk.apiPasswordFile`API 密码文件路径。
- `channels.nextcloud-talk.webhookPort`webhook 监听端口默认8788
- `channels.nextcloud-talk.webhookHost`webhook 主机默认0.0.0.0)。
- `channels.nextcloud-talk.webhookPath`webhook 路径(默认:/nextcloud-talk-webhook
- `channels.nextcloud-talk.webhookPublicUrl`:外部可达的 webhook URL。
- `channels.nextcloud-talk.dmPolicy``pairing | allowlist | open | disabled`。
- `channels.nextcloud-talk.allowFrom`:私信白名单(用户 ID。`open` 需要 `"*"`。
- `channels.nextcloud-talk.groupPolicy``allowlist | open | disabled`。
- `channels.nextcloud-talk.groupAllowFrom`:群组白名单(用户 ID
- `channels.nextcloud-talk.rooms`:每个房间的设置和白名单。
- `channels.nextcloud-talk.historyLimit`群组历史记录限制0 表示禁用)。
- `channels.nextcloud-talk.dmHistoryLimit`私信历史记录限制0 表示禁用)。
- `channels.nextcloud-talk.dms`每个私信的覆盖设置historyLimit
- `channels.nextcloud-talk.textChunkLimit`:出站文本分块大小(字符数)。
- `channels.nextcloud-talk.chunkMode``length`(默认)或 `newline`,在长度分块前按空行(段落边界)分割。
- `channels.nextcloud-talk.blockStreaming`:禁用此渠道的分块流式传输。
- `channels.nextcloud-talk.blockStreamingCoalesce`:分块流式传输合并调优。
- `channels.nextcloud-talk.mediaMaxMb`入站媒体大小上限MB

240
content/channels/nostr.md Normal file
View File

@@ -0,0 +1,240 @@
---
read_when:
- 你希望 OpenClaw 通过 Nostr 接收私信
- 你正在设置去中心化消息
summary: 通过 NIP-04 加密消息的 Nostr 私信渠道
title: Nostr
x-i18n:
generated_at: "2026-02-03T07:44:13Z"
model: claude-opus-4-5
provider: pi
source_hash: 6b9fe4c74bf5e7c0f59bbaa129ec5270fd29a248551a8a9a7dde6cff8fb46111
source_path: channels/nostr.md
workflow: 15
---
# Nostr
**状态:** 可选插件(默认禁用)。
Nostr 是一个去中心化的社交网络协议。此渠道使 OpenClaw 能够通过 NIP-04 接收和回复加密私信DMs
## 安装(按需)
### 新手引导(推荐)
- 新手引导向导(`openclaw onboard`)和 `openclaw channels add` 会列出可选的渠道插件。
- 选择 Nostr 会提示你按需安装插件。
安装默认值:
- **Dev 渠道 + git checkout 可用:** 使用本地插件路径。
- **Stable/Beta** 从 npm 下载。
你可以随时在提示中覆盖选择。
### 手动安装
```bash
openclaw plugins install @openclaw/nostr
```
使用本地 checkout开发工作流
```bash
openclaw plugins install --link <path-to-openclaw>/extensions/nostr
```
安装或启用插件后重启 Gateway 网关。
## 快速设置
1. 生成 Nostr 密钥对(如需要):
```bash
# 使用 nak
nak key generate
```
2. 添加到配置:
```json
{
"channels": {
"nostr": {
"privateKey": "${NOSTR_PRIVATE_KEY}"
}
}
}
```
3. 导出密钥:
```bash
export NOSTR_PRIVATE_KEY="nsec1..."
```
4. 重启 Gateway 网关。
## 配置参考
| 键 | 类型 | 默认值 | 描述 |
| ------------ | -------- | ------------------------------------------- | --------------------------- |
| `privateKey` | string | 必填 | `nsec` 或十六进制格式的私钥 |
| `relays` | string[] | `['wss://relay.damus.io', 'wss://nos.lol']` | 中继 URLWebSocket |
| `dmPolicy` | string | `pairing` | 私信访问策略 |
| `allowFrom` | string[] | `[]` | 允许的发送者公钥 |
| `enabled` | boolean | `true` | 启用/禁用渠道 |
| `name` | string | - | 显示名称 |
| `profile` | object | - | NIP-01 个人资料元数据 |
## 个人资料元数据
个人资料数据作为 NIP-01 `kind:0` 事件发布。你可以从控制界面Channels -> Nostr -> Profile管理它或直接在配置中设置。
示例:
```json
{
"channels": {
"nostr": {
"privateKey": "${NOSTR_PRIVATE_KEY}",
"profile": {
"name": "openclaw",
"displayName": "OpenClaw",
"about": "Personal assistant DM bot",
"picture": "https://example.com/avatar.png",
"banner": "https://example.com/banner.png",
"website": "https://example.com",
"nip05": "openclaw@example.com",
"lud16": "openclaw@example.com"
}
}
}
}
```
注意事项:
- 个人资料 URL 必须使用 `https://`
- 从中继导入会合并字段并保留本地覆盖。
## 访问控制
### 私信策略
- **pairing**(默认):未知发送者会收到配对码。
- **allowlist**:只有 `allowFrom` 中的公钥可以发送私信。
- **open**:公开接收私信(需要 `allowFrom: ["*"]`)。
- **disabled**:忽略接收的私信。
### 允许列表示例
```json
{
"channels": {
"nostr": {
"privateKey": "${NOSTR_PRIVATE_KEY}",
"dmPolicy": "allowlist",
"allowFrom": ["npub1abc...", "npub1xyz..."]
}
}
}
```
## 密钥格式
接受的格式:
- **私钥:** `nsec...` 或 64 字符十六进制
- **公钥(`allowFrom`** `npub...` 或十六进制
## 中继
默认值:`relay.damus.io``nos.lol`
```json
{
"channels": {
"nostr": {
"privateKey": "${NOSTR_PRIVATE_KEY}",
"relays": ["wss://relay.damus.io", "wss://relay.primal.net", "wss://nostr.wine"]
}
}
}
```
提示:
- 使用 2-3 个中继以实现冗余。
- 避免使用过多中继(延迟、重复)。
- 付费中继可以提高可靠性。
- 本地中继适合测试(`ws://localhost:7777`)。
## 协议支持
| NIP | 状态 | 描述 |
| ------ | ------ | ----------------------------- |
| NIP-01 | 已支持 | 基本事件格式 + 个人资料元数据 |
| NIP-04 | 已支持 | 加密私信(`kind:4` |
| NIP-17 | 计划中 | 礼物包装私信 |
| NIP-44 | 计划中 | 版本化加密 |
## 测试
### 本地中继
```bash
# 启动 strfry
docker run -p 7777:7777 ghcr.io/hoytech/strfry
```
```json
{
"channels": {
"nostr": {
"privateKey": "${NOSTR_PRIVATE_KEY}",
"relays": ["ws://localhost:7777"]
}
}
}
```
### 手动测试
1. 从日志中记下机器人公钥npub
2. 打开 Nostr 客户端Damus、Amethyst 等)。
3. 向机器人公钥发送私信。
4. 验证响应。
## 故障排除
### 未收到消息
- 验证私钥是否有效。
- 确保中继 URL 可访问并使用 `wss://`(本地使用 `ws://`)。
- 确认 `enabled` 不是 `false`
- 检查 Gateway 网关日志中的中继连接错误。
### 未发送响应
- 检查中继是否接受写入。
- 验证出站连接。
- 注意中继速率限制。
### 重复响应
- 使用多个中继时属于正常现象。
- 消息按事件 ID 去重;只有首次投递会触发响应。
## 安全
- 切勿提交私钥。
- 使用环境变量存储密钥。
- 生产环境机器人考虑使用 `allowlist`
## 限制MVP
- 仅支持私信(不支持群聊)。
- 不支持媒体附件。
- 仅支持 NIP-04计划支持 NIP-17 礼物包装)。

View File

@@ -0,0 +1,89 @@
---
read_when:
- 设置私信访问控制
- 配对新的 iOS/Android 节点
- 审查 OpenClaw 安全态势
summary: 配对概述:批准谁可以向你发送私信 + 哪些节点可以加入
title: 配对
x-i18n:
generated_at: "2026-02-03T07:54:19Z"
model: claude-opus-4-5
provider: pi
source_hash: c46a5c39f289c8fd0783baacd927f550c3d3ae8889a7bc7de133b795f16fa08a
source_path: channels/pairing.md
workflow: 15
---
# 配对
"配对"是 OpenClaw 的显式**所有者批准**步骤。它用于两个地方:
1. **私信配对**(谁被允许与机器人对话)
2. **节点配对**(哪些设备/节点被允许加入 Gateway 网关网络)
安全上下文:[安全](/gateway/security)
## 1私信配对入站聊天访问
当渠道配置为私信策略 `pairing` 时,未知发送者会收到一个短代码,他们的消息**不会被处理**,直到你批准。
默认私信策略记录在:[安全](/gateway/security)
配对代码:
- 8 个字符,大写,无歧义字符(`0O1I`)。
- **1 小时后过期**。机器人仅在创建新请求时发送配对消息(大约每个发送者每小时一次)。
- 待处理的私信配对请求默认上限为**每个渠道 3 个**;在一个过期或被批准之前,额外的请求将被忽略。
### 批准发送者
```bash
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>
```
支持的渠道:`telegram``whatsapp``signal``imessage``discord``slack`
### 状态存储位置
存储在 `~/.openclaw/credentials/` 下:
- 待处理请求:`<channel>-pairing.json`
- 已批准允许列表存储:`<channel>-allowFrom.json`
将这些视为敏感信息(它们控制对你助手的访问)。
## 2节点设备配对iOS/Android/macOS/无头节点)
节点作为 `role: node` 的**设备**连接到 Gateway 网关。Gateway 网关创建一个必须被批准的设备配对请求。
### 批准节点设备
```bash
openclaw devices list
openclaw devices approve <requestId>
openclaw devices reject <requestId>
```
### 状态存储位置
存储在 `~/.openclaw/devices/` 下:
- `pending.json`(短期;待处理请求会过期)
- `paired.json`(已配对设备 + 令牌)
### 说明
- 旧版 `node.pair.*` APICLI`openclaw nodes pending/approve`)是一个单独的 Gateway 网关拥有的配对存储。WS 节点仍然需要设备配对。
## 相关文档
- 安全模型 + 提示注入:[安全](/gateway/security)
- 安全更新(运行 doctor[更新](/install/updating)
- 渠道配置:
- Telegram[Telegram](/channels/telegram)
- WhatsApp[WhatsApp](/channels/whatsapp)
- Signal[Signal](/channels/signal)
- iMessage[iMessage](/channels/imessage)
- Discord[Discord](/channels/discord)
- Slack[Slack](/channels/slack)

209
content/channels/signal.md Normal file
View File

@@ -0,0 +1,209 @@
---
read_when:
- 设置 Signal 支持
- 调试 Signal 发送/接收
summary: 通过 signal-cliJSON-RPC + SSE支持 Signal设置和号码模型
title: Signal
x-i18n:
generated_at: "2026-02-03T07:44:15Z"
model: claude-opus-4-5
provider: pi
source_hash: ca4de8b3685017f54a959e3e2699357ab40b3e4e68574bd7fb5739e4679e7d8a
source_path: channels/signal.md
workflow: 15
---
# Signal (signal-cli)
状态:外部 CLI 集成。Gateway 网关通过 HTTP JSON-RPC + SSE 与 `signal-cli` 通信。
## 快速设置(初学者)
1. 为 bot 使用**单独的 Signal 号码**(推荐)。
2. 安装 `signal-cli`(需要 Java
3. 链接 bot 设备并启动守护进程:
- `signal-cli link -n "OpenClaw"`
4. 配置 OpenClaw 并启动 Gateway 网关。
最小配置:
```json5
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}
```
## 它是什么
- 通过 `signal-cli` 的 Signal 渠道(非嵌入式 libsignal
- 确定性路由:回复始终返回到 Signal。
- 私信共享智能体的主会话;群组是隔离的(`agent:<agentId>:signal:group:<groupId>`)。
## 配置写入
默认情况下Signal 允许写入由 `/config set|unset` 触发的配置更新(需要 `commands.config: true`)。
禁用方式:
```json5
{
channels: { signal: { configWrites: false } },
}
```
## 号码模型(重要)
- Gateway 网关连接到一个 **Signal 设备**`signal-cli` 账户)。
- 如果你在**个人 Signal 账户**上运行 bot它会忽略你自己的消息循环保护
- 要实现"我发消息给 bot 然后它回复",请使用**单独的 bot 号码**。
## 设置(快速路径)
1. 安装 `signal-cli`(需要 Java
2. 链接 bot 账户:
- `signal-cli link -n "OpenClaw"` 然后在 Signal 中扫描二维码。
3. 配置 Signal 并启动 Gateway 网关。
示例:
```json5
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}
```
多账户支持:使用 `channels.signal.accounts` 配置每个账户及可选的 `name`。共享模式请参见 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts)。
## 外部守护进程模式httpUrl
如果你想自己管理 `signal-cli`JVM 冷启动慢、容器初始化或共享 CPU请单独运行守护进程并将 OpenClaw 指向它:
```json5
{
channels: {
signal: {
httpUrl: "http://127.0.0.1:8080",
autoStart: false,
},
},
}
```
这会跳过自动启动和 OpenClaw 内部的启动等待。对于自动启动时的慢启动,请设置 `channels.signal.startupTimeoutMs`
## 访问控制(私信 + 群组)
私信:
- 默认:`channels.signal.dmPolicy = "pairing"`
- 未知发送者会收到配对码;消息在批准前会被忽略(配对码 1 小时后过期)。
- 通过以下方式批准:
- `openclaw pairing list signal`
- `openclaw pairing approve signal <CODE>`
- 配对是 Signal 私信的默认令牌交换方式。详情:[配对](/channels/pairing)
- 仅有 UUID 的发送者(来自 `sourceUuid`)在 `channels.signal.allowFrom` 中存储为 `uuid:<id>`
群组:
- `channels.signal.groupPolicy = open | allowlist | disabled`
- 当设置为 `allowlist` 时,`channels.signal.groupAllowFrom` 控制谁可以在群组中触发。
## 工作原理(行为)
- `signal-cli` 作为守护进程运行Gateway 网关通过 SSE 读取事件。
- 入站消息被规范化为共享渠道信封。
- 回复始终路由回同一号码或群组。
## 媒体 + 限制
- 出站文本按 `channels.signal.textChunkLimit` 分块(默认 4000
- 可选换行分块:设置 `channels.signal.chunkMode="newline"` 在长度分块前按空行(段落边界)分割。
- 支持附件(从 `signal-cli` 获取 base64
- 默认媒体上限:`channels.signal.mediaMaxMb`(默认 8
- 使用 `channels.signal.ignoreAttachments` 跳过下载媒体。
- 群组历史上下文使用 `channels.signal.historyLimit`(或 `channels.signal.accounts.*.historyLimit`),回退到 `messages.groupChat.historyLimit`。设置 `0` 禁用(默认 50
## 输入指示器 + 已读回执
- **输入指示器**OpenClaw 通过 `signal-cli sendTyping` 发送输入信号,并在回复运行时刷新它们。
- **已读回执**:当 `channels.signal.sendReadReceipts` 为 true 时OpenClaw 为允许的私信转发已读回执。
- Signal-cli 不暴露群组的已读回执。
## 表情回应message 工具)
- 使用 `message action=react` 配合 `channel=signal`
- 目标:发送者 E.164 或 UUID使用配对输出中的 `uuid:<id>`;裸 UUID 也可以)。
- `messageId` 是你要回应的消息的 Signal 时间戳。
- 群组表情回应需要 `targetAuthor``targetAuthorUuid`
示例:
```
message action=react channel=signal target=uuid:123e4567-e89b-12d3-a456-426614174000 messageId=1737630212345 emoji=🔥
message action=react channel=signal target=+15551234567 messageId=1737630212345 emoji=🔥 remove=true
message action=react channel=signal target=signal:group:<groupId> targetAuthor=uuid:<sender-uuid> messageId=1737630212345 emoji=✅
```
配置:
- `channels.signal.actions.reactions`:启用/禁用表情回应操作(默认 true
- `channels.signal.reactionLevel``off | ack | minimal | extensive`
- `off`/`ack` 禁用智能体表情回应message 工具 `react` 会报错)。
- `minimal`/`extensive` 启用智能体表情回应并设置指导级别。
- 每账户覆盖:`channels.signal.accounts.<id>.actions.reactions``channels.signal.accounts.<id>.reactionLevel`
## 投递目标CLI/cron
- 私信:`signal:+15551234567`(或纯 E.164)。
- UUID 私信:`uuid:<id>`(或裸 UUID
- 群组:`signal:group:<groupId>`
- 用户名:`username:<name>`(如果你的 Signal 账户支持)。
## 配置参考Signal
完整配置:[配置](/gateway/configuration)
提供商选项:
- `channels.signal.enabled`:启用/禁用渠道启动。
- `channels.signal.account`bot 账户的 E.164。
- `channels.signal.cliPath``signal-cli` 的路径。
- `channels.signal.httpUrl`:完整守护进程 URL覆盖 host/port
- `channels.signal.httpHost``channels.signal.httpPort`:守护进程绑定(默认 127.0.0.1:8080
- `channels.signal.autoStart`:自动启动守护进程(如果未设置 `httpUrl` 则默认 true
- `channels.signal.startupTimeoutMs`:启动等待超时(毫秒)(上限 120000
- `channels.signal.receiveMode``on-start | manual`
- `channels.signal.ignoreAttachments`:跳过附件下载。
- `channels.signal.ignoreStories`:忽略来自守护进程的动态。
- `channels.signal.sendReadReceipts`:转发已读回执。
- `channels.signal.dmPolicy``pairing | allowlist | open | disabled`默认pairing
- `channels.signal.allowFrom`私信允许列表E.164 或 `uuid:<id>`)。`open` 需要 `"*"`。Signal 没有用户名;使用电话/UUID id。
- `channels.signal.groupPolicy``open | allowlist | disabled`默认allowlist
- `channels.signal.groupAllowFrom`:群组发送者允许列表。
- `channels.signal.historyLimit`作为上下文包含的最大群组消息数0 禁用)。
- `channels.signal.dmHistoryLimit`:私信历史限制(用户轮次)。每用户覆盖:`channels.signal.dms["<phone_or_uuid>"].historyLimit`
- `channels.signal.textChunkLimit`:出站分块大小(字符)。
- `channels.signal.chunkMode``length`(默认)或 `newline` 在长度分块前按空行(段落边界)分割。
- `channels.signal.mediaMaxMb`:入站/出站媒体上限MB
相关全局选项:
- `agents.list[].groupChat.mentionPatterns`Signal 不支持原生提及)。
- `messages.groupChat.mentionPatterns`(全局回退)。
- `messages.responsePrefix`

531
content/channels/slack.md Normal file
View File

@@ -0,0 +1,531 @@
---
read_when: Setting up Slack or debugging Slack socket/HTTP mode
summary: Slack 的 socket 或 HTTP webhook 模式设置
title: Slack
x-i18n:
generated_at: "2026-02-03T07:45:49Z"
model: claude-opus-4-5
provider: pi
source_hash: 703b4b4333bebfef26b64710ba452bdfc3e7d2115048d4e552e8659425b3609b
source_path: channels/slack.md
workflow: 15
---
# Slack
## Socket 模式(默认)
### 快速设置(新手)
1. 创建一个 Slack 应用并启用 **Socket Mode**
2. 创建一个 **App Token**`xapp-...`)和 **Bot Token**`xoxb-...`)。
3. 为 OpenClaw 设置令牌并启动 Gateway 网关。
最小配置:
```json5
{
channels: {
slack: {
enabled: true,
appToken: "xapp-...",
botToken: "xoxb-...",
},
},
}
```
### 设置
1. 在 https://api.slack.com/apps 创建一个 Slack 应用(从头开始)。
2. **Socket Mode** → 开启。然后前往 **Basic Information****App-Level Tokens****Generate Token and Scopes**,添加 `connections:write` 权限范围。复制 **App Token**`xapp-...`)。
3. **OAuth & Permissions** → 添加 bot token 权限范围(使用下面的 manifest。点击 **Install to Workspace**。复制 **Bot User OAuth Token**`xoxb-...`)。
4. 可选:**OAuth & Permissions** → 添加 **User Token Scopes**(参见下面的只读列表)。重新安装应用并复制 **User OAuth Token**`xoxp-...`)。
5. **Event Subscriptions** → 启用事件并订阅:
- `message.*`(包括编辑/删除/线程广播)
- `app_mention`
- `reaction_added``reaction_removed`
- `member_joined_channel``member_left_channel`
- `channel_rename`
- `pin_added``pin_removed`
6. 邀请机器人加入你希望它读取的频道。
7. Slash Commands → 如果你使用 `channels.slack.slashCommand`,创建 `/openclaw`。如果启用原生命令,为每个内置命令添加一个斜杠命令(名称与 `/help` 相同)。除非你设置 `channels.slack.commands.native: true`,否则 Slack 默认关闭原生命令(全局 `commands.native``"auto"`,对 Slack 保持关闭)。
8. App Home → 启用 **Messages Tab** 以便用户可以私信机器人。
使用下面的 manifest 以保持权限范围和事件同步。
多账户支持:使用 `channels.slack.accounts` 配置每个账户的令牌和可选的 `name`。参见 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) 了解共享模式。
### OpenClaw 配置(最小)
通过环境变量设置令牌(推荐):
- `SLACK_APP_TOKEN=xapp-...`
- `SLACK_BOT_TOKEN=xoxb-...`
或通过配置:
```json5
{
channels: {
slack: {
enabled: true,
appToken: "xapp-...",
botToken: "xoxb-...",
},
},
}
```
### 用户令牌(可选)
OpenClaw 可以使用 Slack 用户令牌(`xoxp-...`)进行读取操作(历史记录、置顶、表情回应、表情符号、成员信息)。默认情况下保持只读:当存在用户令牌时,读取优先使用用户令牌,而写入仍然使用 bot 令牌,除非你明确选择加入。即使设置了 `userTokenReadOnly: false`,当 bot 令牌可用时,写入仍然优先使用 bot 令牌。
用户令牌在配置文件中配置(不支持环境变量)。对于多账户,设置 `channels.slack.accounts.<id>.userToken`
包含 bot + app + 用户令牌的示例:
```json5
{
channels: {
slack: {
enabled: true,
appToken: "xapp-...",
botToken: "xoxb-...",
userToken: "xoxp-...",
},
},
}
```
明确设置 userTokenReadOnly 的示例(允许用户令牌写入):
```json5
{
channels: {
slack: {
enabled: true,
appToken: "xapp-...",
botToken: "xoxb-...",
userToken: "xoxp-...",
userTokenReadOnly: false,
},
},
}
```
#### 令牌使用
- 读取操作(历史记录、表情回应列表、置顶列表、表情符号列表、成员信息、搜索)在配置了用户令牌时优先使用用户令牌,否则使用 bot 令牌。
- 写入操作(发送/编辑/删除消息、添加/移除表情回应、置顶/取消置顶、文件上传)默认使用 bot 令牌。如果 `userTokenReadOnly: false` 且没有可用的 bot 令牌OpenClaw 会回退到用户令牌。
### 历史上下文
- `channels.slack.historyLimit`(或 `channels.slack.accounts.*.historyLimit`)控制将多少条最近的频道/群组消息包含到提示中。
- 回退到 `messages.groupChat.historyLimit`。设置为 `0` 以禁用(默认 50
## HTTP 模式Events API
当你的 Gateway 网关可以通过 HTTPS 被 Slack 访问时(服务器部署的典型情况),使用 HTTP webhook 模式。
HTTP 模式使用 Events API + Interactivity + Slash Commands共享一个请求 URL。
### 设置
1. 创建一个 Slack 应用并**禁用 Socket Mode**(如果你只使用 HTTP 则可选)。
2. **Basic Information** → 复制 **Signing Secret**
3. **OAuth & Permissions** → 安装应用并复制 **Bot User OAuth Token**`xoxb-...`)。
4. **Event Subscriptions** → 启用事件并将 **Request URL** 设置为你的 Gateway 网关 webhook 路径(默认 `/slack/events`)。
5. **Interactivity & Shortcuts** → 启用并设置相同的 **Request URL**
6. **Slash Commands** → 为你的命令设置相同的 **Request URL**
示例请求 URL
`https://gateway-host/slack/events`
### OpenClaw 配置(最小)
```json5
{
channels: {
slack: {
enabled: true,
mode: "http",
botToken: "xoxb-...",
signingSecret: "your-signing-secret",
webhookPath: "/slack/events",
},
},
}
```
多账户 HTTP 模式:设置 `channels.slack.accounts.<id>.mode = "http"` 并为每个账户提供唯一的 `webhookPath`,以便每个 Slack 应用可以指向自己的 URL。
### Manifest可选
使用此 Slack 应用 manifest 快速创建应用(如果需要可以调整名称/命令)。如果你计划配置用户令牌,请包含用户权限范围。
```json
{
"display_information": {
"name": "OpenClaw",
"description": "Slack connector for OpenClaw"
},
"features": {
"bot_user": {
"display_name": "OpenClaw",
"always_online": false
},
"app_home": {
"messages_tab_enabled": true,
"messages_tab_read_only_enabled": false
},
"slash_commands": [
{
"command": "/openclaw",
"description": "Send a message to OpenClaw",
"should_escape": false
}
]
},
"oauth_config": {
"scopes": {
"bot": [
"chat:write",
"channels:history",
"channels:read",
"groups:history",
"groups:read",
"groups:write",
"im:history",
"im:read",
"im:write",
"mpim:history",
"mpim:read",
"mpim:write",
"users:read",
"app_mentions:read",
"reactions:read",
"reactions:write",
"pins:read",
"pins:write",
"emoji:read",
"commands",
"files:read",
"files:write"
],
"user": [
"channels:history",
"channels:read",
"groups:history",
"groups:read",
"im:history",
"im:read",
"mpim:history",
"mpim:read",
"users:read",
"reactions:read",
"pins:read",
"emoji:read",
"search:read"
]
}
},
"settings": {
"socket_mode_enabled": true,
"event_subscriptions": {
"bot_events": [
"app_mention",
"message.channels",
"message.groups",
"message.im",
"message.mpim",
"reaction_added",
"reaction_removed",
"member_joined_channel",
"member_left_channel",
"channel_rename",
"pin_added",
"pin_removed"
]
}
}
}
```
如果启用原生命令,为每个要公开的命令添加一个 `slash_commands` 条目(与 `/help` 列表匹配)。使用 `channels.slack.commands.native` 覆盖。
## 权限范围(当前 vs 可选)
Slack 的 Conversations API 是按类型区分的你只需要你实际接触的会话类型channels、groups、im、mpim的权限范围。概述参见 https://docs.slack.dev/apis/web-api/using-the-conversations-api/。
### Bot 令牌权限范围(必需)
- `chat:write`(通过 `chat.postMessage` 发送/更新/删除消息)
https://docs.slack.dev/reference/methods/chat.postMessage
- `im:write`(通过 `conversations.open` 打开私信用于用户私信)
https://docs.slack.dev/reference/methods/conversations.open
- `channels:history``groups:history``im:history``mpim:history`
https://docs.slack.dev/reference/methods/conversations.history
- `channels:read``groups:read``im:read``mpim:read`
https://docs.slack.dev/reference/methods/conversations.info
- `users:read`(用户查询)
https://docs.slack.dev/reference/methods/users.info
- `reactions:read``reactions:write``reactions.get` / `reactions.add`
https://docs.slack.dev/reference/methods/reactions.get
https://docs.slack.dev/reference/methods/reactions.add
- `pins:read``pins:write``pins.list` / `pins.add` / `pins.remove`
https://docs.slack.dev/reference/scopes/pins.read
https://docs.slack.dev/reference/scopes/pins.write
- `emoji:read``emoji.list`
https://docs.slack.dev/reference/scopes/emoji.read
- `files:write`(通过 `files.uploadV2` 上传)
https://docs.slack.dev/messaging/working-with-files/#upload
### 用户令牌权限范围(可选,默认只读)
如果你配置了 `channels.slack.userToken`,在 **User Token Scopes** 下添加这些。
- `channels:history``groups:history``im:history``mpim:history`
- `channels:read``groups:read``im:read``mpim:read`
- `users:read`
- `reactions:read`
- `pins:read`
- `emoji:read`
- `search:read`
### 目前不需要(但未来可能需要)
- `mpim:write`(仅当我们添加群组私信打开/私信启动时通过 `conversations.open`
- `groups:write`(仅当我们添加私有频道管理时:创建/重命名/邀请/归档)
- `chat:write.public`(仅当我们想发布到机器人未加入的频道时)
https://docs.slack.dev/reference/scopes/chat.write.public
- `users:read.email`(仅当我们需要从 `users.info` 获取邮箱字段时)
https://docs.slack.dev/changelog/2017-04-narrowing-email-access
- `files:read`(仅当我们开始列出/读取文件元数据时)
## 配置
Slack 仅使用 Socket Mode无 HTTP webhook 服务器)。提供两个令牌:
```json
{
"slack": {
"enabled": true,
"botToken": "xoxb-...",
"appToken": "xapp-...",
"groupPolicy": "allowlist",
"dm": {
"enabled": true,
"policy": "pairing",
"allowFrom": ["U123", "U456", "*"],
"groupEnabled": false,
"groupChannels": ["G123"],
"replyToMode": "all"
},
"channels": {
"C123": { "allow": true, "requireMention": true },
"#general": {
"allow": true,
"requireMention": true,
"users": ["U123"],
"skills": ["search", "docs"],
"systemPrompt": "Keep answers short."
}
},
"reactionNotifications": "own",
"reactionAllowlist": ["U123"],
"replyToMode": "off",
"actions": {
"reactions": true,
"messages": true,
"pins": true,
"memberInfo": true,
"emojiList": true
},
"slashCommand": {
"enabled": true,
"name": "openclaw",
"sessionPrefix": "slack:slash",
"ephemeral": true
},
"textChunkLimit": 4000,
"mediaMaxMb": 20
}
}
```
令牌也可以通过环境变量提供:
- `SLACK_BOT_TOKEN`
- `SLACK_APP_TOKEN`
确认表情回应通过 `messages.ackReaction` + `messages.ackReactionScope` 全局控制。使用 `messages.removeAckAfterReply` 在机器人回复后清除确认表情回应。
## 限制
- 出站文本按 `channels.slack.textChunkLimit` 分块(默认 4000
- 可选的换行分块:设置 `channels.slack.chunkMode="newline"` 以在长度分块之前按空行(段落边界)分割。
- 媒体上传受 `channels.slack.mediaMaxMb` 限制(默认 20
## 回复线程
默认情况下OpenClaw 在主频道回复。使用 `channels.slack.replyToMode` 控制自动线程:
| 模式 | 行为 |
| ------- | -------------------------------------------------------------------------------------------- |
| `off` | **默认。** 在主频道回复。仅当触发消息已在线程中时才使用线程。 |
| `first` | 第一条回复进入线程(在触发消息下),后续回复进入主频道。适合保持上下文可见同时避免线程混乱。 |
| `all` | 所有回复都进入线程。保持对话集中但可能降低可见性。 |
该模式适用于自动回复和智能体工具调用(`slack sendMessage`)。
### 按聊天类型的线程
你可以通过设置 `channels.slack.replyToModeByChatType` 为每种聊天类型配置不同的线程行为:
```json5
{
channels: {
slack: {
replyToMode: "off", // 频道的默认值
replyToModeByChatType: {
direct: "all", // 私信始终使用线程
group: "first", // 群组私信/MPIM 第一条回复使用线程
},
},
},
}
```
支持的聊天类型:
- `direct`一对一私信Slack `im`
- `group`:群组私信 / MPIMSlack `mpim`
- `channel`:标准频道(公开/私有)
优先级:
1. `replyToModeByChatType.<chatType>`
2. `replyToMode`
3. 提供商默认值(`off`
当未设置聊天类型覆盖时,旧版 `channels.slack.dm.replyToMode` 仍可作为 `direct` 的回退。
示例:
仅对私信使用线程:
```json5
{
channels: {
slack: {
replyToMode: "off",
replyToModeByChatType: { direct: "all" },
},
},
}
```
对群组私信使用线程但保持频道在根级别:
```json5
{
channels: {
slack: {
replyToMode: "off",
replyToModeByChatType: { group: "first" },
},
},
}
```
让频道使用线程,保持私信在根级别:
```json5
{
channels: {
slack: {
replyToMode: "first",
replyToModeByChatType: { direct: "off", group: "off" },
},
},
}
```
### 手动线程标签
对于细粒度控制,在智能体响应中使用这些标签:
- `[[reply_to_current]]` — 回复触发消息(开始/继续线程)。
- `[[reply_to:<id>]]` — 回复特定的消息 id。
## 会话 + 路由
- 私信共享 `main` 会话(与 WhatsApp/Telegram 相同)。
- 频道映射到 `agent:<agentId>:slack:channel:<channelId>` 会话。
- 斜杠命令使用 `agent:<agentId>:slack:slash:<userId>` 会话(前缀可通过 `channels.slack.slashCommand.sessionPrefix` 配置)。
- 如果 Slack 未提供 `channel_type`OpenClaw 会从频道 ID 前缀(`D``C``G`)推断并默认为 `channel` 以保持会话键稳定。
- 原生命令注册使用 `commands.native`(全局默认 `"auto"` → Slack 关闭),可以使用 `channels.slack.commands.native` 按工作空间覆盖。文本命令需要独立的 `/...` 消息,可以使用 `commands.text: false` 禁用。Slack 斜杠命令在 Slack 应用中管理,不会自动移除。使用 `commands.useAccessGroups: false` 绕过命令的访问组检查。
- 完整命令列表 + 配置:[斜杠命令](/tools/slash-commands)
## 私信安全(配对)
- 默认:`channels.slack.dm.policy="pairing"` — 未知的私信发送者会收到配对码1 小时后过期)。
- 通过以下方式批准:`openclaw pairing approve slack <code>`
- 要允许任何人:设置 `channels.slack.dm.policy="open"``channels.slack.dm.allowFrom=["*"]`
- `channels.slack.dm.allowFrom` 接受用户 ID、@用户名或邮箱(在令牌允许时启动时解析)。向导在设置期间接受用户名,并在令牌允许时将其解析为 ID。
## 群组策略
- `channels.slack.groupPolicy` 控制频道处理(`open|disabled|allowlist`)。
- `allowlist` 要求频道列在 `channels.slack.channels` 中。
- 如果你只设置了 `SLACK_BOT_TOKEN`/`SLACK_APP_TOKEN` 而从未创建 `channels.slack` 部分,运行时默认将 `groupPolicy` 设为 `open`。添加 `channels.slack.groupPolicy``channels.defaults.groupPolicy` 或频道白名单来锁定它。
- 配置向导接受 `#channel` 名称,并在可能时(公开 + 私有)将其解析为 ID如果存在多个匹配它优先选择活跃的频道。
- 启动时OpenClaw 将白名单中的频道/用户名解析为 ID在令牌允许时并记录映射未解析的条目按原样保留。
- 要**不允许任何频道**,设置 `channels.slack.groupPolicy: "disabled"`(或保留空白名单)。
频道选项(`channels.slack.channels.<id>``channels.slack.channels.<name>`
- `allow`:当 `groupPolicy="allowlist"` 时允许/拒绝频道。
- `requireMention`:频道的提及门控。
- `tools`:可选的每频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `toolsBySender`:频道内可选的每发送者工具策略覆盖(键为发送者 id/@用户名/邮箱;支持 `"*"` 通配符)。
- `allowBots`允许此频道中机器人发送的消息默认false
- `users`:可选的每频道用户白名单。
- `skills`Skills 过滤器(省略 = 所有 Skills空 = 无)。
- `systemPrompt`:频道的额外系统提示(与主题/目的组合)。
- `enabled`:设置为 `false` 以禁用频道。
## 投递目标
与 cron/CLI 发送一起使用:
- `user:<id>` 用于私信
- `channel:<id>` 用于频道
## 工具操作
Slack 工具操作可以通过 `channels.slack.actions.*` 进行门控:
| 操作组 | 默认 | 说明 |
| ---------- | ------ | ----------------------- |
| reactions | 已启用 | 表情回应 + 列出表情回应 |
| messages | 已启用 | 读取/发送/编辑/删除 |
| pins | 已启用 | 置顶/取消置顶/列表 |
| memberInfo | 已启用 | 成员信息 |
| emojiList | 已启用 | 自定义表情符号列表 |
## 安全说明
- 写入默认使用 bot 令牌,因此状态更改操作保持在应用的机器人权限和身份范围内。
- 设置 `userTokenReadOnly: false` 允许在 bot 令牌不可用时使用用户令牌进行写入操作,这意味着操作以安装用户的访问权限运行。将用户令牌视为高权限,并保持操作门控和白名单严格。
- 如果你启用用户令牌写入,请确保用户令牌包含你期望的写入权限范围(`chat:write``reactions:write``pins:write``files:write`),否则这些操作将失败。
## 说明
- 提及门控通过 `channels.slack.channels` 控制(将 `requireMention` 设置为 `true``agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)也算作提及。
- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每智能体的模式。
- 表情回应通知遵循 `channels.slack.reactionNotifications`(在 `allowlist` 模式下使用 `reactionAllowlist`)。
- 默认忽略机器人发送的消息;通过 `channels.slack.allowBots``channels.slack.channels.<id>.allowBots` 启用。
- 警告:如果你允许回复其他机器人(`channels.slack.allowBots=true``channels.slack.channels.<id>.allowBots=true`),请使用 `requireMention``channels.slack.channels.<id>.users` 白名单和/或在 `AGENTS.md``SOUL.md` 中设置明确的防护措施来防止机器人之间的回复循环。
- 对于 Slack 工具,表情回应移除语义见 [/tools/reactions](/tools/reactions)。
- 附件在允许且在大小限制内时会下载到媒体存储。

View File

@@ -0,0 +1,128 @@
---
summary: "Synology Chat webhook setup and OpenClaw config"
read_when:
- Setting up Synology Chat with OpenClaw
- Debugging Synology Chat webhook routing
title: "Synology Chat"
---
# Synology Chat (plugin)
Status: supported via plugin as a direct-message channel using Synology Chat webhooks.
The plugin accepts inbound messages from Synology Chat outgoing webhooks and sends replies
through a Synology Chat incoming webhook.
## Plugin required
Synology Chat is plugin-based and not part of the default core channel install.
Install from a local checkout:
```bash
openclaw plugins install ./extensions/synology-chat
```
Details: [Plugins](/tools/plugin)
## Quick setup
1. Install and enable the Synology Chat plugin.
2. In Synology Chat integrations:
- Create an incoming webhook and copy its URL.
- Create an outgoing webhook with your secret token.
3. Point the outgoing webhook URL to your OpenClaw gateway:
- `https://gateway-host/webhook/synology` by default.
- Or your custom `channels.synology-chat.webhookPath`.
4. Configure `channels.synology-chat` in OpenClaw.
5. Restart gateway and send a DM to the Synology Chat bot.
Minimal config:
```json5
{
channels: {
"synology-chat": {
enabled: true,
token: "synology-outgoing-token",
incomingUrl: "https://nas.example.com/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=...",
webhookPath: "/webhook/synology",
dmPolicy: "allowlist",
allowedUserIds: ["123456"],
rateLimitPerMinute: 30,
allowInsecureSsl: false,
},
},
}
```
## Environment variables
For the default account, you can use env vars:
- `SYNOLOGY_CHAT_TOKEN`
- `SYNOLOGY_CHAT_INCOMING_URL`
- `SYNOLOGY_NAS_HOST`
- `SYNOLOGY_ALLOWED_USER_IDS` (comma-separated)
- `SYNOLOGY_RATE_LIMIT`
- `OPENCLAW_BOT_NAME`
Config values override env vars.
## DM policy and access control
- `dmPolicy: "allowlist"` is the recommended default.
- `allowedUserIds` accepts a list (or comma-separated string) of Synology user IDs.
- In `allowlist` mode, an empty `allowedUserIds` list is treated as misconfiguration and the webhook route will not start (use `dmPolicy: "open"` for allow-all).
- `dmPolicy: "open"` allows any sender.
- `dmPolicy: "disabled"` blocks DMs.
- Pairing approvals work with:
- `openclaw pairing list synology-chat`
- `openclaw pairing approve synology-chat <CODE>`
## Outbound delivery
Use numeric Synology Chat user IDs as targets.
Examples:
```bash
openclaw message send --channel synology-chat --target 123456 --text "Hello from OpenClaw"
openclaw message send --channel synology-chat --target synology-chat:123456 --text "Hello again"
```
Media sends are supported by URL-based file delivery.
## Multi-account
Multiple Synology Chat accounts are supported under `channels.synology-chat.accounts`.
Each account can override token, incoming URL, webhook path, DM policy, and limits.
```json5
{
channels: {
"synology-chat": {
enabled: true,
accounts: {
default: {
token: "token-a",
incomingUrl: "https://nas-a.example.com/...token=...",
},
alerts: {
token: "token-b",
incomingUrl: "https://nas-b.example.com/...token=...",
webhookPath: "/webhook/synology-alerts",
dmPolicy: "allowlist",
allowedUserIds: ["987654"],
},
},
},
},
}
```
## Security notes
- Keep `token` secret and rotate it if leaked.
- Keep `allowInsecureSsl: false` unless you explicitly trust a self-signed local NAS cert.
- Inbound webhook requests are token-verified and rate-limited per sender.
- Prefer `dmPolicy: "allowlist"` for production.

View File

@@ -0,0 +1,751 @@
---
read_when:
- 开发 Telegram 功能或 webhook
summary: Telegram 机器人支持状态、功能和配置
title: Telegram
x-i18n:
generated_at: "2026-02-03T10:07:32Z"
model: claude-opus-4-5
provider: pi
source_hash: 65da427e5f2383edb674054f8133a5777b2aae8a7c4bd78defa065124090a19c
source_path: channels/telegram.md
workflow: 15
---
# TelegramBot API
状态:通过 grammY 支持机器人私信和群组已可用于生产环境。默认使用长轮询webhook 可选。
## 快速设置(入门)
1. 通过 **@BotFather**[直达链接](https://t.me/BotFather))创建机器人。确认用户名确实是 `@BotFather`,然后复制 token。
2. 设置 token
- 环境变量:`TELEGRAM_BOT_TOKEN=...`
- 或配置:`channels.telegram.botToken: "..."`
- 如果两者都设置了,配置优先(环境变量回退仅适用于默认账户)。
3. 启动 Gateway 网关。
4. 私信访问默认使用配对模式;首次联系时需要批准配对码。
最小配置:
```json5
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing",
},
},
}
```
## 这是什么
- 一个由 Gateway 网关拥有的 Telegram Bot API 渠道。
- 确定性路由:回复返回到 Telegram模型不会选择渠道。
- 私信共享智能体的主会话;群组保持隔离(`agent:<agentId>:telegram:group:<chatId>`)。
## 设置(快速路径)
### 1创建机器人 tokenBotFather
1. 打开 Telegram 并与 **@BotFather**[直达链接](https://t.me/BotFather))对话。确认用户名确实是 `@BotFather`
2. 运行 `/newbot`,然后按照提示操作(名称 + 以 `bot` 结尾的用户名)。
3. 复制 token 并安全保存。
可选的 BotFather 设置:
- `/setjoingroups` — 允许/拒绝将机器人添加到群组。
- `/setprivacy` — 控制机器人是否可以看到所有群组消息。
### 2配置 token环境变量或配置文件
示例:
```json5
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing",
groups: { "*": { requireMention: true } },
},
},
}
```
环境变量选项:`TELEGRAM_BOT_TOKEN=...`(适用于默认账户)。
如果环境变量和配置都设置了,配置优先。
多账户支持:使用 `channels.telegram.accounts`,每个账户有独立的 token 和可选的 `name`。参见 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) 了解共享模式。
3. 启动 Gateway 网关。当 token 解析成功时 Telegram 启动(配置优先,环境变量回退)。
4. 私信访问默认为配对模式。机器人首次被联系时批准配对码。
5. 对于群组:添加机器人,决定隐私/管理员行为(见下文),然后设置 `channels.telegram.groups` 来控制提及门控和允许列表。
## Token + 隐私 + 权限Telegram 端)
### Token 创建BotFather
- `/newbot` 创建机器人并返回 token请保密
- 如果 token 泄露,通过 @BotFather 撤销/重新生成,并更新你的配置。
### 群组消息可见性(隐私模式)
Telegram 机器人默认启用**隐私模式**,这会限制它们接收哪些群组消息。
如果你的机器人必须看到*所有*群组消息,有两个选项:
- 使用 `/setprivacy` 禁用隐私模式**或**
- 将机器人添加为群组**管理员**(管理员机器人可以接收所有消息)。
**注意:** 当你切换隐私模式时Telegram 要求将机器人从每个群组中移除并重新添加,更改才能生效。
### 群组权限(管理员权限)
管理员状态在群组内设置Telegram UI。管理员机器人始终接收所有群组消息因此如果需要完全可见性请使用管理员身份。
## 工作原理(行为)
- 入站消息被规范化为共享渠道信封,包含回复上下文和媒体占位符。
- 群组回复默认需要提及(原生 @提及或 `agents.list[].groupChat.mentionPatterns` / `messages.groupChat.mentionPatterns`)。
- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每个智能体的模式。
- 回复始终路由回同一个 Telegram 聊天。
- 长轮询使用 grammY runner每个聊天按顺序处理总体并发受 `agents.defaults.maxConcurrent` 限制。
- Telegram Bot API 不支持已读回执;没有 `sendReadReceipts` 选项。
## 草稿流式传输
OpenClaw 可以在 Telegram 私信中使用 `sendMessageDraft` 流式传输部分回复。
要求:
-@BotFather 中为机器人启用线程模式(论坛话题模式)。
- 仅限私聊线程Telegram 在入站消息中包含 `message_thread_id`)。
- `channels.telegram.streamMode` 未设置为 `"off"`(默认:`"partial"``"block"` 启用分块草稿更新)。
草稿流式传输仅限私信Telegram 在群组或频道中不支持此功能。
## 格式化Telegram HTML
- 出站 Telegram 文本使用 `parse_mode: "HTML"`Telegram 支持的标签子集)。
- 类 Markdown 输入被渲染为 **Telegram 安全 HTML**(粗体/斜体/删除线/代码/链接);块级元素被扁平化为带换行/项目符号的文本。
- 来自模型的原始 HTML 会被转义,以避免 Telegram 解析错误。
- 如果 Telegram 拒绝 HTML 负载OpenClaw 会以纯文本重试相同的消息。
## 命令(原生 + 自定义)
OpenClaw 在启动时向 Telegram 的机器人菜单注册原生命令(如 `/status``/reset``/model`)。
你可以通过配置向菜单添加自定义命令:
```json5
{
channels: {
telegram: {
customCommands: [
{ command: "backup", description: "Git 备份" },
{ command: "generate", description: "创建图片" },
],
},
},
}
```
## 故障排除
- 日志中出现 `setMyCommands failed` 通常意味着到 `api.telegram.org` 的出站 HTTPS/DNS 被阻止。
- 如果你看到 `sendMessage``sendChatAction` 失败,检查 IPv6 路由和 DNS。
更多帮助:[渠道故障排除](/channels/troubleshooting)。
注意:
- 自定义命令**仅是菜单条目**;除非你在其他地方处理它们,否则 OpenClaw 不会实现它们。
- 命令名称会被规范化(去除前导 `/`,转为小写),必须匹配 `a-z``0-9``_`1-32 个字符)。
- 自定义命令**不能覆盖原生命令**。冲突会被忽略并记录日志。
- 如果禁用了 `commands.native`,则只注册自定义命令(如果没有则清空)。
## 限制
- 出站文本按 `channels.telegram.textChunkLimit` 分块(默认 4000
- 可选的换行分块:设置 `channels.telegram.chunkMode="newline"` 在长度分块之前按空行(段落边界)分割。
- 媒体下载/上传受 `channels.telegram.mediaMaxMb` 限制(默认 5
- Telegram Bot API 请求在 `channels.telegram.timeoutSeconds` 后超时(通过 grammY 默认 500。设置较低的值以避免长时间挂起。
- 群组历史上下文使用 `channels.telegram.historyLimit`(或 `channels.telegram.accounts.*.historyLimit`),回退到 `messages.groupChat.historyLimit`。设置 `0` 禁用(默认 50
- 私信历史可以用 `channels.telegram.dmHistoryLimit`(用户轮次)限制。每用户覆盖:`channels.telegram.dms["<user_id>"].historyLimit`
## 群组激活模式
默认情况下,机器人只响应群组中的提及(`@botname``agents.list[].groupChat.mentionPatterns` 中的模式)。要更改此行为:
### 通过配置(推荐)
```json5
{
channels: {
telegram: {
groups: {
"-1001234567890": { requireMention: false }, // 在此群组中始终响应
},
},
},
}
```
**重要:** 设置 `channels.telegram.groups` 会创建一个**允许列表** - 只有列出的群组(或 `"*"`)会被接受。
论坛话题继承其父群组配置allowFrom、requireMention、skills、prompts除非你在 `channels.telegram.groups.<groupId>.topics.<topicId>` 下添加每话题覆盖。
要允许所有群组并始终响应:
```json5
{
channels: {
telegram: {
groups: {
"*": { requireMention: false }, // 所有群组,始终响应
},
},
},
}
```
要保持所有群组仅提及响应(默认行为):
```json5
{
channels: {
telegram: {
groups: {
"*": { requireMention: true }, // 或完全省略 groups
},
},
},
}
```
### 通过命令(会话级别)
在群组中发送:
- `/activation always` - 响应所有消息
- `/activation mention` - 需要提及(默认)
**注意:** 命令只更新会话状态。要在重启后保持持久行为,请使用配置。
### 获取群组聊天 ID
将群组中的任何消息转发给 Telegram 上的 `@userinfobot``@getidsbot` 以查看聊天 ID负数`-1001234567890`)。
**提示:** 要获取你自己的用户 ID私信机器人它会回复你的用户 ID配对消息或者在命令启用后使用 `/whoami`
**隐私注意:** `@userinfobot` 是第三方机器人。如果你更倾向于其他方式,将机器人添加到群组,发送一条消息,然后使用 `openclaw logs --follow` 读取 `chat.id`,或使用 Bot API `getUpdates`
## 配置写入
默认情况下Telegram 允许写入由渠道事件或 `/config set|unset` 触发的配置更新。
这发生在以下情况:
- 群组升级为超级群组Telegram 发出 `migrate_to_chat_id`(聊天 ID 更改。OpenClaw 可以自动迁移 `channels.telegram.groups`
- 你在 Telegram 聊天中运行 `/config set``/config unset`(需要 `commands.config: true`)。
禁用方式:
```json5
{
channels: { telegram: { configWrites: false } },
}
```
## 话题(论坛超级群组)
Telegram 论坛话题在每条消息中包含 `message_thread_id`。OpenClaw
-`:topic:<threadId>` 附加到 Telegram 群组会话键,使每个话题隔离。
- 发送输入指示器和回复时带上 `message_thread_id`,使响应保持在话题内。
- 通用话题(线程 id `1`)是特殊的:消息发送省略 `message_thread_id`Telegram 会拒绝),但输入指示器仍然包含它。
- 在模板上下文中暴露 `MessageThreadId` + `IsForum` 用于路由/模板。
- 话题特定配置可在 `channels.telegram.groups.<chatId>.topics.<threadId>` 下设置skills、允许列表、自动回复、系统提示、禁用
- 话题配置继承群组设置requireMention、允许列表、skills、提示、enabled除非每话题覆盖。
私聊在某些边缘情况下可能包含 `message_thread_id`。OpenClaw 保持私信会话键不变,但在存在线程 id 时仍将其用于回复/草稿流式传输。
## 内联按钮
Telegram 支持带回调按钮的内联键盘。
```json5
{
channels: {
telegram: {
capabilities: {
inlineButtons: "allowlist",
},
},
},
}
```
对于每账户配置:
```json5
{
channels: {
telegram: {
accounts: {
main: {
capabilities: {
inlineButtons: "allowlist",
},
},
},
},
},
}
```
作用域:
- `off` — 禁用内联按钮
- `dm` — 仅私信(群组目标被阻止)
- `group` — 仅群组(私信目标被阻止)
- `all` — 私信 + 群组
- `allowlist` — 私信 + 群组,但仅限 `allowFrom`/`groupAllowFrom` 允许的发送者(与控制命令规则相同)
默认:`allowlist`
旧版:`capabilities: ["inlineButtons"]` = `inlineButtons: "all"`
### 发送按钮
使用带 `buttons` 参数的消息工具:
```json5
{
action: "send",
channel: "telegram",
to: "123456789",
message: "选择一个选项:",
buttons: [
[
{ text: "是", callback_data: "yes" },
{ text: "否", callback_data: "no" },
],
[{ text: "取消", callback_data: "cancel" }],
],
}
```
当用户点击按钮时,回调数据会以以下格式作为消息发送回智能体:
`callback_data: value`
### 配置选项
Telegram 功能可以在两个级别配置(上面显示的对象形式;旧版字符串数组仍然支持):
- `channels.telegram.capabilities`:应用于所有 Telegram 账户的全局默认功能配置,除非被覆盖。
- `channels.telegram.accounts.<account>.capabilities`:每账户功能,覆盖该特定账户的全局默认值。
当所有 Telegram 机器人/账户应具有相同行为时使用全局设置。当不同机器人需要不同行为时使用每账户配置(例如,一个账户只处理私信,而另一个允许在群组中使用)。
## 访问控制(私信 + 群组)
### 私信访问
- 默认:`channels.telegram.dmPolicy = "pairing"`。未知发送者收到配对码;在批准之前消息被忽略(配对码 1 小时后过期)。
- 批准方式:
- `openclaw pairing list telegram`
- `openclaw pairing approve telegram <CODE>`
- 配对是 Telegram 私信使用的默认 token 交换。详情:[配对](/channels/pairing)
- `channels.telegram.allowFrom` 接受数字用户 ID推荐`@username` 条目。这**不是**机器人用户名;使用人类发送者的 ID。向导接受 `@username` 并在可能时将其解析为数字 ID。
#### 查找你的 Telegram 用户 ID
更安全(无第三方机器人):
1. 启动 Gateway 网关并私信你的机器人。
2. 运行 `openclaw logs --follow` 并查找 `from.id`
备选(官方 Bot API
1. 私信你的机器人。
2. 使用你的机器人 token 获取更新并读取 `message.from.id`
```bash
curl "https://api.telegram.org/bot<bot_token>/getUpdates"
```
第三方(隐私性较低):
- 私信 `@userinfobot` 或 `@getidsbot` 并使用返回的用户 id。
### 群组访问
两个独立的控制:
**1. 允许哪些群组**(通过 `channels.telegram.groups` 的群组允许列表):
- 无 `groups` 配置 = 允许所有群组
- 有 `groups` 配置 = 只允许列出的群组或 `"*"`
- 示例:`"groups": { "-1001234567890": {}, "*": {} }` 允许所有群组
**2. 允许哪些发送者**(通过 `channels.telegram.groupPolicy` 的发送者过滤):
- `"open"` = 允许群组中的所有发送者发消息
- `"allowlist"` = 只有 `channels.telegram.groupAllowFrom` 中的发送者可以发消息
- `"disabled"` = 不接受任何群组消息
默认是 `groupPolicy: "allowlist"`(除非添加 `groupAllowFrom` 否则被阻止)。
大多数用户需要:`groupPolicy: "allowlist"` + `groupAllowFrom` + 在 `channels.telegram.groups` 中列出特定群组
## 长轮询 vs webhook
- 默认:长轮询(不需要公共 URL
- Webhook 模式:设置 `channels.telegram.webhookUrl` 和 `channels.telegram.webhookSecret`(可选 `channels.telegram.webhookPath`)。
- 本地监听器绑定到 `0.0.0.0:8787`,默认服务于 `POST /telegram-webhook`。
- 如果你的公共 URL 不同,使用反向代理并将 `channels.telegram.webhookUrl` 指向公共端点。
## 回复线程
Telegram 通过标签支持可选的线程回复:
- `[[reply_to_current]]` -- 回复触发消息。
- `[[reply_to:<id>]]` -- 回复特定消息 id。
通过 `channels.telegram.replyToMode` 控制:
- `first`(默认)、`all`、`off`。
## 音频消息(语音 vs 文件)
Telegram 区分**语音备忘录**(圆形气泡)和**音频文件**(元数据卡片)。
OpenClaw 默认使用音频文件以保持向后兼容性。
要在智能体回复中强制使用语音备忘录气泡,在回复中的任何位置包含此标签:
- `[[audio_as_voice]]` — 将音频作为语音备忘录而不是文件发送。
该标签会从发送的文本中去除。其他渠道会忽略此标签。
对于消息工具发送,设置 `asVoice: true` 并配合兼容语音的音频 `media` URL当存在 media 时 `message` 是可选的):
```json5
{
action: "send",
channel: "telegram",
to: "123456789",
media: "https://example.com/voice.ogg",
asVoice: true,
}
```
## 贴纸
OpenClaw 支持接收和发送 Telegram 贴纸,并具有智能缓存功能。
### 接收贴纸
当用户发送贴纸时OpenClaw 根据贴纸类型处理:
- **静态贴纸WEBP** 下载并通过视觉处理。贴纸在消息内容中显示为 `<media:sticker>` 占位符。
- **动画贴纸TGS** 跳过Lottie 格式不支持处理)。
- **视频贴纸WEBM** 跳过(视频格式不支持处理)。
接收贴纸时可用的模板上下文字段:
- `Sticker` — 包含以下属性的对象:
- `emoji` — 与贴纸关联的表情符号
- `setName` — 贴纸集名称
- `fileId` — Telegram 文件 ID用于发送相同贴纸
- `fileUniqueId` — 用于缓存查找的稳定 ID
- `cachedDescription` — 可用时的缓存视觉描述
### 贴纸缓存
贴纸通过 AI 的视觉功能处理以生成描述。由于相同的贴纸经常重复发送OpenClaw 缓存这些描述以避免冗余的 API 调用。
**工作原理:**
1. **首次遇到:** 贴纸图像被发送给 AI 进行视觉分析。AI 生成描述(例如"一只卡通猫热情地挥手")。
2. **缓存存储:** 描述与贴纸的文件 ID、表情符号和集合名称一起保存。
3. **后续遇到:** 当再次看到相同贴纸时,直接使用缓存的描述。图像不会发送给 AI。
**缓存位置:** `~/.openclaw/telegram/sticker-cache.json`
**缓存条目格式:**
```json
{
"fileId": "CAACAgIAAxkBAAI...",
"fileUniqueId": "AgADBAADb6cxG2Y",
"emoji": "👋",
"setName": "CoolCats",
"description": "一只卡通猫热情地挥手",
"cachedAt": "2026-01-15T10:30:00.000Z"
}
```
**优点:**
- 通过避免对相同贴纸重复调用视觉 API 来降低 API 成本
- 缓存贴纸响应更快(无视觉处理延迟)
- 基于缓存描述启用贴纸搜索功能
缓存在接收贴纸时自动填充。无需手动缓存管理。
### 发送贴纸
智能体可以使用 `sticker` 和 `sticker-search` 动作发送和搜索贴纸。这些默认禁用,必须在配置中启用:
```json5
{
channels: {
telegram: {
actions: {
sticker: true,
},
},
},
}
```
**发送贴纸:**
```json5
{
action: "sticker",
channel: "telegram",
to: "123456789",
fileId: "CAACAgIAAxkBAAI...",
}
```
参数:
- `fileId`(必需)— 贴纸的 Telegram 文件 ID。从接收贴纸时的 `Sticker.fileId` 获取,或从 `sticker-search` 结果获取。
- `replyTo`(可选)— 要回复的消息 ID。
- `threadId`(可选)— 论坛话题的消息线程 ID。
**搜索贴纸:**
智能体可以按描述、表情符号或集合名称搜索缓存的贴纸:
```json5
{
action: "sticker-search",
channel: "telegram",
query: "猫 挥手",
limit: 5,
}
```
返回缓存中匹配的贴纸:
```json5
{
ok: true,
count: 2,
stickers: [
{
fileId: "CAACAgIAAxkBAAI...",
emoji: "👋",
description: "一只卡通猫热情地挥手",
setName: "CoolCats",
},
],
}
```
搜索在描述文本、表情符号字符和集合名称之间使用模糊匹配。
**带线程的示例:**
```json5
{
action: "sticker",
channel: "telegram",
to: "-1001234567890",
fileId: "CAACAgIAAxkBAAI...",
replyTo: 42,
threadId: 123,
}
```
## 流式传输(草稿)
Telegram 可以在智能体生成响应时流式传输**草稿气泡**。
OpenClaw 使用 Bot API `sendMessageDraft`(不是真实消息),然后将最终回复作为普通消息发送。
要求Telegram Bot API 9.3+
- **启用话题的私聊**(机器人的论坛话题模式)。
- 入站消息必须包含 `message_thread_id`(私有话题线程)。
- 群组/超级群组/频道的流式传输被忽略。
配置:
- `channels.telegram.streamMode: "off" | "partial" | "block"`(默认:`partial`
- `partial`:用最新的流式文本更新草稿气泡。
- `block`:以较大块(分块)更新草稿气泡。
- `off`:禁用草稿流式传输。
- 可选(仅用于 `streamMode: "block"`
- `channels.telegram.draftChunk: { minChars?, maxChars?, breakPreference? }`
- 默认值:`minChars: 200`、`maxChars: 800`、`breakPreference: "paragraph"`(限制在 `channels.telegram.textChunkLimit` 内)。
注意:草稿流式传输与**分块流式传输**(渠道消息)不同。
分块流式传输默认关闭,如果你想要早期 Telegram 消息而不是草稿更新,需要 `channels.telegram.blockStreaming: true`。
推理流(仅限 Telegram
- `/reasoning stream` 在回复生成时将推理流式传输到草稿气泡中,然后发送不带推理的最终答案。
- 如果 `channels.telegram.streamMode` 为 `off`,推理流被禁用。
更多上下文:[流式传输 + 分块](/concepts/streaming)。
## 重试策略
出站 Telegram API 调用在遇到临时网络/429 错误时会以指数退避和抖动进行重试。通过 `channels.telegram.retry` 配置。参见[重试策略](/concepts/retry)。
## 智能体工具(消息 + 反应)
- 工具:`telegram`,使用 `sendMessage` 动作(`to`、`content`,可选 `mediaUrl`、`replyToMessageId`、`messageThreadId`)。
- 工具:`telegram`,使用 `react` 动作(`chatId`、`messageId`、`emoji`)。
- 工具:`telegram`,使用 `deleteMessage` 动作(`chatId`、`messageId`)。
- 反应移除语义:参见 [/tools/reactions](/tools/reactions)。
- 工具门控:`channels.telegram.actions.reactions`、`channels.telegram.actions.sendMessage`、`channels.telegram.actions.deleteMessage`(默认:启用),以及 `channels.telegram.actions.sticker`(默认:禁用)。
## 反应通知
**反应工作原理:**
Telegram 反应作为**单独的 `message_reaction` 事件**到达而不是消息负载中的属性。当用户添加反应时OpenClaw
1. 从 Telegram API 接收 `message_reaction` 更新
2. 将其转换为**系统事件**,格式为:`"Telegram reaction added: {emoji} by {user} on msg {id}"`
3. 使用与常规消息**相同的会话键**将系统事件加入队列
4. 当该对话中的下一条消息到达时,系统事件被排出并前置到智能体的上下文中
智能体将反应视为对话历史中的**系统通知**,而不是消息元数据。
**配置:**
- `channels.telegram.reactionNotifications`:控制哪些反应触发通知
- `"off"` — 忽略所有反应
- `"own"` — 当用户对机器人消息做出反应时通知(尽力而为;内存中)(默认)
- `"all"` — 通知所有反应
- `channels.telegram.reactionLevel`:控制智能体的反应能力
- `"off"` — 智能体不能对消息做出反应
- `"ack"` — 机器人发送确认反应(处理时显示 👀)(默认)
- `"minimal"` — 智能体可以少量反应(指导:每 5-10 次交换 1 次)
- `"extensive"` — 智能体可以在适当时自由反应
**论坛群组:** 论坛群组中的反应包含 `message_thread_id`,使用类似 `agent:main:telegram:group:{chatId}:topic:{threadId}` 的会话键。这确保同一话题中的反应和消息保持在一起。
**示例配置:**
```json5
{
channels: {
telegram: {
reactionNotifications: "all", // 查看所有反应
reactionLevel: "minimal", // 智能体可以少量反应
},
},
}
```
**要求:**
- Telegram 机器人必须在 `allowed_updates` 中明确请求 `message_reaction`(由 OpenClaw 自动配置)
- 对于 webhook 模式,反应包含在 webhook `allowed_updates` 中
- 对于轮询模式,反应包含在 `getUpdates` `allowed_updates` 中
## 投递目标CLI/cron
- 使用聊天 id`123456789`)或用户名(`@name`)作为目标。
- 示例:`openclaw message send --channel telegram --target 123456789 --message "hi"`。
## 故障排除
**机器人不响应群组中的非提及消息:**
- 如果你设置了 `channels.telegram.groups.*.requireMention=false`Telegram 的 Bot API **隐私模式**必须禁用。
- BotFather`/setprivacy` → **Disable**(然后从群组中移除并重新添加机器人)
- `openclaw channels status` 在配置期望未提及群组消息时显示警告。
- `openclaw channels status --probe` 可以额外检查显式数字群组 ID 的成员资格(它无法审计通配符 `"*"` 规则)。
- 快速测试:`/activation always`(仅会话级别;使用配置以持久化)
**机器人完全看不到群组消息:**
- 如果设置了 `channels.telegram.groups`,群组必须被列出或使用 `"*"`
- 在 @BotFather 中检查隐私设置 →"Group Privacy"应为 **OFF**
- 验证机器人确实是成员(不仅仅是没有读取权限的管理员)
- 检查 Gateway 网关日志:`openclaw logs --follow`(查找"skipping group message"
**机器人响应提及但不响应 `/activation always`**
- `/activation` 命令更新会话状态但不持久化到配置
- 要持久化行为,将群组添加到 `channels.telegram.groups` 并设置 `requireMention: false`
**像 `/status` 这样的命令不起作用:**
- 确保你的 Telegram 用户 ID 已授权(通过配对或 `channels.telegram.allowFrom`
- 即使在 `groupPolicy: "open"` 的群组中,命令也需要授权
**长轮询在 Node 22+ 上立即中止(通常与代理/自定义 fetch 有关):**
- Node 22+ 对 `AbortSignal` 实例更严格;外部信号可以立即中止 `fetch` 调用。
- 升级到规范化中止信号的 OpenClaw 构建版本,或在可以升级之前在 Node 20 上运行 Gateway 网关。
**机器人启动后静默停止响应(或日志显示 `HttpError: Network request ... failed`**
- 某些主机首先将 `api.telegram.org` 解析为 IPv6。如果你的服务器没有可用的 IPv6 出口grammY 可能会卡在仅 IPv6 的请求上。
- 通过启用 IPv6 出口**或**强制 `api.telegram.org` 使用 IPv4 解析来修复(例如,使用 IPv4 A 记录添加 `/etc/hosts` 条目,或在你的 OS DNS 堆栈中优先使用 IPv4然后重启 Gateway 网关。
- 快速检查:`dig +short api.telegram.org A` 和 `dig +short api.telegram.org AAAA` 确认 DNS 返回的内容。
## 配置参考Telegram
完整配置:[配置](/gateway/configuration)
提供商选项:
- `channels.telegram.enabled`:启用/禁用渠道启动。
- `channels.telegram.botToken`:机器人 tokenBotFather
- `channels.telegram.tokenFile`:从文件路径读取 token。
- `channels.telegram.dmPolicy``pairing | allowlist | open | disabled`默认pairing
- `channels.telegram.allowFrom`私信允许列表id/用户名)。`open` 需要 `"*"`。
- `channels.telegram.groupPolicy``open | allowlist | disabled`默认allowlist
- `channels.telegram.groupAllowFrom`群组发送者允许列表id/用户名)。
- `channels.telegram.groups`:每群组默认值 + 允许列表(使用 `"*"` 作为全局默认值)。
- `channels.telegram.groups.<id>.requireMention`:提及门控默认值。
- `channels.telegram.groups.<id>.skills`skill 过滤器(省略 = 所有 skills空 = 无)。
- `channels.telegram.groups.<id>.allowFrom`:每群组发送者允许列表覆盖。
- `channels.telegram.groups.<id>.systemPrompt`:群组的额外系统提示。
- `channels.telegram.groups.<id>.enabled`:为 `false` 时禁用群组。
- `channels.telegram.groups.<id>.topics.<threadId>.*`:每话题覆盖(与群组相同的字段)。
- `channels.telegram.groups.<id>.topics.<threadId>.requireMention`:每话题提及门控覆盖。
- `channels.telegram.capabilities.inlineButtons``off | dm | group | all | allowlist`默认allowlist
- `channels.telegram.accounts.<account>.capabilities.inlineButtons`:每账户覆盖。
- `channels.telegram.replyToMode``off | first | all`(默认:`off`)。
- `channels.telegram.textChunkLimit`:出站分块大小(字符)。
- `channels.telegram.chunkMode``length`(默认)或 `newline` 在长度分块之前按空行(段落边界)分割。
- `channels.telegram.linkPreview`切换出站消息的链接预览默认true
- `channels.telegram.streamMode``off | partial | block`(草稿流式传输)。
- `channels.telegram.mediaMaxMb`:入站/出站媒体上限MB
- `channels.telegram.retry`:出站 Telegram API 调用的重试策略attempts、minDelayMs、maxDelayMs、jitter
- `channels.telegram.network.autoSelectFamily`:覆盖 Node autoSelectFamilytrue=启用false=禁用)。在 Node 22 上默认禁用以避免 Happy Eyeballs 超时。
- `channels.telegram.proxy`Bot API 调用的代理 URLSOCKS/HTTP
- `channels.telegram.webhookUrl`:启用 webhook 模式(需要 `channels.telegram.webhookSecret`)。
- `channels.telegram.webhookSecret`webhook 密钥(设置 webhookUrl 时必需)。
- `channels.telegram.webhookPath`:本地 webhook 路径(默认 `/telegram-webhook`)。
- `channels.telegram.actions.reactions`:门控 Telegram 工具反应。
- `channels.telegram.actions.sendMessage`:门控 Telegram 工具消息发送。
- `channels.telegram.actions.deleteMessage`:门控 Telegram 工具消息删除。
- `channels.telegram.actions.sticker`:门控 Telegram 贴纸动作 — 发送和搜索默认false
- `channels.telegram.reactionNotifications``off | own | all` — 控制哪些反应触发系统事件(未设置时默认:`own`)。
- `channels.telegram.reactionLevel``off | ack | minimal | extensive` — 控制智能体的反应能力(未设置时默认:`minimal`)。
相关全局选项:
- `agents.list[].groupChat.mentionPatterns`(提及门控模式)。
- `messages.groupChat.mentionPatterns`(全局回退)。
- `commands.native`(默认为 `"auto"` → Telegram/Discord 开启Slack 关闭)、`commands.text`、`commands.useAccessGroups`(命令行为)。使用 `channels.telegram.commands.native` 覆盖。
- `messages.responsePrefix`、`messages.ackReaction`、`messages.ackReactionScope`、`messages.removeAckAfterReply`。

136
content/channels/tlon.md Normal file
View File

@@ -0,0 +1,136 @@
---
read_when:
- 开发 Tlon/Urbit 渠道功能
summary: Tlon/Urbit 支持状态、功能和配置
title: Tlon
x-i18n:
generated_at: "2026-02-03T07:44:17Z"
model: claude-opus-4-5
provider: pi
source_hash: 19d7ffe23e82239fd2a2e35913e0d52c809b2c2b939dd39184e6c27a539ed97d
source_path: channels/tlon.md
workflow: 15
---
# Tlon插件
Tlon 是一个基于 Urbit 构建的去中心化即时通讯工具。OpenClaw 连接到你的 Urbit ship可以响应私信和群聊消息。群组回复默认需要 @ 提及,并可通过允许列表进一步限制。
状态通过插件支持。支持私信、群组提及、话题回复和纯文本媒体回退URL 附加到说明文字)。不支持表情回应、投票和原生媒体上传。
## 需要插件
Tlon 作为插件提供,不包含在核心安装中。
通过 CLI 安装npm 仓库):
```bash
openclaw plugins install @openclaw/tlon
```
本地检出(从 git 仓库运行时):
```bash
openclaw plugins install ./extensions/tlon
```
详情:[插件](/tools/plugin)
## 设置
1. 安装 Tlon 插件。
2. 获取你的 ship URL 和登录代码。
3. 配置 `channels.tlon`
4. 重启 Gateway 网关。
5. 私信机器人或在群组频道中提及它。
最小配置(单账户):
```json5
{
channels: {
tlon: {
enabled: true,
ship: "~sampel-palnet",
url: "https://your-ship-host",
code: "lidlut-tabwed-pillex-ridrup",
},
},
}
```
## 群组频道
默认启用自动发现。你也可以手动固定频道:
```json5
{
channels: {
tlon: {
groupChannels: ["chat/~host-ship/general", "chat/~host-ship/support"],
},
},
}
```
禁用自动发现:
```json5
{
channels: {
tlon: {
autoDiscoverChannels: false,
},
},
}
```
## 访问控制
私信允许列表(空 = 允许全部):
```json5
{
channels: {
tlon: {
dmAllowlist: ["~zod", "~nec"],
},
},
}
```
群组授权(默认受限):
```json5
{
channels: {
tlon: {
defaultAuthorizedShips: ["~zod"],
authorization: {
channelRules: {
"chat/~host-ship/general": {
mode: "restricted",
allowedShips: ["~zod", "~nec"],
},
"chat/~host-ship/announcements": {
mode: "open",
},
},
},
},
},
}
```
## 投递目标CLI/cron
`openclaw message send` 或 cron 投递一起使用:
- 私信:`~sampel-palnet``dm/~sampel-palnet`
- 群组:`chat/~host-ship/channel``group:~host-ship/channel`
## 注意事项
- 群组回复需要提及(例如 `~your-bot-ship`)才能响应。
- 话题回复如果入站消息在话题中OpenClaw 会在话题内回复。
- 媒体:`sendMedia` 回退为文本 + URL无原生上传

View File

@@ -0,0 +1,36 @@
---
read_when:
- 渠道已连接但消息无法流通
- 排查渠道配置错误(意图、权限、隐私模式)
summary: 渠道专属故障排除快捷指南Discord/Telegram/WhatsApp
title: 渠道故障排除
x-i18n:
generated_at: "2026-02-01T19:58:09Z"
model: claude-opus-4-5
provider: pi
source_hash: 6542ee86b3e50929caeaab127642d135dfbc0d8a44876ec2df0fff15bf57cd63
source_path: channels/troubleshooting.md
workflow: 14
---
# 渠道故障排除
首先运行:
```bash
openclaw doctor
openclaw channels status --probe
```
`channels status --probe` 会在检测到常见渠道配置错误时输出警告,并包含小型实时检查(凭据、部分权限/成员资格)。
## 渠道
- Discord[/channels/discord#troubleshooting](/channels/discord#troubleshooting)
- Telegram[/channels/telegram#troubleshooting](/channels/telegram#troubleshooting)
- WhatsApp[/channels/whatsapp#troubleshooting-quick](/channels/whatsapp#troubleshooting-quick)
## Telegram 快速修复
- 日志显示 `HttpError: Network request for 'sendMessage' failed``sendChatAction` → 检查 IPv6 DNS。如果 `api.telegram.org` 优先解析为 IPv6 而主机缺少 IPv6 出站连接,请强制使用 IPv4 或启用 IPv6。参见 [/channels/telegram#troubleshooting](/channels/telegram#troubleshooting)。
- 日志显示 `setMyCommands failed` → 检查到 `api.telegram.org` 的出站 HTTPS 和 DNS 可达性(常见于限制严格的 VPS 或代理环境)。

385
content/channels/twitch.md Normal file
View File

@@ -0,0 +1,385 @@
---
read_when:
- 为 OpenClaw 设置 Twitch 聊天集成
summary: Twitch 聊天机器人配置和设置
title: Twitch
x-i18n:
generated_at: "2026-02-03T07:44:41Z"
model: claude-opus-4-5
provider: pi
source_hash: 0dd1c05bef570470d8b82c1f6dee5337e8b76b57269c5cad6aee2e711483f8ba
source_path: channels/twitch.md
workflow: 15
---
# Twitch插件
通过 IRC 连接支持 Twitch 聊天。OpenClaw 以 Twitch 用户(机器人账户)身份连接,在频道中接收和发送消息。
## 需要插件
Twitch 作为插件发布,未与核心安装捆绑。
通过 CLI 安装npm 注册表):
```bash
openclaw plugins install @openclaw/twitch
```
本地检出(从 git 仓库运行时):
```bash
openclaw plugins install ./extensions/twitch
```
详情:[插件](/tools/plugin)
## 快速设置(新手)
1. 为机器人创建一个专用的 Twitch 账户(或使用现有账户)。
2. 生成凭证:[Twitch Token Generator](https://twitchtokengenerator.com/)
- 选择 **Bot Token**
- 确认已选择 `chat:read``chat:write` 权限范围
- 复制 **Client ID****Access Token**
3. 查找你的 Twitch 用户 IDhttps://www.streamweasels.com/tools/convert-twitch-username-to-user-id/
4. 配置令牌:
- 环境变量:`OPENCLAW_TWITCH_ACCESS_TOKEN=...`(仅限默认账户)
- 或配置:`channels.twitch.accessToken`
- 如果两者都设置,配置优先(环境变量回退仅适用于默认账户)。
5. 启动 Gateway 网关。
**⚠️ 重要:** 添加访问控制(`allowFrom``allowedRoles`)以防止未授权用户触发机器人。`requireMention` 默认为 `true`
最小配置:
```json5
{
channels: {
twitch: {
enabled: true,
username: "openclaw", // 机器人的 Twitch 账户
accessToken: "oauth:abc123...", // OAuth Access Token或使用 OPENCLAW_TWITCH_ACCESS_TOKEN 环境变量)
clientId: "xyz789...", // Token Generator 中的 Client ID
channel: "vevisk", // 要加入的 Twitch 频道聊天(必填)
allowFrom: ["123456789"], // (推荐)仅限你的 Twitch 用户 ID - 从 https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/ 获取
},
},
}
```
## 它是什么
- 由 Gateway 网关拥有的 Twitch 渠道。
- 确定性路由:回复总是返回到 Twitch。
- 每个账户映射到一个隔离的会话键 `agent:<agentId>:twitch:<accountName>`
- `username` 是机器人账户(进行身份验证的账户),`channel` 是要加入的聊天室。
## 设置(详细)
### 生成凭证
使用 [Twitch Token Generator](https://twitchtokengenerator.com/)
- 选择 **Bot Token**
- 确认已选择 `chat:read``chat:write` 权限范围
- 复制 **Client ID****Access Token**
无需手动注册应用。令牌在几小时后过期。
### 配置机器人
**环境变量(仅限默认账户):**
```bash
OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
```
**或配置:**
```json5
{
channels: {
twitch: {
enabled: true,
username: "openclaw",
accessToken: "oauth:abc123...",
clientId: "xyz789...",
channel: "vevisk",
},
},
}
```
如果环境变量和配置都设置了,配置优先。
### 访问控制(推荐)
```json5
{
channels: {
twitch: {
allowFrom: ["123456789"], // (推荐)仅限你的 Twitch 用户 ID
},
},
}
```
优先使用 `allowFrom` 作为硬性允许列表。如果你想要基于角色的访问控制,请改用 `allowedRoles`
**可用角色:** `"moderator"``"owner"``"vip"``"subscriber"``"all"`
**为什么用用户 ID** 用户名可以更改,允许冒充。用户 ID 是永久的。
查找你的 Twitch 用户 IDhttps://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/(将你的 Twitch 用户名转换为 ID
## 令牌刷新(可选)
来自 [Twitch Token Generator](https://twitchtokengenerator.com/) 的令牌无法自动刷新 - 过期时需要重新生成。
要实现自动令牌刷新,请在 [Twitch Developer Console](https://dev.twitch.tv/console) 创建你自己的 Twitch 应用并添加到配置中:
```json5
{
channels: {
twitch: {
clientSecret: "your_client_secret",
refreshToken: "your_refresh_token",
},
},
}
```
机器人会在令牌过期前自动刷新,并记录刷新事件。
## 多账户支持
使用 `channels.twitch.accounts` 配置每个账户的令牌。参阅 [`gateway/configuration`](/gateway/configuration) 了解共享模式。
示例(一个机器人账户在两个频道中):
```json5
{
channels: {
twitch: {
accounts: {
channel1: {
username: "openclaw",
accessToken: "oauth:abc123...",
clientId: "xyz789...",
channel: "vevisk",
},
channel2: {
username: "openclaw",
accessToken: "oauth:def456...",
clientId: "uvw012...",
channel: "secondchannel",
},
},
},
},
}
```
**注意:** 每个账户需要自己的令牌(每个频道一个令牌)。
## 访问控制
### 基于角色的限制
```json5
{
channels: {
twitch: {
accounts: {
default: {
allowedRoles: ["moderator", "vip"],
},
},
},
},
}
```
### 按用户 ID 允许列表(最安全)
```json5
{
channels: {
twitch: {
accounts: {
default: {
allowFrom: ["123456789", "987654321"],
},
},
},
},
}
```
### 基于角色的访问(替代方案)
`allowFrom` 是硬性允许列表。设置后,只允许这些用户 ID。
如果你想要基于角色的访问,请不设置 `allowFrom`,改为配置 `allowedRoles`
```json5
{
channels: {
twitch: {
accounts: {
default: {
allowedRoles: ["moderator"],
},
},
},
},
}
```
### 禁用 @提及要求
默认情况下,`requireMention``true`。要禁用并响应所有消息:
```json5
{
channels: {
twitch: {
accounts: {
default: {
requireMention: false,
},
},
},
},
}
```
## 故障排除
首先,运行诊断命令:
```bash
openclaw doctor
openclaw channels status --probe
```
### 机器人不响应消息
**检查访问控制:** 确保你的用户 ID 在 `allowFrom` 中,或临时移除 `allowFrom` 并设置 `allowedRoles: ["all"]` 来测试。
**检查机器人是否在频道中:** 机器人必须加入 `channel` 中指定的频道。
### 令牌问题
**"Failed to connect"或身份验证错误:**
- 验证 `accessToken` 是 OAuth 访问令牌值(通常以 `oauth:` 前缀开头)
- 检查令牌具有 `chat:read``chat:write` 权限范围
- 如果使用令牌刷新,验证 `clientSecret``refreshToken` 已设置
### 令牌刷新不工作
**检查日志中的刷新事件:**
```
Using env token source for mybot
Access token refreshed for user 123456 (expires in 14400s)
```
如果你看到"token refresh disabled (no refresh token)"
- 确保提供了 `clientSecret`
- 确保提供了 `refreshToken`
## 配置
**账户配置:**
- `username` - 机器人用户名
- `accessToken` - 具有 `chat:read``chat:write` 权限的 OAuth 访问令牌
- `clientId` - Twitch Client ID来自 Token Generator 或你的应用)
- `channel` - 要加入的频道(必填)
- `enabled` - 启用此账户(默认:`true`
- `clientSecret` - 可选:用于自动令牌刷新
- `refreshToken` - 可选:用于自动令牌刷新
- `expiresIn` - 令牌过期时间(秒)
- `obtainmentTimestamp` - 令牌获取时间戳
- `allowFrom` - 用户 ID 允许列表
- `allowedRoles` - 基于角色的访问控制(`"moderator" | "owner" | "vip" | "subscriber" | "all"`
- `requireMention` - 需要 @提及(默认:`true`
**提供商选项:**
- `channels.twitch.enabled` - 启用/禁用渠道启动
- `channels.twitch.username` - 机器人用户名(简化的单账户配置)
- `channels.twitch.accessToken` - OAuth 访问令牌(简化的单账户配置)
- `channels.twitch.clientId` - Twitch Client ID简化的单账户配置
- `channels.twitch.channel` - 要加入的频道(简化的单账户配置)
- `channels.twitch.accounts.<accountName>` - 多账户配置(以上所有账户字段)
完整示例:
```json5
{
channels: {
twitch: {
enabled: true,
username: "openclaw",
accessToken: "oauth:abc123...",
clientId: "xyz789...",
channel: "vevisk",
clientSecret: "secret123...",
refreshToken: "refresh456...",
allowFrom: ["123456789"],
allowedRoles: ["moderator", "vip"],
accounts: {
default: {
username: "mybot",
accessToken: "oauth:abc123...",
clientId: "xyz789...",
channel: "your_channel",
enabled: true,
clientSecret: "secret123...",
refreshToken: "refresh456...",
expiresIn: 14400,
obtainmentTimestamp: 1706092800000,
allowFrom: ["123456789", "987654321"],
allowedRoles: ["moderator"],
},
},
},
},
}
```
## 工具操作
智能体可以调用 `twitch` 执行以下操作:
- `send` - 向频道发送消息
示例:
```json5
{
action: "twitch",
params: {
message: "Hello Twitch!",
to: "#mychannel",
},
}
```
## 安全与运维
- **将令牌视为密码** - 永远不要将令牌提交到 git
- **使用自动令牌刷新** 用于长时间运行的机器人
- **使用用户 ID 允许列表** 而不是用户名进行访问控制
- **监控日志** 查看令牌刷新事件和连接状态
- **最小化令牌权限范围** - 只请求 `chat:read``chat:write`
- **如果卡住**:在确认没有其他进程拥有会话后重启 Gateway 网关
## 限制
- 每条消息 **500 个字符**(在单词边界自动分块)
- 分块前会去除 Markdown
- 无速率限制(使用 Twitch 内置的速率限制)

View File

@@ -0,0 +1,411 @@
---
read_when:
- 处理 WhatsApp/网页渠道行为或收件箱路由时
summary: WhatsApp网页渠道集成登录、收件箱、回复、媒体和运维
title: WhatsApp
x-i18n:
generated_at: "2026-02-03T07:46:24Z"
model: claude-opus-4-5
provider: pi
source_hash: 44fd88f8e269284999e5a5a52b230edae6e6f978528dd298d6a5603d03c0c38d
source_path: channels/whatsapp.md
workflow: 15
---
# WhatsApp网页渠道
状态:仅支持通过 Baileys 的 WhatsApp Web。Gateway 网关拥有会话。
## 快速设置(新手)
1. 如果可能,使用**单独的手机号码**(推荐)。
2.`~/.openclaw/openclaw.json` 中配置 WhatsApp。
3. 运行 `openclaw channels login` 扫描二维码(关联设备)。
4. 启动 Gateway 网关。
最小配置:
```json5
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}
```
## 目标
- 在一个 Gateway 网关进程中支持多个 WhatsApp 账户(多账户)。
- 确定性路由:回复返回到 WhatsApp无模型路由。
- 模型能看到足够的上下文来理解引用回复。
## 配置写入
默认情况下WhatsApp 允许写入由 `/config set|unset` 触发的配置更新(需要 `commands.config: true`)。
禁用方式:
```json5
{
channels: { whatsapp: { configWrites: false } },
}
```
## 架构(谁拥有什么)
- **Gateway 网关**拥有 Baileys socket 和收件箱循环。
- **CLI / macOS 应用**与 Gateway 网关通信;不直接使用 Baileys。
- 发送出站消息需要**活跃的监听器**;否则发送会快速失败。
## 获取手机号码(两种模式)
WhatsApp 需要真实手机号码进行验证。VoIP 和虚拟号码通常会被封锁。在 WhatsApp 上运行 OpenClaw 有两种支持的方式:
### 专用号码(推荐)
为 OpenClaw 使用**单独的手机号码**。最佳用户体验,清晰的路由,无自聊天怪异问题。理想设置:**备用/旧 Android 手机 + eSIM**。保持 Wi-Fi 和电源连接,通过二维码关联。
**WhatsApp Business** 你可以在同一设备上使用不同号码的 WhatsApp Business。非常适合将个人 WhatsApp 分开——安装 WhatsApp Business 并在那里注册 OpenClaw 号码。
**示例配置(专用号码,单用户允许列表):**
```json5
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}
```
**配对模式(可选):**
如果你想使用配对而不是允许列表,请将 `channels.whatsapp.dmPolicy` 设置为 `pairing`。未知发送者会收到配对码;使用以下命令批准:
`openclaw pairing approve whatsapp <code>`
### 个人号码(备选方案)
快速备选方案:在**你自己的号码**上运行 OpenClaw。给自己发消息WhatsApp"给自己发消息")进行测试,这样就不会打扰联系人。在设置和实验期间需要在主手机上阅读验证码。**必须启用自聊天模式。**
当向导询问你的个人 WhatsApp 号码时,输入你将用于发送消息的手机(所有者/发送者),而不是助手号码。
**示例配置(个人号码,自聊天):**
```json
{
"whatsapp": {
"selfChatMode": true,
"dmPolicy": "allowlist",
"allowFrom": ["+15551234567"]
}
}
```
当设置了 `identity.name` 时,自聊天回复默认为 `[{identity.name}]`(否则为 `[openclaw]`
前提是 `messages.responsePrefix` 未设置。明确设置它可以自定义或禁用
前缀(使用 `""` 来移除)。
### 号码获取提示
- **本地 eSIM** 来自你所在国家的移动运营商(最可靠)
- 奥地利:[hot.at](https://www.hot.at)
- 英国:[giffgaff](https://www.giffgaff.com) — 免费 SIM 卡,无合约
- **预付费 SIM 卡** — 便宜,只需接收一条验证短信
**避免:** TextNow、Google Voice、大多数"免费短信"服务——WhatsApp 会积极封锁这些。
**提示:** 该号码只需要接收一条验证短信。之后WhatsApp Web 会话通过 `creds.json` 持久化。
## 为什么不用 Twilio
- 早期 OpenClaw 版本支持 Twilio 的 WhatsApp Business 集成。
- WhatsApp Business 号码不适合个人助手。
- Meta 强制执行 24 小时回复窗口;如果你在过去 24 小时内没有回复,商业号码无法发起新消息。
- 高频或"频繁"使用会触发激进的封锁,因为商业账户不适合发送大量个人助手消息。
- 结果:投递不可靠且频繁被封锁,因此该支持已被移除。
## 登录 + 凭证
- 登录命令:`openclaw channels login`(通过关联设备扫描二维码)。
- 多账户登录:`openclaw channels login --account <id>``<id>` = `accountId`)。
- 默认账户(省略 `--account` 时):如果存在则为 `default`,否则为第一个配置的账户 id排序后
- 凭证存储在 `~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
- 备份副本在 `creds.json.bak`(损坏时恢复)。
- 旧版兼容性:较旧的安装将 Baileys 文件直接存储在 `~/.openclaw/credentials/` 中。
- 登出:`openclaw channels logout`(或 `--account <id>`)删除 WhatsApp 认证状态(但保留共享的 `oauth.json`)。
- 已登出的 socket => 错误提示重新关联。
## 入站流程(私信 + 群组)
- WhatsApp 事件来自 `messages.upsert`Baileys
- 收件箱监听器在关闭时分离,以避免在测试/重启时累积事件处理器。
- 状态/广播聊天被忽略。
- 直接聊天使用 E.164;群组使用群组 JID。
- **私信策略**`channels.whatsapp.dmPolicy` 控制直接聊天访问(默认:`pairing`)。
- 配对:未知发送者会收到配对码(通过 `openclaw pairing approve whatsapp <code>` 批准;码在 1 小时后过期)。
- 开放:需要 `channels.whatsapp.allowFrom` 包含 `"*"`
- 你关联的 WhatsApp 号码是隐式信任的,因此自身消息会跳过 `channels.whatsapp.dmPolicy``channels.whatsapp.allowFrom` 检查。
### 个人号码模式(备选方案)
如果你在**个人 WhatsApp 号码**上运行 OpenClaw请启用 `channels.whatsapp.selfChatMode`(见上面的示例)。
行为:
- 出站私信永远不会触发配对回复(防止打扰联系人)。
- 入站未知发送者仍遵循 `channels.whatsapp.dmPolicy`
- 自聊天模式allowFrom 包含你的号码)避免自动已读回执并忽略提及 JID。
- 非自聊天私信会发送已读回执。
## 已读回执
默认情况下Gateway 网关在接受入站 WhatsApp 消息后将其标记为已读(蓝色勾号)。
全局禁用:
```json5
{
channels: { whatsapp: { sendReadReceipts: false } },
}
```
按账户禁用:
```json5
{
channels: {
whatsapp: {
accounts: {
personal: { sendReadReceipts: false },
},
},
},
}
```
注意事项:
- 自聊天模式始终跳过已读回执。
## WhatsApp 常见问题:发送消息 + 配对
**当我关联 WhatsApp 时OpenClaw 会给随机联系人发消息吗?**
不会。默认私信策略是**配对**,因此未知发送者只会收到配对码,他们的消息**不会被处理**。OpenClaw 只会回复它收到的聊天,或你明确触发的发送(智能体/CLI
**WhatsApp 上的配对是如何工作的?**
配对是未知发送者的私信门控:
- 来自新发送者的第一条私信返回一个短码(消息不会被处理)。
- 使用以下命令批准:`openclaw pairing approve whatsapp <code>`(使用 `openclaw pairing list whatsapp` 列出)。
- 码在 1 小时后过期;每个渠道的待处理请求上限为 3 个。
**多个人可以在一个 WhatsApp 号码上使用不同的 OpenClaw 实例吗?**
可以,通过 `bindings` 将每个发送者路由到不同的智能体peer `kind: "dm"`,发送者 E.164 如 `+15551234567`)。回复仍然来自**同一个 WhatsApp 账户**,直接聊天会折叠到每个智能体的主会话,因此**每人使用一个智能体**。私信访问控制(`dmPolicy`/`allowFrom`)是每个 WhatsApp 账户全局的。参见[多智能体路由](/concepts/multi-agent)。
**为什么向导会询问我的手机号码?**
向导使用它来设置你的**允许列表/所有者**,以便允许你自己的私信。它不会用于自动发送。如果你在个人 WhatsApp 号码上运行,请使用相同的号码并启用 `channels.whatsapp.selfChatMode`
## 消息规范化(模型看到的内容)
- `Body` 是带有信封的当前消息正文。
- 引用回复上下文**始终附加**
```
[Replying to +1555 id:ABC123]
<quoted text or <media:...>>
[/Replying]
```
- 回复元数据也会设置:
- `ReplyToId` = stanzaId
- `ReplyToBody` = 引用正文或媒体占位符
- `ReplyToSender` = 已知时为 E.164
- 纯媒体入站消息使用占位符:
- `<media:image|video|audio|document|sticker>`
## 群组
- 群组映射到 `agent:<agentId>:whatsapp:group:<jid>` 会话。
- 群组策略:`channels.whatsapp.groupPolicy = open|disabled|allowlist`(默认 `allowlist`)。
- 激活模式:
- `mention`(默认):需要 @提及或正则匹配。
- `always`:始终触发。
- `/activation mention|always` 仅限所有者,必须作为独立消息发送。
- 所有者 = `channels.whatsapp.allowFrom`(如果未设置则为自身 E.164)。
- **历史注入**(仅待处理):
- 最近*未处理*的消息(默认 50 条)插入在:
`[Chat messages since your last reply - for context]`(已在会话中的消息不会重新注入)
- 当前消息在:
`[Current message - respond to this]`
- 附加发送者后缀:`[from: Name (+E164)]`
- 群组元数据缓存 5 分钟(主题 + 参与者)。
## 回复投递(线程)
- WhatsApp Web 发送标准消息(当前 Gateway 网关无引用回复线程)。
- 此渠道忽略回复标签。
## 确认表情(收到时自动回应)
WhatsApp 可以在收到传入消息时立即自动发送表情回应,在机器人生成回复之前。这为用户提供即时反馈,表明他们的消息已收到。
**配置:**
```json
{
"whatsapp": {
"ackReaction": {
"emoji": "👀",
"direct": true,
"group": "mentions"
}
}
}
```
**选项:**
- `emoji`(字符串):用于确认的表情(例如"👀"、"✅"、"📨")。为空或省略 = 功能禁用。
- `direct`(布尔值,默认:`true`):在直接/私信聊天中发送表情回应。
- `group`(字符串,默认:`"mentions"`):群聊行为:
- `"always"`:对所有群消息做出回应(即使没有 @提及)
- `"mentions"`:仅在机器人被 @提及时做出回应
- `"never"`:从不在群组中做出回应
**按账户覆盖:**
```json
{
"whatsapp": {
"accounts": {
"work": {
"ackReaction": {
"emoji": "✅",
"direct": false,
"group": "always"
}
}
}
}
}
```
**行为说明:**
- 表情回应在消息收到时**立即**发送,在输入指示器或机器人回复之前。
- 在 `requireMention: false`激活always的群组中`group: "mentions"` 会对所有消息做出回应(不仅仅是 @提及)。
- 即发即忘:表情回应失败会被记录但不会阻止机器人回复。
- 群组表情回应会自动包含参与者 JID。
- WhatsApp 忽略 `messages.ackReaction`;请改用 `channels.whatsapp.ackReaction`。
## 智能体工具(表情回应)
- 工具:`whatsapp`,带有 `react` 动作(`chatJid`、`messageId`、`emoji`,可选 `remove`)。
- 可选:`participant`(群组发送者)、`fromMe`(对自己的消息做出回应)、`accountId`(多账户)。
- 表情移除语义:参见 [/tools/reactions](/tools/reactions)。
- 工具门控:`channels.whatsapp.actions.reactions`(默认:启用)。
## 限制
- 出站文本按 `channels.whatsapp.textChunkLimit` 分块(默认 4000
- 可选换行分块:设置 `channels.whatsapp.chunkMode="newline"` 在长度分块之前按空行(段落边界)分割。
- 入站媒体保存受 `channels.whatsapp.mediaMaxMb` 限制(默认 50 MB
- 出站媒体项受 `agents.defaults.mediaMaxMb` 限制(默认 5 MB
## 出站发送(文本 + 媒体)
- 使用活跃的网页监听器;如果 Gateway 网关未运行则报错。
- 文本分块:每条消息最大 4k可通过 `channels.whatsapp.textChunkLimit` 配置,可选 `channels.whatsapp.chunkMode`)。
- 媒体:
- 支持图片/视频/音频/文档。
- 音频作为 PTT 发送;`audio/ogg` => `audio/ogg; codecs=opus`。
- 仅在第一个媒体项上添加标题。
- 媒体获取支持 HTTP(S) 和本地路径。
- 动画 GIFWhatsApp 期望带有 `gifPlayback: true` 的 MP4 以实现内联循环。
- CLI`openclaw message send --media <mp4> --gif-playback`
- Gateway 网关:`send` 参数包含 `gifPlayback: true`
## 语音消息PTT 音频)
WhatsApp 将音频作为**语音消息**PTT 气泡)发送。
- 最佳效果OGG/Opus。OpenClaw 将 `audio/ogg` 重写为 `audio/ogg; codecs=opus`。
- WhatsApp 忽略 `[[audio_as_voice]]`(音频已作为语音消息发送)。
## 媒体限制 + 优化
- 默认出站上限5 MB每个媒体项
- 覆盖:`agents.defaults.mediaMaxMb`。
- 图片自动优化为上限以下的 JPEG调整大小 + 质量扫描)。
- 超大媒体 => 错误;媒体回复降级为文本警告。
## 心跳
- **Gateway 网关心跳**记录连接健康状态(`web.heartbeatSeconds`,默认 60 秒)。
- **智能体心跳**可以按智能体配置(`agents.list[].heartbeat`)或通过
`agents.defaults.heartbeat` 全局配置(当没有设置按智能体条目时的降级)。
- 使用配置的心跳提示词(默认:`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`+ `HEARTBEAT_OK` 跳过行为。
- 投递默认为最后使用的渠道(或配置的目标)。
## 重连行为
- 退避策略:`web.reconnect`
- `initialMs`、`maxMs`、`factor`、`jitter`、`maxAttempts`。
- 如果达到 maxAttempts网页监控停止降级
- 已登出 => 停止并要求重新关联。
## 配置快速映射
- `channels.whatsapp.dmPolicy`私信策略pairing/allowlist/open/disabled
- `channels.whatsapp.selfChatMode`(同手机设置;机器人使用你的个人 WhatsApp 号码)。
- `channels.whatsapp.allowFrom`私信允许列表。WhatsApp 使用 E.164 手机号码(无用户名)。
- `channels.whatsapp.mediaMaxMb`(入站媒体保存上限)。
- `channels.whatsapp.ackReaction`(消息收到时的自动回应:`{emoji, direct, group}`)。
- `channels.whatsapp.accounts.<accountId>.*`(按账户设置 + 可选 `authDir`)。
- `channels.whatsapp.accounts.<accountId>.mediaMaxMb`(按账户入站媒体上限)。
- `channels.whatsapp.accounts.<accountId>.ackReaction`(按账户确认回应覆盖)。
- `channels.whatsapp.groupAllowFrom`(群组发送者允许列表)。
- `channels.whatsapp.groupPolicy`(群组策略)。
- `channels.whatsapp.historyLimit` / `channels.whatsapp.accounts.<accountId>.historyLimit`(群组历史上下文;`0` 禁用)。
- `channels.whatsapp.dmHistoryLimit`(私信历史限制,按用户轮次)。按用户覆盖:`channels.whatsapp.dms["<phone>"].historyLimit`。
- `channels.whatsapp.groups`(群组允许列表 + 提及门控默认值;使用 `"*"` 允许全部)
- `channels.whatsapp.actions.reactions`(门控 WhatsApp 工具表情回应)。
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`
- `messages.groupChat.historyLimit`
- `channels.whatsapp.messagePrefix`(入站前缀;按账户:`channels.whatsapp.accounts.<accountId>.messagePrefix`;已弃用:`messages.messagePrefix`
- `messages.responsePrefix`(出站前缀)
- `agents.defaults.mediaMaxMb`
- `agents.defaults.heartbeat.every`
- `agents.defaults.heartbeat.model`(可选覆盖)
- `agents.defaults.heartbeat.target`
- `agents.defaults.heartbeat.to`
- `agents.defaults.heartbeat.session`
- `agents.list[].heartbeat.*`(按智能体覆盖)
- `session.*`scope、idle、store、mainKey
- `web.enabled`(为 false 时禁用渠道启动)
- `web.heartbeatSeconds`
- `web.reconnect.*`
## 日志 + 故障排除
- 子系统:`whatsapp/inbound`、`whatsapp/outbound`、`web-heartbeat`、`web-reconnect`。
- 日志文件:`/tmp/openclaw/openclaw-YYYY-MM-DD.log`(可配置)。
- 故障排除指南:[Gateway 网关故障排除](/gateway/troubleshooting)。
## 故障排除(快速)
**未关联 / 需要二维码登录**
- 症状:`channels status` 显示 `linked: false` 或警告"Not linked"。
- 修复:在 Gateway 网关主机上运行 `openclaw channels login` 并扫描二维码WhatsApp → 设置 → 关联设备)。
**已关联但断开连接 / 重连循环**
- 症状:`channels status` 显示 `running, disconnected` 或警告"Linked but disconnected"。
- 修复:`openclaw doctor`(或重启 Gateway 网关)。如果问题持续,通过 `channels login` 重新关联并检查 `openclaw logs --follow`。
**Bun 运行时**
- **不推荐** Bun。WhatsAppBaileys和 Telegram 在 Bun 上不可靠。
请使用 **Node** 运行 Gateway 网关。(参见入门指南运行时说明。)

196
content/channels/zalo.md Normal file
View File

@@ -0,0 +1,196 @@
---
read_when:
- 开发 Zalo 功能或 webhooks
summary: Zalo bot 支持状态、功能和配置
title: Zalo
x-i18n:
generated_at: "2026-02-03T07:44:44Z"
model: claude-opus-4-5
provider: pi
source_hash: 0311d932349f96412b712970b5d37329b91929bf3020536edf3ca0ff464373c0
source_path: channels/zalo.md
workflow: 15
---
# Zalo (Bot API)
状态:实验性。仅支持私信;根据 Zalo 文档,群组即将推出。
## 需要插件
Zalo 以插件形式提供,不包含在核心安装中。
- 通过 CLI 安装:`openclaw plugins install @openclaw/zalo`
- 或在新手引导期间选择 **Zalo** 并确认安装提示
- 详情:[插件](/tools/plugin)
## 快速设置(初学者)
1. 安装 Zalo 插件:
- 从源代码检出:`openclaw plugins install ./extensions/zalo`
- 从 npm如果已发布`openclaw plugins install @openclaw/zalo`
- 或在新手引导中选择 **Zalo** 并确认安装提示
2. 设置 token
- 环境变量:`ZALO_BOT_TOKEN=...`
- 或配置:`channels.zalo.botToken: "..."`
3. 重启 Gateway 网关(或完成新手引导)。
4. 私信访问默认为配对模式;首次联系时批准配对码。
最小配置:
```json5
{
channels: {
zalo: {
enabled: true,
botToken: "12345689:abc-xyz",
dmPolicy: "pairing",
},
},
}
```
## 它是什么
Zalo 是一款专注于越南市场的即时通讯应用;其 Bot API 让 Gateway 网关可以运行一个用于一对一对话的 bot。
它非常适合需要确定性路由回 Zalo 的支持或通知场景。
- 由 Gateway 网关拥有的 Zalo Bot API 渠道。
- 确定性路由:回复返回到 Zalo模型不会选择渠道。
- 私信共享智能体的主会话。
- 群组尚不支持Zalo 文档标注"即将推出")。
## 设置(快速路径)
### 1创建 bot tokenZalo Bot 平台)
1. 前往 **https://bot.zaloplatforms.com** 并登录。
2. 创建新 bot 并配置其设置。
3. 复制 bot token格式`12345689:abc-xyz`)。
### 2配置 token环境变量或配置
示例:
```json5
{
channels: {
zalo: {
enabled: true,
botToken: "12345689:abc-xyz",
dmPolicy: "pairing",
},
},
}
```
环境变量选项:`ZALO_BOT_TOKEN=...`(仅适用于默认账户)。
多账户支持:使用 `channels.zalo.accounts` 配置每账户 token 和可选的 `name`
3. 重启 Gateway 网关。当 token 被解析环境变量或配置Zalo 启动。
4. 私信访问默认为配对模式。当 bot 首次被联系时批准配对码。
## 工作原理(行为)
- 入站消息被规范化为带有媒体占位符的共享渠道信封。
- 回复始终路由回同一 Zalo 聊天。
- 默认使用长轮询;可通过 `channels.zalo.webhookUrl` 启用 webhook 模式。
## 限制
- 出站文本按 2000 字符分块Zalo API 限制)。
- 媒体下载/上传受 `channels.zalo.mediaMaxMb` 限制(默认 5
- 由于 2000 字符限制使流式传输效果不佳,默认阻止流式传输。
## 访问控制(私信)
### 私信访问
- 默认:`channels.zalo.dmPolicy = "pairing"`。未知发送者会收到配对码;消息在批准前会被忽略(配对码 1 小时后过期)。
- 通过以下方式批准:
- `openclaw pairing list zalo`
- `openclaw pairing approve zalo <CODE>`
- 配对是默认的令牌交换方式。详情:[配对](/channels/pairing)
- `channels.zalo.allowFrom` 接受数字用户 ID无用户名查找功能
## 长轮询与 webhook
- 默认:长轮询(不需要公共 URL
- Webhook 模式:设置 `channels.zalo.webhookUrl``channels.zalo.webhookSecret`
- Webhook secret 必须为 8-256 个字符。
- Webhook URL 必须使用 HTTPS。
- Zalo 发送事件时带有 `X-Bot-Api-Secret-Token` 头用于验证。
- Gateway 网关 HTTP 在 `channels.zalo.webhookPath` 处理 webhook 请求(默认为 webhook URL 路径)。
**注意:** 根据 Zalo API 文档getUpdates轮询和 webhook 是互斥的。
## 支持的消息类型
- **文本消息**完全支持2000 字符分块。
- **图片消息**:下载和处理入站图片;通过 `sendPhoto` 发送图片。
- **贴纸**:已记录但未完全处理(无智能体响应)。
- **不支持的类型**:已记录(例如来自受保护用户的消息)。
## 功能
| 功能 | 状态 |
| ------------ | ----------------------------- |
| 私信 | ✅ 支持 |
| 群组 | ❌ 即将推出(根据 Zalo 文档) |
| 媒体(图片) | ✅ 支持 |
| 表情回应 | ❌ 不支持 |
| 主题 | ❌ 不支持 |
| 投票 | ❌ 不支持 |
| 原生命令 | ❌ 不支持 |
| 流式传输 | ⚠️ 已阻止2000 字符限制) |
## 投递目标CLI/cron
- 使用聊天 id 作为目标。
- 示例:`openclaw message send --channel zalo --target 123456789 --message "hi"`
## 故障排除
**Bot 不响应:**
- 检查 token 是否有效:`openclaw channels status --probe`
- 验证发送者已被批准(配对或 allowFrom
- 检查 Gateway 网关日志:`openclaw logs --follow`
**Webhook 未收到事件:**
- 确保 webhook URL 使用 HTTPS
- 验证 secret token 为 8-256 个字符
- 确认 Gateway 网关 HTTP 端点在配置的路径上可访问
- 检查 getUpdates 轮询未在运行(它们是互斥的)
## 配置参考Zalo
完整配置:[配置](/gateway/configuration)
提供商选项:
- `channels.zalo.enabled`:启用/禁用渠道启动。
- `channels.zalo.botToken`:来自 Zalo Bot 平台的 bot token。
- `channels.zalo.tokenFile`:从文件路径读取 token。
- `channels.zalo.dmPolicy``pairing | allowlist | open | disabled`默认pairing
- `channels.zalo.allowFrom`:私信允许列表(用户 ID`open` 需要 `"*"`。向导会询问数字 ID。
- `channels.zalo.mediaMaxMb`:入站/出站媒体上限MB默认 5
- `channels.zalo.webhookUrl`:启用 webhook 模式(需要 HTTPS
- `channels.zalo.webhookSecret`webhook secret8-256 字符)。
- `channels.zalo.webhookPath`Gateway 网关 HTTP 服务器上的 webhook 路径。
- `channels.zalo.proxy`API 请求的代理 URL。
多账户选项:
- `channels.zalo.accounts.<id>.botToken`:每账户 token。
- `channels.zalo.accounts.<id>.tokenFile`:每账户 token 文件。
- `channels.zalo.accounts.<id>.name`:显示名称。
- `channels.zalo.accounts.<id>.enabled`:启用/禁用账户。
- `channels.zalo.accounts.<id>.dmPolicy`:每账户私信策略。
- `channels.zalo.accounts.<id>.allowFrom`:每账户允许列表。
- `channels.zalo.accounts.<id>.webhookUrl`:每账户 webhook URL。
- `channels.zalo.accounts.<id>.webhookSecret`:每账户 webhook secret。
- `channels.zalo.accounts.<id>.webhookPath`:每账户 webhook 路径。
- `channels.zalo.accounts.<id>.proxy`:每账户代理 URL。

View File

@@ -0,0 +1,147 @@
---
read_when:
- 为 OpenClaw 设置 Zalo Personal
- 调试 Zalo Personal 登录或消息流程
summary: 通过 zca-cliQR 登录)支持 Zalo 个人账户、功能和配置
title: Zalo Personal
x-i18n:
generated_at: "2026-02-03T07:44:34Z"
model: claude-opus-4-5
provider: pi
source_hash: 2a249728d556e5cc52274627bdaf390fa10e815afa04f4497feb57a2a0cb9261
source_path: channels/zalouser.md
workflow: 15
---
# Zalo Personal非官方
状态:实验性。此集成通过 `zca-cli` 自动化**个人 Zalo 账户**。
> **警告:**这是一个非官方集成,可能导致账户被暂停/封禁。使用风险自负。
## 需要插件
Zalo Personal 作为插件提供,不包含在核心安装中。
- 通过 CLI 安装:`openclaw plugins install @openclaw/zalouser`
- 或从源码检出安装:`openclaw plugins install ./extensions/zalouser`
- 详情:[插件](/tools/plugin)
## 前置条件zca-cli
Gateway 网关机器必须在 `PATH` 中有可用的 `zca` 二进制文件。
- 验证:`zca --version`
- 如果缺失,请安装 zca-cli参见 `extensions/zalouser/README.md` 或上游 zca-cli 文档)。
## 快速设置(新手)
1. 安装插件(见上文)。
2. 登录QR在 Gateway 网关机器上):
- `openclaw channels login --channel zalouser`
- 用 Zalo 手机应用扫描终端中的二维码。
3. 启用渠道:
```json5
{
channels: {
zalouser: {
enabled: true,
dmPolicy: "pairing",
},
},
}
```
4. 重启 Gateway 网关(或完成新手引导)。
5. 私信访问默认为配对模式;首次联系时批准配对码。
## 这是什么
- 使用 `zca listen` 接收入站消息。
- 使用 `zca msg ...` 发送回复(文本/媒体/链接)。
- 专为"个人账户"使用场景设计,适用于 Zalo Bot API 不可用的情况。
## 命名
渠道 ID 为 `zalouser`,以明确表示这是自动化**个人 Zalo 用户账户**(非官方)。我们保留 `zalo` 用于未来可能的官方 Zalo API 集成。
## 查找 ID目录
使用目录 CLI 发现联系人/群组及其 ID
```bash
openclaw directory self --channel zalouser
openclaw directory peers list --channel zalouser --query "name"
openclaw directory groups list --channel zalouser --query "work"
```
## 限制
- 出站文本分块为约 2000 字符Zalo 客户端限制)。
- 默认阻止流式传输。
## 访问控制(私信)
`channels.zalouser.dmPolicy` 支持:`pairing | allowlist | open | disabled`(默认:`pairing`)。
`channels.zalouser.allowFrom` 接受用户 ID 或名称。向导会在可用时通过 `zca friend find` 将名称解析为 ID。
通过以下方式批准:
- `openclaw pairing list zalouser`
- `openclaw pairing approve zalouser <code>`
## 群组访问(可选)
- 默认:`channels.zalouser.groupPolicy = "open"`(允许群组)。使用 `channels.defaults.groupPolicy` 在未设置时覆盖默认值。
- 通过以下方式限制为允许列表:
- `channels.zalouser.groupPolicy = "allowlist"`
- `channels.zalouser.groups`(键为群组 ID 或名称)
- 阻止所有群组:`channels.zalouser.groupPolicy = "disabled"`
- 配置向导可以提示输入群组允许列表。
- 启动时OpenClaw 将允许列表中的群组/用户名称解析为 ID 并记录映射;未解析的条目保持原样。
示例:
```json5
{
channels: {
zalouser: {
groupPolicy: "allowlist",
groups: {
"123456789": { allow: true },
"Work Chat": { allow: true },
},
},
},
}
```
## 多账户
账户映射到 zca 配置文件。示例:
```json5
{
channels: {
zalouser: {
enabled: true,
defaultAccount: "default",
accounts: {
work: { enabled: true, profile: "work" },
},
},
},
}
```
## 故障排除
**找不到 `zca`**
- 安装 zca-cli 并确保它在 Gateway 网关进程的 `PATH` 中。
**登录不保持:**
- `openclaw channels status --probe`
- 重新登录:`openclaw channels logout --channel zalouser && openclaw channels login --channel zalouser`

173
content/cli/acp.md Normal file
View File

@@ -0,0 +1,173 @@
---
read_when:
- 设置基于 ACP 的 IDE 集成
- 调试到 Gateway 网关的 ACP 会话路由
summary: 运行用于 IDE 集成的 ACP 桥接器
title: acp
x-i18n:
generated_at: "2026-02-03T07:44:38Z"
model: claude-opus-4-5
provider: pi
source_hash: 0c09844297da250bc1a558423e7e534d6b6be9045de12d797c07ecd64a0c63ed
source_path: cli/acp.md
workflow: 15
---
# acp
运行与 OpenClaw Gateway 网关通信的 ACPAgent Client Protocol桥接器。
此命令通过 stdio 使用 ACP 协议与 IDE 通信,并通过 WebSocket 将提示转发到 Gateway 网关。它将 ACP 会话映射到 Gateway 网关会话键。
## 用法
```bash
openclaw acp
# Remote Gateway
openclaw acp --url wss://gateway-host:18789 --token <token>
# Attach to an existing session key
openclaw acp --session agent:main:main
# Attach by label (must already exist)
openclaw acp --session-label "support inbox"
# Reset the session key before the first prompt
openclaw acp --session agent:main:main --reset-session
```
## ACP 客户端(调试)
使用内置 ACP 客户端在没有 IDE 的情况下检查桥接器的安装完整性。
它会启动 ACP 桥接器并让你交互式输入提示。
```bash
openclaw acp client
# Point the spawned bridge at a remote Gateway
openclaw acp client --server-args --url wss://gateway-host:18789 --token <token>
# Override the server command (default: openclaw)
openclaw acp client --server "node" --server-args openclaw.mjs acp --url ws://127.0.0.1:19001
```
## 如何使用
当 IDE或其他客户端使用 Agent Client Protocol 并且你希望它驱动 OpenClaw Gateway 网关会话时,请使用 ACP。
1. 确保 Gateway 网关正在运行(本地或远程)。
2. 配置 Gateway 网关目标(配置或标志)。
3. 将你的 IDE 配置为通过 stdio 运行 `openclaw acp`
示例配置(持久化):
```bash
openclaw config set gateway.remote.url wss://gateway-host:18789
openclaw config set gateway.remote.token <token>
```
示例直接运行(不写入配置):
```bash
openclaw acp --url wss://gateway-host:18789 --token <token>
```
## 选择智能体
ACP 不直接选择智能体。它通过 Gateway 网关会话键进行路由。
使用智能体作用域的会话键来定位特定智能体:
```bash
openclaw acp --session agent:main:main
openclaw acp --session agent:design:main
openclaw acp --session agent:qa:bug-123
```
每个 ACP 会话映射到单个 Gateway 网关会话键。一个智能体可以有多个会话;除非你覆盖键或标签,否则 ACP 默认使用隔离的 `acp:<uuid>` 会话。
## Zed 编辑器设置
`~/.config/zed/settings.json` 中添加自定义 ACP 智能体(或使用 Zed 的设置界面):
```json
{
"agent_servers": {
"OpenClaw ACP": {
"type": "custom",
"command": "openclaw",
"args": ["acp"],
"env": {}
}
}
}
```
要定位特定的 Gateway 网关或智能体:
```json
{
"agent_servers": {
"OpenClaw ACP": {
"type": "custom",
"command": "openclaw",
"args": [
"acp",
"--url",
"wss://gateway-host:18789",
"--token",
"<token>",
"--session",
"agent:design:main"
],
"env": {}
}
}
}
```
在 Zed 中,打开 Agent 面板并选择"OpenClaw ACP"来开始一个会话。
## 会话映射
默认情况下ACP 会话获得一个带有 `acp:` 前缀的隔离 Gateway 网关会话键。
要重用已知会话,请传递会话键或标签:
- `--session <key>`:使用特定的 Gateway 网关会话键。
- `--session-label <label>`:通过标签解析现有会话。
- `--reset-session`:为该键生成新的会话 ID相同键新对话记录
如果你的 ACP 客户端支持元数据,你可以按会话覆盖:
```json
{
"_meta": {
"sessionKey": "agent:main:main",
"sessionLabel": "support inbox",
"resetSession": true
}
}
```
在 [/concepts/session](/concepts/session) 了解更多关于会话键的信息。
## 选项
- `--url <url>`Gateway 网关 WebSocket URL配置后默认为 gateway.remote.url
- `--token <token>`Gateway 网关认证令牌。
- `--password <password>`Gateway 网关认证密码。
- `--session <key>`:默认会话键。
- `--session-label <label>`:要解析的默认会话标签。
- `--require-existing`:如果会话键/标签不存在则失败。
- `--reset-session`:在首次使用前重置会话键。
- `--no-prefix-cwd`:不在提示前添加工作目录前缀。
- `--verbose, -v`:向 stderr 输出详细日志。
### `acp client` 选项
- `--cwd <dir>`ACP 会话的工作目录。
- `--server <command>`ACP 服务器命令(默认:`openclaw`)。
- `--server-args <args...>`:传递给 ACP 服务器的额外参数。
- `--server-verbose`:启用 ACP 服务器的详细日志。
- `--verbose, -v`:详细客户端日志。

30
content/cli/agent.md Normal file
View File

@@ -0,0 +1,30 @@
---
read_when:
- 你想从脚本运行一个智能体回合(可选发送回复)
summary: "`openclaw agent` 的 CLI 参考(通过 Gateway 网关发送一个智能体回合)"
title: agent
x-i18n:
generated_at: "2026-02-03T07:44:38Z"
model: claude-opus-4-5
provider: pi
source_hash: dcf12fb94e207c68645f58235792596d65afecf8216b8f9ab3acb01e03b50a33
source_path: cli/agent.md
workflow: 15
---
# `openclaw agent`
通过 Gateway 网关运行智能体回合(使用 `--local` 进行嵌入式运行)。使用 `--agent <id>` 直接指定已配置的智能体。
相关内容:
- 智能体发送工具:[Agent send](/tools/agent-send)
## 示例
```bash
openclaw agent --to +15555550123 --message "status update" --deliver
openclaw agent --agent ops --message "Summarize logs"
openclaw agent --session-id 1234 --message "Summarize inbox" --thinking medium
openclaw agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"
```

82
content/cli/agents.md Normal file
View File

@@ -0,0 +1,82 @@
---
read_when:
- 你需要多个隔离的智能体(工作区 + 路由 + 认证)
summary: "`openclaw agents` 的 CLI 参考(列出/添加/删除/设置身份)"
title: agents
x-i18n:
generated_at: "2026-02-01T19:58:38Z"
model: claude-opus-4-5
provider: pi
source_hash: 30556d81636a9ad8972573cc6b498e620fd266e1dfb16eef3f61096ea62f9896
source_path: cli/agents.md
workflow: 14
---
# `openclaw agents`
管理隔离的智能体(工作区 + 认证 + 路由)。
相关内容:
- 多智能体路由:[多智能体路由](/concepts/multi-agent)
- 智能体工作区:[智能体工作区](/concepts/agent-workspace)
## 示例
```bash
openclaw agents list
openclaw agents add work --workspace ~/.openclaw/workspace-work
openclaw agents set-identity --workspace ~/.openclaw/workspace --from-identity
openclaw agents set-identity --agent main --avatar avatars/openclaw.png
openclaw agents delete work
```
## 身份文件
每个智能体工作区可以在工作区根目录包含一个 `IDENTITY.md`
- 示例路径:`~/.openclaw/workspace/IDENTITY.md`
- `set-identity --from-identity` 从工作区根目录读取(或从显式指定的 `--identity-file` 读取)
头像路径相对于工作区根目录解析。
## 设置身份
`set-identity` 将字段写入 `agents.list[].identity`
- `name`
- `theme`
- `emoji`
- `avatar`工作区相对路径、http(s) URL 或 data URI
`IDENTITY.md` 加载:
```bash
openclaw agents set-identity --workspace ~/.openclaw/workspace --from-identity
```
显式覆盖字段:
```bash
openclaw agents set-identity --agent main --name "OpenClaw" --emoji "🦞" --avatar avatars/openclaw.png
```
配置示例:
```json5
{
agents: {
list: [
{
id: "main",
identity: {
name: "OpenClaw",
theme: "space lobster",
emoji: "🦞",
avatar: "avatars/openclaw.png",
},
},
],
},
}
```

57
content/cli/approvals.md Normal file
View File

@@ -0,0 +1,57 @@
---
read_when:
- 你想通过 CLI 编辑执行审批
- 你需要管理 Gateway 网关或节点主机上的允许列表
summary: CLI 参考:`openclaw approvals`Gateway 网关或节点主机的执行审批)
title: approvals
x-i18n:
generated_at: "2026-02-03T10:04:09Z"
model: claude-opus-4-5
provider: pi
source_hash: 4329cdaaec2c5f5d619415b6431196512d4834dc1ccd7363576f03dd9b845130
source_path: cli/approvals.md
workflow: 15
---
# `openclaw approvals`
管理**本地主机**、**Gateway 网关主机**或**节点主机**的执行审批。
默认情况下,命令针对磁盘上的本地审批文件。使用 `--gateway` 可针对 Gateway 网关,使用 `--node` 可针对特定节点。
相关内容:
- 执行审批:[执行审批](/tools/exec-approvals)
- 节点:[节点](/nodes)
## 常用命令
```bash
openclaw approvals get
openclaw approvals get --node <id|name|ip>
openclaw approvals get --gateway
```
## 从文件替换审批
```bash
openclaw approvals set --file ./exec-approvals.json
openclaw approvals set --node <id|name|ip> --file ./exec-approvals.json
openclaw approvals set --gateway --file ./exec-approvals.json
```
## 允许列表辅助命令
```bash
openclaw approvals allowlist add "~/Projects/**/bin/rg"
openclaw approvals allowlist add --agent main --node <id|name|ip> "/usr/bin/uptime"
openclaw approvals allowlist add --agent "*" "/usr/bin/uname"
openclaw approvals allowlist remove "~/Projects/**/bin/rg"
```
## 注意事项
- `--node` 使用与 `openclaw nodes` 相同的解析器id、name、ip 或 id 前缀)。
- `--agent` 默认为 `"*"`,表示适用于所有智能体。
- 节点主机必须公开 `system.execApprovals.get/set`macOS 应用或无头节点主机)。
- 审批文件按主机存储在 `~/.openclaw/exec-approvals.json`

114
content/cli/browser.md Normal file
View File

@@ -0,0 +1,114 @@
---
read_when:
- 你使用 `openclaw browser` 并想要常见任务的示例
- 你想通过 node host 控制在另一台机器上运行的浏览器
- 你想使用 Chrome 扩展中继(通过工具栏按钮附加/分离)
summary: "`openclaw browser` 的 CLI 参考(配置文件、标签页、操作、扩展中继)"
title: browser
x-i18n:
generated_at: "2026-02-03T07:44:49Z"
model: claude-opus-4-5
provider: pi
source_hash: af35adfd68726fd519c704d046451effd330458c2b8305e713137fb07b2571fd
source_path: cli/browser.md
workflow: 15
---
# `openclaw browser`
管理 OpenClaw 的浏览器控制服务器并运行浏览器操作(标签页、快照、截图、导航、点击、输入)。
相关:
- 浏览器工具 + API[浏览器工具](/tools/browser)
- Chrome 扩展中继:[Chrome 扩展](/tools/chrome-extension)
## 通用标志
- `--url <gatewayWsUrl>`Gateway 网关 WebSocket URL默认从配置获取
- `--token <token>`Gateway 网关令牌(如果需要)。
- `--timeout <ms>`:请求超时(毫秒)。
- `--browser-profile <name>`:选择浏览器配置文件(默认从配置获取)。
- `--json`:机器可读输出(在支持的地方)。
## 快速开始(本地)
```bash
openclaw browser --browser-profile chrome tabs
openclaw browser --browser-profile openclaw start
openclaw browser --browser-profile openclaw open https://example.com
openclaw browser --browser-profile openclaw snapshot
```
## 配置文件
配置文件是命名的浏览器路由配置。实际上:
- `openclaw`:启动/附加到专用的 OpenClaw 管理的 Chrome 实例(隔离的用户数据目录)。
- `chrome`:通过 Chrome 扩展中继控制你现有的 Chrome 标签页。
```bash
openclaw browser profiles
openclaw browser create-profile --name work --color "#FF5A36"
openclaw browser delete-profile --name work
```
使用特定配置文件:
```bash
openclaw browser --browser-profile work tabs
```
## 标签页
```bash
openclaw browser tabs
openclaw browser open https://docs.openclaw.ai
openclaw browser focus <targetId>
openclaw browser close <targetId>
```
## 快照 / 截图 / 操作
快照:
```bash
openclaw browser snapshot
```
截图:
```bash
openclaw browser screenshot
```
导航/点击/输入(基于 ref 的 UI 自动化):
```bash
openclaw browser navigate https://example.com
openclaw browser click <ref>
openclaw browser type <ref> "hello"
```
## Chrome 扩展中继(通过工具栏按钮附加)
此模式让智能体控制你手动附加的现有 Chrome 标签页(不会自动附加)。
将未打包的扩展安装到稳定路径:
```bash
openclaw browser extension install
openclaw browser extension path
```
然后 Chrome → `chrome://extensions` → 启用"开发者模式" → "加载已解压的扩展程序" → 选择打印的文件夹。
完整指南:[Chrome 扩展](/tools/chrome-extension)
## 远程浏览器控制node host 代理)
如果 Gateway 网关与浏览器运行在不同的机器上,在有 Chrome/Brave/Edge/Chromium 的机器上运行 **node host**。Gateway 网关会将浏览器操作代理到该节点(无需单独的浏览器控制服务器)。
使用 `gateway.nodes.browser.mode` 控制自动路由,使用 `gateway.nodes.browser.node` 在连接多个节点时固定特定节点。
安全 + 远程设置:[浏览器工具](/tools/browser)、[远程访问](/gateway/remote)、[Tailscale](/gateway/tailscale)、[安全](/gateway/security)

86
content/cli/channels.md Normal file
View File

@@ -0,0 +1,86 @@
---
read_when:
- 你想添加/删除渠道账户WhatsApp/Telegram/Discord/Google Chat/Slack/Mattermost插件/Signal/iMessage
- 你想检查渠道状态或跟踪渠道日志
summary: "`openclaw channels` 的 CLI 参考(账户、状态、登录/登出、日志)"
title: channels
x-i18n:
generated_at: "2026-02-03T07:44:51Z"
model: claude-opus-4-5
provider: pi
source_hash: 16ab1642f247bfa96e8e08dfeb1eedfccb148f40d91099f5423f971df2b54e20
source_path: cli/channels.md
workflow: 15
---
# `openclaw channels`
管理 Gateway 网关上的聊天渠道账户及其运行时状态。
相关文档:
- 渠道指南:[渠道](/channels/index)
- Gateway 网关配置:[配置](/gateway/configuration)
## 常用命令
```bash
openclaw channels list
openclaw channels status
openclaw channels capabilities
openclaw channels capabilities --channel discord --target channel:123
openclaw channels resolve --channel slack "#general" "@jane"
openclaw channels logs --channel all
```
## 添加/删除账户
```bash
openclaw channels add --channel telegram --token <bot-token>
openclaw channels remove --channel telegram --delete
```
提示:`openclaw channels add --help` 显示每个渠道的标志token、app token、signal-cli 路径等)。
## 登录/登出(交互式)
```bash
openclaw channels login --channel whatsapp
openclaw channels logout --channel whatsapp
```
## 故障排除
- 运行 `openclaw status --deep` 进行全面探测。
- 使用 `openclaw doctor` 获取引导式修复。
- `openclaw channels list` 输出 `Claude: HTTP 403 ... user:profile` → 用量快照需要 `user:profile` 权限范围。使用 `--no-usage`,或提供 claude.ai 会话密钥(`CLAUDE_WEB_SESSION_KEY` / `CLAUDE_WEB_COOKIE`),或通过 Claude Code CLI 重新授权。
## 能力探测
获取提供商能力提示(可用的 intents/scopes以及静态功能支持
```bash
openclaw channels capabilities
openclaw channels capabilities --channel discord --target channel:123
```
说明:
- `--channel` 是可选的;省略它可列出所有渠道(包括扩展)。
- `--target` 接受 `channel:<id>` 或原始数字频道 id仅适用于 Discord。
- 探测是特定于提供商的Discord intents + 可选的频道权限Slack bot + user scopesTelegram bot 标志 + webhookSignal daemon 版本MS Teams app token + Graph roles/scopes在已知处标注。没有探测功能的渠道报告 `Probe: unavailable`
## 解析名称为 ID
使用提供商目录将渠道/用户名称解析为 ID
```bash
openclaw channels resolve --channel slack "#general" "@jane"
openclaw channels resolve --channel discord "My Server/#support" "@someone"
openclaw channels resolve --channel matrix "Project Room"
```
说明:
- 使用 `--kind user|group|auto` 强制指定目标类型。
- 当多个条目共享相同名称时,解析优先选择活跃的匹配项。

21
content/cli/clawbot.md Normal file
View File

@@ -0,0 +1,21 @@
---
summary: "CLI reference for `openclaw clawbot` (legacy alias namespace)"
read_when:
- You maintain older scripts using `openclaw clawbot ...`
- You need migration guidance to current commands
title: "clawbot"
---
# `openclaw clawbot`
Legacy alias namespace kept for backwards compatibility.
Current supported alias:
- `openclaw clawbot qr` (same behavior as [`openclaw qr`](/cli/qr))
## Migration
Prefer modern top-level commands directly:
- `openclaw clawbot qr` -> `openclaw qr`

35
content/cli/completion.md Normal file
View File

@@ -0,0 +1,35 @@
---
summary: "CLI reference for `openclaw completion` (generate/install shell completion scripts)"
read_when:
- You want shell completions for zsh/bash/fish/PowerShell
- You need to cache completion scripts under OpenClaw state
title: "completion"
---
# `openclaw completion`
Generate shell completion scripts and optionally install them into your shell profile.
## Usage
```bash
openclaw completion
openclaw completion --shell zsh
openclaw completion --install
openclaw completion --shell fish --install
openclaw completion --write-state
openclaw completion --shell bash --write-state
```
## Options
- `-s, --shell <shell>`: shell target (`zsh`, `bash`, `powershell`, `fish`; default: `zsh`)
- `-i, --install`: install completion by adding a source line to your shell profile
- `--write-state`: write completion script(s) to `$OPENCLAW_STATE_DIR/completions` without printing to stdout
- `-y, --yes`: skip install confirmation prompts
## Notes
- `--install` writes a small "OpenClaw Completion" block into your shell profile and points it at the cached script.
- Without `--install` or `--write-state`, the command prints the script to stdout.
- Completion generation eagerly loads command trees so nested subcommands are included.

57
content/cli/config.md Normal file
View File

@@ -0,0 +1,57 @@
---
read_when:
- 你想以非交互方式读取或编辑配置
summary: "`openclaw config` 的 CLI 参考(获取/设置/取消设置配置值)"
title: config
x-i18n:
generated_at: "2026-02-03T10:04:13Z"
model: claude-opus-4-5
provider: pi
source_hash: d60a35f5330f22bc99a0df090590586109d329ddd2ca294aeed191a22560c1c2
source_path: cli/config.md
workflow: 15
---
# `openclaw config`
配置辅助命令:通过路径获取/设置/取消设置值。不带子命令运行将打开
配置向导(与 `openclaw configure` 相同)。
## 示例
```bash
openclaw config get browser.executablePath
openclaw config set browser.executablePath "/usr/bin/google-chrome"
openclaw config set agents.defaults.heartbeat.every "2h"
openclaw config set agents.list[0].tools.exec.node "node-id-or-name"
openclaw config unset tools.web.search.apiKey
```
## 路径
路径使用点号或括号表示法:
```bash
openclaw config get agents.defaults.workspace
openclaw config get agents.list[0].id
```
使用智能体列表索引来定位特定智能体:
```bash
openclaw config get agents.list
openclaw config set agents.list[1].tools.exec.node "node-id-or-name"
```
## 值
值会尽可能解析为 JSON5否则将被视为字符串。
使用 `--json` 强制要求 JSON5 解析。
```bash
openclaw config set agents.defaults.heartbeat.every "0m"
openclaw config set gateway.port 19001 --json
openclaw config set channels.whatsapp.groups '["*"]' --json
```
编辑后请重启 Gateway 网关。

38
content/cli/configure.md Normal file
View File

@@ -0,0 +1,38 @@
---
read_when:
- 你想交互式地调整凭证、设备或智能体默认设置
summary: "`openclaw configure` 的 CLI 参考(交互式配置提示)"
title: configure
x-i18n:
generated_at: "2026-02-03T07:44:46Z"
model: claude-opus-4-5
provider: pi
source_hash: 9cb2bb5237b02b3a2dca71b5e43b11bd6b9939b9e4aa9ce1882457464b51efd2
source_path: cli/configure.md
workflow: 15
---
# `openclaw configure`
用于设置凭证、设备和智能体默认值的交互式提示。
注意:**模型**部分现在包含一个用于 `agents.defaults.models` 允许列表的多选项(显示在 `/model` 和模型选择器中的内容)。
提示:不带子命令的 `openclaw config` 会打开相同的向导。使用 `openclaw config get|set|unset` 进行非交互式编辑。
相关内容:
- Gateway 网关配置参考:[配置](/gateway/configuration)
- Config CLI[Config](/cli/config)
注意事项:
- 选择 Gateway 网关运行位置始终会更新 `gateway.mode`。如果这是你唯一需要的,可以不选择其他部分直接选择"继续"。
- 面向渠道的服务Slack/Discord/Matrix/Microsoft Teams在设置期间会提示输入频道/房间允许列表。你可以输入名称或 ID向导会尽可能将名称解析为 ID。
## 示例
```bash
openclaw configure
openclaw configure --section models --section channels
```

43
content/cli/cron.md Normal file
View File

@@ -0,0 +1,43 @@
---
read_when:
- 你需要定时作业和唤醒功能
- 你正在调试 cron 执行和日志
summary: "`openclaw cron` 的 CLI 参考(调度和运行后台作业)"
title: cron
x-i18n:
generated_at: "2026-02-03T07:44:47Z"
model: claude-opus-4-5
provider: pi
source_hash: bc9317c824f3b6339df657cc269961d9b5f121da65ec2b23a07d454e6d611135
source_path: cli/cron.md
workflow: 15
---
# `openclaw cron`
管理 Gateway 网关调度器的 cron 作业。
相关内容:
- Cron 作业:[Cron 作业](/automation/cron-jobs)
提示:运行 `openclaw cron --help` 查看完整的命令集。
说明:隔离式 `cron add` 任务默认使用 `--announce` 投递摘要。使用 `--no-deliver` 仅内部运行。
`--deliver` 仍作为 `--announce` 的弃用别名保留。
说明:一次性(`--at`)任务成功后默认删除。使用 `--keep-after-run` 保留。
## 常见编辑
更新投递设置而不更改消息:
```bash
openclaw cron edit <job-id> --announce --channel telegram --to "123456789"
```
为隔离的作业禁用投递:
```bash
openclaw cron edit <job-id> --no-deliver
```

43
content/cli/daemon.md Normal file
View File

@@ -0,0 +1,43 @@
---
summary: "CLI reference for `openclaw daemon` (legacy alias for gateway service management)"
read_when:
- You still use `openclaw daemon ...` in scripts
- You need service lifecycle commands (install/start/stop/restart/status)
title: "daemon"
---
# `openclaw daemon`
Legacy alias for Gateway service management commands.
`openclaw daemon ...` maps to the same service control surface as `openclaw gateway ...` service commands.
## Usage
```bash
openclaw daemon status
openclaw daemon install
openclaw daemon start
openclaw daemon stop
openclaw daemon restart
openclaw daemon uninstall
```
## Subcommands
- `status`: show service install state and probe Gateway health
- `install`: install service (`launchd`/`systemd`/`schtasks`)
- `uninstall`: remove service
- `start`: start service
- `stop`: stop service
- `restart`: restart service
## Common options
- `status`: `--url`, `--token`, `--password`, `--timeout`, `--no-probe`, `--deep`, `--json`
- `install`: `--port`, `--runtime <node|bun>`, `--token`, `--force`, `--json`
- lifecycle (`uninstall|start|stop|restart`): `--json`
## Prefer
Use [`openclaw gateway`](/cli/gateway) for current docs and examples.

23
content/cli/dashboard.md Normal file
View File

@@ -0,0 +1,23 @@
---
read_when:
- 想要使用当前令牌打开控制界面
- 想要打印 URL 而不启动浏览器
summary: "`openclaw dashboard` 的 CLI 参考(打开控制界面)"
title: dashboard
x-i18n:
generated_at: "2026-02-01T19:58:50Z"
model: claude-opus-4-5
provider: pi
source_hash: 242a3b35ea43149be12ee2b8f2bc81b6dc24cea546a15f422dcfd0cf2e7724db
source_path: cli/dashboard.md
workflow: 14
---
# `openclaw dashboard`
使用当前认证信息打开控制界面。
```bash
openclaw dashboard
openclaw dashboard --no-open
```

74
content/cli/devices.md Normal file
View File

@@ -0,0 +1,74 @@
---
read_when:
- 你正在批准设备配对请求
- 你需要轮换或撤销设备 token
summary: "`openclaw devices` 的 CLI 参考(设备配对 + token 轮换/撤销)"
title: devices
x-i18n:
generated_at: "2026-02-03T07:44:52Z"
model: claude-opus-4-5
provider: pi
source_hash: 52f903817d2886c1dc29b85d30168d1edff7944bd120a1e139159c9d99a1f517
source_path: cli/devices.md
workflow: 15
---
# `openclaw devices`
管理设备配对请求和设备范围的 token。
## 命令
### `openclaw devices list`
列出待处理的配对请求和已配对的设备。
```
openclaw devices list
openclaw devices list --json
```
### `openclaw devices approve <requestId>`
批准待处理的设备配对请求。
```
openclaw devices approve <requestId>
```
### `openclaw devices reject <requestId>`
拒绝待处理的设备配对请求。
```
openclaw devices reject <requestId>
```
### `openclaw devices rotate --device <id> --role <role> [--scope <scope...>]`
为特定角色轮换设备 token可选更新 scope
```
openclaw devices rotate --device <deviceId> --role operator --scope operator.read --scope operator.write
```
### `openclaw devices revoke --device <id> --role <role>`
为特定角色撤销设备 token。
```
openclaw devices revoke --device <deviceId> --role node
```
## 通用选项
- `--url <url>`Gateway 网关 WebSocket URL配置后默认使用 `gateway.remote.url`)。
- `--token <token>`Gateway 网关 token如需要
- `--password <password>`Gateway 网关密码(密码认证)。
- `--timeout <ms>`RPC 超时。
- `--json`JSON 输出(推荐用于脚本)。
## 注意事项
- Token 轮换会返回新 token敏感信息。请像对待密钥一样对待它。
- 这些命令需要 `operator.pairing`(或 `operator.admin`scope。

70
content/cli/directory.md Normal file
View File

@@ -0,0 +1,70 @@
---
read_when:
- 你想查找某个渠道的联系人/群组/自身 ID
- 你正在开发渠道目录适配器
summary: "`openclaw directory` 的 CLI 参考self、peers、groups"
title: directory
x-i18n:
generated_at: "2026-02-01T19:58:58Z"
model: claude-opus-4-5
provider: pi
source_hash: 7c878d9013aeaa22c8a21563fac30b465a86be85d8c917c5d4591b5c3d4b2025
source_path: cli/directory.md
workflow: 14
---
# `openclaw directory`
对支持目录功能的渠道进行查找(联系人/对等方、群组和"我")。
## 通用参数
- `--channel <name>`:渠道 ID/别名(配置了多个渠道时为必填;仅配置一个渠道时自动选择)
- `--account <id>`:账号 ID默认渠道默认账号
- `--json`:输出 JSON 格式
## 说明
- `directory` 用于帮助你查找可粘贴到其他命令中的 ID特别是 `openclaw message send --target ...`)。
- 对于许多渠道,结果来源于配置(允许列表/已配置的群组),而非实时的提供商目录。
- 默认输出为以制表符分隔的 `id`(有时包含 `name`);脚本中请使用 `--json`
## 将结果用于 `message send`
```bash
openclaw directory peers list --channel slack --query "U0"
openclaw message send --channel slack --target user:U012ABCDEF --message "hello"
```
## ID 格式(按渠道)
- WhatsApp`+15551234567`(私聊),`1234567890-1234567890@g.us`(群组)
- Telegram`@username` 或数字聊天 ID群组为数字 ID
- Slack`user:U…``channel:C…`
- Discord`user:<id>``channel:<id>`
- Matrix插件`user:@user:server``room:!roomId:server``#alias:server`
- Microsoft Teams插件`user:<id>``conversation:<id>`
- Zalo插件用户 IDBot API
- Zalo Personal / `zalouser`(插件):来自 `zca` 的会话 ID私聊/群组)(`me``friend list``group list`
## Self"我"
```bash
openclaw directory self --channel zalouser
```
## Peers联系人/用户)
```bash
openclaw directory peers list --channel zalouser
openclaw directory peers list --channel zalouser --query "name"
openclaw directory peers list --channel zalouser --limit 50
```
## 群组
```bash
openclaw directory groups list --channel zalouser
openclaw directory groups list --channel zalouser --query "work"
openclaw directory groups members --channel zalouser --group-id <id>
```

30
content/cli/dns.md Normal file
View File

@@ -0,0 +1,30 @@
---
read_when:
- 你想通过 Tailscale + CoreDNS 实现广域设备发现DNS-SD
- Youre setting up split DNS for a custom discovery domain (example: openclaw.internal)
summary: "`openclaw dns` 的 CLI 参考(广域设备发现辅助工具)"
title: dns
x-i18n:
generated_at: "2026-02-03T07:44:52Z"
model: claude-opus-4-5
provider: pi
source_hash: d2011e41982ffb4b71ab98211574529bc1c8b7769ab1838abddd593f42b12380
source_path: cli/dns.md
workflow: 15
---
# `openclaw dns`
用于广域设备发现Tailscale + CoreDNS的 DNS 辅助工具。目前专注于 macOS + Homebrew CoreDNS。
相关内容:
- Gateway 网关设备发现:[设备发现](/gateway/discovery)
- 广域设备发现配置:[配置](/gateway/configuration)
## 设置
```bash
openclaw dns setup
openclaw dns setup --apply
```

22
content/cli/docs.md Normal file
View File

@@ -0,0 +1,22 @@
---
read_when:
- 你想从终端搜索实时 OpenClaw 文档
summary: "`openclaw docs` 的 CLI 参考(搜索实时文档索引)"
title: docs
x-i18n:
generated_at: "2026-02-03T07:44:50Z"
model: claude-opus-4-5
provider: pi
source_hash: 7a4000e91f7c6ed1140f684e2d1849577651e9389c5c90532a74db58c0b86d47
source_path: cli/docs.md
workflow: 15
---
# `openclaw docs`
搜索实时文档索引。
```bash
openclaw docs browser extension
openclaw docs sandbox allowHostControl
```

48
content/cli/doctor.md Normal file
View File

@@ -0,0 +1,48 @@
---
read_when:
- 你遇到连接/认证问题,需要引导式修复
- 你更新后想进行完整性检查
summary: "`openclaw doctor` 的 CLI 参考(健康检查 + 引导式修复)"
title: doctor
x-i18n:
generated_at: "2026-02-03T10:04:15Z"
model: claude-opus-4-5
provider: pi
source_hash: 92310aa3f3d111e91a74ce1150359d5d8a8d70a856666d9419e16c60d78209f2
source_path: cli/doctor.md
workflow: 15
---
# `openclaw doctor`
Gateway 网关和渠道的健康检查 + 快速修复。
相关内容:
- 故障排除:[故障排除](/gateway/troubleshooting)
- 安全审计:[安全](/gateway/security)
## 示例
```bash
openclaw doctor
openclaw doctor --repair
openclaw doctor --deep
```
注意事项:
- 交互式提示(如钥匙串/OAuth 修复)仅在 stdin 是 TTY 且**未**设置 `--non-interactive` 时运行。无头运行cron、Telegram、无终端将跳过提示。
- `--fix``--repair` 的别名)会将备份写入 `~/.openclaw/openclaw.json.bak`,并删除未知的配置键,同时列出每个删除项。
## macOS`launchctl` 环境变量覆盖
如果你之前运行过 `launchctl setenv OPENCLAW_GATEWAY_TOKEN ...`(或 `...PASSWORD`),该值会覆盖你的配置文件,并可能导致持续的"未授权"错误。
```bash
launchctl getenv OPENCLAW_GATEWAY_TOKEN
launchctl getenv OPENCLAW_GATEWAY_PASSWORD
launchctl unsetenv OPENCLAW_GATEWAY_TOKEN
launchctl unsetenv OPENCLAW_GATEWAY_PASSWORD
```

206
content/cli/gateway.md Normal file
View File

@@ -0,0 +1,206 @@
---
read_when:
- 从 CLI 运行 Gateway 网关(开发或服务器)
- 调试 Gateway 网关认证、绑定模式和连接性
- 通过 Bonjour 发现 Gateway 网关(局域网 + tailnet
summary: OpenClaw Gateway 网关 CLI`openclaw gateway`)— 运行、查询和发现 Gateway 网关
title: gateway
x-i18n:
generated_at: "2026-02-03T07:45:15Z"
model: claude-opus-4-5
provider: pi
source_hash: 054dd48056e4784f153c6511c8eb35b56f239db8d4e629661841a00259e9abbf
source_path: cli/gateway.md
workflow: 15
---
# Gateway 网关 CLI
Gateway 网关是 OpenClaw 的 WebSocket 服务器渠道、节点、会话、hooks
本页中的子命令位于 `openclaw gateway …` 下。
相关文档:
- [/gateway/bonjour](/gateway/bonjour)
- [/gateway/discovery](/gateway/discovery)
- [/gateway/configuration](/gateway/configuration)
## 运行 Gateway 网关
运行本地 Gateway 网关进程:
```bash
openclaw gateway
```
前台运行别名:
```bash
openclaw gateway run
```
注意事项:
- 默认情况下,除非在 `~/.openclaw/openclaw.json` 中设置了 `gateway.mode=local`,否则 Gateway 网关将拒绝启动。使用 `--allow-unconfigured` 进行临时/开发运行。
- 在没有认证的情况下绑定到 loopback 之外的地址会被阻止(安全护栏)。
- `SIGUSR1` 在授权时触发进程内重启(启用 `commands.restart` 或使用 gateway 工具/config apply/update
- `SIGINT`/`SIGTERM` 处理程序会停止 Gateway 网关进程,但不会恢复任何自定义终端状态。如果你用 TUI 或 raw-mode 输入包装 CLI请在退出前恢复终端。
### 选项
- `--port <port>`WebSocket 端口(默认来自配置/环境变量;通常为 `18789`)。
- `--bind <loopback|lan|tailnet|auto|custom>`:监听器绑定模式。
- `--auth <token|password>`:认证模式覆盖。
- `--token <token>`:令牌覆盖(同时为进程设置 `OPENCLAW_GATEWAY_TOKEN`)。
- `--password <password>`:密码覆盖(同时为进程设置 `OPENCLAW_GATEWAY_PASSWORD`)。
- `--tailscale <off|serve|funnel>`:通过 Tailscale 暴露 Gateway 网关。
- `--tailscale-reset-on-exit`:关闭时重置 Tailscale serve/funnel 配置。
- `--allow-unconfigured`:允许在配置中没有 `gateway.mode=local` 的情况下启动 Gateway 网关。
- `--dev`:如果缺失则创建开发配置 + 工作区(跳过 BOOTSTRAP.md
- `--reset`:重置开发配置 + 凭证 + 会话 + 工作区(需要 `--dev`)。
- `--force`:启动前杀死所选端口上的任何现有监听器。
- `--verbose`:详细日志。
- `--claude-cli-logs`:仅在控制台显示 claude-cli 日志(并启用其 stdout/stderr
- `--ws-log <auto|full|compact>`WebSocket 日志样式(默认 `auto`)。
- `--compact``--ws-log compact` 的别名。
- `--raw-stream`:将原始模型流事件记录到 jsonl。
- `--raw-stream-path <path>`:原始流 jsonl 路径。
## 查询运行中的 Gateway 网关
所有查询命令使用 WebSocket RPC。
输出模式:
- 默认人类可读TTY 中带颜色)。
- `--json`:机器可读 JSON无样式/进度指示器)。
- `--no-color`(或 `NO_COLOR=1`):禁用 ANSI 但保持人类可读布局。
共享选项(在支持的地方):
- `--url <url>`Gateway 网关 WebSocket URL。
- `--token <token>`Gateway 网关令牌。
- `--password <password>`Gateway 网关密码。
- `--timeout <ms>`:超时/预算(因命令而异)。
- `--expect-final`:等待"最终"响应(智能体调用)。
### `gateway health`
```bash
openclaw gateway health --url ws://127.0.0.1:18789
```
### `gateway status`
`gateway status` 显示 Gateway 网关服务launchd/systemd/schtasks以及可选的 RPC 探测。
```bash
openclaw gateway status
openclaw gateway status --json
```
选项:
- `--url <url>`:覆盖探测 URL。
- `--token <token>`:探测的令牌认证。
- `--password <password>`:探测的密码认证。
- `--timeout <ms>`:探测超时(默认 `10000`)。
- `--no-probe`:跳过 RPC 探测(仅服务视图)。
- `--deep`:也扫描系统级服务。
### `gateway probe`
`gateway probe` 是"调试一切"命令。它始终探测:
- 你配置的远程 Gateway 网关(如果设置了),以及
- localhostloopback**即使配置了远程也会探测**。
如果多个 Gateway 网关可达,它会打印所有。当你使用隔离的配置文件/端口(例如救援机器人)时支持多个 Gateway 网关,但大多数安装仍然运行单个 Gateway 网关。
```bash
openclaw gateway probe
openclaw gateway probe --json
```
#### 通过 SSH 远程Mac 应用对等)
macOS 应用的"通过 SSH 远程"模式使用本地端口转发,因此远程 Gateway 网关(可能仅绑定到 loopback变得可以通过 `ws://127.0.0.1:<port>` 访问。
CLI 等效命令:
```bash
openclaw gateway probe --ssh user@gateway-host
```
选项:
- `--ssh <target>``user@host``user@host:port`(端口默认为 `22`)。
- `--ssh-identity <path>`:身份文件。
- `--ssh-auto`:选择第一个发现的 Gateway 网关主机作为 SSH 目标(仅限局域网/WAB
配置(可选,用作默认值):
- `gateway.remote.sshTarget`
- `gateway.remote.sshIdentity`
### `gateway call <method>`
低级 RPC 辅助工具。
```bash
openclaw gateway call status
openclaw gateway call logs.tail --params '{"sinceMs": 60000}'
```
## 管理 Gateway 网关服务
```bash
openclaw gateway install
openclaw gateway start
openclaw gateway stop
openclaw gateway restart
openclaw gateway uninstall
```
注意事项:
- `gateway install` 支持 `--port``--runtime``--token``--force``--json`
- 生命周期命令接受 `--json` 用于脚本。
## 发现 Gateway 网关Bonjour
`gateway discover` 扫描 Gateway 网关信标(`_openclaw-gw._tcp`)。
- 组播 DNS-SD`local.`
- 单播 DNS-SD广域 Bonjour选择一个域示例`openclaw.internal.`)并设置分割 DNS + DNS 服务器;参见 [/gateway/bonjour](/gateway/bonjour)
只有启用了 Bonjour 发现(默认)的 Gateway 网关才会广播信标。
广域发现记录包括TXT
- `role`Gateway 网关角色提示)
- `transport`(传输提示,例如 `gateway`
- `gatewayPort`WebSocket 端口,通常为 `18789`
- `sshPort`SSH 端口;如果不存在则默认为 `22`
- `tailnetDns`MagicDNS 主机名,如果可用)
- `gatewayTls` / `gatewayTlsSha256`TLS 启用 + 证书指纹)
- `cliPath`(远程安装的可选提示)
### `gateway discover`
```bash
openclaw gateway discover
```
选项:
- `--timeout <ms>`:每个命令的超时(浏览/解析);默认 `2000`
- `--json`:机器可读输出(同时禁用样式/进度指示器)。
示例:
```bash
openclaw gateway discover --timeout 4000
openclaw gateway discover --json | jq '.beacons[].wsUrl'
```

28
content/cli/health.md Normal file
View File

@@ -0,0 +1,28 @@
---
read_when:
- 你想快速检查运行中的 Gateway 网关健康状态
summary: "`openclaw health` 的 CLI 参考(通过 RPC 获取 Gateway 网关健康端点)"
title: health
x-i18n:
generated_at: "2026-02-03T07:44:55Z"
model: claude-opus-4-5
provider: pi
source_hash: 82a78a5a97123f7a5736699ae8d793592a736f336c5caced9eba06d14d973fd7
source_path: cli/health.md
workflow: 15
---
# `openclaw health`
从运行中的 Gateway 网关获取健康状态。
```bash
openclaw health
openclaw health --json
openclaw health --verbose
```
注意:
- `--verbose` 运行实时探测,并在配置了多个账户时打印每个账户的耗时。
- 当配置了多个智能体时,输出包括每个智能体的会话存储。

298
content/cli/hooks.md Normal file
View File

@@ -0,0 +1,298 @@
---
read_when:
- 你想管理智能体钩子
- 你想安装或更新钩子
summary: CLI 参考:`openclaw hooks`(智能体钩子)
title: hooks
x-i18n:
generated_at: "2026-02-03T10:04:32Z"
model: claude-opus-4-5
provider: pi
source_hash: e2032e61ff4b9135cb2708d92eb7889ac627b85a5fc153e3d5b84265f7bd7bc6
source_path: cli/hooks.md
workflow: 15
---
# `openclaw hooks`
管理智能体钩子(针对 `/new``/reset` 等命令以及 Gateway 网关启动的事件驱动自动化)。
相关内容:
- 钩子:[钩子](/automation/hooks)
- 插件钩子:[插件](/tools/plugin#plugin-hooks)
## 列出所有钩子
```bash
openclaw hooks list
```
列出从工作区、托管目录和内置目录中发现的所有钩子。
**选项:**
- `--eligible`:仅显示符合条件的钩子(满足要求)
- `--json`:以 JSON 格式输出
- `-v, --verbose`:显示详细信息,包括缺失的要求
**示例输出:**
```
Hooks (3/3 ready)
Ready:
🚀 boot-md ✓ - Run BOOT.md on gateway startup
📝 command-logger ✓ - Log all command events to a centralized audit file
💾 session-memory ✓ - Save session context to memory when /new command is issued
```
**示例(详细模式):**
```bash
openclaw hooks list --verbose
```
显示不符合条件的钩子缺失的要求。
**示例JSON**
```bash
openclaw hooks list --json
```
返回结构化 JSON供程序化使用。
## 获取钩子信息
```bash
openclaw hooks info <name>
```
显示特定钩子的详细信息。
**参数:**
- `<name>`:钩子名称(例如 `session-memory`
**选项:**
- `--json`:以 JSON 格式输出
**示例:**
```bash
openclaw hooks info session-memory
```
**输出:**
```
💾 session-memory ✓ Ready
Save session context to memory when /new command is issued
Details:
Source: openclaw-bundled
Path: /path/to/openclaw/hooks/bundled/session-memory/HOOK.md
Handler: /path/to/openclaw/hooks/bundled/session-memory/handler.ts
Homepage: https://docs.openclaw.ai/automation/hooks#session-memory
Events: command:new
Requirements:
Config: ✓ workspace.dir
```
## 检查钩子资格
```bash
openclaw hooks check
```
显示钩子资格状态摘要(有多少已就绪,有多少未就绪)。
**选项:**
- `--json`:以 JSON 格式输出
**示例输出:**
```
Hooks Status
Total hooks: 4
Ready: 4
Not ready: 0
```
## 启用钩子
```bash
openclaw hooks enable <name>
```
通过将特定钩子添加到配置(`~/.openclaw/config.json`)来启用它。
**注意:** 由插件管理的钩子在 `openclaw hooks list` 中显示 `plugin:<id>`
无法在此处启用/禁用。请改为启用/禁用该插件。
**参数:**
- `<name>`:钩子名称(例如 `session-memory`
**示例:**
```bash
openclaw hooks enable session-memory
```
**输出:**
```
✓ Enabled hook: 💾 session-memory
```
**执行操作:**
- 检查钩子是否存在且符合条件
- 在配置中更新 `hooks.internal.entries.<name>.enabled = true`
- 将配置保存到磁盘
**启用后:**
- 重启 Gateway 网关以重新加载钩子macOS 上重启菜单栏应用,或在开发环境中重启 Gateway 网关进程)。
## 禁用钩子
```bash
openclaw hooks disable <name>
```
通过更新配置来禁用特定钩子。
**参数:**
- `<name>`:钩子名称(例如 `command-logger`
**示例:**
```bash
openclaw hooks disable command-logger
```
**输出:**
```
⏸ Disabled hook: 📝 command-logger
```
**禁用后:**
- 重启 Gateway 网关以重新加载钩子
## 安装钩子
```bash
openclaw hooks install <path-or-spec>
```
从本地文件夹/压缩包或 npm 安装钩子包。
**执行操作:**
- 将钩子包复制到 `~/.openclaw/hooks/<id>`
-`hooks.internal.entries.*` 中启用已安装的钩子
-`hooks.internal.installs` 下记录安装信息
**选项:**
- `-l, --link`:链接本地目录而不是复制(将其添加到 `hooks.internal.load.extraDirs`
**支持的压缩包格式:** `.zip``.tgz``.tar.gz``.tar`
**示例:**
```bash
# 本地目录
openclaw hooks install ./my-hook-pack
# 本地压缩包
openclaw hooks install ./my-hook-pack.zip
# NPM 包
openclaw hooks install @openclaw/my-hook-pack
# 链接本地目录而不复制
openclaw hooks install -l ./my-hook-pack
```
## 更新钩子
```bash
openclaw hooks update <id>
openclaw hooks update --all
```
更新已安装的钩子包(仅限 npm 安装)。
**选项:**
- `--all`:更新所有已跟踪的钩子包
- `--dry-run`:显示将要进行的更改,但不写入
## 内置钩子
### session-memory
在你执行 `/new` 时将会话上下文保存到记忆中。
**启用:**
```bash
openclaw hooks enable session-memory
```
**输出:** `~/.openclaw/workspace/memory/YYYY-MM-DD-slug.md`
**参见:** [session-memory 文档](/automation/hooks#session-memory)
### command-logger
将所有命令事件记录到集中的审计文件中。
**启用:**
```bash
openclaw hooks enable command-logger
```
**输出:** `~/.openclaw/logs/commands.log`
**查看日志:**
```bash
# 最近的命令
tail -n 20 ~/.openclaw/logs/commands.log
# 格式化输出
cat ~/.openclaw/logs/commands.log | jq .
# 按操作过滤
grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .
```
**参见:** [command-logger 文档](/automation/hooks#command-logger)
### boot-md
在 Gateway 网关启动时(渠道启动后)运行 `BOOT.md`
**事件**`gateway:startup`
**启用**
```bash
openclaw hooks enable boot-md
```
**参见:** [boot-md 文档](/automation/hooks#boot-md)

1032
content/cli/index.md Normal file

File diff suppressed because it is too large Load Diff

31
content/cli/logs.md Normal file
View File

@@ -0,0 +1,31 @@
---
read_when:
- 你需要远程跟踪 Gateway 网关日志(无需 SSH
- 你需要 JSON 日志行用于工具处理
summary: "`openclaw logs` 的 CLI 参考(通过 RPC 跟踪 Gateway 网关日志)"
title: logs
x-i18n:
generated_at: "2026-02-03T07:44:57Z"
model: claude-opus-4-5
provider: pi
source_hash: 911a57f0f3b78412c26312f7bf87a5a26418ab7b74e5e2eb40f16edefb6c6b8e
source_path: cli/logs.md
workflow: 15
---
# `openclaw logs`
通过 RPC 跟踪 Gateway 网关文件日志(在远程模式下可用)。
相关内容:
- 日志概述:[日志](/logging)
## 示例
```bash
openclaw logs
openclaw logs --follow
openclaw logs --json
openclaw logs --limit 500
```

52
content/cli/memory.md Normal file
View File

@@ -0,0 +1,52 @@
---
read_when:
- 你想要索引或搜索语义记忆
- 你正在调试记忆可用性或索引问题
summary: "`openclaw memory`status/index/search的 CLI 参考"
title: memory
x-i18n:
generated_at: "2026-02-01T20:21:11Z"
model: claude-opus-4-5
provider: pi
source_hash: 95a9e94306f95be2218a909be59be5bbaa5d31322b71b23564c71a89c3a3941a
source_path: cli/memory.md
workflow: 14
---
# `openclaw memory`
管理语义记忆的索引和搜索。
由活跃的记忆插件提供(默认:`memory-core`;设置 `plugins.slots.memory = "none"` 可禁用)。
相关内容:
- 记忆概念:[记忆](/concepts/memory)
- 插件:[插件](/tools/plugin)
## 示例
```bash
openclaw memory status
openclaw memory status --deep
openclaw memory status --deep --index
openclaw memory status --deep --index --verbose
openclaw memory index
openclaw memory index --verbose
openclaw memory search "release checklist"
openclaw memory status --agent main
openclaw memory index --agent main --verbose
```
## 选项
通用选项:
- `--agent <id>`:限定到单个智能体(默认:所有已配置的智能体)。
- `--verbose`:在探测和索引期间输出详细日志。
说明:
- `memory status --deep` 探测向量存储和嵌入模型的可用性。
- `memory status --deep --index` 在存储有未同步变更时运行重新索引。
- `memory index --verbose` 打印每个阶段的详细信息(提供商、模型、数据源、批处理活动)。
- `memory status` 包含通过 `memorySearch.extraPaths` 配置的所有额外路径。

246
content/cli/message.md Normal file
View File

@@ -0,0 +1,246 @@
---
read_when:
- 添加或修改消息 CLI 操作
- 更改出站渠道行为
summary: "`openclaw message`(发送 + 渠道操作)的 CLI 参考"
title: message
x-i18n:
generated_at: "2026-02-01T20:21:30Z"
model: claude-opus-4-5
provider: pi
source_hash: 35159baf1ef7136252e3ab1e5e03881ebc4196dd43425e2319a39306ced7f48c
source_path: cli/message.md
workflow: 14
---
# `openclaw message`
用于发送消息和渠道操作的单一出站命令
Discord/Google Chat/Slack/Mattermost插件/Telegram/WhatsApp/Signal/iMessage/MS Teams
## 用法
```
openclaw message <subcommand> [flags]
```
渠道选择:
- 如果配置了多个渠道,则必须指定 `--channel`
- 如果只配置了一个渠道,则该渠道为默认值。
- 可选值:`whatsapp|telegram|discord|googlechat|slack|mattermost|signal|imessage|msteams`Mattermost 需要插件)
目标格式(`--target`
- WhatsAppE.164 或群组 JID
- Telegram聊天 ID 或 `@username`
- Discord`channel:<id>``user:<id>`(或 `<@id>` 提及;纯数字 ID 被视为频道)
- Google Chat`spaces/<spaceId>``users/<userId>`
- Slack`channel:<id>``user:<id>`(接受纯频道 ID
- Mattermost插件`channel:<id>``user:<id>``@username`(纯 ID 被视为频道)
- Signal`+E.164``group:<id>``signal:+E.164``signal:group:<id>``username:<name>`/`u:<name>`
- iMessage句柄、`chat_id:<id>``chat_guid:<guid>``chat_identifier:<id>`
- MS Teams会话 ID`19:...@thread.tacv2`)或 `conversation:<id>``user:<aad-object-id>`
名称查找:
- 对于支持的提供商Discord/Slack 等),如 `Help``#help` 之类的频道名称会通过目录缓存进行解析。
- 缓存未命中时如果提供商支持OpenClaw 将尝试实时目录查找。
## 通用标志
- `--channel <name>`
- `--account <id>`
- `--target <dest>`(用于 send/poll/read 等的目标渠道或用户)
- `--targets <name>`(可重复;仅限广播)
- `--json`
- `--dry-run`
- `--verbose`
## 操作
### 核心
- `send`
- 渠道WhatsApp/Telegram/Discord/Google Chat/Slack/Mattermost插件/Signal/iMessage/MS Teams
- 必需:`--target`,以及 `--message``--media`
- 可选:`--media``--reply-to``--thread-id``--gif-playback`
- 仅限 Telegram`--buttons`(需要 `channels.telegram.capabilities.inlineButtons` 以启用)
- 仅限 Telegram`--thread-id`(论坛主题 ID
- 仅限 Slack`--thread-id`(线程时间戳;`--reply-to` 使用相同字段)
- 仅限 WhatsApp`--gif-playback`
- `poll`
- 渠道WhatsApp/Discord/MS Teams
- 必需:`--target``--poll-question``--poll-option`(可重复)
- 可选:`--poll-multi`
- 仅限 Discord`--poll-duration-hours``--message`
- `react`
- 渠道Discord/Google Chat/Slack/Telegram/WhatsApp/Signal
- 必需:`--message-id``--target`
- 可选:`--emoji``--remove``--participant``--from-me``--target-author``--target-author-uuid`
- 注意:`--remove` 需要 `--emoji`(省略 `--emoji` 可清除自己的表情回应(如果支持);参见 /tools/reactions
- 仅限 WhatsApp`--participant``--from-me`
- Signal 群组表情回应:需要 `--target-author``--target-author-uuid`
- `reactions`
- 渠道Discord/Google Chat/Slack
- 必需:`--message-id``--target`
- 可选:`--limit`
- `read`
- 渠道Discord/Slack
- 必需:`--target`
- 可选:`--limit``--before``--after`
- 仅限 Discord`--around`
- `edit`
- 渠道Discord/Slack
- 必需:`--message-id``--message``--target`
- `delete`
- 渠道Discord/Slack/Telegram
- 必需:`--message-id``--target`
- `pin` / `unpin`
- 渠道Discord/Slack
- 必需:`--message-id``--target`
- `pins`(列表)
- 渠道Discord/Slack
- 必需:`--target`
- `permissions`
- 渠道Discord
- 必需:`--target`
- `search`
- 渠道Discord
- 必需:`--guild-id``--query`
- 可选:`--channel-id``--channel-ids`(可重复)、`--author-id``--author-ids`(可重复)、`--limit`
### 线程
- `thread create`
- 渠道Discord
- 必需:`--thread-name``--target`(频道 ID
- 可选:`--message-id``--auto-archive-min`
- `thread list`
- 渠道Discord
- 必需:`--guild-id`
- 可选:`--channel-id``--include-archived``--before``--limit`
- `thread reply`
- 渠道Discord
- 必需:`--target`(线程 ID`--message`
- 可选:`--media``--reply-to`
### 表情符号
- `emoji list`
- Discord`--guild-id`
- Slack无需额外标志
- `emoji upload`
- 渠道Discord
- 必需:`--guild-id``--emoji-name``--media`
- 可选:`--role-ids`(可重复)
### 贴纸
- `sticker send`
- 渠道Discord
- 必需:`--target``--sticker-id`(可重复)
- 可选:`--message`
- `sticker upload`
- 渠道Discord
- 必需:`--guild-id``--sticker-name``--sticker-desc``--sticker-tags``--media`
### 角色 / 频道 / 成员 / 语音
- `role info`Discord`--guild-id`
- `role add` / `role remove`Discord`--guild-id``--user-id``--role-id`
- `channel info`Discord`--target`
- `channel list`Discord`--guild-id`
- `member info`Discord/Slack`--user-id`Discord 还需要 `--guild-id`
- `voice status`Discord`--guild-id``--user-id`
### 事件
- `event list`Discord`--guild-id`
- `event create`Discord`--guild-id``--event-name``--start-time`
- 可选:`--end-time``--desc``--channel-id``--location``--event-type`
### 管理Discord
- `timeout``--guild-id``--user-id`(可选 `--duration-min``--until`;两者都省略则清除超时)
- `kick``--guild-id``--user-id`+ `--reason`
- `ban``--guild-id``--user-id`+ `--delete-days``--reason`
- `timeout` 也支持 `--reason`
### 广播
- `broadcast`
- 渠道:任何已配置的渠道;使用 `--channel all` 可针对所有提供商
- 必需:`--targets`(可重复)
- 可选:`--message``--media``--dry-run`
## 示例
发送 Discord 回复:
```
openclaw message send --channel discord \
--target channel:123 --message "hi" --reply-to 456
```
创建 Discord 投票:
```
openclaw message poll --channel discord \
--target channel:123 \
--poll-question "Snack?" \
--poll-option Pizza --poll-option Sushi \
--poll-multi --poll-duration-hours 48
```
发送 Teams 主动消息:
```
openclaw message send --channel msteams \
--target conversation:19:abc@thread.tacv2 --message "hi"
```
创建 Teams 投票:
```
openclaw message poll --channel msteams \
--target conversation:19:abc@thread.tacv2 \
--poll-question "Lunch?" \
--poll-option Pizza --poll-option Sushi
```
在 Slack 中添加表情回应:
```
openclaw message react --channel slack \
--target C123 --message-id 456 --emoji "✅"
```
在 Signal 群组中添加表情回应:
```
openclaw message react --channel signal \
--target signal:group:abc123 --message-id 1737630212345 \
--emoji "✅" --target-author-uuid 123e4567-e89b-12d3-a456-426614174000
```
发送 Telegram 内联按钮:
```
openclaw message send --channel telegram --target @mychat --message "Choose:" \
--buttons '[ [{"text":"Yes","callback_data":"cmd:yes"}], [{"text":"No","callback_data":"cmd:no"}] ]'
```

85
content/cli/models.md Normal file
View File

@@ -0,0 +1,85 @@
---
read_when:
- 你想更改默认模型或查看提供商认证状态
- 你想扫描可用的模型/提供商并调试认证配置
summary: "`openclaw models` 的 CLI 参考status/list/set/scan、别名、回退、认证"
title: models
x-i18n:
generated_at: "2026-02-01T20:21:16Z"
model: claude-opus-4-5
provider: pi
source_hash: 923b6ffc7de382ba25bc6e699f0515607e74877b39f2136ccdba2d99e1b1e9c3
source_path: cli/models.md
workflow: 14
---
# `openclaw models`
模型发现、扫描和配置(默认模型、回退、认证配置)。
相关内容:
- 提供商 + 模型:[模型](/providers/models)
- 提供商认证设置:[快速开始](/start/getting-started)
## 常用命令
```bash
openclaw models status
openclaw models list
openclaw models set <model-or-alias>
openclaw models scan
```
`openclaw models status` 显示已解析的默认模型/回退配置以及认证概览。
当提供商使用快照可用时OAuth/令牌状态部分会包含提供商使用头信息。
添加 `--probe` 可对每个已配置的提供商配置运行实时认证探测。
探测会发送真实请求(可能消耗令牌并触发速率限制)。
使用 `--agent <id>` 可检查已配置智能体的模型/认证状态。省略时,
命令会使用 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR`(如已设置),否则使用
已配置的默认智能体。
注意事项:
- `models set <model-or-alias>` 接受 `provider/model` 或别名。
- 模型引用通过在**第一个** `/` 处拆分来解析。如果模型 ID 包含 `/`OpenRouter 风格),需包含提供商前缀(示例:`openrouter/moonshotai/kimi-k2`)。
- 如果省略提供商OpenClaw 会将输入视为别名或**默认提供商**的模型(仅在模型 ID 不包含 `/` 时有效)。
### `models status`
选项:
- `--json`
- `--plain`
- `--check`(退出码 1=已过期/缺失2=即将过期)
- `--probe`(对已配置的认证配置进行实时探测)
- `--probe-provider <name>`(探测单个提供商)
- `--probe-profile <id>`(可重复或逗号分隔的配置 ID
- `--probe-timeout <ms>`
- `--probe-concurrency <n>`
- `--probe-max-tokens <n>`
- `--agent <id>`(已配置的智能体 ID覆盖 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR`
## 别名 + 回退
```bash
openclaw models aliases list
openclaw models fallbacks list
```
## 认证配置
```bash
openclaw models auth add
openclaw models auth login --provider <id>
openclaw models auth setup-token
openclaw models auth paste-token
```
`models auth login` 运行提供商插件的认证流程OAuth/API 密钥)。使用
`openclaw plugins list` 查看已安装的提供商。
注意事项:
- `setup-token` 会提示输入 setup-token 值(在任意机器上使用 `claude setup-token` 生成)。
- `paste-token` 接受在其他地方或通过自动化生成的令牌字符串。

115
content/cli/node.md Normal file
View File

@@ -0,0 +1,115 @@
---
read_when:
- 运行无头节点主机
- 为 system.run 配对非 macOS 节点
summary: "`openclaw node` 的 CLI 参考(无头节点主机)"
title: node
x-i18n:
generated_at: "2026-02-03T07:45:07Z"
model: claude-opus-4-5
provider: pi
source_hash: a8b1a57712663e2285c9ecd306fe57d067eb3e6820d7d8aec650b41b022d995a
source_path: cli/node.md
workflow: 15
---
# `openclaw node`
运行一个**无头节点主机**,连接到 Gateway 网关 WebSocket 并在此机器上暴露
`system.run` / `system.which`
## 为什么使用节点主机?
当你希望智能体**在网络中的其他机器上运行命令**,而无需在那里安装完整的 macOS 配套应用时,请使用节点主机。
常见用例:
- 在远程 Linux/Windows 机器上运行命令构建服务器、实验室机器、NAS
- 在 Gateway 网关上保持执行的**沙箱隔离**,但将批准的运行委托给其他主机。
- 为自动化或 CI 节点提供轻量级、无头的执行目标。
执行仍然受**执行批准**和节点主机上的每智能体允许列表保护,因此你可以保持命令访问的范围明确。
## 浏览器代理(零配置)
如果节点上的 `browser.enabled` 未被禁用,节点主机会自动广播浏览器代理。这让智能体无需额外配置即可在该节点上使用浏览器自动化。
如需在节点上禁用:
```json5
{
nodeHost: {
browserProxy: {
enabled: false,
},
},
}
```
## 运行(前台)
```bash
openclaw node run --host <gateway-host> --port 18789
```
选项:
- `--host <host>`Gateway 网关 WebSocket 主机(默认:`127.0.0.1`
- `--port <port>`Gateway 网关 WebSocket 端口(默认:`18789`
- `--tls`:为 Gateway 网关连接使用 TLS
- `--tls-fingerprint <sha256>`:预期的 TLS 证书指纹sha256
- `--node-id <id>`:覆盖节点 id清除配对 token
- `--display-name <name>`:覆盖节点显示名称
## 服务(后台)
将无头节点主机安装为用户服务。
```bash
openclaw node install --host <gateway-host> --port 18789
```
选项:
- `--host <host>`Gateway 网关 WebSocket 主机(默认:`127.0.0.1`
- `--port <port>`Gateway 网关 WebSocket 端口(默认:`18789`
- `--tls`:为 Gateway 网关连接使用 TLS
- `--tls-fingerprint <sha256>`:预期的 TLS 证书指纹sha256
- `--node-id <id>`:覆盖节点 id清除配对 token
- `--display-name <name>`:覆盖节点显示名称
- `--runtime <runtime>`:服务运行时(`node``bun`
- `--force`:如果已安装则重新安装/覆盖
管理服务:
```bash
openclaw node status
openclaw node stop
openclaw node restart
openclaw node uninstall
```
使用 `openclaw node run` 运行前台节点主机(无服务)。
服务命令接受 `--json` 以获取机器可读输出。
## 配对
首次连接会在 Gateway 网关上创建待处理的节点配对请求。
通过以下方式批准:
```bash
openclaw nodes pending
openclaw nodes approve <requestId>
```
节点主机将其节点 id、token、显示名称和 Gateway 网关连接信息存储在
`~/.openclaw/node.json` 中。
## 执行批准
`system.run` 受本地执行批准限制:
- `~/.openclaw/exec-approvals.json`
- [执行批准](/tools/exec-approvals)
- `openclaw approvals --node <id|name|ip>`(从 Gateway 网关编辑)

80
content/cli/nodes.md Normal file
View File

@@ -0,0 +1,80 @@
---
read_when:
- 你正在管理已配对的节点(摄像头、屏幕、画布)
- 你需要批准请求或调用节点命令
summary: "`openclaw nodes` 的 CLI 参考(列表/状态/批准/调用,摄像头/画布/屏幕)"
title: nodes
x-i18n:
generated_at: "2026-02-03T10:04:26Z"
model: claude-opus-4-5
provider: pi
source_hash: 23da6efdd659a82dbbc4afd18eb4ab1020a2892f69c28d610f912c8a799f734c
source_path: cli/nodes.md
workflow: 15
---
# `openclaw nodes`
管理已配对的节点(设备)并调用节点功能。
相关内容:
- 节点概述:[节点](/nodes)
- 摄像头:[摄像头节点](/nodes/camera)
- 图像:[图像节点](/nodes/images)
通用选项:
- `--url``--token``--timeout``--json`
## 常用命令
```bash
openclaw nodes list
openclaw nodes list --connected
openclaw nodes list --last-connected 24h
openclaw nodes pending
openclaw nodes approve <requestId>
openclaw nodes status
openclaw nodes status --connected
openclaw nodes status --last-connected 24h
```
`nodes list` 打印待处理/已配对表格。已配对行包含最近连接时长Last Connect
使用 `--connected` 仅显示当前已连接的节点。使用 `--last-connected <duration>`
筛选在指定时间段内连接过的节点(例如 `24h``7d`)。
## 调用 / 运行
```bash
openclaw nodes invoke --node <id|name|ip> --command <command> --params <json>
openclaw nodes run --node <id|name|ip> <command...>
openclaw nodes run --raw "git status"
openclaw nodes run --agent main --node <id|name|ip> --raw "git status"
```
调用标志:
- `--params <json>`JSON 对象字符串(默认 `{}`)。
- `--invoke-timeout <ms>`:节点调用超时(默认 `15000`)。
- `--idempotency-key <key>`:可选的幂等键。
### Exec 风格默认值
`nodes run` 与模型的 exec 行为一致(默认值 + 审批):
- 读取 `tools.exec.*`(以及 `agents.list[].tools.exec.*` 覆盖)。
- 在调用 `system.run` 前使用 exec 审批(`exec.approval.request`)。
- 当设置了 `tools.exec.node` 时可省略 `--node`
- 需要支持 `system.run` 的节点macOS 配套应用或无头节点主机)。
标志:
- `--cwd <path>`:工作目录。
- `--env <key=val>`:环境变量覆盖(可重复)。
- `--command-timeout <ms>`:命令超时。
- `--invoke-timeout <ms>`:节点调用超时(默认 `30000`)。
- `--needs-screen-recording`:要求屏幕录制权限。
- `--raw <command>`:运行 shell 字符串(`/bin/sh -lc``cmd.exe /c`)。
- `--agent <id>`:智能体范围的审批/白名单(默认为已配置的智能体)。
- `--ask <off|on-miss|always>``--security <deny|allowlist|full>`:覆盖选项。

36
content/cli/onboard.md Normal file
View File

@@ -0,0 +1,36 @@
---
read_when:
- 你想要 Gateway 网关、工作区、认证、渠道和 Skills 的引导式设置
summary: "`openclaw onboard` 的 CLI 参考(交互式新手引导向导)"
title: onboard
x-i18n:
generated_at: "2026-02-03T07:45:00Z"
model: claude-opus-4-5
provider: pi
source_hash: a661049a6983233986a880a68440a3bcc6869ee2c4c6f5e9f3ab8ff973e22f60
source_path: cli/onboard.md
workflow: 15
---
# `openclaw onboard`
交互式新手引导向导(本地或远程 Gateway 网关设置)。
相关内容:
- 向导指南:[新手引导](/start/onboarding)
## 示例
```bash
openclaw onboard
openclaw onboard --flow quickstart
openclaw onboard --flow manual
openclaw onboard --mode remote --remote-url ws://gateway-host:18789
```
流程说明:
- `quickstart`:最少提示,自动生成 Gateway 网关令牌。
- `manual`:完整的端口/绑定/认证提示(`advanced` 的别名)。
- 最快开始聊天:`openclaw dashboard`(控制 UI无需渠道设置

28
content/cli/pairing.md Normal file
View File

@@ -0,0 +1,28 @@
---
read_when:
- 你正在使用配对模式私信并需要批准发送者
summary: "`openclaw pairing` 的 CLI 参考(批准/列出配对请求)"
title: pairing
x-i18n:
generated_at: "2026-02-03T07:45:02Z"
model: claude-opus-4-5
provider: pi
source_hash: e0bc9707294463c95d13e0deb67d834cfad6a105ab44baf4c25592e5de65ddf5
source_path: cli/pairing.md
workflow: 15
---
# `openclaw pairing`
批准或检查私信配对请求(适用于支持配对的渠道)。
相关内容:
- 配对流程:[配对](/channels/pairing)
## 命令
```bash
openclaw pairing list whatsapp
openclaw pairing approve whatsapp <code> --notify
```

66
content/cli/plugins.md Normal file
View File

@@ -0,0 +1,66 @@
---
read_when:
- 你想安装或管理进程内 Gateway 网关插件
- 你想调试插件加载失败问题
summary: "`openclaw plugins` 的 CLI 参考(列出、安装、启用/禁用、诊断)"
title: plugins
x-i18n:
generated_at: "2026-02-03T07:45:08Z"
model: claude-opus-4-5
provider: pi
source_hash: c6bf76b1e766b912ec30a0101d455151c88f1a778bffa121cdd1d0b4fbe73e1c
source_path: cli/plugins.md
workflow: 15
---
# `openclaw plugins`
管理 Gateway 网关插件/扩展(进程内加载)。
相关内容:
- 插件系统:[插件](/tools/plugin)
- 插件清单 + 模式:[插件清单](/plugins/manifest)
- 安全加固:[安全](/gateway/security)
## 命令
```bash
openclaw plugins list
openclaw plugins info <id>
openclaw plugins enable <id>
openclaw plugins disable <id>
openclaw plugins doctor
openclaw plugins update <id>
openclaw plugins update --all
```
内置插件随 OpenClaw 一起发布,但默认禁用。使用 `plugins enable` 来激活它们。
所有插件必须提供 `openclaw.plugin.json` 文件,其中包含内联 JSON Schema`configSchema`,即使为空)。缺少或无效的清单或模式会阻止插件加载并导致配置验证失败。
### 安装
```bash
openclaw plugins install <path-or-spec>
```
安全提示:将插件安装视为运行代码。优先使用固定版本。
支持的归档格式:`.zip``.tgz``.tar.gz``.tar`
使用 `--link` 避免复制本地目录(添加到 `plugins.load.paths`
```bash
openclaw plugins install -l ./my-plugin
```
### 更新
```bash
openclaw plugins update <id>
openclaw plugins update --all
openclaw plugins update <id> --dry-run
```
更新仅适用于从 npm 安装的插件(在 `plugins.installs` 中跟踪)。

39
content/cli/qr.md Normal file
View File

@@ -0,0 +1,39 @@
---
summary: "CLI reference for `openclaw qr` (generate iOS pairing QR + setup code)"
read_when:
- You want to pair the iOS app with a gateway quickly
- You need setup-code output for remote/manual sharing
title: "qr"
---
# `openclaw qr`
Generate an iOS pairing QR and setup code from your current Gateway configuration.
## Usage
```bash
openclaw qr
openclaw qr --setup-code-only
openclaw qr --json
openclaw qr --remote
openclaw qr --url wss://gateway.example/ws --token '<token>'
```
## Options
- `--remote`: use `gateway.remote.url` plus remote token/password from config
- `--url <url>`: override gateway URL used in payload
- `--public-url <url>`: override public URL used in payload
- `--token <token>`: override gateway token for payload
- `--password <password>`: override gateway password for payload
- `--setup-code-only`: print only setup code
- `--no-ascii`: skip ASCII QR rendering
- `--json`: emit JSON (`setupCode`, `gatewayUrl`, `auth`, `urlSource`)
## Notes
- `--token` and `--password` are mutually exclusive.
- After scanning, approve device pairing with:
- `openclaw devices list`
- `openclaw devices approve <requestId>`

24
content/cli/reset.md Normal file
View File

@@ -0,0 +1,24 @@
---
read_when:
- 你想在保留 CLI 安装的同时清除本地状态
- 你想预览哪些内容会被移除
summary: "`openclaw reset`(重置本地状态/配置)的 CLI 参考"
title: reset
x-i18n:
generated_at: "2026-02-01T20:21:22Z"
model: claude-opus-4-5
provider: pi
source_hash: 08afed5830f892e07d6e2e167f09aaf2d79fd5b2ba2a26a65dca857ebdbf873c
source_path: cli/reset.md
workflow: 14
---
# `openclaw reset`
重置本地配置/状态(保留 CLI 安装)。
```bash
openclaw reset
openclaw reset --dry-run
openclaw reset --scope config+creds+sessions --yes --non-interactive
```

158
content/cli/sandbox.md Normal file
View File

@@ -0,0 +1,158 @@
---
read_when: You are managing sandbox containers or debugging sandbox/tool-policy behavior.
status: active
summary: 管理沙箱容器并检查生效的沙箱策略
title: 沙箱 CLI
x-i18n:
generated_at: "2026-02-03T07:45:18Z"
model: claude-opus-4-5
provider: pi
source_hash: 6e1186f26c77e188206ce5e198ab624d6b38bc7bb7c06e4d2281b6935c39e347
source_path: cli/sandbox.md
workflow: 15
---
# 沙箱 CLI
管理基于 Docker 的沙箱容器,用于隔离智能体执行。
## 概述
OpenClaw 可以在隔离的 Docker 容器中运行智能体以确保安全。`sandbox` 命令帮助你管理这些容器,特别是在更新或配置更改后。
## 命令
### `openclaw sandbox explain`
检查**生效的**沙箱模式/作用域/工作区访问权限、沙箱工具策略和提权门控(附带修复配置的键路径)。
```bash
openclaw sandbox explain
openclaw sandbox explain --session agent:main:main
openclaw sandbox explain --agent work
openclaw sandbox explain --json
```
### `openclaw sandbox list`
列出所有沙箱容器及其状态和配置。
```bash
openclaw sandbox list
openclaw sandbox list --browser # List only browser containers
openclaw sandbox list --json # JSON output
```
**输出包括:**
- 容器名称和状态(运行中/已停止)
- Docker 镜像及其是否与配置匹配
- 创建时间
- 空闲时间(自上次使用以来的时间)
- 关联的会话/智能体
### `openclaw sandbox recreate`
移除沙箱容器以强制使用更新的镜像/配置重新创建。
```bash
openclaw sandbox recreate --all # Recreate all containers
openclaw sandbox recreate --session main # Specific session
openclaw sandbox recreate --agent mybot # Specific agent
openclaw sandbox recreate --browser # Only browser containers
openclaw sandbox recreate --all --force # Skip confirmation
```
**选项:**
- `--all`:重新创建所有沙箱容器
- `--session <key>`:重新创建特定会话的容器
- `--agent <id>`:重新创建特定智能体的容器
- `--browser`:仅重新创建浏览器容器
- `--force`:跳过确认提示
**重要:** 容器会在智能体下次使用时自动重新创建。
## 使用场景
### 更新 Docker 镜像后
```bash
# Pull new image
docker pull openclaw-sandbox:latest
docker tag openclaw-sandbox:latest openclaw-sandbox:bookworm-slim
# Update config to use new image
# Edit config: agents.defaults.sandbox.docker.image (or agents.list[].sandbox.docker.image)
# Recreate containers
openclaw sandbox recreate --all
```
### 更改沙箱配置后
```bash
# Edit config: agents.defaults.sandbox.* (or agents.list[].sandbox.*)
# Recreate to apply new config
openclaw sandbox recreate --all
```
### 更改 setupCommand 后
```bash
openclaw sandbox recreate --all
# or just one agent:
openclaw sandbox recreate --agent family
```
### 仅针对特定智能体
```bash
# Update only one agent's containers
openclaw sandbox recreate --agent alfred
```
## 为什么需要这个?
**问题:** 当你更新沙箱 Docker 镜像或配置时:
- 现有容器继续使用旧设置运行
- 容器仅在空闲 24 小时后才被清理
- 经常使用的智能体会无限期保持旧容器运行
**解决方案:** 使用 `openclaw sandbox recreate` 强制移除旧容器。它们会在下次需要时自动使用当前设置重新创建。
提示:优先使用 `openclaw sandbox recreate` 而不是手动 `docker rm`。它使用 Gateway 网关的容器命名规则,避免在作用域/会话键更改时出现不匹配。
## 配置
沙箱设置位于 `~/.openclaw/openclaw.json``agents.defaults.sandbox` 下(每个智能体的覆盖设置在 `agents.list[].sandbox` 中):
```jsonc
{
"agents": {
"defaults": {
"sandbox": {
"mode": "all", // off, non-main, all
"scope": "agent", // session, agent, shared
"docker": {
"image": "openclaw-sandbox:bookworm-slim",
"containerPrefix": "openclaw-sbx-",
// ... more Docker options
},
"prune": {
"idleHours": 24, // Auto-prune after 24h idle
"maxAgeDays": 7, // Auto-prune after 7 days
},
},
},
},
}
```
## 另请参阅
- [沙箱文档](/gateway/sandboxing)
- [智能体配置](/concepts/agent-workspace)
- [Doctor 命令](/gateway/doctor) - 检查沙箱设置

163
content/cli/secrets.md Normal file
View File

@@ -0,0 +1,163 @@
---
summary: "CLI reference for `openclaw secrets` (reload, audit, configure, apply)"
read_when:
- Re-resolving secret refs at runtime
- Auditing plaintext residues and unresolved refs
- Configuring SecretRefs and applying one-way scrub changes
title: "secrets"
---
# `openclaw secrets`
Use `openclaw secrets` to migrate credentials from plaintext to SecretRefs and keep the active secrets runtime healthy.
Command roles:
- `reload`: gateway RPC (`secrets.reload`) that re-resolves refs and swaps runtime snapshot only on full success (no config writes).
- `audit`: read-only scan of config + auth stores + legacy residues (`.env`, `auth.json`) for plaintext, unresolved refs, and precedence drift.
- `configure`: interactive planner for provider setup + target mapping + preflight (TTY required).
- `apply`: execute a saved plan (`--dry-run` for validation only), then scrub migrated plaintext residues.
Recommended operator loop:
```bash
openclaw secrets audit --check
openclaw secrets configure
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
openclaw secrets audit --check
openclaw secrets reload
```
Exit code note for CI/gates:
- `audit --check` returns `1` on findings, `2` when refs are unresolved.
Related:
- Secrets guide: [Secrets Management](/gateway/secrets)
- Security guide: [Security](/gateway/security)
## Reload runtime snapshot
Re-resolve secret refs and atomically swap runtime snapshot.
```bash
openclaw secrets reload
openclaw secrets reload --json
```
注意事项:
- Uses gateway RPC method `secrets.reload`.
- If resolution fails, gateway keeps last-known-good snapshot and returns an error (no partial activation).
- JSON response includes `warningCount`.
## Audit
Scan OpenClaw state for:
- plaintext secret storage
- unresolved refs
- precedence drift (`auth-profiles` shadowing config refs)
- legacy residues (`auth.json`, OAuth out-of-scope notes)
```bash
openclaw secrets audit
openclaw secrets audit --check
openclaw secrets audit --json
```
Exit behavior:
- `--check` exits non-zero on findings.
- unresolved refs exit with a higher-priority non-zero code.
Report shape highlights:
- `status`: `clean | findings | unresolved`
- `summary`: `plaintextCount`, `unresolvedRefCount`, `shadowedRefCount`, `legacyResidueCount`
- finding codes:
- `PLAINTEXT_FOUND`
- `REF_UNRESOLVED`
- `REF_SHADOWED`
- `LEGACY_RESIDUE`
## Configure (interactive helper)
Build provider + SecretRef changes interactively, run preflight, and optionally apply:
```bash
openclaw secrets configure
openclaw secrets configure --plan-out /tmp/openclaw-secrets-plan.json
openclaw secrets configure --apply --yes
openclaw secrets configure --providers-only
openclaw secrets configure --skip-provider-setup
openclaw secrets configure --json
```
Flow:
- Provider setup first (`add/edit/remove` for `secrets.providers` aliases).
- Credential mapping second (select fields and assign `{source, provider, id}` refs).
- Preflight and optional apply last.
Flags:
- `--providers-only`: configure `secrets.providers` only, skip credential mapping.
- `--skip-provider-setup`: skip provider setup and map credentials to existing providers.
注意事项:
- Requires an interactive TTY.
- You cannot combine `--providers-only` with `--skip-provider-setup`.
- `configure` targets secret-bearing fields in `openclaw.json`.
- Include all secret-bearing fields you intend to migrate (for example both `models.providers.*.apiKey` and `skills.entries.*.apiKey`) so audit can reach a clean state.
- It performs preflight resolution before apply.
- Generated plans default to scrub options (`scrubEnv`, `scrubAuthProfilesForProviderTargets`, `scrubLegacyAuthJson` all enabled).
- Apply path is one-way for migrated plaintext values.
- Without `--apply`, CLI still prompts `Apply this plan now?` after preflight.
- With `--apply` (and no `--yes`), CLI prompts an extra irreversible-migration confirmation.
Exec provider safety note:
- Homebrew installs often expose symlinked binaries under `/opt/homebrew/bin/*`.
- Set `allowSymlinkCommand: true` only when needed for trusted package-manager paths, and pair it with `trustedDirs` (for example `["/opt/homebrew"]`).
## Apply a saved plan
Apply or preflight a plan generated previously:
```bash
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --json
```
Plan contract details (allowed target paths, validation rules, and failure semantics):
- [Secrets Apply Plan Contract](/gateway/secrets-plan-contract)
What `apply` may update:
- `openclaw.json` (SecretRef targets + provider upserts/deletes)
- `auth-profiles.json` (provider-target scrubbing)
- legacy `auth.json` residues
- `~/.openclaw/.env` known secret keys whose values were migrated
## Why no rollback backups
`secrets apply` intentionally does not write rollback backups containing old plaintext values.
Safety comes from strict preflight + atomic-ish apply with best-effort in-memory restore on failure.
## Example
```bash
# Audit first, then configure, then confirm clean:
openclaw secrets audit --check
openclaw secrets configure
openclaw secrets audit --check
```
If `audit --check` still reports plaintext findings after a partial migration, verify you also migrated skill keys (`skills.entries.*.apiKey`) and any other reported target paths.

33
content/cli/security.md Normal file
View File

@@ -0,0 +1,33 @@
---
read_when:
- 你想对配置/状态运行快速安全审计
- 你想应用安全的"修复"建议chmod、收紧默认值
summary: "`openclaw security` 的 CLI 参考(审计和修复常见安全隐患)"
title: security
x-i18n:
generated_at: "2026-02-03T07:45:13Z"
model: claude-opus-4-5
provider: pi
source_hash: 19705b0fff848fa6f302b4ed09b7660c64e09048dba517c7f6a833d2db40bebf
source_path: cli/security.md
workflow: 15
---
# `openclaw security`
安全工具(审计 + 可选修复)。
相关:
- 安全指南:[安全](/gateway/security)
## 审计
```bash
openclaw security audit
openclaw security audit --deep
openclaw security audit --fix
```
当多个私信发送者共享主会话时,审计会发出警告,并建议对共享收件箱使用 `session.dmScope="per-channel-peer"`(或多账户渠道使用 `per-account-channel-peer`)。
当使用小模型(`<=300B`)且未启用沙箱隔离但启用了 web/browser 工具时,它也会发出警告。

23
content/cli/sessions.md Normal file
View File

@@ -0,0 +1,23 @@
---
read_when:
- 你想列出已存储的会话并查看近期活动
summary: "`openclaw sessions`(列出已存储的会话及使用情况)的 CLI 参考"
title: sessions
x-i18n:
generated_at: "2026-02-01T20:21:25Z"
model: claude-opus-4-5
provider: pi
source_hash: d8866ef166c0dea5e8d691bb62171298694935ae0771a46fada537774dadfb32
source_path: cli/sessions.md
workflow: 14
---
# `openclaw sessions`
列出已存储的对话会话。
```bash
openclaw sessions
openclaw sessions --active 120
openclaw sessions --json
```

36
content/cli/setup.md Normal file
View File

@@ -0,0 +1,36 @@
---
read_when:
- 你在不使用完整新手引导向导的情况下进行首次设置
- 你想设置默认工作区路径
summary: "`openclaw setup` 的 CLI 参考(初始化配置 + 工作区)"
title: setup
x-i18n:
generated_at: "2026-02-01T20:21:26Z"
model: claude-opus-4-5
provider: pi
source_hash: 7f3fc8b246924edf48501785be2c0d356bd31bfbb133e75a139a5ee41dbf57f4
source_path: cli/setup.md
workflow: 14
---
# `openclaw setup`
初始化 `~/.openclaw/openclaw.json` 和智能体工作区。
相关内容:
- 快速开始:[快速开始](/start/getting-started)
- 向导:[新手引导](/start/onboarding)
## 示例
```bash
openclaw setup
openclaw setup --workspace ~/.openclaw/workspace
```
通过 setup 运行向导:
```bash
openclaw setup --wizard
```

33
content/cli/skills.md Normal file
View File

@@ -0,0 +1,33 @@
---
read_when:
- 你想查看哪些 Skills 可用并准备好运行
- 你想调试 Skills 缺少的二进制文件/环境变量/配置
summary: "`openclaw skills` 的 CLI 参考(列出/信息/检查)和 skill 资格"
title: skills
x-i18n:
generated_at: "2026-02-03T07:45:14Z"
model: claude-opus-4-5
provider: pi
source_hash: 7878442c88a27ec8033f3125c319e9a6a85a1c497a404a06112ad45185c261b0
source_path: cli/skills.md
workflow: 15
---
# `openclaw skills`
检查 Skills内置 + 工作区 + 托管覆盖)并查看哪些符合条件,哪些缺少要求。
相关内容:
- Skills 系统:[Skills](/tools/skills)
- Skills 配置:[Skills 配置](/tools/skills-config)
- ClawHub 安装:[ClawHub](/tools/clawhub)
## 命令
```bash
openclaw skills list
openclaw skills list --eligible
openclaw skills info <name>
openclaw skills check
```

33
content/cli/status.md Normal file
View File

@@ -0,0 +1,33 @@
---
read_when:
- 你想快速诊断渠道健康状况 + 最近的会话接收者
- 你想获取可粘贴的"all"状态用于调试
summary: "`openclaw status` 的 CLI 参考(诊断、探测、使用量快照)"
title: status
x-i18n:
generated_at: "2026-02-03T07:45:21Z"
model: claude-opus-4-5
provider: pi
source_hash: 2bbf5579c48034fc15c2cbd5506c50456230b17e4a74c06318968c590d8f1501
source_path: cli/status.md
workflow: 15
---
# `openclaw status`
渠道 + 会话的诊断。
```bash
openclaw status
openclaw status --all
openclaw status --deep
openclaw status --usage
```
注意事项:
- `--deep` 运行实时探测WhatsApp Web + Telegram + Discord + Google Chat + Slack + Signal
- 当配置了多个智能体时,输出包含每个智能体的会话存储。
- 概览包含 Gateway 网关 + 节点主机服务安装/运行时状态(如果可用)。
- 概览包含更新渠道 + git SHA用于源代码检出
- 更新信息显示在概览中如果有可用更新status 会打印提示运行 `openclaw update`(参见[更新](/install/updating))。

63
content/cli/system.md Normal file
View File

@@ -0,0 +1,63 @@
---
read_when:
- 你想在不创建 cron 作业的情况下入队系统事件
- 你需要启用或禁用心跳
- 你想检查系统在线状态条目
summary: "`openclaw system` 的 CLI 参考(系统事件、心跳、在线状态)"
title: system
x-i18n:
generated_at: "2026-02-03T07:45:23Z"
model: claude-opus-4-5
provider: pi
source_hash: 36ae5dbdec327f5a32f7ef44bdc1f161bad69868de62f5071bb4d25a71bfdfe9
source_path: cli/system.md
workflow: 15
---
# `openclaw system`
Gateway 网关的系统级辅助工具:入队系统事件、控制心跳和查看在线状态。
## 常用命令
```bash
openclaw system event --text "Check for urgent follow-ups" --mode now
openclaw system heartbeat enable
openclaw system heartbeat last
openclaw system presence
```
## `system event`
在**主**会话上入队系统事件。下一次心跳会将其作为 `System:` 行注入到提示中。使用 `--mode now` 立即触发心跳;`next-heartbeat` 等待下一个计划的心跳时刻。
标志:
- `--text <text>`:必填的系统事件文本。
- `--mode <mode>``now``next-heartbeat`(默认)。
- `--json`:机器可读输出。
## `system heartbeat last|enable|disable`
心跳控制:
- `last`:显示最后一次心跳事件。
- `enable`:重新开启心跳(如果之前被禁用,使用此命令)。
- `disable`:暂停心跳。
标志:
- `--json`:机器可读输出。
## `system presence`
列出 Gateway 网关已知的当前系统在线状态条目(节点、实例和类似状态行)。
标志:
- `--json`:机器可读输出。
## 注意
- 需要一个运行中的 Gateway 网关,可通过你当前的配置访问(本地或远程)。
- 系统事件是临时的,不会在重启后持久化。

30
content/cli/tui.md Normal file
View File

@@ -0,0 +1,30 @@
---
read_when:
- 你想要一个连接 Gateway 网关的终端 UI支持远程
- 你想从脚本传递 url/token/session
summary: "`openclaw tui` 的 CLI 参考(连接到 Gateway 网关的终端 UI"
title: tui
x-i18n:
generated_at: "2026-02-03T07:45:20Z"
model: claude-opus-4-5
provider: pi
source_hash: f0a97d92e08746a9d6a4f31d361ccad9aea4c3dc61cfafb310d88715f61cfb64
source_path: cli/tui.md
workflow: 15
---
# `openclaw tui`
打开连接到 Gateway 网关的终端 UI。
相关:
- TUI 指南:[TUI](/web/tui)
## 示例
```bash
openclaw tui
openclaw tui --url ws://127.0.0.1:18789 --token <token>
openclaw tui --session main --deliver
```

24
content/cli/uninstall.md Normal file
View File

@@ -0,0 +1,24 @@
---
read_when:
- 你想移除 Gateway 网关服务和/或本地状态
- 你想先进行试运行
summary: "`openclaw uninstall` 的 CLI 参考(移除 Gateway 网关服务 + 本地数据)"
title: uninstall
x-i18n:
generated_at: "2026-02-03T10:04:23Z"
model: claude-opus-4-5
provider: pi
source_hash: 8d6c3890923f18f95c12b76443d649a6b404934ebd054fb86a9fa1abae843fe4
source_path: cli/uninstall.md
workflow: 15
---
# `openclaw uninstall`
卸载 Gateway 网关服务 + 本地数据CLI 保留)。
```bash
openclaw uninstall
openclaw uninstall --all --yes
openclaw uninstall --dry-run
```

101
content/cli/update.md Normal file
View File

@@ -0,0 +1,101 @@
---
read_when:
- 你想安全地更新源码检出
- 你需要了解 `--update` 简写行为
summary: "`openclaw update` 的 CLI 参考(相对安全的源码更新 + Gateway 网关自动重启)"
title: update
x-i18n:
generated_at: "2026-02-03T07:45:34Z"
model: claude-opus-4-5
provider: pi
source_hash: 3a08e8ac797612c498eef54ecb83e61c9a1ee5de09162a01dbb4b3bd72897206
source_path: cli/update.md
workflow: 15
---
# `openclaw update`
安全更新 OpenClaw 并在 stable/beta/dev 渠道之间切换。
如果你通过 **npm/pnpm** 安装(全局安装,无 git 元数据),更新通过 [更新](/install/updating) 中的包管理器流程进行。
## 用法
```bash
openclaw update
openclaw update status
openclaw update wizard
openclaw update --channel beta
openclaw update --channel dev
openclaw update --tag beta
openclaw update --no-restart
openclaw update --json
openclaw --update
```
## 选项
- `--no-restart`:成功更新后跳过重启 Gateway 网关服务。
- `--channel <stable|beta|dev>`设置更新渠道git + npm持久化到配置中
- `--tag <dist-tag|version>`:仅为本次更新覆盖 npm dist-tag 或版本。
- `--json`:打印机器可读的 `UpdateRunResult` JSON。
- `--timeout <seconds>`:每步超时时间(默认 1200 秒)。
注意:降级需要确认,因为旧版本可能会破坏配置。
## `update status`
显示当前更新渠道 + git 标签/分支/SHA对于源码检出以及更新可用性。
```bash
openclaw update status
openclaw update status --json
openclaw update status --timeout 10
```
选项:
- `--json`:打印机器可读的状态 JSON。
- `--timeout <seconds>`:检查超时时间(默认 3 秒)。
## `update wizard`
交互式流程,用于选择更新渠道并确认是否在更新后重启 Gateway 网关(默认重启)。如果你选择 `dev` 但没有 git 检出,它会提供创建一个的选项。
## 工作原理
当你显式切换渠道(`--channel ...`OpenClaw 也会保持安装方式一致:
- `dev` → 确保存在 git 检出(默认:`~/openclaw`,可通过 `OPENCLAW_GIT_DIR` 覆盖),更新它,并从该检出安装全局 CLI。
- `stable`/`beta` → 使用匹配的 dist-tag 从 npm 安装。
## Git 检出流程
渠道:
- `stable`:检出最新的非 beta 标签,然后构建 + doctor。
- `beta`:检出最新的 `-beta` 标签,然后构建 + doctor。
- `dev`:检出 `main`,然后 fetch + rebase。
高层概述:
1. 需要干净的工作树(无未提交的更改)。
2. 切换到所选渠道(标签或分支)。
3. 获取上游(仅 dev
4. 仅 dev在临时工作树中预检 lint + TypeScript 构建;如果最新提交失败,回退最多 10 个提交以找到最新的干净构建。
5. Rebase 到所选提交(仅 dev
6. 安装依赖(优先使用 pnpmnpm 作为备选)。
7. 构建 + 构建控制界面。
8. 运行 `openclaw doctor` 作为最终的"安全更新"检查。
9. 将插件同步到当前渠道dev 使用捆绑的扩展stable/beta 使用 npm并更新 npm 安装的插件。
## `--update` 简写
`openclaw --update` 会重写为 `openclaw update`(便于 shell 和启动脚本使用)。
## 另请参阅
- `openclaw doctor`(在 git 检出上会提供先运行更新的选项)
- [开发渠道](/install/development-channels)
- [更新](/install/updating)
- [CLI 参考](/cli)

41
content/cli/voicecall.md Normal file
View File

@@ -0,0 +1,41 @@
---
read_when:
- 使用语音通话插件并想了解 CLI 入口
- 想要 `voicecall call|continue|status|tail|expose` 的快速示例
summary: 语音通话插件命令的 `openclaw voicecall` CLI 参考
title: voicecall
x-i18n:
generated_at: "2026-02-01T20:21:37Z"
model: claude-opus-4-5
provider: pi
source_hash: d93aaee6f6f5c9ac468d8d2905cb23f0f2db75809408cb305c055505be9936f2
source_path: cli/voicecall.md
workflow: 14
---
# `openclaw voicecall`
`voicecall` 是一个由插件提供的命令。只有在安装并启用了语音通话插件时才会出现。
主要文档:
- 语音通话插件:[语音通话](/plugins/voice-call)
## 常用命令
```bash
openclaw voicecall status --call-id <id>
openclaw voicecall call --to "+15555550123" --message "Hello" --mode notify
openclaw voicecall continue --call-id <id> --message "Any questions?"
openclaw voicecall end --call-id <id>
```
## 暴露 WebhookTailscale
```bash
openclaw voicecall expose --mode serve
openclaw voicecall expose --mode funnel
openclaw voicecall unexpose
```
安全提示:仅将 webhook 端点暴露给你信任的网络。尽可能优先使用 Tailscale Serve 而非 Funnel。

32
content/cli/webhooks.md Normal file
View File

@@ -0,0 +1,32 @@
---
read_when:
- 你想将 Gmail Pub/Sub 事件接入 OpenClaw
- 你需要 Webhook 辅助命令
summary: "`openclaw webhooks`Webhook 辅助工具 + Gmail Pub/Sub的 CLI 参考"
title: webhooks
x-i18n:
generated_at: "2026-02-01T20:21:38Z"
model: claude-opus-4-5
provider: pi
source_hash: 785ec62afe6631b340ce4a4541ceb34cd6b97704cf7a9889762cb4c1f29a5ca0
source_path: cli/webhooks.md
workflow: 14
---
# `openclaw webhooks`
Webhook 辅助工具和集成Gmail Pub/Sub、Webhook 辅助工具)。
相关内容:
- Webhook[Webhook](/automation/webhook)
- Gmail Pub/Sub[Gmail Pub/Sub](/automation/gmail-pubsub)
## Gmail
```bash
openclaw webhooks gmail setup --account you@example.com
openclaw webhooks gmail run
```
详情请参阅 [Gmail Pub/Sub 文档](/automation/gmail-pubsub)。

View File

@@ -0,0 +1,146 @@
---
read_when:
- 你需要智能体循环或生命周期事件的详细说明
summary: 智能体循环生命周期、流和等待语义
title: 智能体循环
x-i18n:
generated_at: "2026-02-03T10:05:11Z"
model: claude-opus-4-5
provider: pi
source_hash: 0775b96eb3451e137297661a1095eaefb2bafeebb5f78123174a46290e18b014
source_path: concepts/agent-loop.md
workflow: 15
---
# 智能体循环OpenClaw
智能体循环是智能体的完整"真实"运行:接收 → 上下文组装 → 模型推理 → 工具执行 → 流式回复 → 持久化。这是将消息转化为操作和最终回复的权威路径,同时保持会话状态的一致性。
在 OpenClaw 中,循环是每个会话的单次序列化运行,在模型思考、调用工具和流式输出时发出生命周期和流事件。本文档解释了这个真实循环是如何端到端连接的。
## 入口点
- Gateway 网关 RPC`agent``agent.wait`
- CLI`agent` 命令。
## 工作原理(高层次)
1. `agent` RPC 验证参数解析会话sessionKey/sessionId持久化会话元数据立即返回 `{ runId, acceptedAt }`
2. `agentCommand` 运行智能体:
- 解析模型 + 思考/详细模式默认值
- 加载 Skills 快照
- 调用 `runEmbeddedPiAgent`pi-agent-core 运行时)
- 如果嵌入式循环未发出**生命周期结束/错误**事件,则发出该事件
3. `runEmbeddedPiAgent`
- 通过每会话 + 全局队列序列化运行
- 解析模型 + 认证配置文件并构建 pi 会话
- 订阅 pi 事件并流式传输助手/工具增量
- 强制执行超时 -> 超时则中止运行
- 返回有效负载 + 使用元数据
4. `subscribeEmbeddedPiSession` 将 pi-agent-core 事件桥接到 OpenClaw `agent` 流:
- 工具事件 => `stream: "tool"`
- 助手增量 => `stream: "assistant"`
- 生命周期事件 => `stream: "lifecycle"``phase: "start" | "end" | "error"`
5. `agent.wait` 使用 `waitForAgentJob`
- 等待 `runId` 的**生命周期结束/错误**
- 返回 `{ status: ok|error|timeout, startedAt, endedAt, error? }`
## 队列 + 并发
- 运行按会话键(会话通道)序列化,可选择通过全局通道。
- 这可以防止工具/会话竞争并保持会话历史的一致性。
- 消息渠道可以选择队列模式collect/steer/followup来馈送此通道系统。参见[命令队列](/concepts/queue)。
## 会话 + 工作区准备
- 解析并创建工作区;沙箱隔离运行可能会重定向到沙箱工作区根目录。
- 加载 Skills或从快照中复用并注入到环境和提示中。
- 解析引导/上下文文件并注入到系统提示报告中。
- 获取会话写锁;在流式传输之前打开并准备 `SessionManager`
## 提示组装 + 系统提示
- 系统提示由 OpenClaw 的基础提示、Skills 提示、引导上下文和每次运行的覆盖构建。
- 强制执行模型特定的限制和压缩保留令牌。
- 参见[系统提示](/concepts/system-prompt)了解模型看到的内容。
## 钩子点(可以拦截的位置)
OpenClaw 有两个钩子系统:
- **内部钩子**Gateway 网关钩子):用于命令和生命周期事件的事件驱动脚本。
- **插件钩子**:智能体/工具生命周期和 Gateway 网关管道中的扩展点。
### 内部钩子Gateway 网关钩子)
- **`agent:bootstrap`**:在系统提示最终确定之前构建引导文件时运行。用于添加/删除引导上下文文件。
- **命令钩子**`/new``/reset``/stop` 和其他命令事件(参见钩子文档)。
参见[钩子](/automation/hooks)了解设置和示例。
### 插件钩子(智能体 + Gateway 网关生命周期)
这些在智能体循环或 Gateway 网关管道内运行:
- **`before_agent_start`**:在运行开始前注入上下文或覆盖系统提示。
- **`agent_end`**:在完成后检查最终消息列表和运行元数据。
- **`before_compaction` / `after_compaction`**:观察或注释压缩周期。
- **`before_tool_call` / `after_tool_call`**:拦截工具参数/结果。
- **`tool_result_persist`**:在工具结果写入会话记录之前同步转换它们。
- **`message_received` / `message_sending` / `message_sent`**:入站 + 出站消息钩子。
- **`session_start` / `session_end`**:会话生命周期边界。
- **`gateway_start` / `gateway_stop`**Gateway 网关生命周期事件。
参见[插件](/tools/plugin#plugin-hooks)了解钩子 API 和注册详情。
## 流式传输 + 部分回复
- 助手增量从 pi-agent-core 流式传输并作为 `assistant` 事件发出。
- 分块流式传输可以在 `text_end``message_end` 时发出部分回复。
- 推理流式传输可以作为单独的流或作为块回复发出。
- 参见[流式传输](/concepts/streaming)了解分块和块回复行为。
## 工具执行 + 消息工具
- 工具开始/更新/结束事件在 `tool` 流上发出。
- 工具结果在记录/发出之前会对大小和图像有效负载进行清理。
- 消息工具发送会被跟踪以抑制重复的助手确认。
## 回复整形 + 抑制
- 最终有效负载由以下内容组装:
- 助手文本(和可选的推理)
- 内联工具摘要(当详细模式 + 允许时)
- 模型出错时的助手错误文本
- `NO_REPLY` 被视为静默令牌,从出站有效负载中过滤。
- 消息工具重复项从最终有效负载列表中移除。
- 如果没有剩余可渲染的有效负载且工具出错,则发出回退工具错误回复(除非消息工具已经发送了用户可见的回复)。
## 压缩 + 重试
- 自动压缩发出 `compaction` 流事件,可以触发重试。
- 重试时,内存缓冲区和工具摘要会重置以避免重复输出。
- 参见[压缩](/concepts/compaction)了解压缩管道。
## 事件流(当前)
- `lifecycle`:由 `subscribeEmbeddedPiSession` 发出(以及作为 `agentCommand` 的回退)
- `assistant`:从 pi-agent-core 流式传输的增量
- `tool`:从 pi-agent-core 流式传输的工具事件
## 聊天渠道处理
- 助手增量被缓冲到聊天 `delta` 消息中。
- 在**生命周期结束/错误**时发出聊天 `final`
## 超时
- `agent.wait` 默认30 秒(仅等待)。`timeoutMs` 参数可覆盖。
- 智能体运行时:`agents.defaults.timeoutSeconds` 默认 600 秒;在 `runEmbeddedPiAgent` 中止计时器中强制执行。
## 可能提前结束的情况
- 智能体超时(中止)
- AbortSignal取消
- Gateway 网关断开连接或 RPC 超时
- `agent.wait` 超时(仅等待,不会停止智能体)

View File

@@ -0,0 +1,219 @@
---
read_when:
- 你需要解释智能体工作区或其文件布局
- 你想备份或迁移智能体工作区
summary: 智能体工作区:位置、布局和备份策略
title: 智能体工作区
x-i18n:
generated_at: "2026-02-03T07:45:49Z"
model: claude-opus-4-5
provider: pi
source_hash: 84c550fd89b5f2474aeae586795485fd29d36effbb462f13342b31540fc18b82
source_path: concepts/agent-workspace.md
workflow: 15
---
# 智能体工作区
工作区是智能体的家。它是文件工具和工作区上下文使用的唯一工作目录。请保持其私密性并将其视为记忆。
这与 `~/.openclaw/` 是分开的,后者存储配置、凭证和会话。
**重要:** 工作区是**默认 cwd**,而不是硬性沙箱。工具会根据工作区解析相对路径,但绝对路径仍然可以访问主机上的其他位置,除非启用了沙箱隔离。如果你需要隔离,请使用
[`agents.defaults.sandbox`](/gateway/sandboxing)(和/或每智能体沙箱配置)。
当启用沙箱隔离且 `workspaceAccess` 不是 `"rw"` 时,工具在 `~/.openclaw/sandboxes` 下的沙箱工作区内操作,而不是你的主机工作区。
## 默认位置
- 默认:`~/.openclaw/workspace`
- 如果设置了 `OPENCLAW_PROFILE` 且不是 `"default"`,默认值变为
`~/.openclaw/workspace-<profile>`
-`~/.openclaw/openclaw.json` 中覆盖:
```json5
{
agent: {
workspace: "~/.openclaw/workspace",
},
}
```
`openclaw onboard``openclaw configure``openclaw setup` 将创建工作区并在缺失时填充引导文件。
如果你已经自己管理工作区文件,可以禁用引导文件创建:
```json5
{ agent: { skipBootstrap: true } }
```
## 额外的工作区文件夹
旧版安装可能创建了 `~/openclaw`。保留多个工作区目录可能会导致混乱的认证或状态漂移,因为同一时间只有一个工作区是活动的。
**建议:** 保持单个活动工作区。如果你不再使用额外的文件夹,请归档或移至废纸篓(例如 `trash ~/openclaw`)。
如果你有意保留多个工作区,请确保 `agents.defaults.workspace` 指向活动的那个。
`openclaw doctor` 在检测到额外工作区目录时会发出警告。
## 工作区文件映射(每个文件的含义)
这些是 OpenClaw 在工作区内期望的标准文件:
- `AGENTS.md`
- 智能体的操作指南以及它应该如何使用记忆。
- 在每个会话开始时加载。
- 适合放置规则、优先级和"如何行为"的详细信息。
- `SOUL.md`
- 人设、语气和边界。
- 每个会话加载。
- `USER.md`
- 用户是谁以及如何称呼他们。
- 每个会话加载。
- `IDENTITY.md`
- 智能体的名称、风格和表情符号。
- 在引导仪式期间创建/更新。
- `TOOLS.md`
- 关于你本地工具和惯例的注释。
- 不控制工具可用性;仅作为指导。
- `HEARTBEAT.md`
- 可选的心跳运行小型检查清单。
- 保持简短以避免 token 消耗。
- `BOOT.md`
- 当启用内部 hooks 时,在 Gateway 网关重启时执行的可选启动检查清单。
- 保持简短;使用 message 工具进行出站发送。
- `BOOTSTRAP.md`
- 一次性首次运行仪式。
- 仅为全新工作区创建。
- 仪式完成后删除它。
- `memory/YYYY-MM-DD.md`
- 每日记忆日志(每天一个文件)。
- 建议在会话开始时读取今天 + 昨天的内容。
- `MEMORY.md`(可选)
- 精选的长期记忆。
- 仅在主私密会话中加载(不在共享/群组上下文中)。
参见 [记忆](/concepts/memory) 了解工作流程和自动记忆刷新。
- `skills/`(可选)
- 工作区特定的 Skills。
- 当名称冲突时覆盖托管/捆绑的 Skills。
- `canvas/`(可选)
- 用于节点显示的 Canvas UI 文件(例如 `canvas/index.html`)。
如果任何引导文件缺失OpenClaw 会在会话中注入"缺失文件"标记并继续。大型引导文件在注入时会被截断;使用 `agents.defaults.bootstrapMaxChars` 调整限制默认20000
`openclaw setup` 可以重新创建缺失的默认值而不覆盖现有文件。
## 工作区中不包含的内容
这些位于 `~/.openclaw/` 下,不应提交到工作区仓库:
- `~/.openclaw/openclaw.json`(配置)
- `~/.openclaw/credentials/`OAuth token、API 密钥)
- `~/.openclaw/agents/<agentId>/sessions/`(会话记录 + 元数据)
- `~/.openclaw/skills/`(托管的 Skills
如果你需要迁移会话或配置,请单独复制它们并将它们排除在版本控制之外。
## Git 备份(推荐,私有)
将工作区视为私密记忆。将其放入**私有** git 仓库以便备份和恢复。
在运行 Gateway 网关的机器上执行这些步骤(工作区就在那里)。
### 1初始化仓库
如果安装了 git全新工作区会自动初始化。如果此工作区还不是仓库请运行
```bash
cd ~/.openclaw/workspace
git init
git add AGENTS.md SOUL.md TOOLS.md IDENTITY.md USER.md HEARTBEAT.md memory/
git commit -m "Add agent workspace"
```
### 2添加私有远程适合初学者的选项
选项 AGitHub 网页界面
1. 在 GitHub 上创建新的**私有**仓库。
2. 不要用 README 初始化(避免合并冲突)。
3. 复制 HTTPS 远程 URL。
4. 添加远程并推送:
```bash
git branch -M main
git remote add origin <https-url>
git push -u origin main
```
选项 BGitHub CLI`gh`
```bash
gh auth login
gh repo create openclaw-workspace --private --source . --remote origin --push
```
选项 CGitLab 网页界面
1. 在 GitLab 上创建新的**私有**仓库。
2. 不要用 README 初始化(避免合并冲突)。
3. 复制 HTTPS 远程 URL。
4. 添加远程并推送:
```bash
git branch -M main
git remote add origin <https-url>
git push -u origin main
```
### 3持续更新
```bash
git status
git add .
git commit -m "Update memory"
git push
```
## 不要提交密钥
即使在私有仓库中,也要避免在工作区中存储密钥:
- API 密钥、OAuth token、密码或私有凭证。
- `~/.openclaw/` 下的任何内容。
- 聊天的原始转储或敏感附件。
如果你必须存储敏感引用,请使用占位符并将真正的密钥保存在其他地方(密码管理器、环境变量或 `~/.openclaw/`)。
建议的 `.gitignore` 起始配置:
```gitignore
.DS_Store
.env
**/*.key
**/*.pem
**/secrets*
```
## 将工作区迁移到新机器
1. 将仓库克隆到所需路径(默认 `~/.openclaw/workspace`)。
2.`~/.openclaw/openclaw.json` 中将 `agents.defaults.workspace` 设置为该路径。
3. 运行 `openclaw setup --workspace <path>` 来填充任何缺失的文件。
4. 如果你需要会话,请单独从旧机器复制 `~/.openclaw/agents/<agentId>/sessions/`
## 高级注意事项
- 多智能体路由可以为每个智能体使用不同的工作区。参见
[渠道路由](/channels/channel-routing) 了解路由配置。
- 如果启用了 `agents.defaults.sandbox`,非主会话可以在 `agents.defaults.sandbox.workspaceRoot` 下使用每会话沙箱工作区。

115
content/concepts/agent.md Normal file
View File

@@ -0,0 +1,115 @@
---
read_when:
- 更改智能体运行时、工作区引导或会话行为时
summary: 智能体运行时(嵌入式 pi-mono、工作区契约和会话引导
title: 智能体运行时
x-i18n:
generated_at: "2026-02-03T10:04:53Z"
model: claude-opus-4-5
provider: pi
source_hash: 04b4e0bc6345d2afd9a93186e5d7a02a393ec97da2244e531703cb6a1c182325
source_path: concepts/agent.md
workflow: 15
---
# 智能体运行时 🤖
OpenClaw 运行一个源自 **pi-mono** 的嵌入式智能体运行时。
## 工作区(必需)
OpenClaw 使用单一智能体工作区目录(`agents.defaults.workspace`)作为智能体**唯一**的工作目录(`cwd`),用于工具和上下文。
建议:使用 `openclaw setup` 在缺失时创建 `~/.openclaw/openclaw.json` 并初始化工作区文件。
完整工作区布局 + 备份指南:[智能体工作区](/concepts/agent-workspace)
如果启用了 `agents.defaults.sandbox`,非主会话可以在 `agents.defaults.sandbox.workspaceRoot` 下使用按会话隔离的工作区覆盖此设置(参见 [Gateway 网关配置](/gateway/configuration))。
## 引导文件(注入)
`agents.defaults.workspace`OpenClaw 期望以下用户可编辑的文件:
- `AGENTS.md` — 操作指令 + "记忆"
- `SOUL.md` — 人设、边界、语气
- `TOOLS.md` — 用户维护的工具说明(例如 `imsg``sag`、约定)
- `BOOTSTRAP.md` — 一次性首次运行仪式(完成后删除)
- `IDENTITY.md` — 智能体名称/风格/表情
- `USER.md` — 用户档案 + 偏好称呼
在新会话的第一轮OpenClaw 将这些文件的内容直接注入智能体上下文。
空文件会被跳过。大文件会被修剪和截断并添加标记,以保持提示词精简(阅读文件获取完整内容)。
如果文件缺失OpenClaw 会注入一行"文件缺失"标记(`openclaw setup` 将创建安全的默认模板)。
`BOOTSTRAP.md` 仅在**全新工作区**(没有其他引导文件存在)时创建。如果你在完成仪式后删除它,后续重启不应重新创建。
要完全禁用引导文件创建(用于预置工作区),请设置:
```json5
{ agent: { skipBootstrap: true } }
```
## 内置工具
核心工具read/exec/edit/write 及相关系统工具)始终可用,受工具策略约束。`apply_patch` 是可选的,由 `tools.exec.applyPatch` 控制。`TOOLS.md` **不**控制哪些工具存在;它是关于*你*希望如何使用它们的指导。
## Skills
OpenClaw 从三个位置加载 Skills名称冲突时工作区优先
- 内置(随安装包提供)
- 托管/本地:`~/.openclaw/skills`
- 工作区:`<workspace>/skills`
Skills 可通过配置/环境变量控制(参见 [Gateway 网关配置](/gateway/configuration) 中的 `skills`)。
## pi-mono 集成
OpenClaw 复用 pi-mono 代码库的部分内容(模型/工具),但**会话管理、设备发现和工具连接由 OpenClaw 负责**。
- 无 pi-coding 智能体运行时。
- 不读取 `~/.pi/agent``<workspace>/.pi` 设置。
## 会话
会话记录以 JSONL 格式存储在:
- `~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl`
会话 ID 是稳定的,由 OpenClaw 选择。
**不**读取旧版 Pi/Tau 会话文件夹。
## 流式传输中的引导
当队列模式为 `steer` 时,入站消息会注入当前运行。
队列在**每次工具调用后**检查;如果存在排队消息,当前助手消息的剩余工具调用将被跳过(工具结果显示错误"Skipped due to queued user message."),然后在下一个助手响应前注入排队的用户消息。
当队列模式为 `followup``collect` 时,入站消息会保留到当前轮次结束,然后使用排队的载荷开始新的智能体轮次。参见 [队列](/concepts/queue) 了解模式 + 防抖/上限行为。
分块流式传输在助手块完成后立即发送;默认为**关闭**`agents.defaults.blockStreamingDefault: "off"`)。
通过 `agents.defaults.blockStreamingBreak` 调整边界(`text_end``message_end`;默认为 text_end
使用 `agents.defaults.blockStreamingChunk` 控制软块分块(默认 8001200 字符;优先段落分隔,其次换行;最后是句子)。
使用 `agents.defaults.blockStreamingCoalesce` 合并流式块以减少单行刷屏(发送前基于空闲的合并)。非 Telegram 渠道需要显式设置 `*.blockStreaming: true` 以启用分块回复。
工具启动时发出详细工具摘要无防抖Control UI 在可用时通过智能体事件流式传输工具输出。
更多详情:[流式传输 + 分块](/concepts/streaming)。
## 模型引用
配置中的模型引用(例如 `agents.defaults.model``agents.defaults.models`)通过在**第一个** `/` 处分割来解析。
- 配置模型时使用 `provider/model`
- 如果模型 ID 本身包含 `/`OpenRouter 风格),请包含提供商前缀(例如:`openrouter/moonshotai/kimi-k2`)。
- 如果省略提供商OpenClaw 将输入视为别名或**默认提供商**的模型(仅在模型 ID 中没有 `/` 时有效)。
## 配置(最小)
至少需要设置:
- `agents.defaults.workspace`
- `channels.whatsapp.allowFrom`(强烈建议)
---
_下一篇[群聊](/channels/group-messages)_ 🦞

View File

@@ -0,0 +1,123 @@
---
read_when:
- 正在开发 Gateway 网关协议、客户端或传输层
summary: WebSocket Gateway 网关架构、组件和客户端流程
title: Gateway 网关架构
x-i18n:
generated_at: "2026-02-03T07:45:55Z"
model: claude-opus-4-5
provider: pi
source_hash: c636d5d8a5e628067432b30671466309e3d630b106d413f1708765bf2a9399a1
source_path: concepts/architecture.md
workflow: 15
---
# Gateway 网关架构
最后更新2026-01-22
## 概述
- 单个长期运行的 **Gateway 网关**拥有所有消息平台(通过 Baileys 的 WhatsApp、通过 grammY 的 Telegram、Slack、Discord、Signal、iMessage、WebChat
- 控制平面客户端macOS 应用、CLI、Web 界面、自动化)通过配置的绑定主机(默认 `127.0.0.1:18789`)上的 **WebSocket** 连接到 Gateway 网关。
- **节点**macOS/iOS/Android/无头设备)也通过 **WebSocket** 连接,但声明 `role: node` 并带有明确的能力/命令。
- 每台主机一个 Gateway 网关;它是唯一打开 WhatsApp 会话的位置。
- **canvas 主机**(默认 `18793`)提供智能体可编辑的 HTML 和 A2UI。
## 组件和流程
### Gateway 网关(守护进程)
- 维护提供商连接。
- 暴露类型化的 WS API请求、响应、服务器推送事件
- 根据 JSON Schema 验证入站帧。
- 发出事件如 `agent``chat``presence``health``heartbeat``cron`
### 客户端mac 应用 / CLI / web 管理)
- 每个客户端一个 WS 连接。
- 发送请求(`health``status``send``agent``system-presence`)。
- 订阅事件(`tick``agent``presence``shutdown`)。
### 节点macOS / iOS / Android / 无头设备)
-`role: node` 连接到**同一个 WS 服务器**。
-`connect` 中提供设备身份;配对是**基于设备**的(角色为 `node`),批准存储在设备配对存储中。
- 暴露命令如 `canvas.*``camera.*``screen.record``location.get`
协议详情:
- [Gateway 网关协议](/gateway/protocol)
### WebChat
- 静态界面,使用 Gateway 网关 WS API 获取聊天历史和发送消息。
- 在远程设置中,通过与其他客户端相同的 SSH/Tailscale 隧道连接。
## 连接生命周期(单个客户端)
```
Client Gateway
| |
|---- req:connect -------->|
|<------ res (ok) ---------| (or res error + close)
| (payload=hello-ok carries snapshot: presence + health)
| |
|<------ event:presence ---|
|<------ event:tick -------|
| |
|------- req:agent ------->|
|<------ res:agent --------| (ack: {runId,status:"accepted"})
|<------ event:agent ------| (streaming)
|<------ res:agent --------| (final: {runId,status,summary})
| |
```
## 线路协议(摘要)
- 传输WebSocket带 JSON 载荷的文本帧。
- 第一帧**必须**是 `connect`
- 握手后:
- 请求:`{type:"req", id, method, params}``{type:"res", id, ok, payload|error}`
- 事件:`{type:"event", event, payload, seq?, stateVersion?}`
- 如果设置了 `OPENCLAW_GATEWAY_TOKEN`(或 `--token``connect.params.auth.token` 必须匹配,否则套接字关闭。
- 有副作用的方法(`send``agent`)需要幂等键以安全重试;服务器保持短期去重缓存。
- 节点必须在 `connect` 中包含 `role: "node"` 以及能力/命令/权限。
## 配对 + 本地信任
- 所有 WS 客户端(操作员 + 节点)在 `connect` 时包含**设备身份**。
- 新设备 ID 需要配对批准Gateway 网关为后续连接颁发**设备令牌**。
- **本地**连接loopback 或 Gateway 网关主机自身的 tailnet 地址)可以自动批准以保持同主机用户体验流畅。
- **非本地**连接必须签名 `connect.challenge` nonce 并需要明确批准。
- Gateway 网关认证(`gateway.auth.*`)仍适用于**所有**连接,无论本地还是远程。
详情:[Gateway 网关协议](/gateway/protocol)、[配对](/channels/pairing)、[安全](/gateway/security)。
## 协议类型和代码生成
- TypeBox 模式定义协议。
- 从这些模式生成 JSON Schema。
- 从 JSON Schema 生成 Swift 模型。
## 远程访问
- 推荐Tailscale 或 VPN。
- 替代方案SSH 隧道
```bash
ssh -N -L 18789:127.0.0.1:18789 user@host
```
- 相同的握手 + 认证令牌适用于隧道连接。
- 远程设置中可以为 WS 启用 TLS + 可选的证书固定。
## 操作快照
- 启动:`openclaw gateway`(前台,日志输出到 stdout
- 健康检查:通过 WS 的 `health`(也包含在 `hello-ok` 中)。
- 监控:使用 launchd/systemd 自动重启。
## 不变量
- 每台主机恰好一个 Gateway 网关控制单个 Baileys 会话。
- 握手是强制的;任何非 JSON 或非 connect 的第一帧都会导致硬关闭。
- 事件不会重放;客户端必须在出现间隙时刷新。

View File

@@ -0,0 +1,67 @@
---
read_when:
- 你想了解自动压缩和 /compact
- 你正在调试长会话触及上下文限制的问题
summary: 上下文窗口 + 压缩OpenClaw 如何将会话保持在模型限制内
title: 压缩
x-i18n:
generated_at: "2026-02-01T20:22:17Z"
model: claude-opus-4-5
provider: pi
source_hash: e1d6791f2902044b5798ebf9320a7d055d37211eff4be03caa35d7e328ae803c
source_path: concepts/compaction.md
workflow: 14
---
# 上下文窗口与压缩
每个模型都有一个**上下文窗口**(可见的最大 token 数。长时间运行的对话会累积消息和工具结果一旦窗口空间紧张OpenClaw 会**压缩**较早的历史记录以保持在限制范围内。
## 什么是压缩
压缩会将**较早的对话总结**为一条紧凑的摘要条目,并保持近期消息不变。摘要存储在会话历史中,因此后续请求使用的是:
- 压缩摘要
- 压缩点之后的近期消息
压缩会**持久化**到会话的 JSONL 历史记录中。
## 配置
有关 `agents.defaults.compaction` 设置,请参阅[压缩配置与模式](/concepts/compaction)。
## 自动压缩(默认开启)
当会话接近或超过模型的上下文窗口时OpenClaw 会触发自动压缩,并可能使用压缩后的上下文重试原始请求。
你会看到:
- 详细模式下显示 `🧹 Auto-compaction complete`
- `/status` 显示 `🧹 Compactions: <count>`
在压缩之前OpenClaw 可以运行一次**静默记忆刷写**轮次,将持久化笔记写入磁盘。详情及配置请参阅[记忆](/concepts/memory)。
## 手动压缩
使用 `/compact`(可选附带指令)强制执行一次压缩:
```
/compact Focus on decisions and open questions
```
## 上下文窗口来源
上下文窗口因模型而异。OpenClaw 使用已配置提供商目录中的模型定义来确定限制。
## 压缩与修剪
- **压缩**:总结并**持久化**到 JSONL 中。
- **会话修剪**:仅裁剪旧的**工具结果****在内存中**按请求进行。
有关修剪的详情,请参阅 [/concepts/session-pruning](/concepts/session-pruning)。
## 提示
- 当会话感觉过时或上下文臃肿时,使用 `/compact`
- 大型工具输出已被截断;修剪可以进一步减少工具结果的堆积。
- 如果你需要全新开始,`/new``/reset` 会启动一个新的会话 ID。

Some files were not shown because too many files have changed in this diff Show More