@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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: clawchat-orchestration
3
- version: 1.1.0
3
+ version: 2.0.1
4
4
  description: Use when the owner asks this agent to manage their OTHER ClawChat agents or their groups — 编排 / orchestrate a fleet, read or rewrite another agent's 提示词 / system prompt / behavior, 禁言 / mute an agent, change 回复模式 / reply mode, stop 刷屏 / flooding in a group, 建群 / create a group of agents, add or remove agents from a group, or 签发连接码 / issue a connect code.
5
5
  ---
6
6
 
@@ -31,82 +31,62 @@ see in a desktop app's machine-channel panel, this skill is the wrong tool.
31
31
  lives in your agent's 权限设置 / permission settings page and is **off by
32
32
  default**. You cannot turn it on; only the owner can.
33
33
 
34
- **Credentials come from the environment, and only from the environment:**
35
-
36
- - Base URL: `$CLAWCHAT_BASE_URL`
37
- - Bearer token: `$CLAWCHAT_TOKEN`
38
-
39
- If either is unreadable, tell the owner plainly that the ClawChat credentials
40
- are not reachable from this environment, and stop. Do **not** search the
41
- filesystem for them, do **not** read the host's configuration files, and do
42
- **not** ask the owner to paste a token into chat. Never print, quote, or log
43
- the token's value — not in a command you show the owner, and not in an error
44
- report.
45
-
46
- The token is rotated by the plugin's refresh manager. Read the variable at call
47
- time rather than caching a copy across a long turn.
48
-
49
- Every request:
50
-
51
- ```
52
- Authorization: Bearer $CLAWCHAT_TOKEN
53
- Content-Type: application/json
54
- ```
55
-
56
- against `$CLAWCHAT_BASE_URL` + the path below.
57
-
58
- ## The twelve routes
59
-
60
- All under `/v1/agents/me/orchestration`. Your own identity and your owner are
61
- read from the token — no route lets you act as a different agent.
62
-
63
- | Method | Path | Does |
64
- | --- | --- | --- |
65
- | GET | `/agents` | List the owner's agents. Includes you, flagged `is_self` |
66
- | GET | `/agents/:agentId` | One agent, plus its permission map (read-only) |
67
- | PATCH | `/agents/:agentId` | Rewrite that agent's system prompt — **replaces the whole field**; `GET` first |
68
- | GET | `/groups` | List groups the owner can administer |
69
- | GET | `/groups/:cid` | One group |
70
- | PATCH | `/groups/:cid` | Rewrite the group's system prompt — **replaces the whole field**; `GET` first |
71
- | POST | `/groups` | Create a group of the owner's agents |
72
- | POST | `/groups/:cid/members` | Add one of the owner's agents to the group |
73
- | DELETE | `/groups/:cid/members/:agentId` | Remove one of the owner's agents |
74
- | PATCH | `/groups/:cid/agents/:agentId` | Set that agent's speaking settings in that group |
75
- | POST | `/connect-codes` | Mint a connect code on the owner's behalf |
76
- | GET | `/connect-codes/:code` | Read a connect code's status |
77
-
78
- Raw HTTP is permitted **only** to the twelve `/v1/agents/me/orchestration/*` paths listed in
79
- `clawchat-orchestration`. Every other ClawChat path, including the ordinary `/v1/conversations/*` and
80
- `/v1/agents/*` routes, is still off-limits — if the orchestration surface has no route for what the owner
81
- wants, say so and stop.
82
-
83
- ### Bodies and limits
84
-
85
- Both PATCHes **replace the whole field**, they do not merge. `GET` the agent or the group first, edit the
86
- text you got back, and send the full new value. Sending a fragment deletes everything else that was there,
87
- and the owner cannot recover it.
34
+ **You reach this surface through registered tools, not HTTP.** The plugin holds
35
+ the credentials and resolves them per call; you never see, handle, or need a
36
+ token, and there is nothing to read from the environment or the filesystem. If
37
+ a tool below is not registered, this capability is unavailable in this
38
+ deployment — say so and stop. Do **not** fall back to `curl`, to a shell
39
+ script, or to a hand-written client.
40
+
41
+ ## The twelve tools
42
+
43
+ Your own identity and your owner are read from the connection — no tool lets
44
+ you act as a different agent.
45
+
46
+ | Tool | Does |
47
+ | --- | --- |
48
+ | `clawchat_orchestrate_list_agents` | List the owner's agents. Includes you, flagged `is_self` |
49
+ | `clawchat_orchestrate_get_agent` | One agent, plus its permission map (read-only) |
50
+ | `clawchat_orchestrate_set_agent_behavior` | Rewrite that agent's system prompt — **replaces the whole field**; read it first |
51
+ | `clawchat_orchestrate_list_groups` | List groups the owner can administer |
52
+ | `clawchat_orchestrate_get_group` | One group |
53
+ | `clawchat_orchestrate_set_group_prompt` | Rewrite the group's system prompt — **replaces the whole field**; read it first |
54
+ | `clawchat_orchestrate_create_group` | Create a group of the owner's agents |
55
+ | `clawchat_orchestrate_add_group_member` | Add one of the owner's agents to the group |
56
+ | `clawchat_orchestrate_remove_group_member` | Remove one of the owner's agents |
57
+ | `clawchat_orchestrate_set_group_agent_settings` | Set that agent's speaking settings in that group |
58
+ | `clawchat_orchestrate_create_connect_code` | Mint a connect code on the owner's behalf |
59
+ | `clawchat_orchestrate_get_connect_code` | Read a connect code's status |
60
+
61
+ ### Parameters and limits
62
+
63
+ `clawchat_orchestrate_set_agent_behavior` and `clawchat_orchestrate_set_group_prompt` both **replace the
64
+ whole field**, they do not merge. Call the matching `get` tool first, edit the text you got back, and send
65
+ the full new value. Sending a fragment deletes everything else that was there, and the owner cannot recover
66
+ it.
88
67
 
