openclaw-tool-executor

TotalClaw 作者 totalclaw

每当用户向第三方工具或服务请求信息或想要在第三方工具或服务中采取操作时,请使用此技能。这包括但不限于搜索网络、阅读或编写文档、发送消息、查询数据库、管理任务、从 API 获取数据或与任何连接的 SaaS 产品交互(例如“搜索 Exa for...”、“阅读我的 Notion 页面”、“发送 Slack 消息”、“获取我的 Google Sheet”、“创建 GitHub 问题”、“查询 Snowflake”、“查找 HubSpot 联系人”)。只要用户的请求涉及外部服务、集成或数据源,即使未明确指定提供者,即可触发此技能。通过 Scalekit Connect 处理 OAuth 和非 OAuth(API 密钥、承载、基本)连接、工具发现、执行和代理回退。 ## 提供商映射 某些服务是通过 Scalekit 中的不同提供商名称访问的。始终使用下面映射的提供者名称: |用户询问 |使用提供商 | |---|---| | LinkedIn — 个人资料、职位、公司、帖子、人员搜索、广告、群组 | `收获API` |

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install totalclaw:totalclaw~avinash-kamath-scalekit-agent-auth
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/totalclaw%3Atotalclaw~avinash-kamath-scalekit-agent-auth/file -o avinash-kamath-scalekit-agent-auth.md
## 概述(中文)

每当用户向第三方工具或服务请求信息或想要在第三方工具或服务中采取操作时,请使用此技能。这包括但不限于搜索网络、阅读或编写文档、发送消息、查询数据库、管理任务、从 API 获取数据或与任何连接的 SaaS 产品交互(例如“搜索 Exa for...”、“阅读我的 Notion 页面”、“发送 Slack 消息”、“获取我的 Google Sheet”、“创建 GitHub 问题”、“查询 Snowflake”、“查找 HubSpot 联系人”)。只要用户的请求涉及外部服务、集成或数据源,即使未明确指定提供者,即可触发此技能。通过 Scalekit Connect 处理 OAuth 和非 OAuth(API 密钥、承载、基本)连接、工具发现、执行和代理回退。
## 提供商映射
某些服务是通过 Scalekit 中的不同提供商名称访问的。始终使用下面映射的提供者名称:
|用户询问 |使用提供商 |
|---|---|
| LinkedIn — 个人资料、职位、公司、帖子、人员搜索、广告、群组 | `收获API` |

## 原文

# OpenClaw Tool Executor

General-purpose tool executor for OpenClaw agents. Uses Scalekit Connect to discover and run tools for any connected service — OAuth (Notion, Slack, Gmail, GitHub, etc.) or non-OAuth (API Key, Bearer, Basic auth).

## Environment Variables

Required in `.env`:

```
TOOL_CLIENT_ID=<scalekit_client_id>
TOOL_CLIENT_SECRET=<scalekit_client_secret>
TOOL_ENV_URL=<scalekit_environment_url>
TOOL_IDENTIFIER=<default_identifier>   # optional but recommended
```

`TOOL_IDENTIFIER` is used as the default `--identifier` for all operations. If not set, the script will prompt the user at runtime and display a warning advising them to set it in `.env`.

## Execution Flow

When the user asks to perform an action on a connected service, follow these steps **in order**:

### Step 1 — Discover the Connection

Dynamically resolve the `connection_name` by listing all configured connections for the provider. The API paginates automatically through all pages:

```bash
uv run tool_exec.py --list-connections --provider <PROVIDER>
```

- Only consider connections with `"status": "COMPLETED"` — ignore any with `DRAFT`, `PENDING`, or other non-completed statuses.
- Use the `key_id` from the first **COMPLETED** result as `<CONNECTION_NAME>` for all subsequent steps.
- If **no connection found** → inform the user that no `<PROVIDER>` connection is configured in Scalekit and stop.
- If **connections exist but none are COMPLETED** → inform the user of the connection `key_id`(s) found and tell them the connection configuration is not completed. Ask them to complete setup in the Scalekit Dashboard and stop.
- If **multiple COMPLETED connections found** → the first one is selected automatically (a warning is shown).

### Step 2 — Check & Authorize

Run `--generate-link` for the connection. The tool automatically detects the connection type (OAuth vs non-OAuth) and applies the correct auth flow:

```bash
uv run tool_exec.py --generate-link \
  --connection-name <CONNECTION_NAME>
```

**OAuth connections:**
- If already **ACTIVE** → proceed to Step 3.
- If **not active** → a magic link is generated. Present it to the user, wait for them to complete the flow, then proceed to Step 3.

**Non-OAuth connections (BEARER, BASIC, API Key, etc.):**
- If account **not found** → stop. Tell the user: *"Please create and configure the `<CONNECTION_NAME>` connection in the Scalekit Dashboard."*
- If account exists but **not active** → stop. Tell the user: *"Please activate the `<CONNECTION_NAME>` connection in the Scalekit Dashboard."*
- If **ACTIVE** → proceed to Step 3.

