OpenClaw 架构优化:Request Capabilities 集中化管理

OpenClaw 架构优化:Request Capabilities 集中化管理

OpenClaw 在最新版本中对 Request Capabilities(请求能力)进行了集中化重构,统一了各个 Provider 的请求处理逻辑,提升了性能并简化了配置。

本文将详细介绍这项架构变更的设计理念、实现细节和使用方法。

目录

什么是 Request Capabilities

Request Capabilities 是 OpenClaw Provider 系统中用于描述和管理 HTTP 请求能力的核心概念。它包括:

  • 协议支持 — HTTP/1.1、HTTP/2、HTTPS
  • 认证方式 — Basic Auth、Bearer Token、OAuth
  • 编码格式 — JSON、Form、Multipart
  • 超时控制 — 连接超时、读取超时
  • 重试策略 — 指数退避、固定间隔
  • 连接池 — 最大连接数、 keep-alive

之前的分散管理

// 每个 Provider 自己管理请求能力
class GitHubProvider {
  private httpClient = new HttpClient({
    timeout: 30000,
    retries: 3,
    headers: {
      'User-Agent': 'OpenClaw-GitHub'
    }
  });
}

class SlackProvider { private httpClient = new HttpClient({ timeout: 10000, retries: 2, headers: { 'User-Agent': 'OpenClaw-Slack' } }); }

// 配置重复,难以统一管理

集中化后的统一管理

// 统一的 Request Capabilities 管理
class RequestCapabilityManager {
  private capabilities = new Map();
  
  register(provider: string, capability: RequestCapability) {
    this.capabilities.set(provider, capability);
  }
  
  get(provider: string): RequestCapability {
    return this.capabilities.get(provider);
  }
}

// 所有 Provider 共享统一配置

为什么需要集中化

1. 消除重复配置

之前的问题

  • 10 个 Provider = 10 份重复配置
  • 修改全局超时需要改 10 处
  • 容易遗漏导致不一致

集中化后

  • 1 份基础配置
  • Provider 可继承或覆盖
  • 修改一处,全局生效

2. 提升性能

连接池共享

// 之前:每个 Provider 独立连接池
// GitHubProvider: 10 connections
// SlackProvider: 10 connections
// Total: 20 connections

// 集中化后:共享连接池 // Unified Pool: 15 connections (动态分配) // 节省 25% 资源

3. 简化维护

统一的监控和日志

  • 单一入口查看所有请求
  • 统一的错误处理
  • 一致的审计日志格式

架构变更详解

核心组件

┌─────────────────────────────────────┐
│     Request Capability Manager      │
├─────────────────────────────────────┤
│  ┌──────────────┐  ┌────────────┐  │
│  │  Base Config │  │  Provider  │  │
│  │              │  │  Overrides │  │
│  └──────────────┘  └────────────┘  │
├─────────────────────────────────────┤
│  ┌──────────────┐  ┌────────────┐  │
│  │  Connection  │  │   Retry    │  │
│  │    Pool      │  │  Handler   │  │
│  └──────────────┘  └────────────┘  │
├─────────────────────────────────────┤
│  ┌──────────────┐  ┌────────────┐  │
│  │   Timeout    │  │   Auth     │  │
│  │   Manager    │  │  Handler   │  │
│  └──────────────┘  └────────────┘  │
└─────────────────────────────────────┘

新的配置结构

config.yaml

集中式 Request Capabilities 配置

request_capabilities: # 基础配置(所有 Provider 默认继承) base: timeout: connect: 5000 read: 30000 retry: max_attempts: 3 backoff: exponential max_delay: 60000 pool: max_connections: 100 max_connections_per_host: 10 keep_alive: true keep_alive_duration: 30000 headers: User-Agent: "OpenClaw/2026.4.0" Accept: "application/json" security: verify_ssl: true follow_redirects: true max_redirects: 3 # Provider 特定覆盖 providers: github: timeout: read: 60000 # GitHub API 较慢,延长超时 headers: Accept: "application/vnd.github.v3+json" slack: timeout: connect: 3000 read: 10000 # Slack 响应快 retry: max_attempts: 5 # Slack 可能限流,增加重试 openai: timeout: read: 120000 # OpenAI 生成可能很慢 pool: max_connections: 50 # 并发请求较多

URL 解析基础化

之前每个 Provider 可能有自己的 URL 解析逻辑,现在统一为基础组件:

// providers/core/url-parser.ts
export class ComparableURLParser {
  parse(url: string): ParsedURL {
    // 统一的严格解析
    const normalized = this.normalize(url);
    
    // 可比较的 URL 表示
    return {
      protocol: normalized.protocol,
      hostname: normalized.hostname.toLowerCase(),
      port: normalized.port,
      pathname: this.normalizePath(normalized.pathname),
      search: this.normalizeSearch(normalized.search),
      hash: normalized.hash,
      // 可比较字符串
      comparable: this.toComparableString(normalized)
    };
  }
  
  // 用于缓存键、去重等
  toComparableString(url: ParsedURL): string {
    return ${url.protocol}://${url.hostname}:${url.port}${url.pathname};
  }
}

迁移与配置

自动迁移

OpenClaw 提供自动迁移工具:

迁移旧配置

openclaw migrate request-capabilities

预览变更

openclaw migrate request-capabilities --dry-run

应用变更

openclaw migrate request-capabilities --apply

手动配置

旧配置(v2026.3.x)

providers:
  github:
    http:
      timeout: 60000
      retries: 3
    
  slack:
    http:
      timeout: 10000
      retries: 2

新配置(v2026.4.x)

request_capabilities:
  base:
    timeout:
      connect: 5000
      read: 30000
    retry:
      max_attempts: 3
  
  providers:
    github:
      timeout:
        read: 60000  # 覆盖基础配置
    
    slack:
      timeout:
        read: 10000
      retry:
        max_attempts: 5

Provider 代码迁移

旧代码

class MyProvider {
  private client = new HttpClient({
    timeout: 30000,
    retries: 3
  });
  
  async fetch(url: string) {
    return this.client.get(url);
  }
}

新代码

class MyProvider {
  // 注入集中管理的 Request Capability
  constructor(
    @Inject('REQUEST_CAPABILITY') 
    private capability: RequestCapability
  ) {}
  
  async fetch(url: string) {
    // 使用统一管理的配置
    return this.capability.fetch(url);
  }
}

性能对比

内存使用

| 场景 | 分散管理 | 集中化 | 节省 |
|——|———-|——–|——|
| 10 Providers | 200MB | 120MB | 40% |
| 20 Providers | 400MB | 200MB | 50% |

连接效率

| 指标 | 分散管理 | 集中化 | 提升 |
|——|———-|——–|——|
| 连接复用率 | 60% | 85% | +25% |
| 平均延迟 | 150ms | 120ms | -20% |
| 超时率 | 2% | 0.8% | -60% |

配置维护成本

| 任务 | 分散管理 | 集中化 | 效率 |
|——|———-|——–|——|
| 修改全局超时 | 修改 10 处 | 修改 1 处 | 10x |
| 添加新 Provider | 复制配置 | 继承基础 | 5x |
| 排查问题 | 查看 10 处日志 | 查看统一日志 | 3x |

高级特性

动态能力调整

// 运行时调整请求能力
const capability = requestCapabilityManager.get('github');

// 临时增加超时(针对大文件下载) capability.withTimeout(120000).fetch(url);

// 临时禁用重试(针对幂等操作) capability.withRetry(false).fetch(url);

能力继承链

request_capabilities:
  base:
    # 最基础配置
    timeout:
      connect: 5000
  
  profiles:
    api_client:
      extends: base
      timeout:
        read: 30000
    
    streaming_client:
      extends: api_client
      timeout:
        read: 300000  # 流式需要更长超时

监控和指标

monitoring:
  request_capabilities:
    metrics:
      - request_count
      - response_time
      - error_rate
      - connection_pool_size
    
    alerts:
      - name: "High Error Rate"
        condition: "error_rate > 0.05"
        action: "notify"

总结

Request Capabilities 集中化 是 OpenClaw 架构优化的重要一步:

1. 消除重复 — 统一配置,一处修改全局生效
2. 性能提升 — 共享连接池,资源利用率提升 40-50%
3. 维护简化 — 统一监控、日志和错误处理
4. 扩展性强 — Provider 可灵活继承和覆盖配置

配置建议

request_capabilities:
  base:
    # 设置合理的默认值
    timeout:
      connect: 5000
      read: 30000
  
  providers:
    # 根据 Provider 特性调整
    slow_api:
      timeout:
        read: 120000

常见问题

Q: 集中化后还能为特定 Provider 定制配置吗?

A: 可以,providers 部分允许覆盖基础配置的任何选项。

Q: 对现有 Provider 插件有影响吗?

A: 内部 Provider 已自动迁移,第三方 Provider 需要通过迁移工具更新。

Q: 连接池共享会导致 Provider 之间相互影响吗?

A: 不会,每个 Provider 有独立的连接配额,只是底层复用连接池基础设施。

Q: 如何查看当前的 Request Capability 配置?

A:

openclaw config get request_capabilities

查看特定 Provider 的有效配置(继承+覆盖)

openclaw config get request_capabilities.providers.github --effective

Q: 集中化后错误处理有变化吗?

A: 错误类型统一了,更容易理解和处理:

try {
  await capability.fetch(url);
} catch (error) {
  if (error instanceof TimeoutError) {
    // 统一的超时错误
  } else if (error instanceof RetryExhaustedError) {
    // 统一的重试耗尽错误
  }
}

Q: 是否支持不同环境的配置?

A: 支持:

request_capabilities:
  base:
    timeout:
      read: 30000
  
  environments:
    development:
      timeout:
        read: 60000  # 开发环境更宽松
      verify_ssl: false
    
    production:
      timeout:
        read: 30000
      verify_ssl: true

参考来源

相关阅读:

OpenClaw 安全更新:Web Fetch Provider 边界强化详解

OpenClaw 安全更新:Web Fetch Provider 边界强化详解

OpenClaw 在最新版本中加强了 Web Fetch Provider 的安全边界,通过强化 URL 解析和请求验证,有效防止 SSRF(服务器端请求伪造)等安全攻击。