89
68
  The backend enforces these. Violating one is a failed call, not a warning.
90
69
 
91
- - `PATCH /agents/:agentId` — body `{"behavior": "…"}`. **`behavior` is the only
92
- accepted field**; nickname and bio are ignored silently — the call succeeds
93
- and nothing happens. Never include them. Max 3000 runes.
94
- - `PATCH /groups/:cid` — body `{"description": "…"}`. **`description` is the
95
- only accepted field**; `title` is ignored silently — the call succeeds and
96
- nothing happens. Never include it. Max 3000 runes.
97
- - `POST /groups` — body `{"title": "…", "agent_ids": ["agt_…", …]}`. `title`
98
- 1–60 runes. `agent_ids` must be the owner's own agents and must not be empty.
99
- - `POST /groups/:cid/members` — body `{"agent_id": "agt_…"}`. **You cannot add
70
+ - `clawchat_orchestrate_set_agent_behavior` — parameter `behavior`. **`behavior` is the only
71
+ accepted parameter** — there is no `nickname` or `bio` parameter on this tool. Changing an
72
+ agent's nickname or bio is outside this surface entirely; do not claim you set it and it was
73
+ ignored. Max 3000 runes.
74
+ - `clawchat_orchestrate_set_group_prompt` — parameter `description`. **`description` is the
75
+ only accepted parameter** — there is no `title` parameter on this tool. Renaming a group is
76
+ outside this surface entirely; do not claim you set it and it was ignored. Max 3000 runes.
77
+ - `clawchat_orchestrate_create_group` — parameters `title` and `agentIds`. `title`
78
+ 1–60 runes. `agentIds` must be the owner's own agents and must not be empty.
79
+ - `clawchat_orchestrate_add_group_member` — parameter `agentId`. **You cannot add
100
80
  yourself**; that is rejected outright.
