Tool plugins
기준일: 2026-07-26
공식 기준: Tool plugins
Tool plugins 문서는 OpenClaw 공식 문서(plugins/tool-plugins)를 한국어로 정리한 가이드입니다. Build simple typed agent tools with defineToolPlugin and openclaw plugins init/build/validate 명령·설정 키·코드 예시는 공식 문서를 그대로 보존하며, 해석과 절차 안내는 한국어로 제공합니다. 최종 동작은 설치된 CLI 버전과 공식 원문을 확인하세요.
핵심 요약
Build simple typed agent tools with defineToolPlugin and openclaw plugins init/build/validate
한국어 가이드 범위: plugins/tool-plugins 경로의 설정·명령·제약·예시를 학습용으로 재구성합니다.
문서 구성
공식 문서의 주요 섹션은 다음과 같습니다.
- 요구사항
- Quickstart
- Write a tool
- Optional and factory tools
- Return values
- Output contracts
- 구성
- Generated metadata
- Package metadata
- Validate in CI
- Install and inspect locally
- Publish
- 트러블슈팅
- plugin entry not found: ./dist/index.js
- plugin entry does not expose defineToolPlugin metadata
- package.json openclaw.extensions must include ./dist/index.js
- Cannot find package 'typebox'
- Tool does not appear after install
- 함께 보기
상세 내용
본문
defineToolPlugin builds a plugin that only adds agent-callable tools: no channel, model provider, hook, service, or setup backend. It generates the manifest metadata OpenClaw needs to discover tools without loading plugin runtime code.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
요구사항
주요 항목:
- Node 22.22.3+, Node 24.15+, or Node 25.9+.
- TypeScript ESM package output.
typeboxindependencies(not justdevDependencies- the generatedopenclaw >=2026.5.17, the first version that exports- A package root that ships
dist/,openclaw.plugin.json, and
Quickstart
npm run plugin:build runs npm run build (tsc) then openclaw plugins build --entry ./dist/index.js. npm run plugin:validate rebuilds and runs openclaw plugins validate --entry ./dist/index.js. Successful validation prints:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
| File | Purpose |
|---|---|
src/index.ts |
defineToolPlugin entry with one echo tool |
src/index.test.ts |
Metadata test asserting the tool list |
tsconfig.json |
NodeNext TypeScript output to dist/ |
vitest.config.ts |
Vitest config for src/**/*.test.ts |
package.json |
Scripts, runtime deps, openclaw.extensions: ["./dist/index.js"] |
openclaw.plugin.json |
Generated manifest metadata for the initial tool |
| Flag | Default | Effect |
|---|---|---|
--directory <path> |
<id> |
Output directory |
--name <name> |
Title-cased <id> |
Display name |
--type <type> |
tool |
Scaffold type: tool or provider |
--force |
off | Overwrite an existing output directory |
openclaw plugins init stock-quotes --name "Stock Quotes"
cd stock-quotes
npm install
npm run plugin:build
npm run plugin:validate
npm test
Plugin stock-quotes is valid.
Write a tool
defineToolPlugin takes plugin identity, an optional config schema, and a static list of tools. Parameter and config types are inferred from the TypeBox schemas.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
id: "stock-quotes",
name: "Stock Quotes",
description: "Fetch stock quote snapshots.",
configSchema: Type.Object({
apiKey: Type.Optional(Type.String({ description: "Quote API key." })),
baseUrl: Type.Optional(Type.String({ description: "Quote API base URL." })),
}),
tools: (tool) => [
tool({
name: "stock_quote",
label: "Stock Quote",
description: "Fetch a stock quote snapshot.",
parameters: Type.Object({
symbol: Type.String({ description: "Ticker symbol, for example OPEN." }),
}),
outputSchema: Type.Object(
{
symbol: Type.String(),
configured: Type.Boolean(),
baseUrl: Type.String(),
},
{ additionalProperties: false },
),
async execute({ symbol }, config, context) {
context.signal?.throwIfAborted();
return {
symbol: symbol.toUpperCase(),
configured: Boolean(config.apiKey),
baseUrl: config.baseUrl ?? "https://api.example.com",
};
},
}),
],
});
Optional and factory tools
Set optional: true when users should explicitly allowlist the tool before it is sent to a model. openclaw plugins build writes the matching toolMetadata..optional manifest entry, so OpenClaw can see that the tool is optional without loading plugin runtime code.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
tool({
name: "workflow_run",
description: "Run an external workflow.",
parameters: Type.Object({ goal: Type.String() }),
optional: true,
execute: ({ goal }) => ({ queued: true, goal }),
});
tool({
name: "local_workflow",
description: "Run a local workflow outside sandboxed sessions.",
parameters: Type.Object({ goal: Type.String() }),
optional: true,
factory({ api, toolContext }) {
if (toolContext.sandboxed) {
return null;
}
return createLocalWorkflowTool(api);
},
});
Return values
defineToolPlugin wraps plain return values into the OpenClaw tool-result format:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
- Return a string when the model should see that exact text.
- Return a JSON-compatible value when you want the model to see formatted JSON
tool({
name: "echo_text",
description: "Echo input text.",
parameters: Type.Object({
input: Type.String(),
}),
execute: ({ input }) => input,
});
tool({
name: "echo_json",
description: "Echo input as structured JSON.",
parameters: Type.Object({
input: Type.String(),
}),
execute: ({ input }) => ({ input, length: input.length }),
});
Output contracts
Add outputSchema when a tool returns stable JSON-compatible data. It describes the original value stored in AgentToolResult.details, not the formatted text in content:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
tool({
name: "shipment_list",
description: "List shipments.",
parameters: Type.Object({
buyer: Type.Optional(Type.String()),
}),
outputSchema: Type.Array(
Type.Object(
{
id: Type.String(),
buyer: Type.String(),
paid: Type.Boolean(),
tons: Type.Number(),
},
{ additionalProperties: false },
),
),
execute: ({ buyer }) => listShipments(buyer),
});
구성
configSchema is optional. Omit it and OpenClaw applies a strict empty object schema; the generated manifest still includes configSchema.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
id: "no-config-tools",
name: "No Config Tools",
description: "Adds tools that do not need configuration.",
tools: () => [],
});
const configSchema = Type.Object({
apiKey: Type.String(),
});
id: "configured-tools",
name: "Configured Tools",
description: "Adds configured tools.",
configSchema,
tools: (tool) => [
tool({
name: "configured_ping",
description: "Check whether configuration is available.",
parameters: Type.Object({}),
execute: (_params, config) => ({ hasKey: config.apiKey.length > 0 }),
}),
],
});
Generated metadata
OpenClaw must read the plugin manifest before importing plugin runtime code. defineToolPlugin exposes static metadata for this, and openclaw plugins build writes it into the package. Rerun the generator after changing plugin id, name, description, config schema, activation, or tool names:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
npm run build
openclaw plugins build --entry ./dist/index.js
{
"id": "stock-quotes",
"name": "Stock Quotes",
"description": "Fetch stock quote snapshots.",
"version": "0.1.0",
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {}
},
"activation": {
"onStartup": true
},
"contracts": {
"tools": ["stock_quote"]
}
}
Package metadata
openclaw plugins build also aligns package.json to the selected runtime entry:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
{
"type": "module",
"files": ["dist", "openclaw.plugin.json", "README.md"],
"dependencies": {
"typebox": "^1.1.38"
},
"peerDependencies": {
"openclaw": ">=2026.5.17"
},
"openclaw": {
"extensions": ["./dist/index.js"]
}
}
Validate in CI
plugins build --check fails without rewriting files when generated metadata is stale:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
openclaw.plugin.jsonexists and passes the normal manifest loader.- The current entry exports
defineToolPluginmetadata. - Generated manifest fields match the entry metadata.
contracts.toolsmatches the declared tool names.package.jsonpointsopenclaw.extensionsat the selected runtime entry.
npm run build
openclaw plugins build --entry ./dist/index.js --check
openclaw plugins validate --entry ./dist/index.js
npm test
Install and inspect locally
From a separate OpenClaw checkout or installed CLI, install the package path:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
openclaw plugins install ./stock-quotes
openclaw plugins inspect stock-quotes --runtime
npm pack
openclaw plugins install npm-pack:./openclaw-plugin-stock-quotes-0.1.0.tgz
openclaw plugins inspect stock-quotes --runtime --json
Publish
Publish through ClawHub once the package is ready. clawhub package publish takes a source: a local folder, a GitHub repo (owner/repo[@ref]), or a tarball URL.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
clawhub package publish ./stock-quotes --dry-run
clawhub package publish ./stock-quotes
openclaw plugins install clawhub:your-org/stock-quotes
트러블슈팅
이 섹션의 세부 항목은 공식 문서 트러블슈팅를 참고하세요.
plugin entry not found: ./dist/index.js
The selected entry file does not exist. Run npm run build, then rerun openclaw plugins build --entry ./dist/index.js or openclaw plugins validate --entry ./dist/index.js.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
plugin entry does not expose defineToolPlugin metadata
The entry did not export a value created by defineToolPlugin. Confirm the module's default export is the defineToolPlugin(...) result, or pass the correct entry with --entry.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
openclaw.plugin.json generated metadata is stale
The manifest no longer matches the entry metadata. Run:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
npm run build
openclaw plugins build --entry ./dist/index.js
package.json openclaw.extensions must include ./dist/index.js
The package metadata points at a different runtime entry. Run openclaw plugins build --entry ./dist/index.js so the generator aligns package metadata with the entry you intend to ship.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Cannot find package 'typebox'
The built plugin imports typebox at runtime. Keep it in dependencies, reinstall, rebuild, and rerun validation.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Tool does not appear after install
openclaw plugins inspect --runtime2.openclaw plugins validate --root --entry ./dist/index.js3.openclaw.plugin.jsonhascontracts.toolswith the expected tool names. 4.package.jsonhasopenclaw.extensions: ["./dist/index.js"]. 5. The Gateway was restarted or reloaded after installing the plugin.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
함께 보기
주요 항목:
- Building plugins
- Plugin entry points
- Plugin SDK subpaths
- Plugin manifest
- Plugins CLI
- ClawHub publishing
실습 체크리스트
- 공식 문서와 로컬 버전을 대조합니다:
https://docs.openclaw.ai/plugins/tool-plugins - 관련 CLI는
openclaw --help및 하위 명령--help로 옵션을 확인합니다. - 설정 변경 시
openclaw config/openclaw doctor로 유효성을 검사합니다. - Gateway·채널·플러그인 변경 후에는 필요 시 Gateway를 재시작합니다.
자주 쓰는 명령·설정 예시
openclaw plugins init stock-quotes --name "Stock Quotes"
cd stock-quotes
npm install
npm run plugin:build
npm run plugin:validate
npm test
Plugin stock-quotes is valid.
id: "stock-quotes",
name: "Stock Quotes",
description: "Fetch stock quote snapshots.",
configSchema: Type.Object({
apiKey: Type.Optional(Type.String({ description: "Quote API key." })),
baseUrl: Type.Optional(Type.String({ description: "Quote API base URL." })),
}),
tools: (tool) => [
tool({
name: "stock_quote",
label: "Stock Quote",
description: "Fetch a stock quote snapshot.",
parameters: Type.Object({
symbol: Type.String({ description: "Ticker symbol, for example OPEN." }),
}),
outputSchema: Type.Object(
{
symbol: Type.String(),
configured: Type.Boolean(),
baseUrl: Type.String(),
},
{ additionalProperties: false },
),
async execute({ symbol }, config, context) {
context.signal?.throwIfAborted();
return {
symbol: symbol.toUpperCase(),
configured: Boolean(config.apiKey),
baseUrl: config.baseUrl ?? "https://api.example.com",
};
},
}),
],
});
tool({
name: "workflow_run",
description: "Run an external workflow.",
parameters: Type.Object({ goal: Type.String() }),
optional: true,
execute: ({ goal }) => ({ queued: true, goal }),
});
tool({
name: "local_workflow",
description: "Run a local workflow outside sandboxed sessions.",
parameters: Type.Object({ goal: Type.String() }),
optional: true,
factory({ api, toolContext }) {
if (toolContext.sandboxed) {
return null;
}
return createLocalWorkflowTool(api);
},
});
tool({
name: "echo_text",
description: "Echo input text.",
parameters: Type.Object({
input: Type.String(),
}),
execute: ({ input }) => input,
});
관련 링크
이 가이드는 공식 문서를 한국어 학습용으로 재구성한 것입니다. 옵션 기본값·플래그 이름은 설치 버전에 따라 달라질 수 있습니다.