本文将详细介绍这项安全更新的技术细节和配置方法。

目录

什么是 Web Fetch Provider

Web Fetch Provider 是 OpenClaw 中用于网页内容获取的核心组件。它负责:

  • 发送 HTTP/HTTPS 请求
  • 解析响应内容
  • 处理重定向和超时
  • 管理连接池

典型使用场景

在 Skill 中使用 Web Fetch

web_fetch: url: "https://api.example.com/data" method: GET headers: Authorization: "Bearer ${API_TOKEN}"

安全风险分析

SSRF(服务器端请求伪造)

攻击原理
攻击者通过构造特殊 URL,让服务器向内部网络或敏感资源发起请求。

攻击示例

恶意请求

url: "http://169.254.169.254/latest/meta-data/" # AWS 元数据服务

url: "http://localhost:6379/" # 本地 Redis 服务

url: "file:///etc/passwd" # 本地文件读取

URL 解析漏洞

问题场景

  • 不规范的 URL 格式被意外解析
  • 特殊字符绕过安全检查
  • Unicode 编码混淆

有问题的 URL

http://example.com@evil.com/ # @ 符号混淆 http://example.com%2F..%2Fetc/passwd # 编码绕过

边界强化措施

1. URL 解析加固

新的 URL 解析器采用更严格的 RFC 3986 标准:

// 严格的 URL 解析
class HardenedURLParser {
  parse(url: string): ParsedURL {
    // 1. 规范化编码
    const normalized = this.normalizeEncoding(url);
    
    // 2. 验证协议白名单
    if (!this.isAllowedProtocol(normalized.protocol)) {
      throw new SecurityError(Protocol ${normalized.protocol} not allowed);
    }
    
    // 3. 验证主机名格式
    if (!this.isValidHostname(normalized.hostname)) {
      throw new SecurityError(Invalid hostname: ${normalized.hostname});
    }
    
    // 4. 检查 IP 范围
    if (this.isPrivateIP(normalized.hostname)) {
      throw new SecurityError(Private IP access not allowed: ${normalized.hostname});
    }
    
    return normalized;
  }
}

2. 请求边界控制

config.yaml

providers: web_fetch: security: # 启用边界强化 hardened_boundaries: true # 协议白名单 allowed_protocols: - https - http # 禁止的主机模式 blocked_host_patterns: - "localhost" - "127...*" - "10...*" - "192.168.." - "*.internal" - "*.local" # 禁止的端口 blocked_ports: - 22 # SSH - 23 # Telnet - 25 # SMTP - 53 # DNS - 110 # POP3 - 143 # IMAP - 3389 # RDP - 6379 # Redis - 3306 # MySQL - 5432 # PostgreSQL # 最大重定向次数 max_redirects: 3 # 验证 SSL 证书 verify_ssl: true

3. 响应边界控制

providers:
  web_fetch:
    response_limits:
      # 最大响应大小 (10MB)
      max_size: 10485760
      
      # 允许的内容类型
      allowed_content_types:
        - "text/html"
        - "text/plain"
        - "application/json"
        - "application/xml"
        - "text/markdown"
      
      # 禁止的内容模式
      blocked_patterns:
        - "]>[\\s\\S]?"  # 脚本标签(可选)

配置与使用

基础配置

config.yaml

providers: web_fetch: enabled: true # 安全强化(推荐启用) security: hardened_boundaries: true # 超时设置 timeout: connect: 5000 # 连接超时 5秒 read: 30000 # 读取超时 30秒 # 重试策略 retry: max_attempts: 3 backoff: exponential

在 Skill 中使用

// 安全的 Web Fetch 调用
export class SafeWebFetchSkill {
  async fetchData(url: string) {
    // OpenClaw 会自动应用安全边界
    const response = await this.webFetch({
      url,
      method: 'GET',
      headers: {
        'User-Agent': 'OpenClaw/1.0'
      }
    });
    
    return response.data;
  }
}

自定义安全策略

为特定 provider 定制安全策略

providers: web_fetch: # 默认严格模式 security: hardened_boundaries: true # 特定场景宽松模式(谨慎使用) profiles: internal_api: security: hardened_boundaries: true blocked_host_patterns: # 允许访问内部 API - "localhost" - "127.0.0.1" public_only: security: hardened_boundaries: true blocked_host_patterns: - "*.internal.company.com"

最佳实践

1. 输入验证