> Never use `--get-authorization` in the execution flow — that is only for inspecting raw OAuth tokens and does not work for non-OAuth connections.

### Step 3 — Discover Available Tools

Fetch the list of tools available for the provider:

```bash
uv run tool_exec.py --get-tool --provider <PROVIDER>
```

- Look for a tool that matches the user's intent (e.g. `notion_page_get` for reading a page).
- If a matching tool **exists** → go to Step 3b.
- If **no matching tool exists** → go to Step 5 (proxy fallback).

### Step 3b — Fetch Tool Schema (mandatory before executing)

**Always** fetch the schema of the matched tool before constructing the input. This tells you the exact parameter names, types, required vs optional fields, and valid enum values:

```bash
uv run tool_exec.py --get-tool --tool-name <TOOL_NAME>
```

- Read the `input_schema.properties` from the response — use **only** the parameter names defined there.
- Note which fields are in `required` — these must always be included in `--tool-input`.
- Use `description` and `display_properties` to understand what each field expects.
- **Never guess parameter names** — always derive them from the schema.

### Step 4 — Execute the Tool

Construct the tool input using only parameters from the schema fetched in Step 3b, then run:

```bash
uv run tool_exec.py --execute-tool \
  --tool-name <TOOL_NAME> \
  --connection-name <CONNECTION_NAME> \
  --tool-input '<JSON_INPUT>'
```

Return the result to the user.

### Step 5 — Proxy Fallback (only if no tool exists)

If no Scalekit tool covers the required action, attempt a proxied HTTP request directly to the provider's API:

```bash
uv run tool_exec.py --proxy-request \
  --connection-name <CONNECTION_NAME> \
  --path <API_PATH> \
  --method <GET|POST|PUT|DELETE> \
  --query-params '<JSON>' \   # optional
  --body '<JSON>'             # optional
```

> Note: Proxy may be disabled on some environments. If it returns `TOOL_PROXY_DISABLED`, inform the user that this action isn't supported by the current Scalekit tool catalog and suggest they request a new tool from Scalekit.

## Example: Search LinkedIn (via HarvestAPI)

```
User: "Find software engineers in San Francisco on LinkedIn"
```

1. `--list-connections --provider HARVESTAPI` → `key_id: harvestapi-xxxx`, `type: API_KEY`
2. `--generate-link --connection-name harvestapi-xxxx` → detects API_KEY, checks account → ACTIVE
3. `--get-tool --provider HARVESTAPI` → finds `harvestapi_search_people`
3b. `--get-tool --tool-name harvestapi_search_people` → schema shows valid params: `first_names`, `last_names`, `search`, `locations`, `current_job_titles`, etc.
4. `--execute-tool --tool-name harvestapi_search_people --connection-name harvestapi-xxxx --tool-input '{"first_names": "John", "locations": "San Francisco", "current_job_titles": "Software Engineer"}'`
   → returns matching LinkedIn profiles

> Any LinkedIn-related request (profiles, jobs, companies, posts, people search, ads, groups) → use provider `HARVESTAPI`.

## Example: Search the web with Exa (API Key connection)

```
User: "Search for latest AI news using Exa"
```

1. `--list-connections --provider EXA` → `key_id: exa`, `type: API_KEY`
2. `--generate-link --connection-name exa` → detects API_KEY, checks account → ACTIVE
3. `--get-tool --provider EXA` → finds `exa_search`
3b. `--get-tool --tool-name exa_search` → schema shows `query` (required), `num_results`, `type`, etc.
4. `--execute-tool --tool-name exa_search --connection-name exa --tool-input '{"query": "latest AI news"}'`
   → returns search results

## Example: Read a Notion Page (OAuth connection)

```
User: "Read my Notion page https://notion.so/..."
```

1. `--list-connections --provider NOTION` → `key_id: notion-ijIQedmJ`, `type: OAUTH`
2. `--generate-link --connection-name notion-ijIQedmJ` → detects OAuth, already ACTIVE
3. `--get-tool --provider NOTION` → finds `notion_page_get`
3b. `--get-tool --tool-name notion_page_get` → schema shows `page_id` (required)
4. `--execute-tool --tool-name notion_page_get --connection-name notion-ijIQedmJ --tool-input '{"page_id": "..."}'`
   → returns page metadata

## Example: Action Not Yet in Scalekit

```
User: "Fetch the blocks of a Notion page"
```

1. `--list-connections --provider NOTION` → `key_id: notion-ijIQedmJ`
2. `--generate-link --connection-name notion-ijIQedmJ` → ACTIVE
3. `--get-tool --provider NOTION` → no `notion_blocks_fetch` tool found
4. `--proxy-request --path "/blocks/<page_id>/children"` → fallback attempt
5. If proxy disabled → inform user the action isn't available yet

## File Uploads & Downloads

Some providers do not have Scalekit tools for file operations. Use `--proxy-request` with `--input-file` (upload) or direct S3/CDN URL download (download). Provider-specific flows are documented below.

> ⚠️ **Proxy token expiry:** `--proxy-request` passes the stored OAuth access token directly to the provider.