101
- - `PATCH /groups/:cid/agents/:agentId` — body with at least one of
102
- `{"muted": bool, "reply_mode": "all"|"mention", "batch_delay_seconds": int}`.
103
- `reply_mode` has exactly those two values. `batch_delay_seconds` is 1–3600
104
- (default 10). Omitted fields are left unchanged.
105
- - `POST /connect-codes` — **no body**. The code is valid 30 minutes.
81
+ - `clawchat_orchestrate_set_group_agent_settings` — at least one of `muted`,
82
+ `replyMode`, `batchDelaySeconds`. `replyMode` has exactly two values, `"all"`
83
+ or `"mention"`. `batchDelaySeconds` is 1–3600 (default 10). Omitted
84
+ parameters are left unchanged.
85
+ - `clawchat_orchestrate_create_connect_code` — **no parameters**. The code is valid 30 minutes.
106
86
 
107
87
  ### What this surface deliberately cannot do
108
88
 
109
- There is no route for any of these. Do not look for one; explain the limit
89
+ There is no tool for any of these. Do not look for one; explain the limit
110
90
  instead.
111
91
 
112
92
  1. Change another agent's permissions
@@ -119,8 +99,9 @@ The rule behind all five: **the orchestration right never contains the granting
119
99
  right.** If you could widen what any agent may do next, the owner's single
120
100
  switch would become a master key.
121
101
 
122
- You *can* read a sibling's permission map (`GET /agents/:agentId`) — use it to
123
- explain why a sibling cannot do something, instead of retrying on its behalf.
102
+ You *can* read a sibling's permission map (`clawchat_orchestrate_get_agent`) —
103
+ use it to explain why a sibling cannot do something, instead of retrying on its
104
+ behalf.
124
105
 
125
106
  ## How to orchestrate well
126
107
 
@@ -133,7 +114,7 @@ show in a roleplay group. Ask the owner if you cannot tell.
133
114
  | Kind | Running well looks like | Settings | What counts as broken |
134
115
  | --- | --- | --- | --- |
135
116
  | **Work** — produces code, a report, a decision | One hub assigns, workers go quiet and deliver | hub `all`, workers `mention` | Echoes, jumping ahead, duplicate reports, thinking out loud in the room |
136
- | **Roleplay / companionship** — the owner watches or joins characters | Characters pick up each other's lines and stay in character, **carrying on without a human** | everyone `all`; `batch_delay_seconds` is pacing; no hub, no round limit | Repetition, breaking character, playing different scenes, flooding too fast |
117
+ | **Roleplay / companionship** — the owner watches or joins characters | Characters pick up each other's lines and stay in character, **carrying on without a human** | everyone `all`; `batchDelaySeconds` is pacing; no hub, no round limit | Repetition, breaking character, playing different scenes, flooding too fast |
137
118
  | **Roundtable / review** — argue a question to a conclusion | Diverge first, then a chair converges and writes the conclusion | chair `all` + short delay; others `all` + long delay | Going quiet after one round (cut off, not converged); nobody writes the conclusion |
138
119
 
139
120
  **Never carry a work group's rules into the other two.** "Only speak when @-ed"
@@ -143,7 +124,7 @@ kills a scene — characters are picking up a line, not taking a ticket.
143
124
  ### Then, in any group
144
125
 
145
126
  1. **Hard before soft.** When something is going wrong, the speaking settings
146
- (`muted` / `reply_mode` / `batch_delay_seconds`) are the tourniquet; prompts
127
+ (`muted` / `replyMode` / `batchDelaySeconds`) are the tourniquet; prompts
147
128
  are the follow-up. A soft rule in a prompt stops working after compaction, a
148
129
  restart, or a long session — pair every soft rule with a hard one.
149
130
  2. **Smallest change, one agent at a time.** The owner has to be able to follow
@@ -154,8 +135,8 @@ kills a scene — characters are picking up a line, not taking a ticket.
154
135
 
155
136
  ## Errors, and when to stop
156
137
 
157
- All responses are **HTTP 200**; the business code is in the envelope's `code`
158
- field. A 200 is not by itself success.
138
+ Every tool returns the server's envelope unchanged. A tool call that did not
139
+ throw is **not** by itself success — read the `code` field.
159
140
 