// 始终验证用户输入的 URL
function validateUserURL(input: string): string {
  // 1. 基本格式检查
  const urlPattern = /^https?:\/\/.+/;
  if (!urlPattern.test(input)) {
    throw new Error('URL must start with http:// or https://');
  }
  
  // 2. 长度限制
  if (input.length > 2048) {
    throw new Error('URL too long');
  }
  
  // 3. 危险字符检查
  const dangerousChars = ['<', '>', '{', '}', '|', '^', ''];
  for (const char of dangerousChars) {
    if (input.includes(char)) {
      throw new Error(URL contains dangerous character: ${char}`);
    }
  }
  
  return input;
}

2. 使用 URL 白名单

对于已知安全的 API

providers: web_fetch: whitelist: enabled: true urls: - "https://api.github.com/*" - "https://api.openai.com/*" - "https://docs.openclaw.ai/*"

3. 日志审计

providers:
  web_fetch:
    audit:
      enabled: true
      log_level: info
      log_requests: true
      log_responses: false  # 避免记录敏感数据

4. 监控和告警

monitoring:
  web_fetch:
    alerts:
      - name: "SSRF Attempt Detected"
        condition: "security.blocked_request_count > 0"
        action: "notify_admin"
      
      - name: "High Error Rate"
        condition: "error_rate > 0.1"
        action: "throttle_requests"

测试安全边界

安全测试用例

// tests/security/web-fetch.test.ts
describe('Web Fetch Security Boundaries', () => {
  it('should block private IP access', async () => {
    await expect(
      webFetch('http://192.168.1.1/')
    ).rejects.toThrow('Private IP access not allowed');
  });
  
  it('should block localhost access', async () => {
    await expect(
      webFetch('http://localhost:8080/')
    ).rejects.toThrow('Blocked host pattern: localhost');
  });
  
  it('should block file protocol', async () => {
    await expect(
      webFetch('file:///etc/passwd')
    ).rejects.toThrow('Protocol file not allowed');
  });
  
  it('should block suspicious URL encoding', async () => {
    await expect(
      webFetch('http://example.com%2F..%2Fadmin')
    ).rejects.toThrow('Invalid URL encoding');
  });
});

总结

Web Fetch Provider 边界强化 为 OpenClaw 带来了更强的安全防护:

1. URL 解析加固 — 严格遵循 RFC 标准,防止编码绕过
2. 请求边界控制 — 协议、主机、端口多层次限制
3. 响应边界控制 — 大小、类型双重限制
4. 可观测性 — 完整的审计日志和监控告警

关键配置

providers:
  web_fetch:
    security:
      hardened_boundaries: true  # 启用安全强化

常见问题

Q: 启用边界强化后,原有功能会受影响吗?

A: 正常的外部 API 调用不会受影响。只有尝试访问内部网络或敏感资源的请求会被阻止。

Q: 如何临时禁用某个安全限制?

A: 不建议禁用,但可以添加例外规则:

security:
  hardened_boundaries: true
  exceptions:
    - host: "internal-api.company.com"
      reason: "Internal API access required"

Q: 误拦截了合法请求怎么办?

A:
1. 检查审计日志确认拦截原因
2. 如果是白名单中的 API,更新白名单配置
3. 如果是配置错误,调整 blocked_host_patterns

Q: 支持自定义安全策略吗?

A: 支持,可以通过配置文件自定义协议、端口、主机模式等限制。

Q: 对性能有影响吗?

A: 影响极小。URL 解析和验证在微秒级完成。

Q: 如何查看被拦截的请求?

A:

查看安全审计日志

tail -f ~/.openclaw/logs/security-audit.log | grep "BLOCKED"

统计拦截情况

openclaw stats web-fetch --security

参考来源

相关阅读:

OpenClaw 重磅重构:Flow 更名为 Task-flow 的完整迁移指南

OpenClaw 重磅重构:Flow 更名为 Task-flow 的完整迁移指南

OpenClaw 正在进行一项重大重构:将原有的 “Flow” 系统全面更名为 “Task-flow”。这项变更涉及命名空间、API、工具调用等多个层面,本文将提供完整的迁移指南。

目录

为什么更名为 Task-flow

命名更清晰

Flow 这个词在编程领域含义模糊,可能指:

  • 工作流(Workflow)
  • 数据流(Data Flow)
  • 控制流(Control Flow)
  • 异步流(Async Stream)

Task-flow 明确表达了 “任务流” 的概念:

  • 任务为核心单元
  • 强调执行流程
  • 与 OpenClaw 的任务系统概念一致

架构一致性

OpenClaw 的核心概念体系:

Task(任务)→ Task-flow(任务流)→ Pipeline(管道)

更名为 Task-flow 后,概念层次更加清晰。

变更范围总览

1. 模块重命名

| 旧路径 | 新路径 |
|——–|——–|
| flow/tooling | task-flow/tooling |
| flow/registry | task-flow/registry |
| flow/runtime | task-flow/runtime |

2. API 变更

旧 API(已废弃):

import { FlowTool } from '@openclaw/flow-tooling';
import { FlowRegistry } from '@openclaw/flow-registry';

新 API:

import { TaskFlowTool } from '@openclaw/task-flow/tooling';
import { TaskFlowRegistry } from '@openclaw/task-flow/registry';

3. 工具调用变更

| 旧工具名 | 新工具名 |
|———-|———-|
| flow_tool | task_flow_tool |
| flow_execute | task_flow_execute |
| flow_create | task_flow_create |

4. 配置变更

旧配置:

flow:
  enabled: true
  registry: flow-registry

新配置:

task_flow:
  enabled: true
  registry: task-flow-registry

迁移步骤详解

步骤 1: 更新导入路径

批量替换命令:

在项目根目录执行

find . -type f -name ".ts" -o -name ".js" | xargs sed -i \ -e 's/@openclaw\/flow-tooling/@openclaw\/task-flow\/tooling/g' \ -e 's/@openclaw\/flow-registry/@openclaw\/task-flow\/registry/g' \ -e 's/FlowTool/TaskFlowTool/g' \ -e 's/FlowRegistry/TaskFlowRegistry/g'

步骤 2: 更新配置文件

config.yaml

旧配置(删除)

flow:

enabled: true

新配置

task_flow: enabled: true tooling: default_executor: "builtin" registry: auto_register: true modules: - "task-flow-core" - "task-flow-plugin"

步骤 3: 更新插件代码

ACP 插件更新示例:

// 更新前
import { useFlowRuntime } from '@openclaw/flow-runtime';

export class MyPlugin { async execute() { const flow = await useFlowRuntime(); await flow.execute('my-flow'); } }

// 更新后 import { useTaskFlowRuntime } from '@openclaw/task-flow/runtime';

export class MyPlugin { async execute() { const taskFlow = await useTaskFlowRuntime(); await taskFlow.execute('my-task-flow'); } }

Plugin SDK 更新:

// 更新前
import { FlowConsumer } from '@openclaw/plugin-sdk/flow';

// 更新后 import { TaskFlowConsumer } from '@openclaw/plugin-sdk/task-flow';

步骤 4: 更新运行时调用

// 更新前
await runtime.call('flow', {
  action: 'create',
  params: { name: 'my-flow' }
});

// 更新后 await runtime.call('task-flow', { action: 'create', params: { name: 'my-task-flow' } });

代码示例对比

示例 1: 创建任务流

旧代码:

import { FlowFactory } from '@openclaw/flow-tooling';

const flow = FlowFactory.create({ name: 'data-processing', steps: [ { id: 'step1', action: 'fetch' }, { id: 'step2', action: 'transform' }, { id: 'step3', action: 'save' } ] });

await flow.execute();

新代码:

import { TaskFlowFactory } from '@openclaw/task-flow/tooling';

const taskFlow = TaskFlowFactory.create({ name: 'data-processing', steps: [ { id: 'step1', action: 'fetch' }, { id: 'step2', action: 'transform' }, { id: 'step3', action: 'save' } ] });

await taskFlow.execute();

示例 2: 注册自定义任务流

旧代码:

import { FlowRegistry } from '@openclaw/flow-registry';

const registry = new FlowRegistry(); registry.register('custom-flow', CustomFlowHandler);

新代码:

import { TaskFlowRegistry } from '@openclaw/task-flow/registry';

const registry = new TaskFlowRegistry(); registry.register('custom-task-flow', CustomTaskFlowHandler);

示例 3: ACP 任务流消费

旧代码:

import { ACPFlowConsumer } from '@openclaw/acp/flow';

@FlowConsumer() class MyACPPlugin { async onFlowEvent(event: FlowEvent) { // 处理 flow 事件 } }

新代码:

import { ACPTaskFlowConsumer } from '@openclaw/acp/task-flow';

@TaskFlowConsumer() class MyACPPlugin { async onTaskFlowEvent(event: TaskFlowEvent) { // 处理 task-flow 事件 } }

迁移检查清单

  • [ ] 更新所有导入路径
  • [ ] 替换 Flow → TaskFlow 类名
  • [ ] 更新配置文件
  • [ ] 测试任务流执行
  • [ ] 验证插件兼容性
  • [ ] 更新文档注释

向后兼容性

OpenClaw 提供了临时兼容层:

config.yaml

compatibility: flow_aliases: enabled: true # 启用 Flow → Task-flow 别名 deprecation_warnings: true # 显示废弃警告

注意:兼容层将在 v2026.6.0 版本中移除,请尽快完成迁移。

迁移工具

OpenClaw 提供了自动迁移工具:

安装迁移工具

npm install -g @openclaw/migrate

执行迁移

openclaw-migrate flow-to-task-flow --src ./my-project

预览变更(不实际修改)

openclaw-migrate flow-to-task-flow --src ./my-project --dry-run

总结

Flow → Task-flow 重构 是 OpenClaw 概念体系完善的重要一步:

1. 命名更清晰 — Task-flow 明确表达”任务流”概念
2. 架构更一致 — 与 Task、Pipeline 等概念形成完整体系
3. 迁移有工具 — 提供自动迁移工具和兼容层

关键行动
1. 运行 openclaw-migrate 自动迁移
2. 测试任务流功能
3. 在 v2026.6.0 前完成迁移

常见问题

Q: 为什么需要这次重命名?

A:

  • “Flow” 含义模糊,容易与其他概念混淆
  • “Task-flow” 更准确表达功能
  • 统一 OpenClaw 的概念体系

Q: 旧代码还能运行吗?

A: 可以,通过兼容层暂时支持,但会在 v2026.6.0 移除。

Q: 迁移工具会修改哪些文件?

A:

  • TypeScript/JavaScript 源码文件
  • 配置文件(config.yaml)
  • 类型定义文件
  • 测试文件

Q: 如何验证迁移成功?

A:

1. 检查是否还有 flow 引用

grep -r "from.flow" --include=".ts" src/

2. 运行测试

npm test

3. 验证任务流执行

openclaw task-flow test

Q: 第三方插件受影响吗?

A: 是的,需要插件作者更新。OpenClaw 已通知主要插件作者。

Q: 配置文件需要手动更新吗?

A: 迁移工具会自动处理,但建议人工检查确认。

参考来源

相关阅读:

OpenClaw 架构优化:Request Capabilities 集中化管理

OpenClaw 架构优化:Request Capabilities 集中化管理

OpenClaw 在最新版本中对 Request Capabilities(请求能力)进行了集中化重构,统一了各个 Provider 的请求处理逻辑,提升了性能并简化了配置。

本文将详细介绍这项架构变更的设计理念、实现细节和使用方法。

目录

什么是 Request Capabilities

Request Capabilities 是 OpenClaw Provider 系统中用于描述和管理 HTTP 请求能力的核心概念。它包括:

  • 协议支持 — HTTP/1.1、HTTP/2、HTTPS
  • 认证方式 — Basic Auth、Bearer Token、OAuth
  • 编码格式 — JSON、Form、Multipart
  • 超时控制 — 连接超时、读取超时
  • 重试策略 — 指数退避、固定间隔
  • 连接池 — 最大连接数、 keep-alive

之前的分散管理

// 每个 Provider 自己管理请求能力
class GitHubProvider {
  private httpClient = new HttpClient({
    timeout: 30000,
    retries: 3,
    headers: {
      'User-Agent': 'OpenClaw-GitHub'
    }
  });
}

class SlackProvider { private httpClient = new HttpClient({ timeout: 10000, retries: 2, headers: { 'User-Agent': 'OpenClaw-Slack' } }); }

// 配置重复,难以统一管理

集中化后的统一管理

// 统一的 Request Capabilities 管理
class RequestCapabilityManager {
  private capabilities = new Map();
  
  register(provider: string, capability: RequestCapability) {
    this.capabilities.set(provider, capability);
  }
  
  get(provider: string): RequestCapability {
    return this.capabilities.get(provider);
  }
}

// 所有 Provider 共享统一配置

为什么需要集中化

1. 消除重复配置

之前的问题

  • 10 个 Provider = 10 份重复配置
  • 修改全局超时需要改 10 处
  • 容易遗漏导致不一致

集中化后

  • 1 份基础配置
  • Provider 可继承或覆盖
  • 修改一处,全局生效

2. 提升性能

连接池共享

// 之前:每个 Provider 独立连接池
// GitHubProvider: 10 connections
// SlackProvider: 10 connections
// Total: 20 connections

// 集中化后:共享连接池 // Unified Pool: 15 connections (动态分配) // 节省 25% 资源

3. 简化维护

统一的监控和日志

  • 单一入口查看所有请求
  • 统一的错误处理
  • 一致的审计日志格式

架构变更详解

核心组件

┌─────────────────────────────────────┐
│     Request Capability Manager      │
├─────────────────────────────────────┤
│  ┌──────────────┐  ┌────────────┐  │
│  │  Base Config │  │  Provider  │  │
│  │              │  │  Overrides │  │
│  └──────────────┘  └────────────┘  │
├─────────────────────────────────────┤
│  ┌──────────────┐  ┌────────────┐  │
│  │  Connection  │  │   Retry    │  │
│  │    Pool      │  │  Handler   │  │
│  └──────────────┘  └────────────┘  │
├─────────────────────────────────────┤
│  ┌──────────────┐  ┌────────────┐  │
│  │   Timeout    │  │   Auth     │  │
│  │   Manager    │  │  Handler   │  │
│  └──────────────┘  └────────────┘  │
└─────────────────────────────────────┘

新的配置结构

config.yaml

集中式 Request Capabilities 配置

request_capabilities: # 基础配置(所有 Provider 默认继承) base: timeout: connect: 5000 read: 30000 retry: max_attempts: 3 backoff: exponential max_delay: 60000 pool: max_connections: 100 max_connections_per_host: 10 keep_alive: true keep_alive_duration: 30000 headers: User-Agent: "OpenClaw/2026.4.0" Accept: "application/json" security: verify_ssl: true follow_redirects: true max_redirects: 3 # Provider 特定覆盖 providers: github: timeout: read: 60000 # GitHub API 较慢,延长超时 headers: Accept: "application/vnd.github.v3+json" slack: timeout: connect: 3000 read: 10000 # Slack 响应快 retry: max_attempts: 5 # Slack 可能限流,增加重试 openai: timeout: read: 120000 # OpenAI 生成可能很慢 pool: max_connections: 50 # 并发请求较多

URL 解析基础化

之前每个 Provider 可能有自己的 URL 解析逻辑,现在统一为基础组件:

// providers/core/url-parser.ts
export class ComparableURLParser {
  parse(url: string): ParsedURL {
    // 统一的严格解析
    const normalized = this.normalize(url);
    
    // 可比较的 URL 表示
    return {
      protocol: normalized.protocol,
      hostname: normalized.hostname.toLowerCase(),
      port: normalized.port,
      pathname: this.normalizePath(normalized.pathname),
      search: this.normalizeSearch(normalized.search),
      hash: normalized.hash,
      // 可比较字符串
      comparable: this.toComparableString(normalized)
    };
  }
  
  // 用于缓存键、去重等
  toComparableString(url: ParsedURL): string {
    return ${url.protocol}://${url.hostname}:${url.port}${url.pathname};
  }
}

迁移与配置

自动迁移

OpenClaw 提供自动迁移工具:

迁移旧配置

openclaw migrate request-capabilities

预览变更

openclaw migrate request-capabilities --dry-run

应用变更

openclaw migrate request-capabilities --apply

手动配置

旧配置(v2026.3.x)

providers:
  github:
    http:
      timeout: 60000
      retries: 3
    
  slack:
    http:
      timeout: 10000
      retries: 2

新配置(v2026.4.x)

request_capabilities:
  base:
    timeout:
      connect: 5000
      read: 30000
    retry:
      max_attempts: 3
  
  providers:
    github:
      timeout:
        read: 60000  # 覆盖基础配置
    
    slack:
      timeout:
        read: 10000
      retry:
        max_attempts: 5

Provider 代码迁移

旧代码

class MyProvider {
  private client = new HttpClient({
    timeout: 30000,
    retries: 3
  });
  
  async fetch(url: string) {
    return this.client.get(url);
  }
}

新代码

class MyProvider {
  // 注入集中管理的 Request Capability
  constructor(
    @Inject('REQUEST_CAPABILITY') 
    private capability: RequestCapability
  ) {}
  
  async fetch(url: string) {
    // 使用统一管理的配置
    return this.capability.fetch(url);
  }
}

性能对比

内存使用

| 场景 | 分散管理 | 集中化 | 节省 |
|——|———-|——–|——|
| 10 Providers | 200MB | 120MB | 40% |
| 20 Providers | 400MB | 200MB | 50% |

连接效率

| 指标 | 分散管理 | 集中化 | 提升 |
|——|———-|——–|——|
| 连接复用率 | 60% | 85% | +25% |
| 平均延迟 | 150ms | 120ms | -20% |
| 超时率 | 2% | 0.8% | -60% |

配置维护成本

| 任务 | 分散管理 | 集中化 | 效率 |
|——|———-|——–|——|
| 修改全局超时 | 修改 10 处 | 修改 1 处 | 10x |
| 添加新 Provider | 复制配置 | 继承基础 | 5x |
| 排查问题 | 查看 10 处日志 | 查看统一日志 | 3x |

高级特性

动态能力调整

// 运行时调整请求能力
const capability = requestCapabilityManager.get('github');

// 临时增加超时(针对大文件下载) capability.withTimeout(120000).fetch(url);

// 临时禁用重试(针对幂等操作) capability.withRetry(false).fetch(url);

能力继承链

request_capabilities:
  base:
    # 最基础配置
    timeout:
      connect: 5000
  
  profiles:
    api_client:
      extends: base
      timeout:
        read: 30000
    
    streaming_client:
      extends: api_client
      timeout:
        read: 300000  # 流式需要更长超时

监控和指标

monitoring:
  request_capabilities:
    metrics:
      - request_count
      - response_time
      - error_rate
      - connection_pool_size
    
    alerts:
      - name: "High Error Rate"
        condition: "error_rate > 0.05"
        action: "notify"

总结

Request Capabilities 集中化 是 OpenClaw 架构优化的重要一步:

1. 消除重复 — 统一配置,一处修改全局生效
2. 性能提升 — 共享连接池,资源利用率提升 40-50%
3. 维护简化 — 统一监控、日志和错误处理
4. 扩展性强 — Provider 可灵活继承和覆盖配置

配置建议

request_capabilities:
  base:
    # 设置合理的默认值
    timeout:
      connect: 5000
      read: 30000
  
  providers:
    # 根据 Provider 特性调整
    slow_api:
      timeout:
        read: 120000

常见问题

Q: 集中化后还能为特定 Provider 定制配置吗?

A: 可以,providers 部分允许覆盖基础配置的任何选项。

Q: 对现有 Provider 插件有影响吗?

A: 内部 Provider 已自动迁移,第三方 Provider 需要通过迁移工具更新。

Q: 连接池共享会导致 Provider 之间相互影响吗?

A: 不会,每个 Provider 有独立的连接配额,只是底层复用连接池基础设施。

Q: 如何查看当前的 Request Capability 配置?

A:

openclaw config get request_capabilities

查看特定 Provider 的有效配置(继承+覆盖)

openclaw config get request_capabilities.providers.github --effective

Q: 集中化后错误处理有变化吗?

A: 错误类型统一了,更容易理解和处理:

try {
  await capability.fetch(url);
} catch (error) {
  if (error instanceof TimeoutError) {
    // 统一的超时错误
  } else if (error instanceof RetryExhaustedError) {
    // 统一的重试耗尽错误
  }
}

Q: 是否支持不同环境的配置?

A: 支持:

request_capabilities:
  base:
    timeout:
      read: 30000
  
  environments:
    development:
      timeout:
        read: 60000  # 开发环境更宽松
      verify_ssl: false
    
    production:
      timeout:
        read: 30000
      verify_ssl: true

参考来源

相关阅读:

OpenClaw 安全更新:Web Fetch Provider 边界强化详解

OpenClaw 安全更新:Web Fetch Provider 边界强化详解

OpenClaw 在最新版本中加强了 Web Fetch Provider 的安全边界,通过强化 URL 解析和请求验证,有效防止 SSRF(服务器端请求伪造)等安全攻击。

本文将详细介绍这项安全更新的技术细节和配置方法。

目录

什么是 Web Fetch Provider

Web Fetch Provider 是 OpenClaw 中用于网页内容获取的核心组件。它负责:

  • 发送 HTTP/HTTPS 请求
  • 解析响应内容
  • 处理重定向和超时
  • 管理连接池

典型使用场景

在 Skill 中使用 Web Fetch

web_fetch: url: "https://api.example.com/data" method: GET headers: Authorization: "Bearer ${API_TOKEN}"

安全风险分析

SSRF(服务器端请求伪造)

攻击原理
攻击者通过构造特殊 URL,让服务器向内部网络或敏感资源发起请求。

攻击示例

恶意请求

url: "http://169.254.169.254/latest/meta-data/" # AWS 元数据服务

url: "http://localhost:6379/" # 本地 Redis 服务

url: "file:///etc/passwd" # 本地文件读取

URL 解析漏洞

问题场景

  • 不规范的 URL 格式被意外解析
  • 特殊字符绕过安全检查
  • Unicode 编码混淆

有问题的 URL

http://example.com@evil.com/ # @ 符号混淆 http://example.com%2F..%2Fetc/passwd # 编码绕过

边界强化措施

1. URL 解析加固

新的 URL 解析器采用更严格的 RFC 3986 标准:

// 严格的 URL 解析
class HardenedURLParser {
  parse(url: string): ParsedURL {
    // 1. 规范化编码
    const normalized = this.normalizeEncoding(url);
    
    // 2. 验证协议白名单
    if (!this.isAllowedProtocol(normalized.protocol)) {
      throw new SecurityError(Protocol ${normalized.protocol} not allowed);
    }
    
    // 3. 验证主机名格式
    if (!this.isValidHostname(normalized.hostname)) {
      throw new SecurityError(Invalid hostname: ${normalized.hostname});
    }
    
    // 4. 检查 IP 范围
    if (this.isPrivateIP(normalized.hostname)) {
      throw new SecurityError(Private IP access not allowed: ${normalized.hostname});
    }
    
    return normalized;
  }
}

2. 请求边界控制

config.yaml

providers: web_fetch: security: # 启用边界强化 hardened_boundaries: true # 协议白名单 allowed_protocols: - https - http # 禁止的主机模式 blocked_host_patterns: - "localhost" - "127...*" - "10...*" - "192.168.." - "*.internal" - "*.local" # 禁止的端口 blocked_ports: - 22 # SSH - 23 # Telnet - 25 # SMTP - 53 # DNS - 110 # POP3 - 143 # IMAP - 3389 # RDP - 6379 # Redis - 3306 # MySQL - 5432 # PostgreSQL # 最大重定向次数 max_redirects: 3 # 验证 SSL 证书 verify_ssl: true

3. 响应边界控制

providers:
  web_fetch:
    response_limits:
      # 最大响应大小 (10MB)
      max_size: 10485760
      
      # 允许的内容类型
      allowed_content_types:
        - "text/html"
        - "text/plain"
        - "application/json"
        - "application/xml"
        - "text/markdown"
      
      # 禁止的内容模式
      blocked_patterns:
        - "]>[\\s\\S]?"  # 脚本标签(可选)

配置与使用

基础配置

config.yaml

providers: web_fetch: enabled: true # 安全强化(推荐启用) security: hardened_boundaries: true # 超时设置 timeout: connect: 5000 # 连接超时 5秒 read: 30000 # 读取超时 30秒 # 重试策略 retry: max_attempts: 3 backoff: exponential

在 Skill 中使用

// 安全的 Web Fetch 调用
export class SafeWebFetchSkill {
  async fetchData(url: string) {
    // OpenClaw 会自动应用安全边界
    const response = await this.webFetch({
      url,
      method: 'GET',
      headers: {
        'User-Agent': 'OpenClaw/1.0'
      }
    });
    
    return response.data;
  }
}

自定义安全策略

为特定 provider 定制安全策略

providers: web_fetch: # 默认严格模式 security: hardened_boundaries: true # 特定场景宽松模式(谨慎使用) profiles: internal_api: security: hardened_boundaries: true blocked_host_patterns: # 允许访问内部 API - "localhost" - "127.0.0.1" public_only: security: hardened_boundaries: true blocked_host_patterns: - "*.internal.company.com"

最佳实践

1. 输入验证

// 始终验证用户输入的 URL
function validateUserURL(input: string): string {
  // 1. 基本格式检查
  const urlPattern = /^https?:\/\/.+/;
  if (!urlPattern.test(input)) {
    throw new Error('URL must start with http:// or https://');
  }
  
  // 2. 长度限制
  if (input.length > 2048) {
    throw new Error('URL too long');
  }
  
  // 3. 危险字符检查
  const dangerousChars = ['<', '>', '{', '}', '|', '^', ''];
  for (const char of dangerousChars) {
    if (input.includes(char)) {
      throw new Error(URL contains dangerous character: ${char}`);
    }
  }
  
  return input;
}

