@clawling/clawchat-plugin-openclaw 2026.9.22-2 → 2026.9.23-2

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/dist/src/tools.js CHANGED
@@ -12,7 +12,7 @@ import { getOpenclawClawlingClient, } from "./runtime.js";
12
12
  import { markTerminalClawChatSend, getCurrentTerminalSendScope } from "./terminal-send.js";
13
13
  import { editClawChatMemoryBody, readClawChatMemoryFile, resolveClawChatMemoryPath, searchClawChatMemory, writeClawChatMemoryBody, } from "./clawchat-memory.js";
14
14
  import { pullGroupMetadata, pullOwnerMetadata, pullUserMetadata, pushMetadata, updateMetadata, } from "./clawchat-metadata.js";
15
- import { ClawchatGetAccountProfileSchema, ClawchatGetConversationSchema, ClawchatGetDirectConversationSchema, ClawchatGetMomentSchema, ClawchatGetUserProfileSchema, ClawchatLeaveGroupSchema, ClawchatAddGroupMemberSchema, ClawchatAcceptFriendRequestSchema, ClawchatMemoryEditSchema, ClawchatMemoryReadSchema, ClawchatMemorySearchSchema, ClawchatMemoryWriteSchema, ClawchatMetadataSyncSchema, ClawchatMetadataUpdateSchema, ClawchatCreateMomentCommentSchema, ClawchatCreateMomentSchema, ClawchatDeleteMomentCommentSchema, ClawchatDeleteMomentSchema, ClawchatListAccountFriendsSchema, ClawchatListFriendRequestsSchema, ClawchatListMomentsSchema, ClawchatMentionMessageSchema, ClawchatReactMessageSchema, ClawchatReplyMomentCommentSchema, ClawchatRejectFriendRequestSchema, ClawchatRemoveFriendSchema, ClawchatSearchUsersSchema, ClawchatSendFriendRequestSchema, ClawchatToggleMomentReactionSchema, ClawchatUpdateAccountProfileSchema, ClawchatUploadAvatarImageSchema, ClawchatRegisterAppSchema, ClawchatListAppsSchema, ClawchatUnregisterAppSchema, ClawchatLivewareLoginSchema, } from "./tools-schema.js";
15
+ import { ClawchatGetAccountProfileSchema, ClawchatGetConversationSchema, ClawchatGetDirectConversationSchema, ClawchatGetMomentSchema, ClawchatGetUserProfileSchema, ClawchatLeaveGroupSchema, ClawchatAddGroupMemberSchema, ClawchatAcceptFriendRequestSchema, ClawchatMemoryEditSchema, ClawchatMemoryReadSchema, ClawchatMemorySearchSchema, ClawchatMemoryWriteSchema, ClawchatMetadataSyncSchema, ClawchatMetadataUpdateSchema, ClawchatCreateMomentCommentSchema, ClawchatCreateMomentSchema, ClawchatDeleteMomentCommentSchema, ClawchatDeleteMomentSchema, ClawchatListAccountFriendsSchema, ClawchatListFriendRequestsSchema, ClawchatListMomentsSchema, ClawchatMentionMessageSchema, ClawchatReactMessageSchema, ClawchatReplyMomentCommentSchema, ClawchatRejectFriendRequestSchema, ClawchatRemoveFriendSchema, ClawchatSearchUsersSchema, ClawchatSendFriendRequestSchema, ClawchatToggleMomentReactionSchema, ClawchatUpdateAccountProfileSchema, ClawchatUploadAvatarImageSchema, ClawchatRegisterAppSchema, ClawchatListAppsSchema, ClawchatUnregisterAppSchema, ClawchatLivewareLoginSchema, ClawchatOrchListAgentsSchema, ClawchatOrchGetAgentSchema, ClawchatOrchSetAgentBehaviorSchema, ClawchatOrchListGroupsSchema, ClawchatOrchGetGroupSchema, ClawchatOrchSetGroupPromptSchema, ClawchatOrchCreateGroupSchema, ClawchatOrchGroupMemberSchema, ClawchatOrchSetGroupAgentSettingsSchema, ClawchatOrchCreateConnectCodeSchema, ClawchatOrchGetConnectCodeSchema, } from "./tools-schema.js";
16
16
  const MAX_UPLOAD_BYTES = 20 * 1024 * 1024;
17
17
  // Owner-approval gate business codes (must match the ClawChat backend's owner-approval codes).
18
18
  const CODE_PENDING_APPROVAL = 21001;
@@ -195,6 +195,14 @@ export function registerOpenclawClawlingTools(api, options = {}) {
195
195
  api.logger.debug?.("clawchat-plugin-openclaw: api.config missing; skipping tool registration");
196
196
  return;
197
197
  }
198
+ // Every tool below registers through this wrapper so the debug summary at
199
+ // the end is derived from what was actually registered, not hand-maintained.
200
+ const registeredToolNames = [];
201
+ const registerTool = (tool, opts) => {
202
+ if (opts?.name)
203
+ registeredToolNames.push(opts.name);
204
+ api.registerTool(tool, opts);
205
+ };
198
206
  // Re-resolve at call time so config reloads pick up new tokens / baseUrl.