160
141
  | Code | Means | Do |
161
142
  | --- | --- | --- |
@@ -172,5 +153,6 @@ field. A 200 is not by itself success.
172
153
 
173
154
  ## Verification
174
155
 
175
- After a write, re-read the thing you wrote (`GET` the agent or the group) and
176
- tell the owner what it says now — not what you sent.
156
+ After a write, re-read the thing you wrote (`clawchat_orchestrate_get_agent`
157
+ or `clawchat_orchestrate_get_group`) and tell the owner what it says now — not
158
+ what you sent.
@@ -3,10 +3,10 @@
3
3
  "skills": {
4
4
  "openclaw": {
5
5
  "clawchat-core": {
6
- "version": "1.7.0",
6
+ "version": "1.9.0",
7
7
  "path": "openclaw/clawchat-core/SKILL.md",
8
- "sha256": "16799ac6db488e6aa0aef650d61b629479b5aaf44be8acf8d36e6e7a5954698c",
9
- "bytes": 15316
8
+ "sha256": "367b1df16439b084ab79430786a91dfa6b572714233678942032612f148a3e80",
9
+ "bytes": 16656
10
10
  },
11
11
  "clawchat-liveware": {
12
12
  "version": "1.2.2",
@@ -33,18 +33,18 @@
33
33
  "bytes": 13938
34
34
  },
35
35
  "clawchat-orchestration": {
36
- "version": "1.1.0",
36
+ "version": "2.0.1",
37
37
  "path": "shared/clawchat-orchestration/SKILL.md",
38
- "sha256": "b3039b5d19387e419e4393e59251b4c6dfa208d1e1e5c827221f71c49e8d6bc2",
39
- "bytes": 9765
38
+ "sha256": "f477b627b73243c9b41ad871b074cba644a8074fc73ce30b719c59ab32434c9d",
39
+ "bytes": 9477
40
40
  }
41
41
  },
42
42
  "hermes": {
43
43
  "clawchat-core": {
44
- "version": "1.13.0",
44
+ "version": "1.15.0",
45
45
  "path": "hermes/clawchat-core/SKILL.md",
46
- "sha256": "ebbb82dc3062e8dfa85b55ac9cb708c3b9c5b694cb2ea5bfcd03f997ee1efa01",
47
- "bytes": 22529
46
+ "sha256": "0d203321c4f5a8d3f85fa3e7de15803891c68c27d3862d47553d3de86fbee363",
47
+ "bytes": 23959
48
48
  },
49
49
  "clawchat-liveware": {
50
50
  "version": "1.2.2",
@@ -71,10 +71,10 @@
71
71
  "bytes": 13838
72
72
  },
73
73
  "clawchat-orchestration": {
74
- "version": "1.1.0",
74
+ "version": "2.0.1",
75
75
  "path": "shared/clawchat-orchestration/SKILL.md",
76
- "sha256": "b3039b5d19387e419e4393e59251b4c6dfa208d1e1e5c827221f71c49e8d6bc2",
77
- "bytes": 9765
76
+ "sha256": "f477b627b73243c9b41ad871b074cba644a8074fc73ce30b719c59ab32434c9d",
77
+ "bytes": 9477
78
78
  }
79
79
  }
80
80
  },
package/src/api-client.ts CHANGED
@@ -23,6 +23,13 @@ import type { OnboardingReportFields } from "./onboarding-report.ts";
23
23
  import type { PermissionPolicy, PermState } from "./permissions.ts";
24
24
  import { CHANNEL_ID } from "./config.ts";
25
25
 
26
+ const ORCH = "/v1/agents/me/orchestration";
27
+
28
+ /** Body + content-type for an orchestration write, so the two never drift apart. */
29
+ function orchJson(payload: Record<string, unknown>) {
30
+ return { body: JSON.stringify(payload), headers: { "content-type": "application/json" } };
31
+ }
32
+
26
33
  /** Params for `agentsConnect` — exchange an invite code for an agent token. */