2. 使用 URL 白名单

对于已知安全的 API

providers: web_fetch: whitelist: enabled: true urls: - "https://api.github.com/*" - "https://api.openai.com/*" - "https://docs.openclaw.ai/*"

3. 日志审计

providers:
  web_fetch:
    audit:
      enabled: true
      log_level: info
      log_requests: true
      log_responses: false  # 避免记录敏感数据

4. 监控和告警

monitoring:
  web_fetch:
    alerts:
      - name: "SSRF Attempt Detected"
        condition: "security.blocked_request_count > 0"
        action: "notify_admin"
      
      - name: "High Error Rate"
        condition: "error_rate > 0.1"
        action: "throttle_requests"

测试安全边界

安全测试用例

// tests/security/web-fetch.test.ts
describe('Web Fetch Security Boundaries', () => {
  it('should block private IP access', async () => {
    await expect(
      webFetch('http://192.168.1.1/')
    ).rejects.toThrow('Private IP access not allowed');
  });
  
  it('should block localhost access', async () => {
    await expect(
      webFetch('http://localhost:8080/')
    ).rejects.toThrow('Blocked host pattern: localhost');
  });
  
  it('should block file protocol', async () => {
    await expect(
      webFetch('file:///etc/passwd')
    ).rejects.toThrow('Protocol file not allowed');
  });
  
  it('should block suspicious URL encoding', async () => {
    await expect(
      webFetch('http://example.com%2F..%2Fadmin')
    ).rejects.toThrow('Invalid URL encoding');
  });
});

