@dhfpub/clawpool-admin 0.1.2 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -3
- package/dist/index.js +288 -0
- package/package.json +1 -1
- package/skills/clawpool-group-governance/SKILL.md +30 -4
- package/skills/clawpool-group-governance/references/api-contract.md +2 -0
- package/skills/clawpool-query/SKILL.md +114 -0
- package/skills/clawpool-query/agents/openai.yaml +4 -0
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ If you are reading the channel plugin documentation first, also read:
|
|
|
14
14
|
## Which Package Do I Need?
|
|
15
15
|
|
|
16
16
|
- Install only `@dhfpub/clawpool` when you only need ClawPool channel transport, website onboarding, and the bundled onboarding skill
|
|
17
|
-
- Install both `@dhfpub/clawpool` and `@dhfpub/clawpool-admin` when you want typed group governance or typed API-agent admin actions inside OpenClaw
|
|
17
|
+
- Install both `@dhfpub/clawpool` and `@dhfpub/clawpool-admin` when you want typed query, group governance, or typed API-agent admin actions inside OpenClaw
|
|
18
18
|
- Do not install only `@dhfpub/clawpool-admin` and expect it to work alone, because it depends on the `channels.clawpool` credentials managed by `@dhfpub/clawpool`
|
|
19
19
|
|
|
20
20
|
## Install
|
|
@@ -48,7 +48,7 @@ For the channel-side setup flow, see:
|
|
|
48
48
|
3. Enable the required tools in OpenClaw config
|
|
49
49
|
4. Restart the OpenClaw gateway
|
|
50
50
|
|
|
51
|
-
If the `tools` block is missing, the plugin may be installed and loaded, but the agent still cannot use `clawpool_group
|
|
51
|
+
If the `tools` block is missing, the plugin may be installed and loaded, but the agent still cannot use `clawpool_query`, `clawpool_group`, or `clawpool_agent_admin`.
|
|
52
52
|
|
|
53
53
|
## Configure `channels.clawpool` First
|
|
54
54
|
|
|
@@ -79,6 +79,7 @@ To make the admin capabilities available to the OpenClaw agent, configure `tools
|
|
|
79
79
|
"profile": "coding",
|
|
80
80
|
"alsoAllow": [
|
|
81
81
|
"message",
|
|
82
|
+
"clawpool_query",
|
|
82
83
|
"clawpool_group",
|
|
83
84
|
"clawpool_agent_admin"
|
|
84
85
|
],
|
|
@@ -92,6 +93,7 @@ To make the admin capabilities available to the OpenClaw agent, configure `tools
|
|
|
92
93
|
These fields are required for the intended ClawPool group-governance workflow:
|
|
93
94
|
|
|
94
95
|
- `message`: lets the agent send and coordinate messages in the group workflow
|
|
96
|
+
- `clawpool_query`: enables typed contact search, session search, and session message-history lookup
|
|
95
97
|
- `clawpool_group`: enables typed group governance actions
|
|
96
98
|
- `clawpool_agent_admin`: enables typed API-agent admin actions
|
|
97
99
|
- `sessions.visibility = agent`: ensures the tool session context is visible to the agent runtime
|
|
@@ -112,6 +114,7 @@ These fields are required for the intended ClawPool group-governance workflow:
|
|
|
112
114
|
"profile": "coding",
|
|
113
115
|
"alsoAllow": [
|
|
114
116
|
"message",
|
|
117
|
+
"clawpool_query",
|
|
115
118
|
"clawpool_group",
|
|
116
119
|
"clawpool_agent_admin"
|
|
117
120
|
],
|
|
@@ -134,11 +137,19 @@ openclaw clawpool-admin doctor
|
|
|
134
137
|
Expected result:
|
|
135
138
|
|
|
136
139
|
- `plugins info clawpool-admin` shows `enabled=true`, `status=loaded`
|
|
137
|
-
- the plugin exposes `clawpool_group
|
|
140
|
+
- the plugin exposes `clawpool_query`, `clawpool_group`, and `clawpool_agent_admin`
|
|
138
141
|
- `clawpool-admin doctor` can see the configured `channels.clawpool` account
|
|
139
142
|
|
|
140
143
|
## Agent Tools
|
|
141
144
|
|
|
145
|
+
### `clawpool_query`
|
|
146
|
+
|
|
147
|
+
Typed query tool with these actions:
|
|
148
|
+
|
|
149
|
+
- `contact_search`
|
|
150
|
+
- `session_search`
|
|
151
|
+
- `message_history`
|
|
152
|
+
|
|
142
153
|
### `clawpool_group`
|
|
143
154
|
|
|
144
155
|
Typed group governance tool with these actions:
|
|
@@ -148,6 +159,8 @@ Typed group governance tool with these actions:
|
|
|
148
159
|
- `add_members`
|
|
149
160
|
- `remove_members`
|
|
150
161
|
- `update_member_role`
|
|
162
|
+
- `update_all_members_muted`
|
|
163
|
+
- `update_member_speaking`
|
|
151
164
|
- `dissolve`
|
|
152
165
|
|
|
153
166
|
### `clawpool_agent_admin`
|
package/dist/index.js
CHANGED
|
@@ -87,6 +87,32 @@ function readRequiredInt(params, key) {
|
|
|
87
87
|
}
|
|
88
88
|
return value;
|
|
89
89
|
}
|
|
90
|
+
function readOptionalBool(params, key) {
|
|
91
|
+
const raw = readRawParam(params, key);
|
|
92
|
+
if (raw == null) {
|
|
93
|
+
return void 0;
|
|
94
|
+
}
|
|
95
|
+
if (typeof raw === "boolean") {
|
|
96
|
+
return raw;
|
|
97
|
+
}
|
|
98
|
+
if (typeof raw === "number") {
|
|
99
|
+
if (raw === 1) return true;
|
|
100
|
+
if (raw === 0) return false;
|
|
101
|
+
}
|
|
102
|
+
if (typeof raw === "string") {
|
|
103
|
+
const normalized = raw.trim().toLowerCase();
|
|
104
|
+
if (normalized === "true" || normalized === "1") return true;
|
|
105
|
+
if (normalized === "false" || normalized === "0") return false;
|
|
106
|
+
}
|
|
107
|
+
throw new Error(`Clawpool action ${key} must be a boolean.`);
|
|
108
|
+
}
|
|
109
|
+
function readRequiredBool(params, key) {
|
|
110
|
+
const value = readOptionalBool(params, key);
|
|
111
|
+
if (value == null) {
|
|
112
|
+
throw new Error(`Clawpool action requires ${key}.`);
|
|
113
|
+
}
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
90
116
|
function ensureMemberTypes(types) {
|
|
91
117
|
for (const memberType of types) {
|
|
92
118
|
if (memberType !== 1 && memberType !== 2) {
|
|
@@ -99,6 +125,11 @@ function ensureMemberType(memberType) {
|
|
|
99
125
|
throw new Error("Clawpool action member_type only supports 1 for role update.");
|
|
100
126
|
}
|
|
101
127
|
}
|
|
128
|
+
function ensureSpeakingMemberType(memberType) {
|
|
129
|
+
if (memberType !== 1 && memberType !== 2) {
|
|
130
|
+
throw new Error("Clawpool action member_type only supports 1 (human) or 2 (agent).");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
102
133
|
function buildGroupCreateRequest(params) {
|
|
103
134
|
const name = readRequiredStringParam(params, "name");
|
|
104
135
|
const memberIDs = readNumericIDArray(params, "memberIds", false);
|
|
@@ -206,6 +237,52 @@ function buildGroupDissolveRequest(params) {
|
|
|
206
237
|
}
|
|
207
238
|
};
|
|
208
239
|
}
|
|
240
|
+
function buildGroupAllMembersMutedUpdateRequest(params) {
|
|
241
|
+
const sessionID = readRequiredStringParam(params, "sessionId");
|
|
242
|
+
const allMembersMuted = readRequiredBool(params, "allMembersMuted");
|
|
243
|
+
return {
|
|
244
|
+
actionName: "group_all_members_muted_update",
|
|
245
|
+
method: "POST",
|
|
246
|
+
path: "/sessions/speaking/all_muted",
|
|
247
|
+
body: {
|
|
248
|
+
session_id: sessionID,
|
|
249
|
+
all_members_muted: allMembersMuted
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function buildGroupMemberSpeakingUpdateRequest(params) {
|
|
254
|
+
const sessionID = readRequiredStringParam(params, "sessionId");
|
|
255
|
+
const memberID = readRequiredStringParam(params, "memberId");
|
|
256
|
+
if (!/^\d+$/.test(memberID)) {
|
|
257
|
+
throw new Error("Clawpool action memberId must be numeric.");
|
|
258
|
+
}
|
|
259
|
+
const memberType = readOptionalInt(params, "memberType") ?? 1;
|
|
260
|
+
ensureSpeakingMemberType(memberType);
|
|
261
|
+
const isSpeakMuted = readOptionalBool(params, "isSpeakMuted");
|
|
262
|
+
const canSpeakWhenAllMuted = readOptionalBool(params, "canSpeakWhenAllMuted");
|
|
263
|
+
if (isSpeakMuted == null && canSpeakWhenAllMuted == null) {
|
|
264
|
+
throw new Error(
|
|
265
|
+
"Clawpool action update_member_speaking requires isSpeakMuted or canSpeakWhenAllMuted."
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
const body = {
|
|
269
|
+
session_id: sessionID,
|
|
270
|
+
member_id: memberID,
|
|
271
|
+
member_type: memberType
|
|
272
|
+
};
|
|
273
|
+
if (isSpeakMuted != null) {
|
|
274
|
+
body.is_speak_muted = isSpeakMuted;
|
|
275
|
+
}
|
|
276
|
+
if (canSpeakWhenAllMuted != null) {
|
|
277
|
+
body.can_speak_when_all_muted = canSpeakWhenAllMuted;
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
actionName: "group_member_speaking_update",
|
|
281
|
+
method: "POST",
|
|
282
|
+
path: "/sessions/members/speaking",
|
|
283
|
+
body
|
|
284
|
+
};
|
|
285
|
+
}
|
|
209
286
|
function buildGroupDetailReadRequest(params) {
|
|
210
287
|
const sessionID = readRequiredStringParam(params, "sessionId");
|
|
211
288
|
return {
|
|
@@ -217,6 +294,66 @@ function buildGroupDetailReadRequest(params) {
|
|
|
217
294
|
}
|
|
218
295
|
};
|
|
219
296
|
}
|
|
297
|
+
function buildContactSearchRequest(params) {
|
|
298
|
+
const keyword = readRequiredStringParam(params, "keyword");
|
|
299
|
+
const limit = readOptionalInt(params, "limit");
|
|
300
|
+
const offset = readOptionalInt(params, "offset");
|
|
301
|
+
const query = {
|
|
302
|
+
keyword
|
|
303
|
+
};
|
|
304
|
+
if (limit != null) {
|
|
305
|
+
query.limit = String(limit);
|
|
306
|
+
}
|
|
307
|
+
if (offset != null) {
|
|
308
|
+
query.offset = String(offset);
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
actionName: "contact_search",
|
|
312
|
+
method: "GET",
|
|
313
|
+
path: "/contacts/search",
|
|
314
|
+
query
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function buildSessionSearchRequest(params) {
|
|
318
|
+
const keyword = readRequiredStringParam(params, "keyword");
|
|
319
|
+
const limit = readOptionalInt(params, "limit");
|
|
320
|
+
const offset = readOptionalInt(params, "offset");
|
|
321
|
+
const query = {
|
|
322
|
+
keyword
|
|
323
|
+
};
|
|
324
|
+
if (limit != null) {
|
|
325
|
+
query.limit = String(limit);
|
|
326
|
+
}
|
|
327
|
+
if (offset != null) {
|
|
328
|
+
query.offset = String(offset);
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
actionName: "session_search",
|
|
332
|
+
method: "GET",
|
|
333
|
+
path: "/sessions/search",
|
|
334
|
+
query
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function buildMessageHistoryRequest(params) {
|
|
338
|
+
const sessionID = readRequiredStringParam(params, "sessionId");
|
|
339
|
+
const beforeID = readStringParam(params, "beforeId");
|
|
340
|
+
const limit = readOptionalInt(params, "limit");
|
|
341
|
+
const query = {
|
|
342
|
+
session_id: sessionID
|
|
343
|
+
};
|
|
344
|
+
if (beforeID) {
|
|
345
|
+
query.before_id = beforeID;
|
|
346
|
+
}
|
|
347
|
+
if (limit != null) {
|
|
348
|
+
query.limit = String(limit);
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
actionName: "message_history",
|
|
352
|
+
method: "GET",
|
|
353
|
+
path: "/messages/history",
|
|
354
|
+
query
|
|
355
|
+
};
|
|
356
|
+
}
|
|
220
357
|
function buildAgentAPICreateRequest(params) {
|
|
221
358
|
const agentName = readRequiredStringParam(params, "agentName");
|
|
222
359
|
if (!AGENT_NAME_RE.test(agentName)) {
|
|
@@ -238,6 +375,12 @@ function buildAgentAPICreateRequest(params) {
|
|
|
238
375
|
}
|
|
239
376
|
function buildAgentHTTPRequest(action, params) {
|
|
240
377
|
switch (action) {
|
|
378
|
+
case "contact_search":
|
|
379
|
+
return buildContactSearchRequest(params);
|
|
380
|
+
case "session_search":
|
|
381
|
+
return buildSessionSearchRequest(params);
|
|
382
|
+
case "message_history":
|
|
383
|
+
return buildMessageHistoryRequest(params);
|
|
241
384
|
case "group_create":
|
|
242
385
|
return buildGroupCreateRequest(params);
|
|
243
386
|
case "group_member_add":
|
|
@@ -246,6 +389,10 @@ function buildAgentHTTPRequest(action, params) {
|
|
|
246
389
|
return buildGroupMemberRemoveRequest(params);
|
|
247
390
|
case "group_member_role_update":
|
|
248
391
|
return buildGroupMemberRoleUpdateRequest(params);
|
|
392
|
+
case "group_all_members_muted_update":
|
|
393
|
+
return buildGroupAllMembersMutedUpdateRequest(params);
|
|
394
|
+
case "group_member_speaking_update":
|
|
395
|
+
return buildGroupMemberSpeakingUpdateRequest(params);
|
|
249
396
|
case "group_dissolve":
|
|
250
397
|
return buildGroupDissolveRequest(params);
|
|
251
398
|
case "group_detail_read":
|
|
@@ -668,6 +815,10 @@ function mapGroupActionToRequestAction(action) {
|
|
|
668
815
|
return "group_member_remove";
|
|
669
816
|
case "update_member_role":
|
|
670
817
|
return "group_member_role_update";
|
|
818
|
+
case "update_all_members_muted":
|
|
819
|
+
return "group_all_members_muted_update";
|
|
820
|
+
case "update_member_speaking":
|
|
821
|
+
return "group_member_speaking_update";
|
|
671
822
|
case "dissolve":
|
|
672
823
|
return "group_dissolve";
|
|
673
824
|
default:
|
|
@@ -770,6 +921,35 @@ var ClawpoolGroupToolSchema = {
|
|
|
770
921
|
},
|
|
771
922
|
required: ["action", "sessionId", "memberId", "role"]
|
|
772
923
|
},
|
|
924
|
+
{
|
|
925
|
+
type: "object",
|
|
926
|
+
additionalProperties: false,
|
|
927
|
+
properties: {
|
|
928
|
+
action: { const: "update_all_members_muted" },
|
|
929
|
+
accountId: { type: "string", minLength: 1 },
|
|
930
|
+
sessionId: { type: "string", minLength: 1 },
|
|
931
|
+
allMembersMuted: { type: "boolean" }
|
|
932
|
+
},
|
|
933
|
+
required: ["action", "sessionId", "allMembersMuted"]
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
type: "object",
|
|
937
|
+
additionalProperties: false,
|
|
938
|
+
properties: {
|
|
939
|
+
action: { const: "update_member_speaking" },
|
|
940
|
+
accountId: { type: "string", minLength: 1 },
|
|
941
|
+
sessionId: { type: "string", minLength: 1 },
|
|
942
|
+
memberId: numericIdSchema,
|
|
943
|
+
memberType: { type: "integer", enum: [1, 2] },
|
|
944
|
+
isSpeakMuted: { type: "boolean" },
|
|
945
|
+
canSpeakWhenAllMuted: { type: "boolean" }
|
|
946
|
+
},
|
|
947
|
+
required: ["action", "sessionId", "memberId"],
|
|
948
|
+
anyOf: [
|
|
949
|
+
{ required: ["isSpeakMuted"] },
|
|
950
|
+
{ required: ["canSpeakWhenAllMuted"] }
|
|
951
|
+
]
|
|
952
|
+
},
|
|
773
953
|
{
|
|
774
954
|
type: "object",
|
|
775
955
|
additionalProperties: false,
|
|
@@ -805,6 +985,113 @@ function createClawpoolGroupTool(api) {
|
|
|
805
985
|
};
|
|
806
986
|
}
|
|
807
987
|
|
|
988
|
+
// src/query-service.ts
|
|
989
|
+
function mapQueryActionToRequestAction(action) {
|
|
990
|
+
switch (action) {
|
|
991
|
+
case "contact_search":
|
|
992
|
+
return "contact_search";
|
|
993
|
+
case "session_search":
|
|
994
|
+
return "session_search";
|
|
995
|
+
case "message_history":
|
|
996
|
+
return "message_history";
|
|
997
|
+
default:
|
|
998
|
+
action;
|
|
999
|
+
throw new Error(`Unsupported Clawpool query action: ${String(action)}`);
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
async function runClawpoolQueryAction(params) {
|
|
1003
|
+
const account = resolveClawpoolAccount({
|
|
1004
|
+
cfg: params.cfg,
|
|
1005
|
+
accountId: params.toolParams.accountId
|
|
1006
|
+
});
|
|
1007
|
+
if (!account.enabled) {
|
|
1008
|
+
throw new Error(`Clawpool account "${account.accountId}" is disabled.`);
|
|
1009
|
+
}
|
|
1010
|
+
if (!account.configured) {
|
|
1011
|
+
throw new Error(`Clawpool account "${account.accountId}" is not configured.`);
|
|
1012
|
+
}
|
|
1013
|
+
const requestAction = mapQueryActionToRequestAction(params.toolParams.action);
|
|
1014
|
+
const request = buildAgentHTTPRequest(requestAction, params.toolParams);
|
|
1015
|
+
const data = await callAgentAPI({
|
|
1016
|
+
account,
|
|
1017
|
+
actionName: request.actionName,
|
|
1018
|
+
method: request.method,
|
|
1019
|
+
path: request.path,
|
|
1020
|
+
query: request.query,
|
|
1021
|
+
body: request.body
|
|
1022
|
+
});
|
|
1023
|
+
return {
|
|
1024
|
+
ok: true,
|
|
1025
|
+
accountId: account.accountId,
|
|
1026
|
+
action: params.toolParams.action,
|
|
1027
|
+
data
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// src/query-tool.ts
|
|
1032
|
+
var ClawpoolQueryToolSchema = {
|
|
1033
|
+
oneOf: [
|
|
1034
|
+
{
|
|
1035
|
+
type: "object",
|
|
1036
|
+
additionalProperties: false,
|
|
1037
|
+
properties: {
|
|
1038
|
+
action: { const: "contact_search" },
|
|
1039
|
+
accountId: { type: "string", minLength: 1 },
|
|
1040
|
+
keyword: { type: "string", minLength: 1 },
|
|
1041
|
+
limit: { type: "integer", minimum: 1 },
|
|
1042
|
+
offset: { type: "integer", minimum: 0 }
|
|
1043
|
+
},
|
|
1044
|
+
required: ["action", "keyword"]
|
|
1045
|
+
},
|
|
1046
|
+
{
|
|
1047
|
+
type: "object",
|
|
1048
|
+
additionalProperties: false,
|
|
1049
|
+
properties: {
|
|
1050
|
+
action: { const: "session_search" },
|
|
1051
|
+
accountId: { type: "string", minLength: 1 },
|
|
1052
|
+
keyword: { type: "string", minLength: 1 },
|
|
1053
|
+
limit: { type: "integer", minimum: 1 },
|
|
1054
|
+
offset: { type: "integer", minimum: 0 }
|
|
1055
|
+
},
|
|
1056
|
+
required: ["action", "keyword"]
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
type: "object",
|
|
1060
|
+
additionalProperties: false,
|
|
1061
|
+
properties: {
|
|
1062
|
+
action: { const: "message_history" },
|
|
1063
|
+
accountId: { type: "string", minLength: 1 },
|
|
1064
|
+
sessionId: { type: "string", minLength: 1 },
|
|
1065
|
+
beforeId: { type: "string", pattern: "^[0-9]+$" },
|
|
1066
|
+
limit: { type: "integer", minimum: 1 }
|
|
1067
|
+
},
|
|
1068
|
+
required: ["action", "sessionId"]
|
|
1069
|
+
}
|
|
1070
|
+
]
|
|
1071
|
+
};
|
|
1072
|
+
function createClawpoolQueryTool(api) {
|
|
1073
|
+
return {
|
|
1074
|
+
name: "clawpool_query",
|
|
1075
|
+
label: "Clawpool Query",
|
|
1076
|
+
description: "Search Clawpool contacts and sessions, or read session message history through typed query operations.",
|
|
1077
|
+
parameters: ClawpoolQueryToolSchema,
|
|
1078
|
+
async execute(_toolCallId, params) {
|
|
1079
|
+
try {
|
|
1080
|
+
return jsonToolResult(
|
|
1081
|
+
await runClawpoolQueryAction({
|
|
1082
|
+
cfg: api.config,
|
|
1083
|
+
toolParams: params
|
|
1084
|
+
})
|
|
1085
|
+
);
|
|
1086
|
+
} catch (err) {
|
|
1087
|
+
return jsonToolResult({
|
|
1088
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
|
|
808
1095
|
// index.ts
|
|
809
1096
|
var plugin = {
|
|
810
1097
|
id: "clawpool-admin",
|
|
@@ -812,6 +1099,7 @@ var plugin = {
|
|
|
812
1099
|
description: "Typed optional admin tools and operator CLI for Clawpool",
|
|
813
1100
|
configSchema: emptyPluginConfigSchema(),
|
|
814
1101
|
register(api) {
|
|
1102
|
+
api.registerTool(createClawpoolQueryTool(api), { optional: true });
|
|
815
1103
|
api.registerTool(createClawpoolGroupTool(api), { optional: true });
|
|
816
1104
|
api.registerTool(createClawpoolAgentAdminTool(api), { optional: true });
|
|
817
1105
|
api.registerCli(({ program }) => registerClawpoolAdminCli({ api, program }), {
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@ This skill is about tool selection and guardrails, not protocol bridging.
|
|
|
11
11
|
## Workflow
|
|
12
12
|
|
|
13
13
|
1. Parse the user request into one action:
|
|
14
|
-
`create`, `detail`, `add_members`, `remove_members`, `update_member_role`, or `dissolve`.
|
|
14
|
+
`create`, `detail`, `add_members`, `remove_members`, `update_member_role`, `update_all_members_muted`, `update_member_speaking`, or `dissolve`.
|
|
15
15
|
2. Validate required fields before any call.
|
|
16
16
|
3. Call `clawpool_group` exactly once per business action.
|
|
17
17
|
4. Classify failures by HTTP/BizCode and return exact remediation.
|
|
@@ -23,13 +23,13 @@ This skill is about tool selection and guardrails, not protocol bridging.
|
|
|
23
23
|
For Clawpool group governance, always call:
|
|
24
24
|
|
|
25
25
|
1. Tool: `clawpool_group`
|
|
26
|
-
2. `action`: one of `create`, `detail`, `add_members`, `remove_members`, `update_member_role`, `dissolve`
|
|
26
|
+
2. `action`: one of `create`, `detail`, `add_members`, `remove_members`, `update_member_role`, `update_all_members_muted`, `update_member_speaking`, `dissolve`
|
|
27
27
|
3. `accountId`: optional; include it when the configured account is ambiguous
|
|
28
28
|
|
|
29
29
|
Rules:
|
|
30
30
|
|
|
31
31
|
1. Pass business parameters with their exact typed field names.
|
|
32
|
-
2. Use `sessionId`, `memberIds`, `memberTypes`, `memberId`, `memberType`, and `
|
|
32
|
+
2. Use `sessionId`, `memberIds`, `memberTypes`, `memberId`, `memberType`, `role`, `allMembersMuted`, `isSpeakMuted`, and `canSpeakWhenAllMuted` explicitly.
|
|
33
33
|
3. Do not invent aliases or fallback fields.
|
|
34
34
|
4. Keep one tool call per action for audit clarity.
|
|
35
35
|
|
|
@@ -87,6 +87,32 @@ Guardrails:
|
|
|
87
87
|
1. Only use `memberType=1` for role updates.
|
|
88
88
|
2. Never guess a role value; confirm when unclear.
|
|
89
89
|
|
|
90
|
+
### update_all_members_muted
|
|
91
|
+
|
|
92
|
+
Required input:
|
|
93
|
+
|
|
94
|
+
1. `sessionId`
|
|
95
|
+
2. `allMembersMuted`
|
|
96
|
+
|
|
97
|
+
Guardrails:
|
|
98
|
+
|
|
99
|
+
1. Only use this for group-wide mute state changes.
|
|
100
|
+
2. Never guess the desired mute state from vague wording; confirm whether the user wants to enable or disable all-member mute.
|
|
101
|
+
|
|
102
|
+
### update_member_speaking
|
|
103
|
+
|
|
104
|
+
Required input:
|
|
105
|
+
|
|
106
|
+
1. `sessionId`
|
|
107
|
+
2. `memberId`
|
|
108
|
+
3. At least one of `isSpeakMuted` or `canSpeakWhenAllMuted`
|
|
109
|
+
|
|
110
|
+
Guardrails:
|
|
111
|
+
|
|
112
|
+
1. Only use `memberType=1` or `memberType=2`.
|
|
113
|
+
2. Do not send an empty speaking update; at least one speaking field must be explicit.
|
|
114
|
+
3. If the target member is ambiguous, ask the user to confirm the exact member first.
|
|
115
|
+
|
|
90
116
|
### detail / dissolve
|
|
91
117
|
|
|
92
118
|
Required input:
|
|
@@ -109,7 +135,7 @@ Required input:
|
|
|
109
135
|
## Response Style
|
|
110
136
|
|
|
111
137
|
1. State action result first.
|
|
112
|
-
2. Include key identifiers (`session_id`, member count) when successful.
|
|
138
|
+
2. Include key identifiers (`session_id`, member count, mute state) when successful.
|
|
113
139
|
3. Include exact remediation when failed.
|
|
114
140
|
4. Never hide scope or auth errors behind generic wording.
|
|
115
141
|
|
|
@@ -29,6 +29,8 @@ Use the native `clawpool_group` tool with typed fields:
|
|
|
29
29
|
| `add_members` | `group_member_add` | `sessionId`, `memberIds` |
|
|
30
30
|
| `remove_members` | `group_member_remove` | `sessionId`, `memberIds` |
|
|
31
31
|
| `update_member_role` | `group_member_role_update` | `sessionId`, `memberId`, `role` |
|
|
32
|
+
| `update_all_members_muted` | `group_all_members_muted_update` | `sessionId`, `allMembersMuted` |
|
|
33
|
+
| `update_member_speaking` | `group_member_speaking_update` | `sessionId`, `memberId`, `isSpeakMuted` or `canSpeakWhenAllMuted` |
|
|
32
34
|
| `dissolve` | `group_dissolve` | `sessionId` |
|
|
33
35
|
|
|
34
36
|
## Payload Templates
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: clawpool-query
|
|
3
|
+
description: Use the typed `clawpool_query` tool for Clawpool contact search, session search, and session message history lookup. Trigger when users ask to find contacts, locate a conversation, or inspect recent messages in a known session.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Clawpool Query
|
|
7
|
+
|
|
8
|
+
Use the `clawpool_query` tool for read-only Clawpool lookup actions.
|
|
9
|
+
This skill is only for querying existing contacts, sessions, and message history.
|
|
10
|
+
|
|
11
|
+
## Workflow
|
|
12
|
+
|
|
13
|
+
1. Parse the user request into one action:
|
|
14
|
+
`contact_search`, `session_search`, or `message_history`.
|
|
15
|
+
2. Validate required fields before any tool call.
|
|
16
|
+
3. Call `clawpool_query` exactly once per business action.
|
|
17
|
+
4. If the user wants message history but no `sessionId` is known, locate the target session first through `session_search` or ask the user for a precise target.
|
|
18
|
+
5. Return exact remediation for scope, auth, and parameter failures.
|
|
19
|
+
|
|
20
|
+
## Tool Contract
|
|
21
|
+
|
|
22
|
+
For Clawpool query actions, always call:
|
|
23
|
+
|
|
24
|
+
1. Tool: `clawpool_query`
|
|
25
|
+
2. `action`: one of `contact_search`, `session_search`, or `message_history`
|
|
26
|
+
3. `accountId`: optional; include it when the configured account is ambiguous
|
|
27
|
+
|
|
28
|
+
Rules:
|
|
29
|
+
|
|
30
|
+
1. Pass query parameters with their exact typed field names.
|
|
31
|
+
2. Use `keyword` for search actions.
|
|
32
|
+
3. Use `sessionId`, `beforeId`, and `limit` explicitly for message history.
|
|
33
|
+
4. Never invent a `sessionId`. Resolve it from context, from a previous tool result, or ask the user.
|
|
34
|
+
5. Keep one tool call per action for audit clarity.
|
|
35
|
+
|
|
36
|
+
## Action Contracts
|
|
37
|
+
|
|
38
|
+
### contact_search
|
|
39
|
+
|
|
40
|
+
Purpose: search the owner's Clawpool contact directory.
|
|
41
|
+
|
|
42
|
+
Required input:
|
|
43
|
+
|
|
44
|
+
1. `keyword` (non-empty string)
|
|
45
|
+
|
|
46
|
+
Optional input:
|
|
47
|
+
|
|
48
|
+
1. `limit`
|
|
49
|
+
2. `offset`
|
|
50
|
+
|
|
51
|
+
Guardrails:
|
|
52
|
+
|
|
53
|
+
1. Use this when the user is trying to find a person or active agent by display name, remark, nickname, username, or agent name.
|
|
54
|
+
2. Do not jump directly to session history from a vague contact hint; resolve the contact or session first.
|
|
55
|
+
|
|
56
|
+
### session_search
|
|
57
|
+
|
|
58
|
+
Purpose: search the owner's visible sessions by final display title.
|
|
59
|
+
|
|
60
|
+
Required input:
|
|
61
|
+
|
|
62
|
+
1. `keyword` (non-empty string)
|
|
63
|
+
|
|
64
|
+
Optional input:
|
|
65
|
+
|
|
66
|
+
1. `limit`
|
|
67
|
+
2. `offset`
|
|
68
|
+
|
|
69
|
+
Guardrails:
|
|
70
|
+
|
|
71
|
+
1. Use this when the user describes a conversation by session title, group name, or known list title.
|
|
72
|
+
2. If multiple sessions match, present the candidates and let the user choose before reading history.
|
|
73
|
+
|
|
74
|
+
### message_history
|
|
75
|
+
|
|
76
|
+
Purpose: read recent message history from a known session.
|
|
77
|
+
|
|
78
|
+
Required input:
|
|
79
|
+
|
|
80
|
+
1. `sessionId`
|
|
81
|
+
|
|
82
|
+
Optional input:
|
|
83
|
+
|
|
84
|
+
1. `beforeId`
|
|
85
|
+
2. `limit`
|
|
86
|
+
|
|
87
|
+
Guardrails:
|
|
88
|
+
|
|
89
|
+
1. Only call this after the target session is unambiguous.
|
|
90
|
+
2. Use `beforeId` only for older-page pagination.
|
|
91
|
+
3. Do not claim to have full history if only one page was fetched.
|
|
92
|
+
|
|
93
|
+
## Error Handling Rules
|
|
94
|
+
|
|
95
|
+
1. `403/20011`:
|
|
96
|
+
report missing scope and ask the owner to grant the required scope in the Aibot Agent permission page.
|
|
97
|
+
2. `401/10001`:
|
|
98
|
+
report invalid key/auth and suggest checking agent config or rotating the API key.
|
|
99
|
+
3. `403/10002`:
|
|
100
|
+
report the agent is not active or has an invalid provider type.
|
|
101
|
+
4. `400/10003`:
|
|
102
|
+
report invalid or missing parameters and ask the user for corrected values.
|
|
103
|
+
5. `404/4004`:
|
|
104
|
+
report the target session does not exist or is not visible.
|
|
105
|
+
6. Other errors:
|
|
106
|
+
return the backend `msg` and stop automatic retries.
|
|
107
|
+
|
|
108
|
+
## Response Style
|
|
109
|
+
|
|
110
|
+
1. State the query result first.
|
|
111
|
+
2. Include key identifiers from successful lookups:
|
|
112
|
+
`peer_id` / `peer_type` for contacts, `session_id` for sessions, and message identifiers for history.
|
|
113
|
+
3. If history results may be partial, state that clearly.
|
|
114
|
+
4. Never hide scope or auth errors behind generic wording.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
agent:
|
|
3
|
+
name: clawpool-query
|
|
4
|
+
default_prompt: "Use this skill when users ask to find Clawpool contacts, locate sessions, or inspect a known session's message history. Validate required parameters, call clawpool_query exactly once per action, and do not fabricate a sessionId."
|