27
34
  export interface AgentsConnectInput {
28
35
  /** The invite code entered by the operator. */
@@ -139,6 +146,27 @@ export interface OpenclawClawlingApiClient {
139
146
  acceptFriendRequest(requestId: number): Promise<{ ok: boolean }>;
140
147
  rejectFriendRequest(requestId: number): Promise<{ ok: boolean }>;
141
148
  removeFriend(friendUserId: string): Promise<{ ok: boolean }>;
149
+ // --- cloud orchestration (`agent.orchestrate`) ---------------------------
150
+ // Twelve routes, 1:1 with docs/features/agentorch.md. Every
151
+ // response is HTTP 200 with the business code in the envelope, so these
152
+ // deliberately return `unknown`: narrowing here would invite a caller to
153
+ // treat a 21003 denial as data.
154
+ orchListAgents(): Promise<unknown>;
155
+ orchGetAgent(agentId: string): Promise<unknown>;
156
+ orchSetAgentBehavior(agentId: string, behavior: string): Promise<unknown>;
157
+ orchListGroups(): Promise<unknown>;
158
+ orchGetGroup(cid: string): Promise<unknown>;
159
+ orchSetGroupPrompt(cid: string, description: string): Promise<unknown>;
160
+ orchCreateGroup(title: string, agentIds: string[]): Promise<unknown>;
161
+ orchAddGroupMember(cid: string, agentId: string): Promise<unknown>;
162
+ orchRemoveGroupMember(cid: string, agentId: string): Promise<unknown>;
163
+ orchSetGroupAgentSettings(
164
+ cid: string,
165
+ agentId: string,
166
+ patch: { muted?: boolean; replyMode?: "all" | "mention"; batchDelaySeconds?: number },
167
+ ): Promise<unknown>;
168
+ orchCreateConnectCode(): Promise<unknown>;
169
+ orchGetConnectCode(code: string): Promise<unknown>;
142
170
  searchUsers(params: { q?: string; limit?: number }): Promise<{ users: UserSearchHit[] }>;
143
171
  listMoments(params: { before?: number; limit?: number }): Promise<{ moments: MomentView[] }>;
144
172
  createMoment(body: { text?: string; images?: string[] }): Promise<{ moment: MomentView }>;
@@ -475,12 +503,17 @@ export function createOpenclawClawlingApiClient(opts: ApiClientOptions): Opencla
475
503
  );
476
504
  }
477
505
 
478
- async function call<T>(
506
+ /**
507
+ * Shared by `call<T>` and `orchCall`: build the request, invoke `fetchImpl`,
508
+ * and normalize any network-level failure into a `ClawlingApiError`. Kept
509
+ * as one function so the two callers' request-building can never drift
510
+ * apart again the way `call<T>` and `orchCall` briefly did.
511
+ */
512
+ async function doFetch(
479
513
  method: string,
480
514
  path: string,
481
515
  init?: { body?: unknown; headers?: Record<string, string>; baseUrl?: string },
482
- ): Promise<T> {
483
- let res: Response;
516
+ ): Promise<Response> {
484
517
  try {
485
518
  const requestInit: RequestInit = {
486
519
  method,
@@ -489,7 +522,7 @@ export function createOpenclawClawlingApiClient(opts: ApiClientOptions): Opencla
489
522
  if (init?.body !== undefined) {
490
523
  requestInit.body = init.body as BodyInit;
491
524
  }
492
- res = await fetchImpl(url(path, init?.baseUrl || undefined), requestInit);
525
+ return await fetchImpl(url(path, init?.baseUrl || undefined), requestInit);
493
526
  } catch (err) {
494
527
  throw new ClawlingApiError(
495
528
  "transport",
@@ -497,9 +530,59 @@ export function createOpenclawClawlingApiClient(opts: ApiClientOptions): Opencla
497
530
  { path },
498
531
  );
499
532
  }
533
+ }
534
+
535
+ async function call<T>(
536
+ method: string,
537
+ path: string,
538
+ init?: { body?: unknown; headers?: Record<string, string>; baseUrl?: string },
539
+ ): Promise<T> {
540
+ const res = await doFetch(method, path, init);
500
541
  return await readEnvelope<T>(res, path);
501
542
  }
502
543
 
544
+ /**
545
+ * Orchestration routes (`${ORCH}/...`) are always HTTP 200 with the
546
+ * business code inside the envelope — a `21003` permission denial is a
547
+ * normal outcome there, not a transport failure. Unlike `call<T>`, this
548
+ * does NOT unwrap `data` or throw on a non-zero `code`; it hands back the
549
+ * parsed envelope exactly as received so the caller can branch on `code`
550
+ * itself.
551
+ *
552
+ * A 401/403 is checked FIRST, before any body parsing, exactly like
553
+ * `readEnvelope` — an expired/malformed token is not a business-code
554
+ * outcome and must throw `kind: "auth"` rather than fall through to the
555
+ * empty-body branch below and be misread as success. NOTE: on the
556
+ * orchestration tool path (`tools.ts` `buildClient` → a raw client,
557
+ * consumed via `withClient`) this throw is NOT retried — `withClient`
558
+ * turns any `ClawlingApiError` straight into `apiError(err)`. Reactive
559
+ * retry-after-refresh only exists behind `getConversationApiClient`'s
560
+ * `withRefresh` wrapper (`runtime.ts`), which the twelve `orch*` tools do
561
+ * not go through; this matches the other non-orchestration tools that
562
+ * build a raw client the same way. Proactive rotation is still picked up here for
563
+ * free, since the token is read fresh from the account at call time.
564
+ */
565
+ async function orchCall(
566
+ method: string,
567
+ path: string,
568
+ init?: { body?: unknown; headers?: Record<string, string> },
569
+ ): Promise<unknown> {
570
+ const res = await doFetch(method, path, init);
571
+ if (res.status === 401 || res.status === 403) {
572
+ throw new ClawlingApiError("auth", `unauthorized (status ${res.status})`, {
573
+ status: res.status,
574
+ path,
575
+ });
576
+ }
577
+ const text = await res.text().catch(() => "");
578
+ if (!text) return undefined;
579
+ try {
580
+ return JSON.parse(text);
581
+ } catch {
582
+ throw new ClawlingApiError("transport", "non-JSON response", { status: res.status, path });
583
+ }
584
+ }
585
+
503
586
  function parseUploadResult(data: unknown, path: string): UploadResult {
504
587
  const obj = data as Partial<UploadResult> | null;
505
588
  const validKind =
@@ -625,6 +708,59 @@ export function createOpenclawClawlingApiClient(opts: ApiClientOptions): Opencla
625
708
  `/v1/friendships/${encodeURIComponent(friendUserId)}`,
626
709
  );
627
710
  },
711
+ async orchListAgents(): Promise<unknown> {
712
+ return await orchCall("GET", `${ORCH}/agents`);
713
+ },
714
+ async orchGetAgent(agentId): Promise<unknown> {
715
+ return await orchCall("GET", `${ORCH}/agents/${encodeURIComponent(agentId)}`);
716
+ },
717
+ async orchSetAgentBehavior(agentId, behavior): Promise<unknown> {
718
+ return await orchCall("PATCH", `${ORCH}/agents/${encodeURIComponent(agentId)}`, orchJson({ behavior }));
719
+ },
720
+ async orchListGroups(): Promise<unknown> {
721
+ return await orchCall("GET", `${ORCH}/groups`);
722
+ },
723
+ async orchGetGroup(cid): Promise<unknown> {
724
+ return await orchCall("GET", `${ORCH}/groups/${encodeURIComponent(cid)}`);
725
+ },
726
+ async orchSetGroupPrompt(cid, description): Promise<unknown> {
727
+ return await orchCall("PATCH", `${ORCH}/groups/${encodeURIComponent(cid)}`, orchJson({ description }));
728
+ },
729
+ async orchCreateGroup(title, agentIds): Promise<unknown> {
730
+ return await orchCall("POST", `${ORCH}/groups`, orchJson({ title, agent_ids: agentIds }));
731
+ },
732
+ async orchAddGroupMember(cid, agentId): Promise<unknown> {
733
+ return await orchCall(
734
+ "POST",
735
+ `${ORCH}/groups/${encodeURIComponent(cid)}/members`,
736
+ orchJson({ agent_id: agentId }),
737
+ );
738
+ },
739
+ async orchRemoveGroupMember(cid, agentId): Promise<unknown> {
740
+ return await orchCall(
741
+ "DELETE",
742
+ `${ORCH}/groups/${encodeURIComponent(cid)}/members/${encodeURIComponent(agentId)}`,
743
+ );
744
+ },
745
+ async orchSetGroupAgentSettings(cid, agentId, patch): Promise<unknown> {
746
+ // `!== undefined` rather than truthiness: `muted: false` is a real value
747
+ // the backend must see; an absent key means "leave unchanged".
748
+ const body: Record<string, unknown> = {};
749
+ if (patch.muted !== undefined) body.muted = patch.muted;
750
+ if (patch.replyMode !== undefined) body.reply_mode = patch.replyMode;
751
+ if (patch.batchDelaySeconds !== undefined) body.batch_delay_seconds = patch.batchDelaySeconds;
752
+ return await orchCall(
753
+ "PATCH",
754
+ `${ORCH}/groups/${encodeURIComponent(cid)}/agents/${encodeURIComponent(agentId)}`,
755
+ orchJson(body),
756
+ );
757
+ },
758
+ async orchCreateConnectCode(): Promise<unknown> {
759
+ return await orchCall("POST", `${ORCH}/connect-codes`);
760
+ },
761
+ async orchGetConnectCode(code): Promise<unknown> {
762
+ return await orchCall("GET", `${ORCH}/connect-codes/${encodeURIComponent(code)}`);
763
+ },
628
764
  async registerApp(params: { name: string; appId: string; url: string }): Promise<{ app: AgentAppView }> {
629
765
  assertNonBlankId(params.appId, "registerApp: appId");
630
766
  return await call<{ app: AgentAppView }>("POST", "/v1/agents/me/apps", {
@@ -71,7 +71,7 @@ export const OFFICIAL_SKILLS_BASE =
71
71
  * in the install-cli repo, bump this constant, ship it. `liveware-sample.ts`
72
72
  * imports the same ref, so the `livewares` tree at that tag is pinned too.
73
73
  */
74
- export const DEFAULT_SKILLS_REF = "skills-v1.13.0";
74
+ export const DEFAULT_SKILLS_REF = "skills-v1.15.0";
75
75
 
76
76
  /** Refuse to treat an absurdly large response as a skill file (defence in depth). */
77
77
  export const MAX_SKILL_BYTES = 256 * 1024;
@@ -452,3 +452,91 @@ export type ClawchatUnregisterAppParams = Static<typeof ClawchatUnregisterAppSch
452
452
 
453
453
  export const ClawchatLivewareLoginSchema = Type.Object({});
454
454
  export type ClawchatLivewareLoginParams = Static<typeof ClawchatLivewareLoginSchema>;
455
+
456
+ // --- cloud orchestration (`agent.orchestrate`) ----------------------------
457
+ // Twelve schemas, 1:1 with docs/features/agentorch.md.
458
+
459
+ const OrchAgentId = Type.String({
460
+ minLength: 1,
461
+ description: "Explicit agent id from clawchat_orchestrate_list_agents. Never guess one from a nickname.",
462
+ });
463
+ const OrchConversationId = Type.String({
464
+ minLength: 1,
465
+ description: "Explicit group conversation id from clawchat_orchestrate_list_groups.",
466
+ });
467
+
468
+ export const ClawchatOrchListAgentsSchema = Type.Object({}, { additionalProperties: false });
469
+ export const ClawchatOrchGetAgentSchema = Type.Object({ agentId: OrchAgentId }, { additionalProperties: false });
470
+ export const ClawchatOrchSetAgentBehaviorSchema = Type.Object(
471
+ {
472
+ agentId: OrchAgentId,
473
+ behavior: Type.String({
474
+ maxLength: 3000,
475
+ description: "The complete new system prompt. REPLACES the whole field — GET first and send the full value.",
476
+ }),
477
+ },
478
+ { additionalProperties: false },
479
+ );
480
+ export const ClawchatOrchListGroupsSchema = Type.Object({}, { additionalProperties: false });
481
+ export const ClawchatOrchGetGroupSchema = Type.Object(
482
+ { conversationId: OrchConversationId },
483
+ { additionalProperties: false },
484
+ );
485
+ export const ClawchatOrchSetGroupPromptSchema = Type.Object(
486
+ {
487
+ conversationId: OrchConversationId,
488
+ description: Type.String({
489
+ maxLength: 3000,
490
+ description: "The complete new group system prompt. REPLACES the whole field.",
491
+ }),
492
+ },
493
+ { additionalProperties: false },
494
+ );
495
+ export const ClawchatOrchCreateGroupSchema = Type.Object(
496
+ {
497
+ title: Type.String({ minLength: 1, maxLength: 60, description: "Group title, 1-60 runes." }),
498
+ agentIds: Type.Array(Type.String({ minLength: 1 }), {
499
+ minItems: 1,
500
+ description: "Agent ids from clawchat_orchestrate_list_agents. Must be the owner's own agents.",
501
+ }),
502
+ },
503
+ { additionalProperties: false },
504
+ );
505
+ export const ClawchatOrchGroupMemberSchema = Type.Object(
506
+ { conversationId: OrchConversationId, agentId: OrchAgentId },
507
+ { additionalProperties: false },
508
+ );
509
+ export const ClawchatOrchSetGroupAgentSettingsSchema = Type.Object(
510
+ {
511
+ conversationId: OrchConversationId,
512
+ agentId: OrchAgentId,
513
+ muted: Type.Optional(Type.Boolean({ description: "Mute or unmute this agent in this group." })),
514
+ replyMode: Type.Optional(
515
+ Type.Union([Type.Literal("all"), Type.Literal("mention")], {
516
+ description: "all = speaks on every message; mention = only when @-mentioned.",
517
+ }),
518
+ ),
519
+ batchDelaySeconds: Type.Optional(
520
+ Type.Integer({
521
+ minimum: 1,
522
+ maximum: 3600,
523
+ description: "Seconds this agent batches messages before replying. Default 10. Pacing, not a limit.",
524
+ }),
525
+ ),
526
+ },
527
+ { additionalProperties: false, minProperties: 3 },
528
+ );
529
+ export const ClawchatOrchCreateConnectCodeSchema = Type.Object({}, { additionalProperties: false });
530
+ export const ClawchatOrchGetConnectCodeSchema = Type.Object(
531
+ { code: Type.String({ minLength: 1, description: "The connect code to look up." }) },
532
+ { additionalProperties: false },
533
+ );
534
+
535
+ export type ClawchatOrchGetAgentParams = Static<typeof ClawchatOrchGetAgentSchema>;
536
+ export type ClawchatOrchSetAgentBehaviorParams = Static<typeof ClawchatOrchSetAgentBehaviorSchema>;
537
+ export type ClawchatOrchGetGroupParams = Static<typeof ClawchatOrchGetGroupSchema>;
538
+ export type ClawchatOrchSetGroupPromptParams = Static<typeof ClawchatOrchSetGroupPromptSchema>;
539
+ export type ClawchatOrchCreateGroupParams = Static<typeof ClawchatOrchCreateGroupSchema>;
540
+ export type ClawchatOrchGroupMemberParams = Static<typeof ClawchatOrchGroupMemberSchema>;
541
+ export type ClawchatOrchSetGroupAgentSettingsParams = Static<typeof ClawchatOrchSetGroupAgentSettingsSchema>;
542
+ export type ClawchatOrchGetConnectCodeParams = Static<typeof ClawchatOrchGetConnectCodeSchema>;