总结

Web Fetch Provider 边界强化 为 OpenClaw 带来了更强的安全防护:

1. URL 解析加固 — 严格遵循 RFC 标准,防止编码绕过
2. 请求边界控制 — 协议、主机、端口多层次限制
3. 响应边界控制 — 大小、类型双重限制
4. 可观测性 — 完整的审计日志和监控告警

关键配置

providers:
  web_fetch:
    security:
      hardened_boundaries: true  # 启用安全强化

常见问题

Q: 启用边界强化后,原有功能会受影响吗?

A: 正常的外部 API 调用不会受影响。只有尝试访问内部网络或敏感资源的请求会被阻止。

Q: 如何临时禁用某个安全限制?

A: 不建议禁用,但可以添加例外规则:

security:
  hardened_boundaries: true
  exceptions:
    - host: "internal-api.company.com"
      reason: "Internal API access required"

Q: 误拦截了合法请求怎么办?

A:
1. 检查审计日志确认拦截原因
2. 如果是白名单中的 API,更新白名单配置
3. 如果是配置错误,调整 blocked_host_patterns

Q: 支持自定义安全策略吗?

A: 支持,可以通过配置文件自定义协议、端口、主机模式等限制。

Q: 对性能有影响吗?

A: 影响极小。URL 解析和验证在微秒级完成。

Q: 如何查看被拦截的请求?

A:

查看安全审计日志

tail -f ~/.openclaw/logs/security-audit.log | grep "BLOCKED"

统计拦截情况

openclaw stats web-fetch --security

参考来源

相关阅读:

OpenClaw 重磅重构:Flow 更名为 Task-flow 的完整迁移指南

OpenClaw 重磅重构:Flow 更名为 Task-flow 的完整迁移指南

OpenClaw 正在进行一项重大重构:将原有的 “Flow” 系统全面更名为 “Task-flow”。这项变更涉及命名空间、API、工具调用等多个层面,本文将提供完整的迁移指南。

目录

为什么更名为 Task-flow

命名更清晰

Flow 这个词在编程领域含义模糊,可能指:

  • 工作流(Workflow)
  • 数据流(Data Flow)
  • 控制流(Control Flow)
  • 异步流(Async Stream)

Task-flow 明确表达了 “任务流” 的概念:

  • 任务为核心单元
  • 强调执行流程
  • 与 OpenClaw 的任务系统概念一致

架构一致性

OpenClaw 的核心概念体系:

Task(任务)→ Task-flow(任务流)→ Pipeline(管道)

更名为 Task-flow 后,概念层次更加清晰。

变更范围总览

1. 模块重命名

| 旧路径 | 新路径 |
|——–|——–|
| flow/tooling | task-flow/tooling |
| flow/registry | task-flow/registry |
| flow/runtime | task-flow/runtime |

2. API 变更

旧 API(已废弃):

import { FlowTool } from '@openclaw/flow-tooling';
import { FlowRegistry } from '@openclaw/flow-registry';

新 API:

import { TaskFlowTool } from '@openclaw/task-flow/tooling';
import { TaskFlowRegistry } from '@openclaw/task-flow/registry';

3. 工具调用变更

| 旧工具名 | 新工具名 |
|———-|———-|
| flow_tool | task_flow_tool |
| flow_execute | task_flow_execute |
| flow_create | task_flow_create |

4. 配置变更

旧配置:

flow:
  enabled: true
  registry: flow-registry

新配置:

task_flow:
  enabled: true
  registry: task-flow-registry

迁移步骤详解

步骤 1: 更新导入路径

批量替换命令:

在项目根目录执行

find . -type f -name ".ts" -o -name ".js" | xargs sed -i \ -e 's/@openclaw\/flow-tooling/@openclaw\/task-flow\/tooling/g' \ -e 's/@openclaw\/flow-registry/@openclaw\/task-flow\/registry/g' \ -e 's/FlowTool/TaskFlowTool/g' \ -e 's/FlowRegistry/TaskFlowRegistry/g'

步骤 2: 更新配置文件

config.yaml

旧配置(删除)

flow:

enabled: true

新配置

task_flow: enabled: true tooling: default_executor: "builtin" registry: auto_register: true modules: - "task-flow-core" - "task-flow-plugin"

步骤 3: 更新插件代码

ACP 插件更新示例:

// 更新前
import { useFlowRuntime } from '@openclaw/flow-runtime';

export class MyPlugin { async execute() { const flow = await useFlowRuntime(); await flow.execute('my-flow'); } }

// 更新后 import { useTaskFlowRuntime } from '@openclaw/task-flow/runtime';

export class MyPlugin { async execute() { const taskFlow = await useTaskFlowRuntime(); await taskFlow.execute('my-task-flow'); } }

Plugin SDK 更新:

// 更新前
import { FlowConsumer } from '@openclaw/plugin-sdk/flow';

// 更新后 import { TaskFlowConsumer } from '@openclaw/plugin-sdk/task-flow';

步骤 4: 更新运行时调用

// 更新前
await runtime.call('flow', {
  action: 'create',
  params: { name: 'my-flow' }
});

// 更新后 await runtime.call('task-flow', { action: 'create', params: { name: 'my-task-flow' } });

代码示例对比

示例 1: 创建任务流

旧代码:

import { FlowFactory } from '@openclaw/flow-tooling';

const flow = FlowFactory.create({ name: 'data-processing', steps: [ { id: 'step1', action: 'fetch' }, { id: 'step2', action: 'transform' }, { id: 'step3', action: 'save' } ] });

await flow.execute();

新代码:

import { TaskFlowFactory } from '@openclaw/task-flow/tooling';

const taskFlow = TaskFlowFactory.create({ name: 'data-processing', steps: [ { id: 'step1', action: 'fetch' }, { id: 'step2', action: 'transform' }, { id: 'step3', action: 'save' } ] });

await taskFlow.execute();

示例 2: 注册自定义任务流

旧代码:

import { FlowRegistry } from '@openclaw/flow-registry';

const registry = new FlowRegistry(); registry.register('custom-flow', CustomFlowHandler);

新代码:

import { TaskFlowRegistry } from '@openclaw/task-flow/registry';

const registry = new TaskFlowRegistry(); registry.register('custom-task-flow', CustomTaskFlowHandler);

示例 3: ACP 任务流消费

旧代码:

import { ACPFlowConsumer } from '@openclaw/acp/flow';

@FlowConsumer() class MyACPPlugin { async onFlowEvent(event: FlowEvent) { // 处理 flow 事件 } }

新代码:

import { ACPTaskFlowConsumer } from '@openclaw/acp/task-flow';

@TaskFlowConsumer() class MyACPPlugin { async onTaskFlowEvent(event: TaskFlowEvent) { // 处理 task-flow 事件 } }

迁移检查清单

  • [ ] 更新所有导入路径
  • [ ] 替换 Flow → TaskFlow 类名
  • [ ] 更新配置文件
  • [ ] 测试任务流执行
  • [ ] 验证插件兼容性
  • [ ] 更新文档注释

向后兼容性

OpenClaw 提供了临时兼容层:

config.yaml

compatibility: flow_aliases: enabled: true # 启用 Flow → Task-flow 别名 deprecation_warnings: true # 显示废弃警告

注意:兼容层将在 v2026.6.0 版本中移除,请尽快完成迁移。

迁移工具

OpenClaw 提供了自动迁移工具:

安装迁移工具

npm install -g @openclaw/migrate

执行迁移

openclaw-migrate flow-to-task-flow --src ./my-project

预览变更(不实际修改)

openclaw-migrate flow-to-task-flow --src ./my-project --dry-run

总结

Flow → Task-flow 重构 是 OpenClaw 概念体系完善的重要一步:

1. 命名更清晰 — Task-flow 明确表达”任务流”概念
2. 架构更一致 — 与 Task、Pipeline 等概念形成完整体系
3. 迁移有工具 — 提供自动迁移工具和兼容层

关键行动
1. 运行 openclaw-migrate 自动迁移
2. 测试任务流功能
3. 在 v2026.6.0 前完成迁移

常见问题

Q: 为什么需要这次重命名?

A:

  • “Flow” 含义模糊,容易与其他概念混淆
  • “Task-flow” 更准确表达功能
  • 统一 OpenClaw 的概念体系

Q: 旧代码还能运行吗?

A: 可以,通过兼容层暂时支持,但会在 v2026.6.0 移除。

Q: 迁移工具会修改哪些文件?

A:

  • TypeScript/JavaScript 源码文件
  • 配置文件(config.yaml)
  • 类型定义文件
  • 测试文件

Q: 如何验证迁移成功?

A:

1. 检查是否还有 flow 引用

grep -r "from.flow" --include=".ts" src/

2. 运行测试

npm test

3. 验证任务流执行

openclaw task-flow test

Q: 第三方插件受影响吗?

A: 是的,需要插件作者更新。OpenClaw 已通知主要插件作者。

Q: 配置文件需要手动更新吗?

A: 迁移工具会自动处理,但建议人工检查确认。

参考来源

相关阅读:

OpenClaw 插件安全加固:Runtime Facade 激活保护机制详解

OpenClaw 插件安全加固:Runtime Facade 激活保护机制详解

OpenClaw 在最新更新中引入了 Runtime Facade 激活保护机制,有效防止插件在激活过程中的潜在安全风险,提升整体系统稳定性。

本文将详细介绍这项安全加固措施的原理、实现方式以及对现有插件的影响。

目录

什么是 Facade 激活保护

Facade(外观模式) 是 OpenClaw 插件架构中的核心概念。它提供了一个统一的接口,让插件能够与 OpenClaw 核心进行交互。

激活过程的风险

在插件加载时,Facade 需要被激活以建立插件与核心的通信。这个过程如果缺乏保护,可能导致:

  • 未授权访问 — 恶意插件在激活时执行危险操作
  • 资源泄漏 — 激活失败时清理不当
  • 系统不稳定 — 激活过程中的异常导致核心服务崩溃

保护机制概览

新的保护机制在 Facade 激活 阶段增加了安全检查:

插件加载 → 安全检查 → Facade 激活 → 受限运行 → 完整功能

为什么需要这项保护

安全场景分析

#### 场景 1: 恶意插件注入

// 恶意插件可能在激活时尝试
module.exports = {
  activate() {
    // 尝试访问受限 API
    const fs = require('fs');
    fs.writeFileSync('/etc/passwd', '...'); // 危险操作
  }
}

保护机制:激活阶段限制文件系统访问,阻止此类操作。

#### 场景 2: 激活失败资源泄漏

// 插件激活时创建资源,失败时未清理
module.exports = {
  activate() {
    this.server = createServer(); // 创建服务器
    throw new Error('激活失败');  // 异常退出,服务器未关闭
  }
}

保护机制:激活守卫确保失败时自动清理资源。

实际安全案例

在 Discord 和浏览器插件中发现的潜在问题:

  • Discord 插件:清理线程解绑操作在激活守卫内,可能导致死锁
  • 浏览器插件:清理辅助函数被错误地包含在激活守卫中

技术实现细节

1. 激活守卫(Activation Guard)

// plugin-sdk/runtime/facade.ts
export class PluginFacade {
  async activate(plugin: Plugin): Promise {
    // 进入激活守卫
    return await activationGuard(async () => {
      // 验证插件签名
      await this.verifyPluginSignature(plugin);
      
      // 限制环境下的初始化
      await plugin.activate(this.restrictedContext);
      
      // 验证激活结果
      this.validateActivationState();
    });
  }
}

2. 本地化 Facade 加载策略

config.yaml

plugins: security: facade: # 本地加载策略 load_policy: localized # 激活守卫配置 activation_guard: enabled: true timeout: 30000 # 30秒超时 # 权限限制 restricted_permissions: - fs_write - network_outbound - process_spawn

3. 清理操作的保护

修复了清理操作被错误包含在激活守卫中的问题:

// 修复前(有问题)
class BrowserPlugin {
  activate() {
    activationGuard(() => {
      this.setupBrowser();
      this.cleanup = () => {  // ❌ 清理不应该在守卫内
        this.browser.close();
      };
    });
  }
}

// 修复后(正确) class BrowserPlugin { activate() { activationGuard(() => { this.setupBrowser(); }); // ✅ 清理操作在守卫外 this.cleanup = () => { this.browser.close(); }; } }

4. Discord 插件的修复

// discord/plugin.ts
export class DiscordPlugin {
  async activate() {
    await this.facade.activateGuard(async () => {
      await this.initializeBot();
    });
    
    // 清理操作移出守卫
    this.registerCleanup(() => {
      this.threadUnbind();  // ✅ 在线程外执行
    });
  }
}

5. 非零退出处理

浏览器插件现在能优雅处理清理失败:

async cleanup() {
  try {
    await this.browser.close();
  } catch (error) {
    // 非零退出时提供回退方案
    if (error.exitCode !== 0) {
      logger.warn('浏览器清理异常,使用强制终止');
      await this.browser.kill();
    }
  }
}

对现有插件的影响

需要检查的插件类型

| 插件类型 | 影响程度 | 检查重点 |
|———-|———-|———-|
| 浏览器自动化 | 高 | 清理操作位置 |
| Discord 集成 | 中 | 线程解绑逻辑 |
| 文件系统操作 | 中 | 激活阶段权限 |
| 网络请求 | 低 | 一般无影响 |

迁移检查清单

  • [ ] 检查清理操作是否在激活守卫外
  • [ ] 验证激活失败时的资源清理
  • [ ] 测试插件在受限环境下的行为
  • [ ] 更新插件 manifest 声明权限

最佳实践

1. 插件开发规范

// ✅ 推荐的插件结构
export default class MyPlugin {
  // 激活阶段 - 受限环境
  async activate(context: RestrictedContext) {
    // 只进行基本初始化
    this.config = await context.loadConfig();
    this.validateConfig();
  }
  
  // 完全激活后 - 正常环境
  async onReady(context: FullContext) {
    // 此时可以执行完整功能
    await this.initializeServices();
  }
  
  // 清理 - 确保在守卫外
  async deactivate() {
    await this.cleanup();
  }
}

2. 错误处理

async activate(context: Context) {
  try {
    await this.initialize();
  } catch (error) {
    // 激活失败时确保清理
    await this.cleanup();
    throw new ActivationError('插件激活失败', { cause: error });
  }
}

3. 权限声明

{
  "name": "my-plugin",
  "permissions": {
    "activation": ["config_read"],
    "runtime": ["network", "filesystem"]
  }
}

总结

Runtime Facade 激活保护 是 OpenClaw 插件安全的重要加固:

1. 激活阶段隔离 — 限制插件在初始化时的权限
2. 资源清理保证 — 失败时自动清理,防止泄漏
3. 清理操作分离 — 避免死锁和资源竞争
4. 非零退出处理 — 提供优雅的错误回退

下一步行动:
1. 检查你的自定义插件是否符合新规范
2. 更新插件声明权限
3. 测试插件在激活守卫下的行为

常见问题

Q: 这项更新会影响现有插件的运行吗?

A: 大多数插件不会受影响。只有那些在激活阶段执行敏感操作或清理逻辑不当的插件需要调整。

Q: 如何检查我的插件是否需要更新?

A: 运行 OpenClaw 的插件检查工具:

openclaw plugins check --compatibility

Q: 激活守卫的超时可以配置吗?

A: 可以,在 config.yaml 中调整:

plugins:
  security:
    facade:
      activation_guard:
        timeout: 60000  # 60秒

Q: 清理操作应该在什么时候注册?

A:activate() 方法中注册,但确保回调函数在守卫外执行:

activate() {
  // 守卫内的初始化
  activationGuard(() => {
    this.resource = createResource();
  });
  
  // 守卫外的清理注册
  this.onDeactivate(() => {
    this.resource.close();
  });
}

Q: 如果插件在激活时超时怎么办?

A: 系统会自动终止激活过程并清理资源。建议:

  • 将耗时操作移到 onReady 阶段
  • 优化初始化逻辑
  • 增加激活守卫超时时间

参考来源

相关阅读:

OpenClaw 2026.3.28 发布:14项重大更新与迁移指南

OpenClaw 2026.3.28 发布:14项重大更新与迁移指南

OpenClaw 2026.3.28 带来了 xAI/Grok 深度集成、MiniMax 图像生成、插件工具审批流程等重大更新,同时废弃了一些旧功能。本文将详细解析这些变更和迁移方法。

目录

破坏性变更

1. Qwen 认证方式变更 ⚠️

旧方式(已废弃): qwen-portal-auth OAuth 集成

新方式: Model Studio API Key

#### 迁移步骤

1. 获取新的 Model Studio API Key

访问 https://modelscope.cn 获取 API Key

2. 重新配置认证

openclaw onboard --auth-choice modelstudio-api-key

3. 更新 config.yaml

providers: qwen: api_key: ${QWEN_MODELSTUDIO_API_KEY}

#### 配置示例

providers:
  qwen:
    enabled: true
    api_key:
      value: ${QWEN_MODELSTUDIO_API_KEY}
    models:
      - qwen-turbo
      - qwen-plus
      - qwen-max

2. 配置迁移策略变更 ⚠️

变更: 超过两个月的旧配置自动迁移现在被禁用。

影响: 非常旧的配置键现在会验证失败,而不是被重写。

#### 建议操作

运行配置检查

openclaw doctor

查看需要更新的配置

openclaw doctor --check-deprecated

手动更新旧配置

openclaw config migrate --interactive

新增功能

3. xAI/Grok 深度集成

OpenClaw 现在深度集成 xAI(Grok),支持 Responses API 和原生搜索功能。

#### 主要特性

  • Responses API — 新一代对话接口
  • x_search — 原生 X 平台搜索
  • 自动插件启用 — 无需手动切换

#### 配置方法

providers:
  xai:
    enabled: true
    api_key: ${XAI_API_KEY}
    default_model: grok-2
    
    # 启用 X 搜索
    web_search:
      provider: x_search
      auto_enable: true

#### 使用示例

使用 Grok 进行对话

openclaw chat --provider xai --model grok-2

启用 X 搜索的查询

@openclaw 搜索 X 上关于 OpenClaw 的最新讨论

4. xAI 引导流程

openclaw onboard 现在支持 xAI 配置:

openclaw onboard

选择:Configure web search

选择:xAI (Grok)

输入 XAI API Key

选择搜索模型

5. MiniMax 图像生成

MiniMax 现在支持图像生成功能!

#### 支持的模型

  • image-01 — 高质量图像生成
  • 支持文生图和图生图编辑
  • 可控制长宽比

#### 配置方法

providers:
  minimax:
    enabled: true
    api_key: ${MINIMAX_API_KEY}
    