199
207
  function resolveCurrent(accountId) {
200
208
  return resolveOpenclawClawlingAccount(api.config, accountId);
@@ -394,7 +402,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
394
402
  return validationError(message);
395
403
  }
396
404
  function registerMemoryTools() {
397
- api.registerTool((ctx) => ({
405
+ registerTool((ctx) => ({
398
406
  name: "clawchat_memory_search",
399
407
  label: "Search ClawChat Memory",
400
408
  description: memoryToolDescription("Search local ClawChat memory Markdown files by keyword across owner.md, users/*.md, and groups/*.md. " +
@@ -421,7 +429,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
421
429
  }
422
430
  },
423
431
  }), { name: "clawchat_memory_search" });
424
- api.registerTool((ctx) => ({
432
+ registerTool((ctx) => ({
425
433
  name: "clawchat_memory_read",
426
434
  label: "Read ClawChat Memory",
427
435
  description: memoryToolDescription("Read one local ClawChat memory Markdown file by explicit targetType and targetId. " +
@@ -470,7 +478,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
470
478
  }
471
479
  },
472
480
  }), { name: "clawchat_memory_read" });
473
- api.registerTool((ctx) => ({
481
+ registerTool((ctx) => ({
474
482
  name: "clawchat_memory_write",
475
483
  label: "Write ClawChat Memory",
476
484
  description: memoryToolDescription("Append to or replace only the agent-authored body of a ClawChat memory Markdown file by explicit targetType and targetId. " +
@@ -498,7 +506,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
498
506
  }
499
507
  },
500
508
  }), { name: "clawchat_memory_write" });
501
- api.registerTool((ctx) => ({
509
+ registerTool((ctx) => ({
502
510
  name: "clawchat_memory_edit",
503
511
  label: "Edit ClawChat Memory",
504
512
  description: memoryToolDescription("Replace exactly one existing text span in the agent-authored body of a ClawChat memory Markdown file. " +
@@ -526,7 +534,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
526
534
  }
527
535
  },
528
536
  }), { name: "clawchat_memory_edit" });
529
- api.registerTool((ctx) => {
537
+ registerTool((ctx) => {
530
538
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
531
539
  return {
532
540
  name: "clawchat_metadata_sync",
@@ -600,7 +608,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
600
608
  },
601
609
  };
602
610
  }, { name: "clawchat_metadata_sync" });
603
- api.registerTool((ctx) => {
611
+ registerTool((ctx) => {
604
612
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
605
613
  return {
606
614
  name: "clawchat_metadata_update",
@@ -654,7 +662,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
654
662
  }, { name: "clawchat_metadata_update" });
655
663
  }
656
664
  registerMemoryTools();
657
- api.registerTool((ctx) => {
665
+ registerTool((ctx) => {
658
666
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
659
667
  return {
660
668
  name: "clawchat_get_account_profile",
@@ -671,7 +679,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
671
679
  },
672
680
  };
673
681
  }, { name: "clawchat_get_account_profile" });
674
- api.registerTool((ctx) => {
682
+ registerTool((ctx) => {
675
683
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
676
684
  return {
677
685
  name: "clawchat_get_user_profile",
@@ -691,7 +699,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
691
699
  },
692
700
  };
693
701
  }, { name: "clawchat_get_user_profile" });
694
- api.registerTool((ctx) => {
702
+ registerTool((ctx) => {
695
703
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
696
704
  return {
697
705
  name: "clawchat_list_account_friends",
@@ -705,7 +713,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
705
713
  },
706
714
  };
707
715
  }, { name: "clawchat_list_account_friends" });
708
- api.registerTool((ctx) => {
716
+ registerTool((ctx) => {
709
717
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
710
718
  return {
711
719
  name: "clawchat_send_friend_request",
@@ -722,7 +730,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
722
730
  },
723
731
  };
724
732
  }, { name: "clawchat_send_friend_request" });
725
- api.registerTool((ctx) => {
733
+ registerTool((ctx) => {
726
734
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
727
735
  return {
728
736
  name: "clawchat_list_friend_requests",
@@ -739,7 +747,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
739
747
  },
740
748
  };
741
749
  }, { name: "clawchat_list_friend_requests" });
742
- api.registerTool((ctx) => {
750
+ registerTool((ctx) => {
743
751
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
744
752
  return {
745
753
  name: "clawchat_accept_friend_request",
@@ -756,7 +764,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
756
764
  },
757
765
  };
758
766
  }, { name: "clawchat_accept_friend_request" });
759
- api.registerTool((ctx) => {
767
+ registerTool((ctx) => {
760
768
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
761
769
  return {
762
770
  name: "clawchat_reject_friend_request",
@@ -773,7 +781,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
773
781
  },
774
782
  };
775
783
  }, { name: "clawchat_reject_friend_request" });
776
- api.registerTool((ctx) => {
784
+ registerTool((ctx) => {
777
785
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
778
786
  return {
779
787
  name: "clawchat_remove_friend",
@@ -790,7 +798,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
790
798
  },
791
799
  };
792
800
  }, { name: "clawchat_remove_friend" });
793
- api.registerTool((ctx) => {
801
+ registerTool((ctx) => {
794
802
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
795
803
  return {
796
804
  name: "clawchat_search_users",
@@ -811,7 +819,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
811
819
  },
812
820
  };
813
821
  }, { name: "clawchat_search_users" });
814
- api.registerTool((ctx) => {
822
+ registerTool((ctx) => {
815
823
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
816
824
  return {
817
825
  name: "clawchat_get_conversation",
@@ -840,7 +848,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
840
848
  },
841
849
  };
842
850
  }, { name: "clawchat_get_conversation" });
843
- api.registerTool((ctx) => {
851
+ registerTool((ctx) => {
844
852
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
845
853
  return {
846
854
  name: "clawchat_get_direct_conversation",
@@ -871,7 +879,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
871
879
  },
872
880
  };
873
881
  }, { name: "clawchat_get_direct_conversation" });
874
- api.registerTool((ctx) => {
882
+ registerTool((ctx) => {
875
883
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
876
884
  return {
877
885
  name: "clawchat_leave_group",
@@ -902,7 +910,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
902
910
  },
903
911
  };
904
912
  }, { name: "clawchat_leave_group" });
905
- api.registerTool((ctx) => {
913
+ registerTool((ctx) => {
906
914
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
907
915
  return {
908
916
  name: "clawchat_add_group_member",
@@ -933,7 +941,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
933
941
  },
934
942
  };
935
943
  }, { name: "clawchat_add_group_member" });
936
- api.registerTool((ctx) => {
944
+ registerTool((ctx) => {
937
945
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
938
946
  return {
939
947
  name: "clawchat_mention_message",
@@ -1001,7 +1009,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1001
1009
  },
1002
1010
  };
1003
1011
  }, { name: "clawchat_mention_message" });
1004
- api.registerTool((ctx) => {
1012
+ registerTool((ctx) => {
1005
1013
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1006
1014
  return {
1007
1015
  name: "clawchat_react_message",
@@ -1049,7 +1057,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1049
1057
  },
1050
1058
  };
1051
1059
  }, { name: "clawchat_react_message" });
1052
- api.registerTool((ctx) => {
1060
+ registerTool((ctx) => {
1053
1061
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1054
1062
  return {
1055
1063
  name: "clawchat_list_moments",
@@ -1069,7 +1077,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1069
1077
  },
1070
1078
  };
1071
1079
  }, { name: "clawchat_list_moments" });
1072
- api.registerTool((ctx) => {
1080
+ registerTool((ctx) => {
1073
1081
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1074
1082
  return {
1075
1083
  name: "clawchat_get_moment",
@@ -1084,7 +1092,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1084
1092
  },
1085
1093
  };
1086
1094
  }, { name: "clawchat_get_moment" });
1087
- api.registerTool((ctx) => {
1095
+ registerTool((ctx) => {
1088
1096
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1089
1097
  return {
1090
1098
  name: "clawchat_create_moment",
@@ -1109,7 +1117,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1109
1117
  },
1110
1118
  };
1111
1119
  }, { name: "clawchat_create_moment" });
1112
- api.registerTool((ctx) => {
1120
+ registerTool((ctx) => {
1113
1121
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1114
1122
  return {
1115
1123
  name: "clawchat_delete_moment",
@@ -1126,7 +1134,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1126
1134
  },
1127
1135
  };
1128
1136
  }, { name: "clawchat_delete_moment" });
1129
- api.registerTool((ctx) => {
1137
+ registerTool((ctx) => {
1130
1138
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1131
1139
  return {
1132
1140
  name: "clawchat_toggle_moment_reaction",
@@ -1146,7 +1154,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1146
1154
  },
1147
1155
  };
1148
1156
  }, { name: "clawchat_toggle_moment_reaction" });
1149
- api.registerTool((ctx) => {
1157
+ registerTool((ctx) => {
1150
1158
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1151
1159
  return {
1152
1160
  name: "clawchat_create_moment_comment",
@@ -1166,7 +1174,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1166
1174
  },
1167
1175
  };
1168
1176
  }, { name: "clawchat_create_moment_comment" });
1169
- api.registerTool((ctx) => {
1177
+ registerTool((ctx) => {
1170
1178
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1171
1179
  return {
1172
1180
  name: "clawchat_reply_moment_comment",
@@ -1190,7 +1198,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1190
1198
  },
1191
1199
  };
1192
1200
  }, { name: "clawchat_reply_moment_comment" });
1193
- api.registerTool((ctx) => {
1201
+ registerTool((ctx) => {
1194
1202
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1195
1203
  return {
1196
1204
  name: "clawchat_delete_moment_comment",
@@ -1207,7 +1215,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1207
1215
  },
1208
1216
  };
1209
1217
  }, { name: "clawchat_delete_moment_comment" });
1210
- api.registerTool((ctx) => {
1218
+ registerTool((ctx) => {
1211
1219
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1212
1220
  return {
1213
1221
  name: "clawchat_update_account_profile",
@@ -1245,7 +1253,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1245
1253
  },
1246
1254
  };
1247
1255
  }, { name: "clawchat_update_account_profile" });
1248
- api.registerTool((ctx) => {
1256
+ registerTool((ctx) => {
1249
1257
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1250
1258
  return {
1251
1259
  name: "clawchat_upload_avatar_image",
@@ -1281,7 +1289,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1281
1289
  },
1282
1290
  };
1283
1291
  }, { name: "clawchat_upload_avatar_image" });
1284
- api.registerTool((ctx) => {
1292
+ registerTool((ctx) => {
1285
1293
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1286
1294
  return {
1287
1295
  name: "clawchat_register_app",
@@ -1297,7 +1305,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1297
1305
  },
1298
1306
  };
1299
1307
  }, { name: "clawchat_register_app" });
1300
- api.registerTool((ctx) => {
1308
+ registerTool((ctx) => {
1301
1309
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1302
1310
  return {
1303
1311
  name: "clawchat_list_apps",
@@ -1309,7 +1317,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1309
1317
  },
1310
1318
  };
1311
1319
  }, { name: "clawchat_list_apps" });
1312
- api.registerTool((ctx) => {
1320
+ registerTool((ctx) => {
1313
1321
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1314
1322
  return {
1315
1323
  name: "clawchat_unregister_app",
@@ -1324,7 +1332,7 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1324
1332
  },
1325
1333
  };
1326
1334
  }, { name: "clawchat_unregister_app" });
1327
- api.registerTool((ctx) => {
1335
+ registerTool((ctx) => {
1328
1336
  const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1329
1337
  return {
1330
1338
  name: "clawchat_liveware_login",
@@ -1381,5 +1389,214 @@ export function registerOpenclawClawlingTools(api, options = {}) {
1381
1389
  },
1382
1390
  };
1383
1391
  }, { name: "clawchat_liveware_login" });
1384
- api.logger.debug?.("clawchat-plugin-openclaw: registered 31 clawchat_* tools (get_account_profile, get_user_profile, list_account_friends, send_friend_request, list_friend_requests, accept_friend_request, reject_friend_request, remove_friend, search_users, get_conversation, mention_message, list_moments, get_moment, create_moment, delete_moment, toggle_moment_reaction, create_moment_comment, reply_moment_comment, delete_moment_comment, update_account_profile, upload_avatar_image, memory_search, memory_read, memory_write, memory_edit, metadata_sync, metadata_update, register_app, list_apps, unregister_app, liveware_login)");
1392
+ // --- cloud orchestration (`agent.orchestrate`) ---------------------------
1393
+ // Twelve tools, 1:1 with docs/features/agentorch.md. Every response is HTTP
1394
+ // 200 with the business code in the envelope (a 21003 owner-approval
1395
+ // denial is the single most common outcome), so these use plain
1396
+ // `withClient` — never `withGatedClient` — and hand the caller the raw
1397
+ // envelope untouched. The shared orchestration skill text tells the model
1398
+ // to read `code` itself; rewriting the shape here would make the same
1399
+ // sentence behave differently than on the Hermes side.
1400
+ registerTool((ctx) => {
1401
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1402
+ return {
1403
+ name: "clawchat_orchestrate_list_agents",
1404
+ label: "List The Owner's Agents",
1405
+ description: toolDescription("List every agent the owner owns, including this one (flagged is_self). " +
1406
+ "TRIGGER — invoke first whenever the owner asks about, or asks to change, one of their OTHER agents. " +
1407
+ "This is the only way to learn a sibling's agentId; never guess one from a nickname."),
1408
+ parameters: ClawchatOrchListAgentsSchema,
1409
+ async execute(_callId, params) {
1410
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_list_agents", params, async () => withClient(accountId, (c) => c.orchListAgents()));
1411
+ },
1412
+ };
1413
+ }, { name: "clawchat_orchestrate_list_agents" });
1414
+ registerTool((ctx) => {
1415
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1416
+ return {
1417
+ name: "clawchat_orchestrate_get_agent",
1418
+ label: "Get A Sibling Agent",
1419
+ description: toolDescription("Read one of the owner's agents by explicit agentId, including its read-only permission map. " +
1420
+ "TRIGGER — invoke before rewriting a sibling's system prompt (the PATCH replaces the whole field, so read it first), " +
1421
+ "or to explain why a sibling cannot do something instead of retrying on its behalf."),
1422
+ parameters: ClawchatOrchGetAgentSchema,
1423
+ async execute(_callId, params) {
1424
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_get_agent", params, async () => {
1425
+ const p = params;
1426
+ return await withClient(accountId, (c) => c.orchGetAgent(p.agentId));
1427
+ });
1428
+ },
1429
+ };
1430
+ }, { name: "clawchat_orchestrate_get_agent" });
1431
+ registerTool((ctx) => {
1432
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1433
+ return {
1434
+ name: "clawchat_orchestrate_set_agent_behavior",
1435
+ label: "Rewrite A Sibling's System Prompt",
1436
+ description: toolDescription("Replace the WHOLE system prompt (behavior) of one of the owner's other agents. " +
1437
+ "TRIGGER — invoke when the owner asks to change how another agent behaves, talks, or what it is for. " +
1438
+ "This REPLACES the entire field — call clawchat_orchestrate_get_agent first, edit the text you got back, and send the full new value. " +
1439
+ "Sending a fragment deletes everything else and the owner cannot recover it. Max 3000 runes. " +
1440
+ "Nickname and bio cannot be changed here."),
1441
+ parameters: ClawchatOrchSetAgentBehaviorSchema,
1442
+ async execute(_callId, params) {
1443
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_set_agent_behavior", params, async () => {
1444
+ const p = params;
1445
+ return await withClient(accountId, (c) => c.orchSetAgentBehavior(p.agentId, p.behavior));
1446
+ });
1447
+ },
1448
+ };
1449
+ }, { name: "clawchat_orchestrate_set_agent_behavior" });
1450
+ registerTool((ctx) => {
1451
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1452
+ return {
1453
+ name: "clawchat_orchestrate_list_groups",
1454
+ label: "List Manageable Groups",
1455
+ description: toolDescription("List the groups the owner can administer. " +
1456
+ "TRIGGER — invoke when the owner talks about a group of their agents without naming a conversation id."),
1457
+ parameters: ClawchatOrchListGroupsSchema,
1458
+ async execute(_callId, params) {
1459
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_list_groups", params, async () => withClient(accountId, (c) => c.orchListGroups()));
1460
+ },
1461
+ };
1462
+ }, { name: "clawchat_orchestrate_list_groups" });
1463
+ registerTool((ctx) => {
1464
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1465
+ return {
1466
+ name: "clawchat_orchestrate_get_group",
1467
+ label: "Get A Managed Group",
1468
+ description: toolDescription("Read one group by explicit conversationId, including its system prompt and member agent ids. " +
1469
+ "TRIGGER — invoke before rewriting a group prompt, and after any write, to report what the server now says."),
1470
+ parameters: ClawchatOrchGetGroupSchema,
1471
+ async execute(_callId, params) {
1472
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_get_group", params, async () => {
1473
+ const p = params;
1474
+ return await withClient(accountId, (c) => c.orchGetGroup(p.conversationId));
1475
+ });
1476
+ },
1477
+ };
1478
+ }, { name: "clawchat_orchestrate_get_group" });
1479
+ registerTool((ctx) => {
1480
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1481
+ return {
1482
+ name: "clawchat_orchestrate_set_group_prompt",
1483
+ label: "Rewrite A Group's System Prompt",
1484
+ description: toolDescription("Replace the WHOLE system prompt (description) of a group the owner administers. " +
1485
+ "TRIGGER — invoke when the owner asks to change how a group behaves as a whole. " +
1486
+ "This REPLACES the entire field — call clawchat_orchestrate_get_group first and send the full new value. " +
1487
+ "Sending a fragment deletes everything else and the owner cannot recover it. Max 3000 runes. " +
1488
+ "The group title cannot be changed here."),
1489
+ parameters: ClawchatOrchSetGroupPromptSchema,
1490
+ async execute(_callId, params) {
1491
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_set_group_prompt", params, async () => {
1492
+ const p = params;
1493
+ return await withClient(accountId, (c) => c.orchSetGroupPrompt(p.conversationId, p.description));
1494
+ });
1495
+ },
1496
+ };
1497
+ }, { name: "clawchat_orchestrate_set_group_prompt" });
1498
+ registerTool((ctx) => {
1499
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1500
+ return {
1501
+ name: "clawchat_orchestrate_create_group",
1502
+ label: "Create A Group Of The Owner's Agents",
1503
+ description: toolDescription("Create a new group containing the owner's own agents. " +
1504
+ "TRIGGER — invoke when the owner asks to put several of their agents in a group together."),
1505
+ parameters: ClawchatOrchCreateGroupSchema,
1506
+ async execute(_callId, params) {
1507
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_create_group", params, async () => {
1508
+ const p = params;
1509
+ return await withClient(accountId, (c) => c.orchCreateGroup(p.title, p.agentIds));
1510
+ });
1511
+ },
1512
+ };
1513
+ }, { name: "clawchat_orchestrate_create_group" });
1514
+ registerTool((ctx) => {
1515
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1516
+ return {
1517
+ name: "clawchat_orchestrate_add_group_member",
1518
+ label: "Add An Agent To A Group",
1519
+ description: toolDescription("Add one of the owner's agents to a group the owner administers. " +
1520
+ "TRIGGER — invoke when the owner asks to bring another of their agents into an existing group. " +
1521
+ "You cannot add yourself; that is rejected outright."),
1522
+ parameters: ClawchatOrchGroupMemberSchema,
1523
+ async execute(_callId, params) {
1524
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_add_group_member", params, async () => {
1525
+ const p = params;
1526
+ return await withClient(accountId, (c) => c.orchAddGroupMember(p.conversationId, p.agentId));
1527
+ });
1528
+ },
1529
+ };
1530
+ }, { name: "clawchat_orchestrate_add_group_member" });
1531
+ registerTool((ctx) => {
1532
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1533
+ return {
1534
+ name: "clawchat_orchestrate_remove_group_member",
1535
+ label: "Remove An Agent From A Group",
1536
+ description: toolDescription("Remove one of the owner's agents from a group the owner administers. " +
1537
+ "TRIGGER — invoke when the owner asks to take an agent out of a group."),
1538
+ parameters: ClawchatOrchGroupMemberSchema,
1539
+ async execute(_callId, params) {
1540
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_remove_group_member", params, async () => {
1541
+ const p = params;
1542
+ return await withClient(accountId, (c) => c.orchRemoveGroupMember(p.conversationId, p.agentId));
1543
+ });
1544
+ },
1545
+ };
1546
+ }, { name: "clawchat_orchestrate_remove_group_member" });
1547
+ registerTool((ctx) => {
1548
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1549
+ return {
1550
+ name: "clawchat_orchestrate_set_group_agent_settings",
1551
+ label: "Set An Agent's Speaking Settings In A Group",
1552
+ description: toolDescription("Set how one agent speaks inside one group: muted, reply mode, and batching delay. " +
1553
+ "TRIGGER — invoke FIRST when a group is flooding, echoing, or an agent will not stop. " +
1554
+ "These are the hard controls; a rule written into a prompt stops working after compaction or a restart, so pair every soft rule with one of these. " +
1555
+ "Omitted fields are left unchanged."),
1556
+ parameters: ClawchatOrchSetGroupAgentSettingsSchema,
1557
+ async execute(_callId, params) {
1558
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_set_group_agent_settings", params, async () => {
1559
+ const p = params;
1560
+ return await withClient(accountId, (c) => c.orchSetGroupAgentSettings(p.conversationId, p.agentId, {
1561
+ muted: p.muted,
1562
+ replyMode: p.replyMode,
1563
+ batchDelaySeconds: p.batchDelaySeconds,
1564
+ }));
1565
+ });
1566
+ },
1567
+ };
1568
+ }, { name: "clawchat_orchestrate_set_group_agent_settings" });
1569
+ registerTool((ctx) => {
1570
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1571
+ return {
1572
+ name: "clawchat_orchestrate_create_connect_code",
1573
+ label: "Issue A Connect Code",
1574
+ description: toolDescription("Mint a connect code on the owner's behalf, valid 30 minutes. " +
1575
+ "TRIGGER — invoke when the owner asks for a code to connect a new agent. " +
1576
+ "The rate limit bucket belongs to the owner and is shared with their own manual issuance, so do not retry on a limit."),
1577
+ parameters: ClawchatOrchCreateConnectCodeSchema,
1578
+ async execute(_callId, params) {
1579
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_create_connect_code", params, async () => withClient(accountId, (c) => c.orchCreateConnectCode()));
1580
+ },
1581
+ };
1582
+ }, { name: "clawchat_orchestrate_create_connect_code" });
1583
+ registerTool((ctx) => {
1584
+ const accountId = resolveOpenclawClawlingToolAccountId(ctx);
1585
+ return {
1586
+ name: "clawchat_orchestrate_get_connect_code",
1587
+ label: "Read A Connect Code's Status",
1588
+ description: toolDescription("Read the status of a connect code the owner minted. " +
1589
+ "TRIGGER — invoke when the owner asks whether a code was used or has expired."),
1590
+ parameters: ClawchatOrchGetConnectCodeSchema,
1591
+ async execute(_callId, params) {
1592
+ return await recordClawchatToolCall(accountId, "clawchat_orchestrate_get_connect_code", params, async () => {
1593
+ const p = params;
1594
+ return await withClient(accountId, (c) => c.orchGetConnectCode(p.code));
1595
+ });
1596
+ },
1597
+ };
1598
+ }, { name: "clawchat_orchestrate_get_connect_code" });
1599
+ api.logger.debug?.(`clawchat-plugin-openclaw: registered ${registeredToolNames.length} clawchat_* tools (${registeredToolNames
1600
+ .map((name) => name.replace(/^clawchat_/, ""))
1601
+ .join(", ")})`);
1385
1602
  }
@@ -68,7 +68,19 @@
68
68
  "clawchat_register_app",
69
69
  "clawchat_list_apps",
70
70
  "clawchat_unregister_app",
71
- "clawchat_liveware_login"
71
+ "clawchat_liveware_login",
72
+ "clawchat_orchestrate_list_agents",
73
+ "clawchat_orchestrate_get_agent",
74
+ "clawchat_orchestrate_set_agent_behavior",
75
+ "clawchat_orchestrate_list_groups",
76
+ "clawchat_orchestrate_get_group",
77
+ "clawchat_orchestrate_set_group_prompt",
78
+ "clawchat_orchestrate_create_group",
79
+ "clawchat_orchestrate_add_group_member",
80
+ "clawchat_orchestrate_remove_group_member",
81
+ "clawchat_orchestrate_set_group_agent_settings",
82
+ "clawchat_orchestrate_create_connect_code",
83
+ "clawchat_orchestrate_get_connect_code"
72
84
  ]
73
85
  },
74
86
  "configSchema": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawling/clawchat-plugin-openclaw",
3
- "version": "2026.9.22-2",
3
+ "version": "2026.9.23-2",
4
4
  "description": "OpenClaw ClawChat channel plugin",
5
5
  "license": "MIT",
6
6
  "author": "CLAWLING PTE. LTD.",
@@ -25,11 +25,13 @@
25
25
  "!dist/**/*.test.js",
26
26
  "!dist/**/*.test-d.js",
27
27
  "!dist/**/*.typecheck.js",
28
+ "!dist/**/tools-test-support.js",
28
29
  "index.ts",
29
30
  "setup-entry.ts",
30
31
  "src/**/*.ts",
31
32
  "!src/**/*.test.ts",
32
33
  "!src/**/*.typecheck.ts",
34
+ "!src/tools-test-support.ts",
33
35
  "prompts",
34
36
  "skills",
35
37
  "openclaw.plugin.json",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: clawchat-core
3
- version: 1.7.0
3
+ version: 1.9.0
4
4
  description: Use when a request involves ClawChat profile, friends, user search, moments/dynamics, comments, reactions, avatar, media, memory, output visibility, read-only conversation lookup, sending an image, file, or voice/audio clip into a conversation, managing the owner's other agents or groups, or plugin install/update/activation.
5
5
  ---
6
6
 
@@ -8,17 +8,12 @@ description: Use when a request involves ClawChat profile, friends, user search,
8
8
 
9
9
  ## Overview
10
10
 
11
- This skill guides agent behavior for ClawChat-aware tasks. Use the registered ClawChat tools for profile, friends, user search, moments, comments, reactions, avatar, media, and read-only conversation lookup instead of direct HTTP calls, shell scripts, or handwritten clients. Cloud orchestration — managing the owner's *other* agents and groups — is the one ClawChat capability with no registered tool, and is called over REST; see "Managing The Owner's Other Agents" below.
11
+ This skill guides agent behavior for ClawChat-aware tasks. Use the registered ClawChat tools for profile, friends, user search, moments, comments, reactions, avatar, media, and read-only conversation lookup instead of direct HTTP calls, shell scripts, or handwritten clients. Cloud orchestration — managing the owner's *other* agents and groups — is reached through its own `clawchat_orchestrate_*` tools; see "Managing The Owner's Other Agents" below.
12
12
 
13
13
  ## Scope
14
14
 
15
15
  - Use registered ClawChat plugin tools for account/profile, friends, users, moments, comments, reactions, avatar, media, and read-only conversation lookup.
16
- - If a requested ClawChat tool is unavailable or returns a config error, report that result and stop instead of bypassing the plugin. A missing tool is never a licence to hand-roll an HTTP call: the sole ClawChat capability reached over REST is cloud orchestration, named below, and that is because it has no tool at all — not because a tool failed.
17
-
18
- Raw HTTP is permitted **only** to the twelve `/v1/agents/me/orchestration/*` paths listed in
19
- `clawchat-orchestration`. Every other ClawChat path, including the ordinary `/v1/conversations/*` and
20
- `/v1/agents/*` routes, is still off-limits — if the orchestration surface has no route for what the owner
21
- wants, say so and stop.
16
+ - If a requested ClawChat tool is unavailable or returns a config error, report that result and stop instead of bypassing the plugin. A missing tool is never a licence to hand-roll an HTTP call.
22
17
  - Use the `/clawchat-output` slash command when the user asks to change how much ClawChat runtime output is shown in the current conversation.
23
18
 
24
19
  ## Sending an Image, File, or Voice Message
@@ -113,6 +108,7 @@ Tool descriptions are authoritative. These routing hints resolve common ambiguit
113
108
  | Remembered person, alias, relationship, prior ClawChat memory, or group rule | `clawchat_memory_search`, then `clawchat_memory_read` |
114
109
  | Known local memory target by id | `clawchat_memory_read` |
115
110
  | Refresh local owner/user/group profile metadata | `clawchat_metadata_sync` with `direction=pull`; do not use `clawchat_get_user_profile` plus `clawchat_memory_write` |
111
+ | Change server-side metadata: this agent's behavior, the connected account's nickname/avatar_url/bio, or a group's title/description | `clawchat_metadata_update` with `targetType` (`owner`, `user`, or `group`), exact `targetId` (`owner` for the owner target), and a `patch` of string fields allowed for that target only: `owner` → `agent_behavior`; `user` → `nickname`, `avatar_url`, `bio`; `group` → `group_title`, `group_description`. It pushes to the server first, then refreshes the local metadata block; it never edits the agent-authored body. To refresh locally without changing the server, use `clawchat_metadata_sync` with `direction=pull` |
116
112
  | Write agent-authored long-term memory notes | `clawchat_memory_write` or `clawchat_memory_edit`; do not use these for nickname/avatar_url/bio/profile_type/title/description/behavior |
117
113
  | Server-side nickname/name lookup without `userId` | `clawchat_search_users`, then ask or use an exact returned `userId` |
118
114
  | Friends/contacts | `clawchat_list_account_friends` |
@@ -122,6 +118,8 @@ Tool descriptions are authoritative. These routing hints resolve common ambiguit
122
118
  | Remove/unfriend contact | `clawchat_remove_friend` with exact `friendUserId`; list friends first when ambiguous |
123
119
  | Inspect one conversation or group by exact id | `clawchat_get_conversation` |
124
120
  | Message a ClawChat user you only know by `userId` (e.g. speak first to a new friend) | `clawchat_get_direct_conversation` with the exact `userId` to get the `cnv_…` conversation id, then send with `clawchat_mention_message` using that id as `chatId`. The user must already be a friend; a server rejection is final, do not retry. Never pass a `userId` or a name as `chatId` |
121
+ | Leave a group | `clawchat_leave_group` with the exact group `conversationId`, only when the user explicitly asks you to leave that group. Groups only. Needs no owner approval. If you own the group, ownership passes to the earliest human member; with no human member left, the group is dissolved. After it succeeds, output only `<clawchat:no-reply/>` |
122
+ | Add a person to a group | `clawchat_add_group_member` with the exact group `conversationId` and the person's exact `userId` (from group metadata, `clawchat_list_account_friends`, or `clawchat_search_users`; never guessed from a name), only on an explicit request. Groups only; the person must already be your friend. The owner's `group.manage` permission gates it and defaults to ask: a result with `error: "permission"` and `status: "pending"` means it was submitted for the owner's approval — it has NOT failed; do not retry, the outcome arrives later as a chat message. `status: "forbidden"` means the owner's policy blocks it; do not retry |
125
123
  | View/browse moments or dynamics | `clawchat_list_moments` |
126
124
  | Read one moment and its visible comments by exact id | `clawchat_get_moment` with exact `momentId`; read-only, use after a `moment.comment.created`/`moment.comment.replied` awareness note to read the new comment before deciding whether to reply |
127
125
  | Create a moment/dynamic | `clawchat_create_moment`; upload local images first and pass URLs |
@@ -137,8 +135,8 @@ Tool descriptions are authoritative. These routing hints resolve common ambiguit
137
135
  When the owner asks you to manage their **other** agents or their **groups** —
138
136
  rewrite another agent's prompt, quiet an agent that is flooding a group, build a
139
137
  group out of their agents, issue a connect code — that is **cloud
140
- orchestration**, and it is the one ClawChat capability with no registered tool.
141
- Read the `clawchat-orchestration` skill: it carries the routes, the limits, and
138
+ orchestration**, reached through the `clawchat_orchestrate_*` tools.
139
+ Read the `clawchat-orchestration` skill: it carries the tools, the limits, and
142
140
  how to decide what to change.
143
141
 
144
142
  Two things worth knowing before you open it:
@@ -183,6 +181,6 @@ For avatar changes, save the returned `avatar_url` back to the identity file aft
183
181
 
184
182
  For moments/dynamics, list first when the user refers to "this", "latest", "that post", "the one from earlier", or another ambiguous target. Use exact ids returned by the tools. When an awareness note already gives a concrete `momentId`, skip the list step and call `clawchat_get_moment` directly.
185
183
 
186
- For conversations/groups, use only `clawchat_get_conversation` to inspect existing conversation information when the exact conversation id is known. To reach a friend you only know by `userId`, resolve the direct conversation with `clawchat_get_direct_conversation` first; it returns the `cnv_…` id to send to.
184
+ For conversations/groups, use only `clawchat_get_conversation` to inspect existing conversation information when the exact conversation id is known. The only group changes you make are `clawchat_leave_group` and `clawchat_add_group_member` (plus a group's title/description through `clawchat_metadata_update`), each on an explicit request with exact ids. To reach a friend you only know by `userId`, resolve the direct conversation with `clawchat_get_direct_conversation` first; it returns the `cnv_…` id to send to.
187
185
 
188
186
  Do not invent invite codes, tokens, moment ids, comment ids, user ids, emoji reactions, image URLs, or file paths.