    image_generation:
      model: image-01
      default_aspect_ratio: "16:9"  # 或 1:1, 4:3, 9:16

#### 使用示例

生成图像

openclaw image generate --provider minimax --prompt "一只穿着西装的猫在写代码"

图生图编辑

openclaw image edit --provider minimax \ --input image.png \ --prompt "将背景改为未来城市风格"

6. 插件工具审批流程

重大更新: 插件现在可以在执行工具前要求用户审批!

#### 工作原理

用户请求 → 插件拦截 → 等待审批 → 执行/拒绝

#### 配置方法

plugins:
  my-plugin:
    hooks:
      before_tool_call:
        require_approval: true
        
        # 审批方式
        approval_methods:
          - exec_overlay      # 执行界面弹窗
          - telegram_buttons  # Telegram 按钮
          - discord_interactions  # Discord 交互
          - slash_approve     # /approve 命令

#### 使用示例

当插件工具需要审批时

🤖 插件 "my-plugin" 请求执行工具 "send_email" 请批准或拒绝: [批准] [拒绝]

用户可以使用以下方式响应:

1. 点击界面按钮

2. 在 Telegram/Discord 中点击按钮

3. 发送 /approve 命令

7. ACP 频道绑定增强

ACP (Agent Collaboration Protocol) 现在支持更多频道的当前会话绑定。

#### 支持的频道

  • Discord/acp spawn codex --bind here
  • BlueBubbles — iMessage 支持
  • iMessage — 原生支持

#### 使用示例

将当前 Discord 频道变成 Codex 工作区

/acp spawn codex --bind here

创建一个子线程(旧方式)

/acp spawn codex --thread

#### 区别说明

| 方式 | 行为 | 适用场景 |
|——|——|———-|
| --bind here | 当前频道直接变成工作区 | 已有频道改造 |
| --thread | 创建子线程作为工作区 | 保持原频道整洁 |

8. OpenAI apply_patch 默认启用

OpenAIOpenAI Codex 模型现在默认启用 apply_patch 功能。

providers:
  openai:
    models:
      - gpt-4
      - gpt-4-turbo
    features:
      apply_patch: true  # 默认启用
      sandbox_policy: write  # 与 write 权限对齐

9. CLI 后端插件化

Claude CLI、Codex CLI 和 Gemini CLI 现在都作为插件运行:

plugins:
  # 自动加载,无需手动启用
  bundled_claude_cli:
    enabled: true
    
  bundled_codex_cli:
    enabled: true
    
  bundled_gemini_cli:
    enabled: true

#### 日志配置

使用新的日志选项

gateway run --cli-backend-logs

旧选项仍然兼容

gateway run --claude-cli-logs # 自动映射到新选项

10. Podman 容器支持简化

Podman 容器设置现在更加简洁:

新的简化流程

podman run --rm -it \ -v ~/.openclaw:/root/.openclaw \ openclaw/openclaw:latest

本地 CLI 控制容器

openclaw --container my-openclaw status

#### 安装助手

安装启动助手到 ~/.local/bin

openclaw install-podman-helper

使用

~/.local/bin/openclaw-container start

11. Slack 文件上传动作

新增 upload-file Slack 动作,支持:

channels:
  slack:
    actions:
      upload-file:
        enabled: true
        defaults:
          filename: "{{original_name}}"
          title: "{{description}}"
          comment: "由 OpenClaw 上传"

12. Microsoft Teams 文件支持

开始统一文件发送操作:

channels:
  teams:
    actions:
      upload-file:
        enabled: true
        max_file_size: 100MB

迁移指南

快速检查清单

1. 检查废弃配置

openclaw doctor --check-deprecated

2. 更新 Qwen 认证

openclaw onboard --auth-choice modelstudio-api-key

3. 验证配置

openclaw config validate

4. 重启服务

openclaw restart

配置更新示例

更新前

providers: qwen: auth_type: portal-oauth # 已废弃

更新后

providers: qwen: api_key: ${QWEN_MODELSTUDIO_API_KEY}

---

更新前

plugins: allow: - claude-cli # 不再需要显式允许

更新后(可选)

bundled 插件现在自动加载

总结

OpenClaw 2026.3.28 是一次功能丰富的更新:

1. AI 能力扩展 — xAI/Grok、MiniMax 图像生成
2. 安全增强 — 插件审批流程、配置验证
3. 集成深化 — ACP 多频道支持、Slack/Teams 文件上传
4. 架构优化 — CLI 后端插件化、Podman 简化

关键迁移点:

  • Qwen 认证方式更新
  • 旧配置自动迁移停止

下一步行动:
1. 运行 openclaw doctor 检查配置
2. 更新 Qwen 认证
3. 尝试新的 xAI/Grok 功能
4. 配置 MiniMax 图像生成

常见问题

Q: xAI API Key 在哪里获取?

A: 访问 https://x.ai/api 注册并获取 API Key。

Q: MiniMax 图像生成有费用吗?

A: 是的,按生成次数计费。查看 MiniMax 官方定价页面。

Q: 插件审批可以关闭吗?

A: 可以,将 require_approval 设为 false

before_tool_call:
  require_approval: false

Q: ACP bind 和 thread 有什么区别?

A:

  • --bind here — 直接使用当前频道作为工作区
  • --thread — 创建新的子线程作为工作区

Q: Podman 和 Docker 有什么区别?

A: Podman 是无守护进程的容器工具,更适合 rootless 运行。OpenClaw 现在对两者都提供良好支持。

Q: 如何回退到旧版本?

A:

docker pull openclaw/openclaw:2026.3.27
docker run ... openclaw/openclaw:2026.3.27

参考来源

相关阅读:

OpenClaw Slack 集成新特性:Scoped Prompts 和 Markdown 提示

OpenClaw Slack 集成新特性:Scoped Prompts 和 Markdown 提示

OpenClaw 为 Slack 集成带来了两项重要改进:Scoped Prompts(作用域提示词)和 Markdown 格式优化(mrkdwn hints),让多频道工作流更加智能,消息展示更加美观。

本文将详细介绍这两项功能的原理、配置方法和实际应用场景。

目录

Scoped Prompts 是什么

Scoped Prompts(作用域提示词) 是 OpenClaw 为 Slack 多频道环境设计的新功能。它允许你:

  • 为不同 Slack 频道设置不同的提示词上下文
  • 根据频道类型(公开频道、私有频道、DM)定制 AI 行为
  • 实现更精准的多工作流管理

为什么需要 Scoped Prompts?

在多频道工作环境中,同一个 OpenClaw Agent 可能需要处理不同类型的任务:

| 频道类型 | 典型用途 | 需要的提示词风格 |
|———-|———-|——————|
| #general | 日常讨论 | 友好、简洁 |
| #dev-alerts | 技术告警 | 专业、详细 |
| #marketing | 营销内容 | 创意、吸引人 |
| DM(私聊)| 个人助手 | 个性化、隐私保护 |

工作原理

Scoped Prompts 通过频道标识符动态选择提示词:

用户消息 → 频道识别 → 选择对应 Prompt → AI 处理 → 返回响应

mrkdwn Hints 格式优化

mrkdwn 是 Slack 特有的标记语言,类似 Markdown 但有自己的语法规则。OpenClaw 现在原生支持 mrkdwn 格式优化,让你的消息在 Slack 中显示更美观。

主要改进

#### 1. 自动格式转换

OpenClaw 会自动将标准 Markdown 转换为 Slack mrkdwn:


标题

粗体文字
  • 列表项 1
  • 列表项 2
链接文字 标题 粗体文字 • 列表项 1 • 列表项 2

#### 2. 智能代码块

代码块会根据内容长度自动选择显示方式:

短代码(< 10行)→ 直接内联显示
长代码(> 10行)→ 折叠,点击查看
超长代码(> 50行)→ 提供下载链接

#### 3. 富媒体支持

优化图片、文件和表情符号的展示:

图片附件

image_attachment: max_width: 800 alt_text: "自动生成描述"

表情符号

emoji: auto_convert: true # 将 :smile: 转换为 😊

配置与使用

启用 Scoped Prompts

编辑 config.yaml

channels:
  slack:
    # 全局默认提示词
    default_prompt: |
      你是一个专业的 AI 助手,帮助团队提高效率。
    
    # 频道特定提示词
    scoped_prompts:
      "#general": |
        你在 #general 频道,请保持友好、简洁的回复风格。
        适合日常讨论和快速问答。
      
      "#dev-alerts": |
        你在 #dev-alerts 频道,这是一个技术告警频道。
        请提供详细的技术分析和解决方案。
        如果涉及代码,请提供具体的修复建议。
      
      "#marketing": |
        你在 #marketing 频道,负责营销内容创作。
        请提供创意、吸引人的文案建议。
        注意品牌调性和目标受众。
      
    # DM(私聊)提示词
    dm_prompt: |
      这是私聊模式,请提供个性化、隐私保护的回复。
      不要提及频道名称或其他用户。

配置 mrkdwn 优化

channels:
  slack:
    formatting:
      mrkdwn:
        enabled: true
        auto_convert: true
        
        # 代码块设置
        code_blocks:
          inline_threshold: 80  # 字符数
          collapse_threshold: 10  # 行数
          max_lines: 50
          
        # 列表设置
        lists:
          bullet: "•"
          numbered: true
          
        # 引用设置
        quotes:
          style: "blockquote"
          
        # 链接设置
        links:
          unfurl: true  # 展开链接预览
          shorten: false

动态提示词变量

Scoped Prompts 支持动态变量:

scoped_prompts:
  "#general": |
    当前频道:{{channel_name}}
    频道成员:{{member_count}} 人
    当前用户:{{user_name}}
    
    请根据以上信息调整回复风格。

实际应用场景

场景 1: 技术支持频道

频道: #tech-support

scoped_prompts:
  "#tech-support": |
    你是技术支持专家,在 #tech-support 频道提供帮助。
    
    回复规范:
    1. 首先确认用户问题的具体症状
    2. 提供分步排查指南
    3. 如果涉及代码,提供可复制的示例
    4. 标记需要进一步协助的情况
    
    格式要求:
    - 使用 标题 分隔不同部分
    - 代码块使用 

标记语言
– 关键步骤用 粗体 强调


实际效果:

👤 用户:数据库连接超时怎么办?

🤖 OpenClaw:
问题确认
请检查以下可能原因:

1. 网络连接

ping your-db-host.com

2. 连接池配置
检查最大连接数设置…

3. 超时参数
建议调整 connect_timeout 为 30 秒


场景 2: 项目管理频道

频道: #project-alpha

yaml
scoped_prompts:
“#project-alpha”: |
你在 #project-alpha 项目管理频道。
熟悉项目里程碑、任务分配和进度跟踪。

回复风格:
– 简洁明了,适合快速决策
– 涉及任务时提供截止日期建议
– 主动识别潜在风险和依赖


场景 3: 多语言支持

yaml
scoped_prompts:
“#chinese”: |
请使用中文回复,保持专业但友好的语气。

“#english”: |
Please reply in English with a professional tone.

“#japanese”: |
日本語で丁寧に返信してください。


高级配置

条件提示词

根据消息内容动态选择提示词:

yaml
scoped_prompts:
“#general”:
default: “标准回复模式”
conditions:
– if: “message.contains(‘urgent’)”
prompt: “紧急模式:快速响应,优先处理”
– if: “message.contains(‘bug’)”
prompt: “技术支持模式:详细分析,提供解决方案”


提示词继承

频道提示词可以继承全局设置:

yaml
global_prompt: |
你是 OpenClaw AI,一个智能助手。

scoped_prompts:
“#dev”: |
{{inherit_global}}

附加:你在开发团队频道,熟悉技术术语。


总结

Scoped Prompts 和 mrkdwn Hints 为 OpenClaw 的 Slack 集成带来了显著提升:

1. 多频道智能 — 不同频道使用不同的 AI 人格 2. 消息美观 — 原生 mrkdwn 格式支持 3. 灵活配置 — 支持动态变量和条件提示词 4. 上下文感知 — AI 了解所在频道环境

下一步行动: 1. 在 config.yaml 中配置频道特定提示词 2. 启用 mrkdwn 格式优化 3. 测试不同频道的回复风格

常见问题

Q: Scoped Prompts 会覆盖全局提示词吗?

A: 取决于配置方式。使用 {{inherit_global}} 可以继承全局提示词,否则完全替换。

Q: 如何为私有频道设置提示词?

A: 使用频道 ID 代替名称:

yaml
scoped_prompts:
“C1234567890”: | # 私有频道 ID
这是私有频道的提示词…


Q: mrkdwn 和标准 Markdown 有什么区别?

A: 主要区别: | 特性 | Markdown | mrkdwn | |------|----------|--------| | 标题 | # H1 | H1 | | 粗体 | bold | bold | | 列表 | - item | • item | | 链接 | text | | | 代码块 |

language | “`语言可选 |

Q: 可以禁用特定频道的 Scoped Prompts 吗?

A: 可以,将该频道设置为空或设置为全局提示词:

scoped_prompts:
  "#simple": null  # 使用全局默认

Q: 如何测试提示词效果?

A: 使用 OpenClaw 的测试命令:

openclaw test-prompt --channel "#general" --message "测试消息"

Q: Scoped Prompts 会影响性能吗?

A: 影响极小。提示词在初始化时加载,运行时只是选择对应的字符串。

参考来源

相关阅读:

OpenClaw 新功能:TinyFish 浏览器自动化插件使用指南

OpenClaw 新功能:TinyFish 浏览器自动化插件使用指南

OpenClaw 现在内置 TinyFish 浏览器自动化插件,让你能够自动化复杂的网页工作流程,无需手动编写 Selenium 或 Puppeteer 代码。

本文将详细介绍 TinyFish 的功能、配置方法和实际应用场景。

目录

什么是 TinyFish

TinyFish 是一个托管式浏览器自动化插件,专为 OpenClaw 设计。它提供了一个简单的工具 tinyfish_automation,让你能够:

  • 自动化复杂的公共网页工作流程
  • 执行需要浏览器交互的任务
  • 处理动态加载的网页内容
  • 与现有的 web_fetch 和 web_search 工具形成能力升级链

能力升级链

OpenClaw 提供了一系列网页工具,按复杂度递增:

web_fetch → web_search → tinyfish → browser
  • web_fetch — 简单静态页面获取
  • web_search — 网页搜索
  • tinyfish — 托管浏览器自动化
  • browser — 本地浏览器控制

核心功能

1. 托管浏览器自动化

TinyFish 在托管环境中运行浏览器,无需本地安装 Chrome 或 Firefox:

config.yaml

plugins: tinyfish: enabled: true api_key: ${TINYFISH_API_KEY} # 可选,高级功能需要

2. SSE 流式响应

支持 Server-Sent Events (SSE) 流式响应,实时获取自动化进度:

  • COMPLETE 终端标记 — 明确知道何时完成
  • SSRF 防护 — 防止服务器端请求伪造攻击
  • 凭据拒绝 — 自动检测和拒绝敏感信息

3. 工具调用升级指导

当简单工具无法满足需求时,OpenClaw 会自动建议升级到 TinyFish:

用户:帮我从京东抓取商品价格
AI:这个页面需要 JavaScript 渲染,建议使用 tinyfish 自动化工具...

安装与配置

步骤 1: 启用插件

编辑 config.yaml

plugins:
  allow:
    - tinyfish  # 显式允许 TinyFish 插件
  
  tinyfish:
    enabled: true
    # 可选:配置 API 密钥以使用高级功能
    api_key:
      value: ${TINYFISH_API_KEY}  # 从环境变量读取

步骤 2: 配置安全策略

plugins:
  tinyfish:
    security:
      ssrf_guard: true        # 启用 SSRF 防护
      credential_rejection: true  # 拒绝包含凭据的请求
      max_execution_time: 300000  # 最大执行时间(毫秒)

步骤 3: 重启 OpenClaw

openclaw restart

使用示例

示例 1: 自动化登录流程

使用 tinyfish_automation 工具

  • tool: tinyfish_automation
params: url: "https://example.com/login" steps: - action: "fill" selector: "#username" value: "myusername" - action: "fill" selector: "#password" value: "${PASSWORD}" # 使用环境变量 - action: "click" selector: "#login-button" - action: "wait" duration: 2000 # 等待 2 秒 - action: "extract" selector: ".dashboard-title" as: "page_title"

示例 2: 抓取动态内容

- tool: tinyfish_automation
  params:
    url: "https://spa-app.example.com"
    steps:
      - action: "wait_for"
        selector: "#data-loaded"  # 等待数据加载完成
        timeout: 10000
      - action: "extract_all"
        selector: ".product-item"
        properties:
          - name: "title"
            selector: ".product-title"
          - name: "price"
            selector: ".product-price"

示例 3: 表单提交自动化

- tool: tinyfish_automation
  params:
    url: "https://forms.example.com/apply"
    steps:
      - action: "select"
        selector: "#country"
        value: "China"
      - action: "fill"
        selector: "#email"
        value: "user@example.com"
      - action: "upload"
        selector: "#resume-upload"
        file: "/path/to/resume.pdf"
      - action: "click"
        selector: "#submit-button"
      - action: "wait_for_navigation"
        timeout: 5000

安全特性

1. SSRF 防护

TinyFish 内置 SSRF (Server-Side Request Forgery) 防护:

security:
  ssrf_guard: true
  blocked_hosts:
    - "localhost"
    - "127.0.0.1"
    - "10.0.0.0/8"
    - "192.168.0.0/16"

2. 凭据自动检测

自动检测请求中是否包含敏感信息(密码、API 密钥等):

警告:检测到请求包含可能的凭据信息
建议:使用 SecretRef 方式安全存储凭据

3. 执行超时控制

防止自动化任务无限期运行:

max_execution_time: 300000  # 5 分钟

4. 请求审计日志

所有自动化操作都会被记录:

查看 TinyFish 审计日志

tail -f ~/.openclaw/logs/tinyfish-audit.log

最佳实践

1. 错误处理

为自动化任务添加错误处理:

- tool: tinyfish_automation
  params:
    url: "https://example.com"
    steps: [...]
  on_error:
    action: "retry"
    max_retries: 3
    fallback: "notify_admin"

2. 速率限制

避免对目标网站造成过大压力:

plugins:
  tinyfish:
    rate_limit:
      requests_per_minute: 10
      delay_between_requests: 2000  # 毫秒

3. 选择器优化

使用稳定的选择器:

推荐:使用 data-testid 或 id

selector: "[data-testid='submit-button']"

避免:过于依赖 DOM 结构

selector: "div.container > div.row > button"

总结

TinyFish 为 OpenClaw 带来了强大的浏览器自动化能力:

1. 托管运行 — 无需本地浏览器环境
2. 安全可靠 — SSRF 防护、凭据检测
3. 易于使用 — 声明式步骤配置
4. 能力升级 — 与现有工具无缝集成

下一步行动:
1. 在 config.yaml 中启用 TinyFish 插件
2. 尝试自动化一个简单的网页任务
3. 根据需要配置安全策略

常见问题

Q: TinyFish 和本地 browser 工具有什么区别?

A:

  • TinyFish — 托管浏览器,适合云端自动化,无需本地环境
  • browser — 本地浏览器控制,适合需要本地交互的场景

Q: TinyFish 需要 API Key 吗?

A: 基础功能免费,高级功能(如更多并发、更长执行时间)需要 API Key。

Q: 如何处理验证码?

A: TinyFish 不自动处理验证码。建议:

  • 使用支持验证码识别的第三方服务
  • 在测试环境中禁用验证码
  • 使用 API 替代网页自动化

Q: 自动化任务失败如何调试?

A:
1. 查看审计日志:~/.openclaw/logs/tinyfish-audit.log
2. 启用调试模式:debug: true
3. 使用 screenshot 步骤捕获页面状态

Q: TinyFish 支持哪些浏览器?

A: 目前支持 Chromium 内核的浏览器(Chrome、Edge 等),Firefox 支持即将推出。

Q: 可以同时运行多个自动化任务吗?

A: 可以,但受限于:

  • 配置的最大并发数
  • TinyFish API 的速率限制
  • 目标网站的承受能力

参考来源

相关阅读: