@channlize/core 0.4.0 → 0.6.0
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/CHANGELOG.md +36 -0
- package/README.md +389 -1
- package/dist/index.d.mts +1906 -2
- package/dist/index.d.ts +1906 -2
- package/dist/index.js +1374 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1338 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,1630 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channlize for Agents: the JSON shapes of the `/v1/agents` API. They mirror
|
|
3
|
+
* the API's DTOs (`api/lib/agents/dto.ts`), so fields are `snake_case` as
|
|
4
|
+
* the API sends them. Request options are `camelCase`, like the rest of the
|
|
5
|
+
* SDK.
|
|
6
|
+
*/
|
|
7
|
+
/** An agent's lifecycle status. Only `active` agents can send. */
|
|
8
|
+
declare const AGENT_STATUSES: readonly ["active", "paused", "retired"];
|
|
9
|
+
type AgentStatus = (typeof AGENT_STATUSES)[number];
|
|
10
|
+
/** How channel messages reach an agent. */
|
|
11
|
+
declare const AGENT_DELIVERY_MODES: readonly ["webhook", "inbox", "a2a"];
|
|
12
|
+
type AgentDeliveryMode = (typeof AGENT_DELIVERY_MODES)[number];
|
|
13
|
+
/** Every message type a channel can hold. */
|
|
14
|
+
declare const AGENT_MESSAGE_TYPES: readonly ["message", "task", "question", "escalation", "status"];
|
|
15
|
+
type AgentMessageType = (typeof AGENT_MESSAGE_TYPES)[number];
|
|
16
|
+
/** The message types an agent can send (`agents.send`). */
|
|
17
|
+
declare const SENDABLE_AGENT_MESSAGE_TYPES: readonly ["message", "task", "status"];
|
|
18
|
+
type SendableAgentMessageType = (typeof SENDABLE_AGENT_MESSAGE_TYPES)[number];
|
|
19
|
+
/**
|
|
20
|
+
* A task's lifecycle. A `task` starts `open`; a `status` message moves it.
|
|
21
|
+
* `completed`, `failed`, `canceled` and `rejected` are final.
|
|
22
|
+
*/
|
|
23
|
+
declare const AGENT_TASK_STATUSES: readonly ["open", "working", "input_required", "completed", "failed", "canceled", "rejected"];
|
|
24
|
+
type AgentTaskStatus = (typeof AGENT_TASK_STATUSES)[number];
|
|
25
|
+
/** Agents are `member`s (post and read) or `observer`s (read); people are `supervisor`s. */
|
|
26
|
+
type AgentMemberRole = 'member' | 'observer' | 'supervisor';
|
|
27
|
+
/**
|
|
28
|
+
* Where one delivery stands: `inbox` (waiting to be pulled), `pending`
|
|
29
|
+
* (webhook or A2A push queued), `delivered`, `failed` (pushes gave up; still
|
|
30
|
+
* in the inbox), `held` (recipient paused), `pending_a2a`, `skipped`.
|
|
31
|
+
*/
|
|
32
|
+
type AgentDeliveryStatus = 'pending' | 'inbox' | 'delivered' | 'failed' | 'held' | 'pending_a2a' | 'skipped';
|
|
33
|
+
/** An agent of the directory (`GET /v1/agents`). Never carries its secret. */
|
|
34
|
+
interface Agent {
|
|
35
|
+
id: string;
|
|
36
|
+
slug: string;
|
|
37
|
+
name: string;
|
|
38
|
+
/** `webhook` (run by you) or `builtin` (run by Channlize). */
|
|
39
|
+
type: string;
|
|
40
|
+
delivery: AgentDeliveryMode;
|
|
41
|
+
status: AgentStatus;
|
|
42
|
+
enabled: boolean;
|
|
43
|
+
avatar_url: string | null;
|
|
44
|
+
emoji: string | null;
|
|
45
|
+
role: string | null;
|
|
46
|
+
description: string | null;
|
|
47
|
+
owner_user_id: string | null;
|
|
48
|
+
manager_agent_id: string | null;
|
|
49
|
+
manager_user_id: string | null;
|
|
50
|
+
webhook_url: string | null;
|
|
51
|
+
a2a_agent_card_url: string | null;
|
|
52
|
+
a2a_agent_card: unknown;
|
|
53
|
+
a2a_agent_card_fetched_at: string | null;
|
|
54
|
+
has_secret: boolean;
|
|
55
|
+
last_seen_at: string | null;
|
|
56
|
+
created_at: string;
|
|
57
|
+
updated_at: string;
|
|
58
|
+
}
|
|
59
|
+
/** Slack mirroring of a channel. Default: everything on. */
|
|
60
|
+
interface AgentMirrorConfig {
|
|
61
|
+
enabled: boolean;
|
|
62
|
+
types: Record<AgentMessageType, boolean>;
|
|
63
|
+
/** Each task (and its status updates) gets its own Slack thread. */
|
|
64
|
+
thread_per_task: boolean;
|
|
65
|
+
}
|
|
66
|
+
/** An agent channel. */
|
|
67
|
+
interface AgentChannel {
|
|
68
|
+
id: string;
|
|
69
|
+
slug: string;
|
|
70
|
+
name: string;
|
|
71
|
+
description: string | null;
|
|
72
|
+
slack_channel_id: string | null;
|
|
73
|
+
mirror: AgentMirrorConfig;
|
|
74
|
+
archived: boolean;
|
|
75
|
+
archived_at: string | null;
|
|
76
|
+
created_by: string | null;
|
|
77
|
+
created_at: string;
|
|
78
|
+
updated_at: string;
|
|
79
|
+
}
|
|
80
|
+
/** A channel member: an agent (`member` / `observer`) or a person (`supervisor`). */
|
|
81
|
+
interface AgentChannelMember {
|
|
82
|
+
id: string;
|
|
83
|
+
channel_id: string;
|
|
84
|
+
kind: 'agent' | 'user';
|
|
85
|
+
agent_id: string | null;
|
|
86
|
+
user_id: string | null;
|
|
87
|
+
role: AgentMemberRole;
|
|
88
|
+
name: string | null;
|
|
89
|
+
agent_slug?: string | null;
|
|
90
|
+
agent_status?: string | null;
|
|
91
|
+
user_email?: string | null;
|
|
92
|
+
created_at: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Who sent a message. `slack_user`: a person replying in Slack who isn't
|
|
96
|
+
* matched to a Channlize user. `deleted`: the sender no longer exists.
|
|
97
|
+
*/
|
|
98
|
+
type AgentMessageSender = {
|
|
99
|
+
kind: 'agent';
|
|
100
|
+
agent_id: string;
|
|
101
|
+
} | {
|
|
102
|
+
kind: 'user';
|
|
103
|
+
user_id: string;
|
|
104
|
+
} | {
|
|
105
|
+
kind: 'slack_user';
|
|
106
|
+
slack_user_id: string;
|
|
107
|
+
name: string;
|
|
108
|
+
} | {
|
|
109
|
+
kind: 'deleted';
|
|
110
|
+
};
|
|
111
|
+
/** A message in an agent channel. */
|
|
112
|
+
interface AgentMessage {
|
|
113
|
+
id: string;
|
|
114
|
+
/** Position in the channel feed. */
|
|
115
|
+
seq: string;
|
|
116
|
+
channel_id: string;
|
|
117
|
+
/** Root message of its thread; null on a root. */
|
|
118
|
+
thread_id: string | null;
|
|
119
|
+
sender: AgentMessageSender;
|
|
120
|
+
type: AgentMessageType;
|
|
121
|
+
text: string;
|
|
122
|
+
data: Record<string, unknown>;
|
|
123
|
+
/** Mentioned agent ids. */
|
|
124
|
+
mentions: string[];
|
|
125
|
+
/** On a `status` message: the task it updates. */
|
|
126
|
+
task_id: string | null;
|
|
127
|
+
/** On a `task`: its current status. On a `status` message: the status it reported. */
|
|
128
|
+
task_status: AgentTaskStatus | null;
|
|
129
|
+
tokens: number | null;
|
|
130
|
+
cost: number | null;
|
|
131
|
+
slack_ts: string | null;
|
|
132
|
+
a2a: {
|
|
133
|
+
context_id: string | null;
|
|
134
|
+
task_id: string | null;
|
|
135
|
+
message_id: string | null;
|
|
136
|
+
};
|
|
137
|
+
created_at: string;
|
|
138
|
+
}
|
|
139
|
+
/** One message for one recipient agent. */
|
|
140
|
+
interface AgentDelivery {
|
|
141
|
+
id: string;
|
|
142
|
+
message_id: string;
|
|
143
|
+
agent_id: string;
|
|
144
|
+
status: AgentDeliveryStatus;
|
|
145
|
+
attempts: number;
|
|
146
|
+
last_error: string | null;
|
|
147
|
+
delivered_at: string | null;
|
|
148
|
+
acked_at: string | null;
|
|
149
|
+
created_at: string;
|
|
150
|
+
}
|
|
151
|
+
/** `agents.send` input. */
|
|
152
|
+
interface SendAgentMessageInput {
|
|
153
|
+
/**
|
|
154
|
+
* The agent that sends. Required with a multi-agent key (unless it lists
|
|
155
|
+
* one agent); optional with an agent key. Defaults to the client's `agentId`.
|
|
156
|
+
*/
|
|
157
|
+
agentId?: string;
|
|
158
|
+
/** The channel id. The agent must be a `member` (observers can't post). */
|
|
159
|
+
channel: string;
|
|
160
|
+
/** Default `message`. A `task` starts `open`; a `status` updates `taskId`. */
|
|
161
|
+
type?: SendableAgentMessageType;
|
|
162
|
+
text: string;
|
|
163
|
+
/** Reply in this thread (any message of it). */
|
|
164
|
+
threadId?: string;
|
|
165
|
+
/** Agent ids to mention. */
|
|
166
|
+
mentions?: string[];
|
|
167
|
+
/** Structured data, stored and delivered with the message. */
|
|
168
|
+
data?: Record<string, unknown>;
|
|
169
|
+
/** Tokens the agent used for this message, for reporting. */
|
|
170
|
+
tokens?: number;
|
|
171
|
+
/** Cost the agent reports for this message, for reporting. */
|
|
172
|
+
cost?: number;
|
|
173
|
+
/** On a `status` message: the task to update. */
|
|
174
|
+
taskId?: string;
|
|
175
|
+
/** On a `status` message: the task's new status. */
|
|
176
|
+
taskStatus?: AgentTaskStatus;
|
|
177
|
+
}
|
|
178
|
+
/** `agents.send` result (`201`). */
|
|
179
|
+
interface SendAgentMessageResult {
|
|
180
|
+
message: AgentMessage;
|
|
181
|
+
/** One per recipient agent. */
|
|
182
|
+
deliveries: Array<{
|
|
183
|
+
id: string;
|
|
184
|
+
agent_id: string;
|
|
185
|
+
status: AgentDeliveryStatus;
|
|
186
|
+
}>;
|
|
187
|
+
}
|
|
188
|
+
/** One unacked message of an agent's inbox. */
|
|
189
|
+
interface AgentInboxItem {
|
|
190
|
+
delivery_id: string;
|
|
191
|
+
/** This item's position; pass it as `cursor` to read after it. */
|
|
192
|
+
cursor: string;
|
|
193
|
+
status: AgentDeliveryStatus;
|
|
194
|
+
attempts: number;
|
|
195
|
+
message: AgentMessage;
|
|
196
|
+
}
|
|
197
|
+
interface AgentInboxOptions {
|
|
198
|
+
/** Read after this cursor (`nextCursor` of the previous page). Default: the oldest unacked message. */
|
|
199
|
+
cursor?: string;
|
|
200
|
+
/** Page size (1-200, default 50). */
|
|
201
|
+
limit?: number;
|
|
202
|
+
}
|
|
203
|
+
/** `agents.inbox` result: unacked messages, oldest first. */
|
|
204
|
+
interface AgentInboxPage {
|
|
205
|
+
messages: AgentInboxItem[];
|
|
206
|
+
/** Pass as `cursor` for the next page; the same cursor when nothing is newer. */
|
|
207
|
+
nextCursor: string | null;
|
|
208
|
+
hasMore: boolean;
|
|
209
|
+
}
|
|
210
|
+
/** `agents.ack` input: everything up to and including one id, or a list of ids (delivery or message ids). */
|
|
211
|
+
type AgentAckInput = {
|
|
212
|
+
upTo: string;
|
|
213
|
+
} | {
|
|
214
|
+
ids: string[];
|
|
215
|
+
};
|
|
216
|
+
interface AgentAckResult {
|
|
217
|
+
/** How many were newly acked (acking twice is harmless). */
|
|
218
|
+
acked: number;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* `agents.get` result. An `agents:admin` key also gets the dashboard detail:
|
|
222
|
+
* recent messages, delivery stats, keys and channels.
|
|
223
|
+
*/
|
|
224
|
+
interface AgentDetail {
|
|
225
|
+
agent: Agent;
|
|
226
|
+
recent_messages?: AgentMessage[];
|
|
227
|
+
delivery_stats?: Record<string, unknown>;
|
|
228
|
+
keys?: Array<Record<string, unknown>>;
|
|
229
|
+
channels?: AgentChannel[];
|
|
230
|
+
}
|
|
231
|
+
interface AgentChannelReadOptions {
|
|
232
|
+
/** Read as this agent (multi-agent keys). Defaults to the client's `agentId`. */
|
|
233
|
+
agentId?: string;
|
|
234
|
+
}
|
|
235
|
+
interface AgentChannelFeedOptions extends AgentChannelReadOptions {
|
|
236
|
+
/** Older page: `nextCursor` of the previous page. */
|
|
237
|
+
cursor?: string;
|
|
238
|
+
/** Newer messages only: `latestCursor` of the previous read (for polling). */
|
|
239
|
+
after?: string;
|
|
240
|
+
/** Page size (1-200, default 50). */
|
|
241
|
+
limit?: number;
|
|
242
|
+
/** Only messages from this agent. */
|
|
243
|
+
senderAgentId?: string;
|
|
244
|
+
type?: AgentMessageType;
|
|
245
|
+
/** Only this thread. */
|
|
246
|
+
threadId?: string;
|
|
247
|
+
}
|
|
248
|
+
/** `agents.channels.messages` result. */
|
|
249
|
+
interface AgentChannelFeed {
|
|
250
|
+
channel: AgentChannel;
|
|
251
|
+
messages: AgentMessage[];
|
|
252
|
+
/** Pass as `cursor` for the older page (null when there is none). */
|
|
253
|
+
nextCursor: string | null;
|
|
254
|
+
/** Pass as `after` on the next poll. */
|
|
255
|
+
latestCursor: string | null;
|
|
256
|
+
hasMore: boolean;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* The body Channlize POSTs to a webhook agent (`version: 1`), with the
|
|
260
|
+
* headers `X-Webhook-Event: agent.message`, `X-Webhook-Delivery-ID` and
|
|
261
|
+
* `X-Webhook-Signature` (check it with `verifyAgentWebhook`). Answer 2xx to
|
|
262
|
+
* ack it; anything else is retried with backoff, and the message stays in
|
|
263
|
+
* the agent's inbox.
|
|
264
|
+
*/
|
|
265
|
+
interface AgentWebhookPayload {
|
|
266
|
+
version: 1;
|
|
267
|
+
event: 'agent.message';
|
|
268
|
+
delivery_id: string;
|
|
269
|
+
/** The recipient. */
|
|
270
|
+
agent: {
|
|
271
|
+
id: string;
|
|
272
|
+
slug: string;
|
|
273
|
+
name: string;
|
|
274
|
+
};
|
|
275
|
+
channel: {
|
|
276
|
+
id: string;
|
|
277
|
+
slug: string;
|
|
278
|
+
name: string;
|
|
279
|
+
};
|
|
280
|
+
sender: {
|
|
281
|
+
kind: 'agent';
|
|
282
|
+
id: string;
|
|
283
|
+
slug: string | null;
|
|
284
|
+
name: string | null;
|
|
285
|
+
} | {
|
|
286
|
+
kind: 'user';
|
|
287
|
+
id: string;
|
|
288
|
+
} | {
|
|
289
|
+
kind: 'slack_user';
|
|
290
|
+
id: string;
|
|
291
|
+
name: string;
|
|
292
|
+
} | {
|
|
293
|
+
kind: 'deleted';
|
|
294
|
+
};
|
|
295
|
+
message: AgentMessage;
|
|
296
|
+
ack_url: string;
|
|
297
|
+
}
|
|
298
|
+
/** `createAgentsClient` options; each falls back to an environment variable. */
|
|
299
|
+
interface AgentsClientConfig {
|
|
300
|
+
/**
|
|
301
|
+
* An agent key, a multi-agent key, or an `agents:admin` key (read
|
|
302
|
+
* helpers only). Default: `CHANNLIZE_SERVER_API_KEY`, else `CHANNLIZE_API_KEY`.
|
|
303
|
+
*/
|
|
304
|
+
apiKey?: string;
|
|
305
|
+
/**
|
|
306
|
+
* The agent this client acts as by default (needed with a multi-agent
|
|
307
|
+
* key, and for `inbox` / `ack` / `poll`). Default: `CHANNLIZE_AGENT_ID`.
|
|
308
|
+
*/
|
|
309
|
+
agentId?: string;
|
|
310
|
+
/** API base URL. Default: `CHANNLIZE_BASE_URL`, else `https://api.channlize.com`. */
|
|
311
|
+
baseUrl?: string;
|
|
312
|
+
/** Request timeout in ms (default 10000). */
|
|
313
|
+
timeout?: number;
|
|
314
|
+
}
|
|
315
|
+
/** `agents.poll` options. */
|
|
316
|
+
interface AgentPollOptions {
|
|
317
|
+
/** Wait between polls when the inbox is empty (default 5000 ms). */
|
|
318
|
+
intervalMs?: number;
|
|
319
|
+
/** Upper bound of the backoff after errors (default 60000 ms). */
|
|
320
|
+
maxBackoffMs?: number;
|
|
321
|
+
/** Inbox page size (default 50). */
|
|
322
|
+
limit?: number;
|
|
323
|
+
/** Stops the loop; `poll` then resolves. */
|
|
324
|
+
signal?: AbortSignal;
|
|
325
|
+
/**
|
|
326
|
+
* Called when reading the inbox, the handler or the ack fails (`item` is
|
|
327
|
+
* set for a handler failure). The loop backs off and retries; the failed
|
|
328
|
+
* message isn't acked, so it comes back.
|
|
329
|
+
*/
|
|
330
|
+
onError?: (error: unknown, item?: AgentInboxItem) => void;
|
|
331
|
+
}
|
|
332
|
+
/** What `agents.poll` calls for each message, oldest first. Acked once it resolves. */
|
|
333
|
+
type AgentMessageHandler = (message: AgentMessage, item: AgentInboxItem) => unknown | Promise<unknown>;
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Channlize for Agents, Phases 2 and 3: asking humans (questions and
|
|
337
|
+
* approvals), tasks and handoffs, teams, policies, the org chart and
|
|
338
|
+
* onboarding. Shapes mirror the API's DTOs (`api/lib/agents/questions-dto.ts`,
|
|
339
|
+
* `tasks.ts`, `teams.ts`, `policies.ts`, `org-chart.ts`), so fields are
|
|
340
|
+
* `snake_case`; request options are `camelCase`.
|
|
341
|
+
*/
|
|
342
|
+
|
|
343
|
+
declare const QUESTION_KINDS: readonly ["question", "approval"];
|
|
344
|
+
/** `approval` questions are always Approve / Deny (option ids `approve` / `deny`). */
|
|
345
|
+
type QuestionKind = (typeof QUESTION_KINDS)[number];
|
|
346
|
+
declare const QUESTION_URGENCIES: readonly ["low", "normal", "high", "urgent"];
|
|
347
|
+
/** Sets how fast the question escalates (default step timeouts: 4h, 1h, 15min, 5min). */
|
|
348
|
+
type QuestionUrgency = (typeof QUESTION_URGENCIES)[number];
|
|
349
|
+
/**
|
|
350
|
+
* `open` until someone answers. `expired_default`: the deadline applied the
|
|
351
|
+
* default option (delivered as `question.answered`). `expired`: the
|
|
352
|
+
* deadline passed with no default.
|
|
353
|
+
*/
|
|
354
|
+
declare const QUESTION_STATUSES: readonly ["open", "answered", "expired_default", "expired", "canceled"];
|
|
355
|
+
type QuestionStatus = (typeof QUESTION_STATUSES)[number];
|
|
356
|
+
/** The longest single `questions.wait` long-poll, in seconds. */
|
|
357
|
+
declare const QUESTION_WAIT_MAX_SECONDS = 25;
|
|
358
|
+
interface QuestionOption {
|
|
359
|
+
id: string;
|
|
360
|
+
/** At most 75 characters (Slack button text). */
|
|
361
|
+
label: string;
|
|
362
|
+
}
|
|
363
|
+
/** How a closed question was answered. */
|
|
364
|
+
interface QuestionAnswer {
|
|
365
|
+
status: Exclude<QuestionStatus, 'open'>;
|
|
366
|
+
option_id: string | null;
|
|
367
|
+
/** The chosen option's label. */
|
|
368
|
+
option_label: string | null;
|
|
369
|
+
text: string | null;
|
|
370
|
+
comment: string | null;
|
|
371
|
+
/** Null when it expired without a default, or was canceled. */
|
|
372
|
+
answered_by: 'user' | 'agent' | 'default' | null;
|
|
373
|
+
user_id: string | null;
|
|
374
|
+
slack_user_id: string | null;
|
|
375
|
+
agent_id: string | null;
|
|
376
|
+
answered_at: string | null;
|
|
377
|
+
canceled_at: string | null;
|
|
378
|
+
/** Approvals: `approve` → true, `deny` → false. */
|
|
379
|
+
approved?: boolean;
|
|
380
|
+
}
|
|
381
|
+
/** A question or approval an agent asked people. */
|
|
382
|
+
interface AgentQuestion {
|
|
383
|
+
id: string;
|
|
384
|
+
/** The agent that asked. */
|
|
385
|
+
agent_id: string | null;
|
|
386
|
+
channel_id: string | null;
|
|
387
|
+
thread_id: string | null;
|
|
388
|
+
/** The `question` message in the channel, when it has one. */
|
|
389
|
+
message_id: string | null;
|
|
390
|
+
kind: QuestionKind;
|
|
391
|
+
question: string;
|
|
392
|
+
options: QuestionOption[];
|
|
393
|
+
free_text: boolean;
|
|
394
|
+
urgency: QuestionUrgency;
|
|
395
|
+
deadline: string | null;
|
|
396
|
+
default_option: string | null;
|
|
397
|
+
context: Record<string, unknown>;
|
|
398
|
+
amount: number | null;
|
|
399
|
+
currency: string | null;
|
|
400
|
+
resource: Record<string, unknown> | null;
|
|
401
|
+
required_roles: string[];
|
|
402
|
+
status: QuestionStatus;
|
|
403
|
+
/** Null while open. */
|
|
404
|
+
answer: QuestionAnswer | null;
|
|
405
|
+
a2a_task_id: string | null;
|
|
406
|
+
slack: {
|
|
407
|
+
channel_id: string;
|
|
408
|
+
ts: string;
|
|
409
|
+
} | null;
|
|
410
|
+
escalation: {
|
|
411
|
+
step: number;
|
|
412
|
+
next_check_at: string | null;
|
|
413
|
+
muted_until: string | null;
|
|
414
|
+
};
|
|
415
|
+
created_at: string;
|
|
416
|
+
updated_at: string;
|
|
417
|
+
}
|
|
418
|
+
/** One step of a question's escalation chain. */
|
|
419
|
+
interface QuestionEscalation {
|
|
420
|
+
step: number;
|
|
421
|
+
target_kind: string;
|
|
422
|
+
target_ref: string | null;
|
|
423
|
+
target_user_ids: string[];
|
|
424
|
+
notified_at: string | null;
|
|
425
|
+
timeout_at: string | null;
|
|
426
|
+
slack: {
|
|
427
|
+
channel_id: string;
|
|
428
|
+
ts: string;
|
|
429
|
+
} | null;
|
|
430
|
+
error: string | null;
|
|
431
|
+
}
|
|
432
|
+
/** `agents.ask` input (`POST /v1/agents/questions`, scope `agents:ask_human`). */
|
|
433
|
+
interface AskHumanInput {
|
|
434
|
+
/** The asking agent. Defaults to the client's `agentId`. */
|
|
435
|
+
agentId?: string;
|
|
436
|
+
/** Default `question`. An `approval` is answered Approve / Deny. */
|
|
437
|
+
kind?: QuestionKind;
|
|
438
|
+
/** At most 3000 characters. */
|
|
439
|
+
question: string;
|
|
440
|
+
/** Up to 10. Ignored for approvals. */
|
|
441
|
+
options?: QuestionOption[];
|
|
442
|
+
/** Allow a free-text answer (forced on without options). */
|
|
443
|
+
freeText?: boolean;
|
|
444
|
+
/** Default `normal`. Capped by the policy's `max_ask_urgency`. */
|
|
445
|
+
urgency?: QuestionUrgency;
|
|
446
|
+
/** ISO time, at most 30 days away. */
|
|
447
|
+
deadline?: string | Date;
|
|
448
|
+
/** Option id applied at the deadline. */
|
|
449
|
+
defaultOption?: string;
|
|
450
|
+
/** Post the question in this agent channel (else the escalation channel). */
|
|
451
|
+
channelId?: string;
|
|
452
|
+
/** Any message of the thread it is about. */
|
|
453
|
+
threadId?: string;
|
|
454
|
+
/** Shown with the question (at most 16 KB of JSON). */
|
|
455
|
+
context?: Record<string, unknown>;
|
|
456
|
+
/** Approvals: shown, and matched against the policy's `approval_rules`. */
|
|
457
|
+
amount?: number;
|
|
458
|
+
/** ISO 4217 code. */
|
|
459
|
+
currency?: string;
|
|
460
|
+
/** Approvals: what is being approved (at most 4 KB of JSON). */
|
|
461
|
+
resource?: Record<string, unknown>;
|
|
462
|
+
/** Approvals: roles that may answer (`owner` > `admin` > `agent` > `viewer`). */
|
|
463
|
+
requiredRoles?: string[];
|
|
464
|
+
}
|
|
465
|
+
interface QuestionReadOptions {
|
|
466
|
+
/** Read as this agent (multi-agent keys). Defaults to the client's `agentId`. */
|
|
467
|
+
agentId?: string;
|
|
468
|
+
}
|
|
469
|
+
interface ListQuestionsOptions extends QuestionReadOptions {
|
|
470
|
+
status?: QuestionStatus;
|
|
471
|
+
kind?: QuestionKind;
|
|
472
|
+
urgency?: QuestionUrgency;
|
|
473
|
+
channelId?: string;
|
|
474
|
+
/** `nextCursor` of the previous page. */
|
|
475
|
+
cursor?: string;
|
|
476
|
+
/** 1-200, default 50. */
|
|
477
|
+
limit?: number;
|
|
478
|
+
}
|
|
479
|
+
/** `agents.questions.list`: newest first; the agent's own and those escalated to it. */
|
|
480
|
+
interface QuestionPage {
|
|
481
|
+
questions: AgentQuestion[];
|
|
482
|
+
nextCursor: string | null;
|
|
483
|
+
}
|
|
484
|
+
interface WaitQuestionOptions extends QuestionReadOptions {
|
|
485
|
+
/** Seconds to hold the request (0-25, default 25). */
|
|
486
|
+
timeoutSec?: number;
|
|
487
|
+
signal?: AbortSignal;
|
|
488
|
+
}
|
|
489
|
+
/** One long-poll: `timedOut` when the question is still open. */
|
|
490
|
+
interface WaitQuestionResult {
|
|
491
|
+
question: AgentQuestion;
|
|
492
|
+
timedOut: boolean;
|
|
493
|
+
}
|
|
494
|
+
/** `agents.questions.answer` input (a manager agent answering an escalated question). */
|
|
495
|
+
interface AnswerQuestionInput {
|
|
496
|
+
/** The answering agent. Defaults to the client's `agentId`. */
|
|
497
|
+
agentId?: string;
|
|
498
|
+
/** One of the options (`approve` / `deny` for approvals). */
|
|
499
|
+
optionId?: string;
|
|
500
|
+
/** A free-text answer (questions that allow it). */
|
|
501
|
+
text?: string;
|
|
502
|
+
comment?: string;
|
|
503
|
+
}
|
|
504
|
+
interface AskAndWaitOptions {
|
|
505
|
+
/**
|
|
506
|
+
* The overall wait, in ms (default 600000: 10 minutes). Questions can take
|
|
507
|
+
* hours: past it, the call resolves with `timedOut: true` and the open
|
|
508
|
+
* question, to wait on later with `questions.wait`.
|
|
509
|
+
*/
|
|
510
|
+
timeoutMs?: number;
|
|
511
|
+
/** Rejects the call (code `ABORTED`) when it aborts. */
|
|
512
|
+
signal?: AbortSignal;
|
|
513
|
+
}
|
|
514
|
+
/** `agents.askAndWait` result. */
|
|
515
|
+
interface AskAndWaitResult {
|
|
516
|
+
question: AgentQuestion;
|
|
517
|
+
/** Null while open (`timedOut`). */
|
|
518
|
+
answer: QuestionAnswer | null;
|
|
519
|
+
/** True when `timeoutMs` ran out with the question still open. */
|
|
520
|
+
timedOut: boolean;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Board columns. They map onto `task_status`: `open` → `open`,
|
|
524
|
+
* `in_progress` → `working`, `blocked` → `input_required`, `done` →
|
|
525
|
+
* `completed`, `failed` → `failed` (`canceled` and `rejected` show as
|
|
526
|
+
* `failed`).
|
|
527
|
+
*/
|
|
528
|
+
declare const TASK_BOARD_STATUSES: readonly ["open", "in_progress", "blocked", "done", "failed"];
|
|
529
|
+
type TaskBoardStatus = (typeof TASK_BOARD_STATUSES)[number];
|
|
530
|
+
interface TaskHandoff {
|
|
531
|
+
from_agent_id: string | null;
|
|
532
|
+
to_agent_id: string | null;
|
|
533
|
+
reason: string | null;
|
|
534
|
+
by_agent_id: string | null;
|
|
535
|
+
by_user_id: string | null;
|
|
536
|
+
at: string;
|
|
537
|
+
}
|
|
538
|
+
/** A task: its `task` message plus the board fields. */
|
|
539
|
+
interface AgentTask extends AgentMessage {
|
|
540
|
+
board_status: TaskBoardStatus;
|
|
541
|
+
assignee_agent_id: string | null;
|
|
542
|
+
due_at: string | null;
|
|
543
|
+
last_handoff: TaskHandoff | null;
|
|
544
|
+
}
|
|
545
|
+
/** One entry of a task's history. */
|
|
546
|
+
interface AgentTaskEvent {
|
|
547
|
+
id: string;
|
|
548
|
+
kind: 'assigned' | 'handoff' | 'status' | 'due_changed';
|
|
549
|
+
from_agent_id: string | null;
|
|
550
|
+
to_agent_id: string | null;
|
|
551
|
+
by_agent_id: string | null;
|
|
552
|
+
by_user_id: string | null;
|
|
553
|
+
from_status: string | null;
|
|
554
|
+
to_status: string | null;
|
|
555
|
+
reason: string | null;
|
|
556
|
+
data: Record<string, unknown> | null;
|
|
557
|
+
created_at: string;
|
|
558
|
+
}
|
|
559
|
+
interface TaskDeliverySummary {
|
|
560
|
+
id: string;
|
|
561
|
+
agent_id: string;
|
|
562
|
+
status: AgentDeliveryStatus;
|
|
563
|
+
}
|
|
564
|
+
/** `agents.tasks.create` input (`agents:send`). */
|
|
565
|
+
interface CreateTaskInput {
|
|
566
|
+
/** The creating agent. Defaults to the client's `agentId`. */
|
|
567
|
+
agentId?: string;
|
|
568
|
+
channelId: string;
|
|
569
|
+
/** What should be done. */
|
|
570
|
+
text: string;
|
|
571
|
+
/** A `member` of the channel; mentioned, and the task's owner on the board. */
|
|
572
|
+
assigneeAgentId?: string;
|
|
573
|
+
/** ISO date or date-time. */
|
|
574
|
+
dueAt?: string | Date;
|
|
575
|
+
threadId?: string;
|
|
576
|
+
mentions?: string[];
|
|
577
|
+
data?: Record<string, unknown>;
|
|
578
|
+
}
|
|
579
|
+
interface CreateTaskResult {
|
|
580
|
+
task: AgentTask;
|
|
581
|
+
deliveries: TaskDeliverySummary[];
|
|
582
|
+
}
|
|
583
|
+
interface ListTasksOptions {
|
|
584
|
+
/** Required with a key bound to agents. */
|
|
585
|
+
channelId?: string;
|
|
586
|
+
assigneeAgentId?: string;
|
|
587
|
+
status?: TaskBoardStatus;
|
|
588
|
+
/** 1-500. */
|
|
589
|
+
limit?: number;
|
|
590
|
+
/** Read as this agent (multi-agent keys). Defaults to the client's `agentId`. */
|
|
591
|
+
agentId?: string;
|
|
592
|
+
}
|
|
593
|
+
interface TaskBoardOptions {
|
|
594
|
+
assigneeAgentId?: string;
|
|
595
|
+
agentId?: string;
|
|
596
|
+
}
|
|
597
|
+
interface TaskBoard {
|
|
598
|
+
channel_id: string;
|
|
599
|
+
columns: Record<TaskBoardStatus, AgentTask[]>;
|
|
600
|
+
counts: Record<TaskBoardStatus, number>;
|
|
601
|
+
agents: Array<Pick<Agent, 'id' | 'slug' | 'name' | 'emoji' | 'avatar_url' | 'status'>>;
|
|
602
|
+
/** More than 500 tasks: the board shows the newest. */
|
|
603
|
+
truncated: boolean;
|
|
604
|
+
}
|
|
605
|
+
interface TaskDetail {
|
|
606
|
+
task: AgentTask;
|
|
607
|
+
events: AgentTaskEvent[];
|
|
608
|
+
}
|
|
609
|
+
/** `agents.tasks.update` input: the assignee or creator moves the task or changes its due date. */
|
|
610
|
+
interface UpdateTaskInput {
|
|
611
|
+
agentId?: string;
|
|
612
|
+
status?: TaskBoardStatus;
|
|
613
|
+
/** ISO date or date-time; null clears it. */
|
|
614
|
+
dueAt?: string | Date | null;
|
|
615
|
+
/** Shown with the change (at most 2000 characters). */
|
|
616
|
+
note?: string;
|
|
617
|
+
}
|
|
618
|
+
interface UpdateTaskResult {
|
|
619
|
+
task: AgentTask;
|
|
620
|
+
/** False when nothing changed. */
|
|
621
|
+
changed: boolean;
|
|
622
|
+
}
|
|
623
|
+
interface HandoffTaskInput {
|
|
624
|
+
agentId?: string;
|
|
625
|
+
/** A `member` of the task's channel. */
|
|
626
|
+
toAgentId: string;
|
|
627
|
+
reason?: string;
|
|
628
|
+
}
|
|
629
|
+
interface HandoffTaskResult {
|
|
630
|
+
task: AgentTask;
|
|
631
|
+
event: AgentTaskEvent;
|
|
632
|
+
deliveries: TaskDeliverySummary[];
|
|
633
|
+
}
|
|
634
|
+
interface AgentTeam {
|
|
635
|
+
id: string;
|
|
636
|
+
slug: string;
|
|
637
|
+
name: string;
|
|
638
|
+
description: string | null;
|
|
639
|
+
member_count?: number;
|
|
640
|
+
channel_count?: number;
|
|
641
|
+
created_by: string | null;
|
|
642
|
+
created_at: string;
|
|
643
|
+
updated_at: string;
|
|
644
|
+
}
|
|
645
|
+
interface AgentTeamChannelGrant {
|
|
646
|
+
channel_id: string;
|
|
647
|
+
team_id: string;
|
|
648
|
+
role: AgentMemberRole;
|
|
649
|
+
added_by: string | null;
|
|
650
|
+
created_at: string;
|
|
651
|
+
}
|
|
652
|
+
interface AgentTeamDetail {
|
|
653
|
+
team: AgentTeam;
|
|
654
|
+
members: Array<{
|
|
655
|
+
agent: Agent;
|
|
656
|
+
added_by: string | null;
|
|
657
|
+
added_at: string;
|
|
658
|
+
}>;
|
|
659
|
+
channels: AgentTeamChannelGrant[];
|
|
660
|
+
policy: {
|
|
661
|
+
id: string;
|
|
662
|
+
rules: AgentPolicyRules;
|
|
663
|
+
enabled: boolean;
|
|
664
|
+
updated_at: string;
|
|
665
|
+
} | null;
|
|
666
|
+
}
|
|
667
|
+
interface CreateTeamInput {
|
|
668
|
+
name: string;
|
|
669
|
+
slug?: string;
|
|
670
|
+
description?: string | null;
|
|
671
|
+
/** Agents to add right away. */
|
|
672
|
+
agentIds?: string[];
|
|
673
|
+
}
|
|
674
|
+
interface UpdateTeamInput {
|
|
675
|
+
name?: string;
|
|
676
|
+
slug?: string;
|
|
677
|
+
description?: string | null;
|
|
678
|
+
}
|
|
679
|
+
declare const POLICY_SCOPES: readonly ["org", "team", "agent", "channel"];
|
|
680
|
+
/** Precedence: org < team < agent < channel, merged key by key. */
|
|
681
|
+
type PolicyScope = (typeof POLICY_SCOPES)[number];
|
|
682
|
+
/** A policy's rules. Every key is optional; a key left out inherits. */
|
|
683
|
+
interface AgentPolicyRules {
|
|
684
|
+
/** Channels it may post in (null: any it's a member of). */
|
|
685
|
+
post_channel_ids?: string[] | null;
|
|
686
|
+
read_channel_ids?: string[] | null;
|
|
687
|
+
direct_messages?: {
|
|
688
|
+
default: 'allow' | 'deny';
|
|
689
|
+
allow_agent_ids?: string[];
|
|
690
|
+
} | null;
|
|
691
|
+
can_ask_humans?: boolean;
|
|
692
|
+
max_ask_urgency?: QuestionUrgency;
|
|
693
|
+
approval_rules?: Array<{
|
|
694
|
+
min_amount: number;
|
|
695
|
+
currency?: string;
|
|
696
|
+
required_roles: string[];
|
|
697
|
+
}> | null;
|
|
698
|
+
rate_per_minute?: number | null;
|
|
699
|
+
daily_message_budget?: number | null;
|
|
700
|
+
monthly_event_budget?: number | null;
|
|
701
|
+
working_hours?: {
|
|
702
|
+
/** IANA time zone. */
|
|
703
|
+
timezone: string;
|
|
704
|
+
/** 0 = Sunday; empty: every day. */
|
|
705
|
+
days: number[];
|
|
706
|
+
/** HH:MM */
|
|
707
|
+
start: string;
|
|
708
|
+
/** HH:MM */
|
|
709
|
+
end: string;
|
|
710
|
+
/** `queue` holds messages; `owner_if_urgent` also tells the owner about urgent ones. */
|
|
711
|
+
out_of_hours: 'queue' | 'owner_if_urgent';
|
|
712
|
+
} | null;
|
|
713
|
+
max_thread_depth?: number | null;
|
|
714
|
+
humans_win_minutes?: number | null;
|
|
715
|
+
}
|
|
716
|
+
interface AgentPolicy {
|
|
717
|
+
id: string;
|
|
718
|
+
scope: PolicyScope;
|
|
719
|
+
scope_id: string;
|
|
720
|
+
rules: AgentPolicyRules;
|
|
721
|
+
enabled: boolean;
|
|
722
|
+
created_by: string | null;
|
|
723
|
+
updated_by: string | null;
|
|
724
|
+
created_at: string;
|
|
725
|
+
updated_at: string;
|
|
726
|
+
}
|
|
727
|
+
interface PutPolicyInput {
|
|
728
|
+
scope: PolicyScope;
|
|
729
|
+
/** The team, agent or channel id; leave out for `org`. */
|
|
730
|
+
scopeId?: string;
|
|
731
|
+
rules: AgentPolicyRules;
|
|
732
|
+
enabled?: boolean;
|
|
733
|
+
}
|
|
734
|
+
interface PolicySource {
|
|
735
|
+
id: string;
|
|
736
|
+
scope: PolicyScope;
|
|
737
|
+
scope_id: string;
|
|
738
|
+
}
|
|
739
|
+
/** A policy check: allowed, or the refusal it would be. */
|
|
740
|
+
type PolicyCheck = {
|
|
741
|
+
allow: true;
|
|
742
|
+
} | {
|
|
743
|
+
allow: false;
|
|
744
|
+
code: string;
|
|
745
|
+
message: string;
|
|
746
|
+
retryAt?: string;
|
|
747
|
+
status?: number;
|
|
748
|
+
};
|
|
749
|
+
/** `agents.policies.preview`: the policy in force for an agent (in a channel). */
|
|
750
|
+
interface EffectivePolicyPreview {
|
|
751
|
+
agent_id: string;
|
|
752
|
+
channel_id: string | null;
|
|
753
|
+
/** Every key resolved (defaults included). */
|
|
754
|
+
rules: Required<AgentPolicyRules>;
|
|
755
|
+
/** The policies merged, lowest precedence first. */
|
|
756
|
+
sources: PolicySource[];
|
|
757
|
+
/** Which policy set each key (null: the default). */
|
|
758
|
+
set_by: Record<string, PolicySource | null>;
|
|
759
|
+
/** False when loading failed and the defaults were used. */
|
|
760
|
+
loaded: boolean;
|
|
761
|
+
working_hours: {
|
|
762
|
+
configured: boolean;
|
|
763
|
+
within: boolean;
|
|
764
|
+
/** When the next window opens (outside working hours). */
|
|
765
|
+
next_start: string | null;
|
|
766
|
+
};
|
|
767
|
+
usage: {
|
|
768
|
+
rate_per_minute: {
|
|
769
|
+
limit: number;
|
|
770
|
+
used: number | null;
|
|
771
|
+
} | null;
|
|
772
|
+
daily_messages: {
|
|
773
|
+
budget: number;
|
|
774
|
+
used: number | null;
|
|
775
|
+
resets_at: string;
|
|
776
|
+
} | null;
|
|
777
|
+
monthly_events: {
|
|
778
|
+
budget: number;
|
|
779
|
+
used: number | null;
|
|
780
|
+
pool: unknown;
|
|
781
|
+
resets_at: string;
|
|
782
|
+
} | null;
|
|
783
|
+
};
|
|
784
|
+
/** With a channel: whether it may post and read there now. */
|
|
785
|
+
checks: {
|
|
786
|
+
send: PolicyCheck;
|
|
787
|
+
read: PolicyCheck;
|
|
788
|
+
} | null;
|
|
789
|
+
}
|
|
790
|
+
interface OrgChartAgent {
|
|
791
|
+
id: string;
|
|
792
|
+
slug: string;
|
|
793
|
+
name: string;
|
|
794
|
+
status: Agent['status'];
|
|
795
|
+
role: string | null;
|
|
796
|
+
emoji: string | null;
|
|
797
|
+
avatar_url: string | null;
|
|
798
|
+
owner_user_id: string | null;
|
|
799
|
+
manager: {
|
|
800
|
+
type: 'agent' | 'user';
|
|
801
|
+
id: string;
|
|
802
|
+
} | null;
|
|
803
|
+
team_ids: string[];
|
|
804
|
+
}
|
|
805
|
+
interface OrgChartNode {
|
|
806
|
+
type: 'agent' | 'user';
|
|
807
|
+
id: string;
|
|
808
|
+
children: OrgChartNode[];
|
|
809
|
+
}
|
|
810
|
+
interface OrgChart {
|
|
811
|
+
agents: OrgChartAgent[];
|
|
812
|
+
users: Array<{
|
|
813
|
+
id: string;
|
|
814
|
+
name: string;
|
|
815
|
+
email: string;
|
|
816
|
+
}>;
|
|
817
|
+
teams: Array<{
|
|
818
|
+
id: string;
|
|
819
|
+
slug: string;
|
|
820
|
+
name: string;
|
|
821
|
+
agent_ids: string[];
|
|
822
|
+
}>;
|
|
823
|
+
tree: OrgChartNode[];
|
|
824
|
+
}
|
|
825
|
+
interface OrgChartOptions {
|
|
826
|
+
teamId?: string;
|
|
827
|
+
channelId?: string;
|
|
828
|
+
includeRetired?: boolean;
|
|
829
|
+
}
|
|
830
|
+
/** An agent's manager: an agent or a person, never both; `{}` clears it. */
|
|
831
|
+
type SetManagerInput = {
|
|
832
|
+
managerAgentId: string;
|
|
833
|
+
managerUserId?: undefined;
|
|
834
|
+
} | {
|
|
835
|
+
managerUserId: string;
|
|
836
|
+
managerAgentId?: undefined;
|
|
837
|
+
} | {
|
|
838
|
+
managerAgentId?: null;
|
|
839
|
+
managerUserId?: null;
|
|
840
|
+
};
|
|
841
|
+
interface AgentOnboarding {
|
|
842
|
+
agent_id: string;
|
|
843
|
+
steps: Array<{
|
|
844
|
+
id: 'created' | 'key_issued' | 'in_channel' | 'test_message_sent' | 'delivery_working';
|
|
845
|
+
label: string;
|
|
846
|
+
done: boolean;
|
|
847
|
+
}>;
|
|
848
|
+
complete: boolean;
|
|
849
|
+
}
|
|
850
|
+
/** `agents.setStatus` result. */
|
|
851
|
+
interface AgentStatusResult {
|
|
852
|
+
agent: Agent;
|
|
853
|
+
previous_status: Agent['status'];
|
|
854
|
+
keys_revoked: number;
|
|
855
|
+
memberships_removed: number;
|
|
856
|
+
/** On a resume: the held deliveries released. */
|
|
857
|
+
released?: number;
|
|
858
|
+
}
|
|
859
|
+
/** The events a closed question is pushed to its asker as. */
|
|
860
|
+
type QuestionOutcomeEvent = 'question.answered' | 'question.expired' | 'question.canceled';
|
|
861
|
+
/**
|
|
862
|
+
* A closed question pushed to the agent that asked it, when the question
|
|
863
|
+
* has no channel (`X-Webhook-Event: question.answered`, ...). Questions in a
|
|
864
|
+
* channel come back as an `agent.message` in its thread instead, with the
|
|
865
|
+
* same `{ type, question, answer }` as `message.data` (see
|
|
866
|
+
* `isQuestionOutcomeMessage`).
|
|
867
|
+
*/
|
|
868
|
+
interface QuestionOutcomeWebhookPayload {
|
|
869
|
+
version: 1;
|
|
870
|
+
event: QuestionOutcomeEvent;
|
|
871
|
+
type: QuestionOutcomeEvent;
|
|
872
|
+
delivery_id: string;
|
|
873
|
+
/** The recipient. */
|
|
874
|
+
agent: {
|
|
875
|
+
id: string;
|
|
876
|
+
slug: string;
|
|
877
|
+
name: string;
|
|
878
|
+
};
|
|
879
|
+
question: AgentQuestion;
|
|
880
|
+
answer: QuestionAnswer | null;
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* A question escalated to its asker's manager agent
|
|
884
|
+
* (`X-Webhook-Event: question.escalated`). Answer it with
|
|
885
|
+
* `agents.questions.answer(question.id, …)` (`answer_url`).
|
|
886
|
+
*/
|
|
887
|
+
interface QuestionEscalatedWebhookPayload {
|
|
888
|
+
version: 1;
|
|
889
|
+
event: 'question.escalated';
|
|
890
|
+
type: 'question.escalated';
|
|
891
|
+
delivery_id: string;
|
|
892
|
+
agent: {
|
|
893
|
+
id: string;
|
|
894
|
+
slug: string;
|
|
895
|
+
name: string;
|
|
896
|
+
};
|
|
897
|
+
question: AgentQuestion;
|
|
898
|
+
asker: {
|
|
899
|
+
id: string;
|
|
900
|
+
slug: string;
|
|
901
|
+
name: string;
|
|
902
|
+
} | null;
|
|
903
|
+
answer_url: string;
|
|
904
|
+
}
|
|
905
|
+
/** Every body Channlize POSTs to a webhook agent. */
|
|
906
|
+
type AgentWebhookEvent = AgentWebhookPayload | QuestionOutcomeWebhookPayload | QuestionEscalatedWebhookPayload;
|
|
907
|
+
/** `message.data` of a question outcome in the question's thread. */
|
|
908
|
+
interface QuestionOutcomeData {
|
|
909
|
+
type: QuestionOutcomeEvent;
|
|
910
|
+
question: AgentQuestion;
|
|
911
|
+
answer: QuestionAnswer | null;
|
|
912
|
+
[key: string]: unknown;
|
|
913
|
+
}
|
|
914
|
+
/** `message.data.handoff` of the `status` message a handoff posts. */
|
|
915
|
+
interface TaskHandoffData {
|
|
916
|
+
handoff: {
|
|
917
|
+
from_agent_id: string | null;
|
|
918
|
+
to_agent_id: string;
|
|
919
|
+
reason: string | null;
|
|
920
|
+
};
|
|
921
|
+
[key: string]: unknown;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
/** Phases 2 and 3 of `AgentsClient`. */
|
|
925
|
+
interface AgentsGovernance {
|
|
926
|
+
/**
|
|
927
|
+
* Ask people a question, or for an approval (`agents:ask_human`). It is
|
|
928
|
+
* posted in Slack (the channel's linked channel, else the escalation
|
|
929
|
+
* channel) and escalates until someone answers or the deadline passes.
|
|
930
|
+
* One Event. Read the answer with `questions.wait`, or use `askAndWait`.
|
|
931
|
+
*/
|
|
932
|
+
ask(input: AskHumanInput): Promise<AgentQuestion>;
|
|
933
|
+
/**
|
|
934
|
+
* `ask`, then `questions.wait` in a loop until the question is answered,
|
|
935
|
+
* expired or canceled, or `timeoutMs` (default 10 minutes) runs out:
|
|
936
|
+
* then it resolves with `timedOut: true` and the open question. Network
|
|
937
|
+
* errors, 5xx and 429s are retried (after `Retry-After`) inside the
|
|
938
|
+
* timeout; others reject. `signal` rejects it with code `ABORTED`.
|
|
939
|
+
*/
|
|
940
|
+
askAndWait(input: AskHumanInput, options?: AskAndWaitOptions): Promise<AskAndWaitResult>;
|
|
941
|
+
questions: {
|
|
942
|
+
/** A question with its escalation steps (`agents:ask_human` or `agents:read`). */
|
|
943
|
+
get(questionId: string, options?: QuestionReadOptions): Promise<{
|
|
944
|
+
question: AgentQuestion;
|
|
945
|
+
escalations: QuestionEscalation[];
|
|
946
|
+
}>;
|
|
947
|
+
/** The agent's questions and those escalated to it, newest first. */
|
|
948
|
+
list(options?: ListQuestionsOptions): Promise<QuestionPage>;
|
|
949
|
+
/**
|
|
950
|
+
* One long-poll (at most 25 s): resolves as soon as the question closes,
|
|
951
|
+
* or with `timedOut: true` while it's still open.
|
|
952
|
+
*/
|
|
953
|
+
wait(questionId: string, options?: WaitQuestionOptions): Promise<WaitQuestionResult>;
|
|
954
|
+
/**
|
|
955
|
+
* Answer a question escalated to this agent (its asker's manager agent;
|
|
956
|
+
* `agents:send` or `agents:ask_human`). The first answer wins: later
|
|
957
|
+
* ones get `QuestionClosedError`. Approvals that ask for a role need a
|
|
958
|
+
* person (403 `APPROVAL_ROLE_REQUIRED`).
|
|
959
|
+
*/
|
|
960
|
+
answer(questionId: string, input: AnswerQuestionInput): Promise<AgentQuestion>;
|
|
961
|
+
/** Cancel one of the agent's own open questions (`agents:ask_human`). */
|
|
962
|
+
cancel(questionId: string, options?: QuestionReadOptions): Promise<AgentQuestion>;
|
|
963
|
+
};
|
|
964
|
+
tasks: {
|
|
965
|
+
/** Create a task, optionally assigned and with a due date (`agents:send`). */
|
|
966
|
+
create(input: CreateTaskInput): Promise<CreateTaskResult>;
|
|
967
|
+
/** Tasks, newest first (`agents:read`; keys bound to agents need `channelId`). */
|
|
968
|
+
list(options?: ListTasksOptions): Promise<AgentTask[]>;
|
|
969
|
+
/** A channel's board: tasks by column, counts and the agents on it. */
|
|
970
|
+
board(channelId: string, options?: TaskBoardOptions): Promise<TaskBoard>;
|
|
971
|
+
/** A task with its history. */
|
|
972
|
+
get(taskId: string, options?: {
|
|
973
|
+
agentId?: string;
|
|
974
|
+
}): Promise<TaskDetail>;
|
|
975
|
+
/**
|
|
976
|
+
* Move a task on the board, change its due date, with a note (the
|
|
977
|
+
* assignee or creator; `agents:send`). 409 `TASK_CLOSED` once closed.
|
|
978
|
+
*/
|
|
979
|
+
update(taskId: string, input: UpdateTaskInput): Promise<UpdateTaskResult>;
|
|
980
|
+
/** Hand a task to another member agent of its channel (`agents:send`). */
|
|
981
|
+
handoff(taskId: string, input: HandoffTaskInput): Promise<HandoffTaskResult>;
|
|
982
|
+
};
|
|
983
|
+
/** Teams (reads: `agents:read`; writes: an unbound `agents:admin` key). */
|
|
984
|
+
teams: {
|
|
985
|
+
list(): Promise<AgentTeam[]>;
|
|
986
|
+
get(teamId: string): Promise<AgentTeamDetail>;
|
|
987
|
+
create(input: CreateTeamInput): Promise<AgentTeam>;
|
|
988
|
+
update(teamId: string, input: UpdateTeamInput): Promise<AgentTeam>;
|
|
989
|
+
delete(teamId: string): Promise<{
|
|
990
|
+
memberships_removed: number;
|
|
991
|
+
}>;
|
|
992
|
+
addMember(teamId: string, agentId: string): Promise<{
|
|
993
|
+
member: unknown;
|
|
994
|
+
channels_granted: number;
|
|
995
|
+
}>;
|
|
996
|
+
removeMember(teamId: string, agentId: string): Promise<{
|
|
997
|
+
memberships_removed: number;
|
|
998
|
+
}>;
|
|
999
|
+
grantChannel(teamId: string, channelId: string, role?: AgentMemberRole): Promise<{
|
|
1000
|
+
grant: AgentTeamChannelGrant;
|
|
1001
|
+
memberships_added: number;
|
|
1002
|
+
}>;
|
|
1003
|
+
revokeChannel(teamId: string, channelId: string): Promise<{
|
|
1004
|
+
memberships_removed: number;
|
|
1005
|
+
}>;
|
|
1006
|
+
};
|
|
1007
|
+
/** Policies (an unbound `agents:admin` key). */
|
|
1008
|
+
policies: {
|
|
1009
|
+
list(options?: {
|
|
1010
|
+
scope?: PolicyScope;
|
|
1011
|
+
}): Promise<AgentPolicy[]>;
|
|
1012
|
+
get(policyId: string): Promise<AgentPolicy>;
|
|
1013
|
+
/** Create or replace the policy of a scope. */
|
|
1014
|
+
put(input: PutPolicyInput): Promise<AgentPolicy>;
|
|
1015
|
+
delete(policyId: string): Promise<void>;
|
|
1016
|
+
/** The effective policy of an agent (in a channel): rules, sources, usage and checks. */
|
|
1017
|
+
preview(agentId: string, options?: {
|
|
1018
|
+
channelId?: string;
|
|
1019
|
+
}): Promise<EffectivePolicyPreview>;
|
|
1020
|
+
};
|
|
1021
|
+
orgChart: {
|
|
1022
|
+
/** The org chart (`agents:read`). */
|
|
1023
|
+
get(options?: OrgChartOptions): Promise<OrgChart>;
|
|
1024
|
+
/** Set or clear an agent's manager (`agents:admin`). 409 `ORG_CHART_CYCLE`. */
|
|
1025
|
+
setManager(agentId: string, input: SetManagerInput): Promise<Agent>;
|
|
1026
|
+
/** Set or clear an agent's owner, a person (`agents:admin`). */
|
|
1027
|
+
setOwner(agentId: string, ownerUserId: string | null): Promise<Agent>;
|
|
1028
|
+
};
|
|
1029
|
+
/** An agent's onboarding checklist (`agents:admin`). */
|
|
1030
|
+
onboarding(agentId: string): Promise<AgentOnboarding>;
|
|
1031
|
+
/**
|
|
1032
|
+
* Pause (with a reason), resume or retire an agent (`agents:admin`).
|
|
1033
|
+
* Resuming releases its held deliveries, oldest first.
|
|
1034
|
+
*/
|
|
1035
|
+
setStatus(agentId: string, status: AgentStatus, options?: {
|
|
1036
|
+
reason?: string;
|
|
1037
|
+
}): Promise<AgentStatusResult>;
|
|
1038
|
+
}
|
|
1039
|
+
/** An `agent.message` delivery (a channel message, task or status). */
|
|
1040
|
+
declare function isAgentMessageWebhook(payload: AgentWebhookEvent | null | undefined): payload is AgentWebhookPayload;
|
|
1041
|
+
/** A closed question pushed to its asker (`question.answered` / `expired` / `canceled`). */
|
|
1042
|
+
declare function isQuestionOutcomeWebhook(payload: AgentWebhookEvent | null | undefined): payload is QuestionOutcomeWebhookPayload;
|
|
1043
|
+
/** A question escalated to this (manager) agent: answer it with `questions.answer`. */
|
|
1044
|
+
declare function isQuestionEscalatedWebhook(payload: AgentWebhookEvent | null | undefined): payload is QuestionEscalatedWebhookPayload;
|
|
1045
|
+
/**
|
|
1046
|
+
* A question's outcome posted in its thread (questions asked with a
|
|
1047
|
+
* `channelId`): `message.data` is `{ type, question, answer }`.
|
|
1048
|
+
*/
|
|
1049
|
+
declare function isQuestionOutcomeMessage(message: AgentMessage | null | undefined): message is AgentMessage & {
|
|
1050
|
+
data: QuestionOutcomeData;
|
|
1051
|
+
};
|
|
1052
|
+
/**
|
|
1053
|
+
* The `status` message a task handoff posts (delivered to the previous and
|
|
1054
|
+
* new assignees): `message.data.handoff` says who to whom, and why.
|
|
1055
|
+
*/
|
|
1056
|
+
declare function isTaskHandoffMessage(message: AgentMessage | null | undefined): message is AgentMessage & {
|
|
1057
|
+
data: TaskHandoffData;
|
|
1058
|
+
};
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* Types for Channlize for Agents, Phase 4 (deeper observability): the
|
|
1062
|
+
* insights (communication graph, edge threads, cost, response metrics),
|
|
1063
|
+
* full-text search, CSV / JSON exports and the telemetry sinks
|
|
1064
|
+
* (OpenTelemetry and the signed activity webhook).
|
|
1065
|
+
*
|
|
1066
|
+
* Response DTOs mirror the API (`/v1/agents/insights/*`, `/v1/agents/search`,
|
|
1067
|
+
* `/v1/agents/export`, `/v1/agents/telemetry/*`), field for field, in
|
|
1068
|
+
* snake_case. Options are camelCase.
|
|
1069
|
+
*/
|
|
1070
|
+
|
|
1071
|
+
/** A UTC day, `YYYY-MM-DD`; a `Date` is sent as its UTC day. */
|
|
1072
|
+
type InsightsDay = string | Date;
|
|
1073
|
+
/**
|
|
1074
|
+
* The range an insights response covers: `from` / `to` (UTC days,
|
|
1075
|
+
* inclusive) after the defaults (the last 30 days), the cap at today and the
|
|
1076
|
+
* plan's history window.
|
|
1077
|
+
*/
|
|
1078
|
+
interface InsightsRange {
|
|
1079
|
+
from: string;
|
|
1080
|
+
to: string;
|
|
1081
|
+
days: number;
|
|
1082
|
+
/** The plan's `log_retention_days`. */
|
|
1083
|
+
retention_days: number;
|
|
1084
|
+
/** The first day the plan shows. */
|
|
1085
|
+
history_start: string;
|
|
1086
|
+
/** `from` was moved forward to `history_start`. */
|
|
1087
|
+
clamped: boolean;
|
|
1088
|
+
/** No visible day in the range (it ends before `history_start`). */
|
|
1089
|
+
empty: boolean;
|
|
1090
|
+
/** Days read from the nightly rollup, and days computed live. */
|
|
1091
|
+
rolled_days: number;
|
|
1092
|
+
live_days: number;
|
|
1093
|
+
}
|
|
1094
|
+
/** Latencies; the numbers are null when `count` is 0. */
|
|
1095
|
+
interface LatencyStats {
|
|
1096
|
+
count: number;
|
|
1097
|
+
avg_ms: number | null;
|
|
1098
|
+
/** Estimated from 17 latency buckets. */
|
|
1099
|
+
p50_ms: number | null;
|
|
1100
|
+
p90_ms: number | null;
|
|
1101
|
+
}
|
|
1102
|
+
/** Filters every insights endpoint takes. */
|
|
1103
|
+
interface InsightsFilters {
|
|
1104
|
+
/** First UTC day (default: 30 days before `to`). */
|
|
1105
|
+
from?: InsightsDay;
|
|
1106
|
+
/** Last UTC day, inclusive (default: today). */
|
|
1107
|
+
to?: InsightsDay;
|
|
1108
|
+
channelId?: string;
|
|
1109
|
+
/** Edges touching this agent (graph), what it sent (cost), its metrics. */
|
|
1110
|
+
agentId?: string;
|
|
1111
|
+
}
|
|
1112
|
+
type InsightsNodeKind = 'agent' | 'user' | 'slack_user' | 'deleted' | 'other';
|
|
1113
|
+
/** A node id: `agent:<id>`, `user:<id>`, `slack_user:<slack id>`, `deleted:deleted` or `other:other`. */
|
|
1114
|
+
type InsightsNodeId = string;
|
|
1115
|
+
interface InsightsNode {
|
|
1116
|
+
id: InsightsNodeId;
|
|
1117
|
+
kind: InsightsNodeKind;
|
|
1118
|
+
/** The agent / user id, the Slack user id; null for `deleted` and `other`. */
|
|
1119
|
+
ref_id: string | null;
|
|
1120
|
+
label: string;
|
|
1121
|
+
slug: string | null;
|
|
1122
|
+
emoji: string | null;
|
|
1123
|
+
avatar_url: string | null;
|
|
1124
|
+
/** Agents: active | paused | retired. */
|
|
1125
|
+
status: AgentStatus | null;
|
|
1126
|
+
sent: number;
|
|
1127
|
+
received: number;
|
|
1128
|
+
tokens: number;
|
|
1129
|
+
cost: number;
|
|
1130
|
+
}
|
|
1131
|
+
/** A directed sender → recipient edge. */
|
|
1132
|
+
interface InsightsEdge {
|
|
1133
|
+
/** `<source>|<target>`. */
|
|
1134
|
+
id: string;
|
|
1135
|
+
source: InsightsNodeId;
|
|
1136
|
+
target: InsightsNodeId;
|
|
1137
|
+
messages: number;
|
|
1138
|
+
tokens: number;
|
|
1139
|
+
cost: number;
|
|
1140
|
+
/** Messages the target replied to (same thread, within 24 h). */
|
|
1141
|
+
replies: number;
|
|
1142
|
+
reply_latency: LatencyStats;
|
|
1143
|
+
last_at: string | null;
|
|
1144
|
+
}
|
|
1145
|
+
interface InsightsGraphFilters extends InsightsFilters {
|
|
1146
|
+
/** Edges with one of the team's agents at either end. */
|
|
1147
|
+
teamId?: string;
|
|
1148
|
+
/** Nodes kept (default 50, max 200); the rest fold into `other:other`. */
|
|
1149
|
+
limit?: number;
|
|
1150
|
+
/** Edges kept (default 300, max 1000). */
|
|
1151
|
+
edgeLimit?: number;
|
|
1152
|
+
}
|
|
1153
|
+
interface InsightsGraph {
|
|
1154
|
+
range: InsightsRange;
|
|
1155
|
+
nodes: InsightsNode[];
|
|
1156
|
+
edges: InsightsEdge[];
|
|
1157
|
+
/** Before the cap. */
|
|
1158
|
+
totals: {
|
|
1159
|
+
nodes: number;
|
|
1160
|
+
edges: number;
|
|
1161
|
+
messages: number;
|
|
1162
|
+
tokens: number;
|
|
1163
|
+
cost: number;
|
|
1164
|
+
};
|
|
1165
|
+
/** Nodes folded into `other:other`, edges dropped. */
|
|
1166
|
+
truncated: {
|
|
1167
|
+
nodes: number;
|
|
1168
|
+
edges: number;
|
|
1169
|
+
};
|
|
1170
|
+
limits: {
|
|
1171
|
+
nodes: number;
|
|
1172
|
+
edges: number;
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1175
|
+
type InsightsNodeRef = Pick<InsightsNode, 'id' | 'kind' | 'ref_id' | 'label' | 'slug' | 'emoji' | 'avatar_url'>;
|
|
1176
|
+
interface InsightsEdgeThread {
|
|
1177
|
+
thread_id: string;
|
|
1178
|
+
channel: {
|
|
1179
|
+
id: string;
|
|
1180
|
+
name: string | null;
|
|
1181
|
+
slug: string | null;
|
|
1182
|
+
};
|
|
1183
|
+
root: {
|
|
1184
|
+
id: string;
|
|
1185
|
+
type: AgentMessageType;
|
|
1186
|
+
/** At most 280 characters. */
|
|
1187
|
+
text: string;
|
|
1188
|
+
slack_ts: string | null;
|
|
1189
|
+
created_at: string;
|
|
1190
|
+
} | null;
|
|
1191
|
+
messages: number;
|
|
1192
|
+
tokens: number;
|
|
1193
|
+
cost: number;
|
|
1194
|
+
replies: number;
|
|
1195
|
+
reply_latency: {
|
|
1196
|
+
count: number;
|
|
1197
|
+
avg_ms: number | null;
|
|
1198
|
+
};
|
|
1199
|
+
first_at: string;
|
|
1200
|
+
last_at: string;
|
|
1201
|
+
}
|
|
1202
|
+
interface InsightsEdgeOptions {
|
|
1203
|
+
from?: InsightsDay;
|
|
1204
|
+
to?: InsightsDay;
|
|
1205
|
+
channelId?: string;
|
|
1206
|
+
/** `nextCursor` of the previous page. */
|
|
1207
|
+
cursor?: string;
|
|
1208
|
+
/** 1-100, default 25. */
|
|
1209
|
+
limit?: number;
|
|
1210
|
+
}
|
|
1211
|
+
/** The threads behind one edge, newest activity first. */
|
|
1212
|
+
interface InsightsEdgePage {
|
|
1213
|
+
range: InsightsRange;
|
|
1214
|
+
source: InsightsNodeRef;
|
|
1215
|
+
target: InsightsNodeRef;
|
|
1216
|
+
threads: InsightsEdgeThread[];
|
|
1217
|
+
nextCursor: string | null;
|
|
1218
|
+
}
|
|
1219
|
+
declare const COST_GROUPINGS: readonly ["agent", "channel", "team", "task", "day"];
|
|
1220
|
+
type CostGrouping = (typeof COST_GROUPINGS)[number];
|
|
1221
|
+
interface InsightsCostOptions extends InsightsFilters {
|
|
1222
|
+
/** Default `agent`. */
|
|
1223
|
+
groupBy?: CostGrouping;
|
|
1224
|
+
teamId?: string;
|
|
1225
|
+
/** Groups returned (default 50, max 200). */
|
|
1226
|
+
limit?: number;
|
|
1227
|
+
}
|
|
1228
|
+
interface CostTotals {
|
|
1229
|
+
messages: number;
|
|
1230
|
+
/** Messages that reported tokens or cost. */
|
|
1231
|
+
priced_messages: number;
|
|
1232
|
+
tokens: number;
|
|
1233
|
+
cost: number;
|
|
1234
|
+
}
|
|
1235
|
+
interface CostGroup {
|
|
1236
|
+
/** The agent / channel / team / task id, or the day. */
|
|
1237
|
+
key: string;
|
|
1238
|
+
label: string;
|
|
1239
|
+
messages: number;
|
|
1240
|
+
tokens: number;
|
|
1241
|
+
cost: number;
|
|
1242
|
+
/** Share of `totals.cost` (0..1); null when the total is 0. */
|
|
1243
|
+
share: number | null;
|
|
1244
|
+
agent?: {
|
|
1245
|
+
id: string;
|
|
1246
|
+
slug: string | null;
|
|
1247
|
+
status: AgentStatus | null;
|
|
1248
|
+
};
|
|
1249
|
+
channel?: {
|
|
1250
|
+
id: string;
|
|
1251
|
+
slug: string | null;
|
|
1252
|
+
archived: boolean;
|
|
1253
|
+
};
|
|
1254
|
+
team?: {
|
|
1255
|
+
id: string;
|
|
1256
|
+
slug: string | null;
|
|
1257
|
+
};
|
|
1258
|
+
task?: {
|
|
1259
|
+
id: string;
|
|
1260
|
+
channel_id: string | null;
|
|
1261
|
+
status: string | null;
|
|
1262
|
+
assignee_agent_id: string | null;
|
|
1263
|
+
created_at: string | null;
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
interface CostSeriesPoint {
|
|
1267
|
+
day: string;
|
|
1268
|
+
messages: number;
|
|
1269
|
+
tokens: number;
|
|
1270
|
+
cost: number;
|
|
1271
|
+
/** Cost per `series_keys` group, plus `other` (not for teams, which overlap). */
|
|
1272
|
+
groups: Record<string, number>;
|
|
1273
|
+
}
|
|
1274
|
+
interface InsightsCost {
|
|
1275
|
+
range: InsightsRange;
|
|
1276
|
+
group_by: CostGrouping;
|
|
1277
|
+
/** The whole range with the filters. */
|
|
1278
|
+
totals: CostTotals;
|
|
1279
|
+
/** Sorted by cost (days by date). */
|
|
1280
|
+
groups: CostGroup[];
|
|
1281
|
+
/** Every day of the range. */
|
|
1282
|
+
series: CostSeriesPoint[];
|
|
1283
|
+
/** The top 8 groups broken out in `series`. */
|
|
1284
|
+
series_keys: string[];
|
|
1285
|
+
/** More groups than `limit`. */
|
|
1286
|
+
truncated: boolean;
|
|
1287
|
+
}
|
|
1288
|
+
interface ReplyPairMetrics {
|
|
1289
|
+
messages: number;
|
|
1290
|
+
replied: number;
|
|
1291
|
+
reply_rate: number | null;
|
|
1292
|
+
latency: LatencyStats;
|
|
1293
|
+
}
|
|
1294
|
+
interface QuestionMetrics {
|
|
1295
|
+
asked: number;
|
|
1296
|
+
answered: number;
|
|
1297
|
+
answered_by_user: number;
|
|
1298
|
+
answered_by_agent: number;
|
|
1299
|
+
expired: number;
|
|
1300
|
+
expired_default: number;
|
|
1301
|
+
canceled: number;
|
|
1302
|
+
closed: number;
|
|
1303
|
+
answer_rate: number | null;
|
|
1304
|
+
expired_rate: number | null;
|
|
1305
|
+
default_rate: number | null;
|
|
1306
|
+
cancel_rate: number | null;
|
|
1307
|
+
time_to_human_answer: LatencyStats;
|
|
1308
|
+
}
|
|
1309
|
+
interface DeliveryModeMetrics {
|
|
1310
|
+
deliveries: number;
|
|
1311
|
+
delivered: number;
|
|
1312
|
+
inbox: number;
|
|
1313
|
+
pending: number;
|
|
1314
|
+
failed: number;
|
|
1315
|
+
held: number;
|
|
1316
|
+
skipped: number;
|
|
1317
|
+
retried: number;
|
|
1318
|
+
acked: number;
|
|
1319
|
+
failure_rate: number | null;
|
|
1320
|
+
retry_rate: number | null;
|
|
1321
|
+
avg_attempts: number | null;
|
|
1322
|
+
}
|
|
1323
|
+
interface BacklogAgent {
|
|
1324
|
+
agent_id: string;
|
|
1325
|
+
name: string;
|
|
1326
|
+
slug: string;
|
|
1327
|
+
delivery: AgentDeliveryMode;
|
|
1328
|
+
unacked: number;
|
|
1329
|
+
held: number;
|
|
1330
|
+
oldest_unacked_at: string | null;
|
|
1331
|
+
oldest_age_seconds: number | null;
|
|
1332
|
+
}
|
|
1333
|
+
interface InsightsMetrics {
|
|
1334
|
+
range: InsightsRange;
|
|
1335
|
+
replies: {
|
|
1336
|
+
agent_to_agent: ReplyPairMetrics;
|
|
1337
|
+
human_to_agent: ReplyPairMetrics;
|
|
1338
|
+
agent_to_human: ReplyPairMetrics;
|
|
1339
|
+
/** As the responder, busiest first (at most 50). */
|
|
1340
|
+
by_agent: Array<{
|
|
1341
|
+
agent_id: string;
|
|
1342
|
+
name: string | null;
|
|
1343
|
+
slug: string | null;
|
|
1344
|
+
messages: number;
|
|
1345
|
+
replied: number;
|
|
1346
|
+
latency: LatencyStats;
|
|
1347
|
+
}>;
|
|
1348
|
+
};
|
|
1349
|
+
questions: QuestionMetrics & {
|
|
1350
|
+
by_urgency: Record<'low' | 'normal' | 'high' | 'urgent', QuestionMetrics>;
|
|
1351
|
+
by_kind: Record<'question' | 'approval', QuestionMetrics>;
|
|
1352
|
+
};
|
|
1353
|
+
deliveries: {
|
|
1354
|
+
deliveries: number;
|
|
1355
|
+
failed: number;
|
|
1356
|
+
retried: number;
|
|
1357
|
+
failure_rate: number | null;
|
|
1358
|
+
retry_rate: number | null;
|
|
1359
|
+
by_mode: Record<AgentDeliveryMode, DeliveryModeMetrics>;
|
|
1360
|
+
};
|
|
1361
|
+
/** Right now, whatever the range. */
|
|
1362
|
+
backlog: {
|
|
1363
|
+
as_of: string;
|
|
1364
|
+
unacked: number;
|
|
1365
|
+
held: number;
|
|
1366
|
+
agents_with_backlog: number;
|
|
1367
|
+
/** At most 50. */
|
|
1368
|
+
agents: BacklogAgent[];
|
|
1369
|
+
};
|
|
1370
|
+
held: number;
|
|
1371
|
+
}
|
|
1372
|
+
type AgentSearchInclude = 'messages' | 'questions';
|
|
1373
|
+
interface AgentSearchOptions {
|
|
1374
|
+
/** 2-200 characters; websearch syntax: `"exact phrase"`, `or`, `-word`. */
|
|
1375
|
+
q: string;
|
|
1376
|
+
/**
|
|
1377
|
+
* Messages sent by or mentioning the agent, questions it asked. With a key
|
|
1378
|
+
* bound to several agents it also picks whose channels are searched.
|
|
1379
|
+
*/
|
|
1380
|
+
agentId?: string;
|
|
1381
|
+
channelId?: string;
|
|
1382
|
+
type?: AgentMessageType;
|
|
1383
|
+
/** Default both. */
|
|
1384
|
+
include?: AgentSearchInclude | AgentSearchInclude[];
|
|
1385
|
+
/** ISO date-time (or a `Date`); clamped to the plan's history window. */
|
|
1386
|
+
from?: string | Date;
|
|
1387
|
+
to?: string | Date;
|
|
1388
|
+
/** `nextCursor` of the previous page. */
|
|
1389
|
+
cursor?: string;
|
|
1390
|
+
/** 1-50, default 20. */
|
|
1391
|
+
limit?: number;
|
|
1392
|
+
}
|
|
1393
|
+
interface AgentSearchChannelRef {
|
|
1394
|
+
id: string;
|
|
1395
|
+
slug: string;
|
|
1396
|
+
name: string;
|
|
1397
|
+
}
|
|
1398
|
+
type AgentSearchResult = {
|
|
1399
|
+
kind: 'message';
|
|
1400
|
+
message: AgentMessage;
|
|
1401
|
+
/** Safe HTML: an escaped snippet with the hits in `<mark>`. */
|
|
1402
|
+
highlight: string;
|
|
1403
|
+
/** 0..1, best first. */
|
|
1404
|
+
rank: number;
|
|
1405
|
+
channel: AgentSearchChannelRef;
|
|
1406
|
+
/** The thread root (the message's own id for a root). */
|
|
1407
|
+
thread_id: string;
|
|
1408
|
+
slack_permalink: string | null;
|
|
1409
|
+
} | {
|
|
1410
|
+
kind: 'question';
|
|
1411
|
+
question: AgentQuestion;
|
|
1412
|
+
highlight: string;
|
|
1413
|
+
rank: number;
|
|
1414
|
+
channel: AgentSearchChannelRef | null;
|
|
1415
|
+
thread_id: string | null;
|
|
1416
|
+
slack_permalink: string | null;
|
|
1417
|
+
};
|
|
1418
|
+
interface AgentSearchPage {
|
|
1419
|
+
results: AgentSearchResult[];
|
|
1420
|
+
nextCursor: string | null;
|
|
1421
|
+
/** The history window searched: its start and the plan's days. */
|
|
1422
|
+
window: {
|
|
1423
|
+
from: string;
|
|
1424
|
+
days: number;
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
interface AgentSearchAllOptions extends Omit<AgentSearchOptions, 'cursor'> {
|
|
1428
|
+
/** Stop after this many results (default: every page). */
|
|
1429
|
+
max?: number;
|
|
1430
|
+
}
|
|
1431
|
+
declare const AGENT_EXPORT_KINDS: readonly ["messages", "tasks", "questions", "audit"];
|
|
1432
|
+
type AgentExportKind = (typeof AGENT_EXPORT_KINDS)[number];
|
|
1433
|
+
declare const AGENT_EXPORT_FORMATS: readonly ["csv", "json"];
|
|
1434
|
+
type AgentExportFormat = (typeof AGENT_EXPORT_FORMATS)[number];
|
|
1435
|
+
/** Rows in a synchronous download; larger ranges go through `exports.start`. */
|
|
1436
|
+
declare const AGENT_EXPORT_SYNC_MAX_ROWS = 10000;
|
|
1437
|
+
/**
|
|
1438
|
+
* Export filters. `from`, `to` and `agentId` apply to every kind,
|
|
1439
|
+
* `channelId` to all but `audit`; the others to one kind each. A filter the
|
|
1440
|
+
* kind doesn't take is a 400.
|
|
1441
|
+
*/
|
|
1442
|
+
interface AgentExportFilters {
|
|
1443
|
+
/** ISO date-time (or a `Date`); clamped to the plan's history window. */
|
|
1444
|
+
from?: string | Date;
|
|
1445
|
+
to?: string | Date;
|
|
1446
|
+
agentId?: string;
|
|
1447
|
+
channelId?: string;
|
|
1448
|
+
/** `messages`. */
|
|
1449
|
+
threadId?: string;
|
|
1450
|
+
/** `messages`. */
|
|
1451
|
+
type?: AgentMessageType;
|
|
1452
|
+
/** `tasks`: task statuses; `questions`: question statuses. */
|
|
1453
|
+
status?: string | string[];
|
|
1454
|
+
/** `audit`: an action, exact or a namespace. */
|
|
1455
|
+
action?: string;
|
|
1456
|
+
/** `audit`. */
|
|
1457
|
+
actorType?: string;
|
|
1458
|
+
actorId?: string;
|
|
1459
|
+
targetType?: string;
|
|
1460
|
+
targetId?: string;
|
|
1461
|
+
}
|
|
1462
|
+
/** A synchronous download: the file and what the API said about it. */
|
|
1463
|
+
interface AgentExportDownload {
|
|
1464
|
+
/** The CSV text, or the JSON array as text (parse it with `JSON.parse`). */
|
|
1465
|
+
body: string;
|
|
1466
|
+
/** `X-Export-Rows`. */
|
|
1467
|
+
rows: number;
|
|
1468
|
+
/** `X-Export-Truncated`: more than `AGENT_EXPORT_SYNC_MAX_ROWS` rows matched. */
|
|
1469
|
+
truncated: boolean;
|
|
1470
|
+
contentType: string;
|
|
1471
|
+
/** From `Content-Disposition`, e.g. `agents-messages-2026-11-05.csv`. */
|
|
1472
|
+
filename: string | null;
|
|
1473
|
+
}
|
|
1474
|
+
type AgentExportStatus = 'queued' | 'running' | 'completed' | 'failed';
|
|
1475
|
+
interface AgentExport {
|
|
1476
|
+
id: string;
|
|
1477
|
+
kind: AgentExportKind;
|
|
1478
|
+
format: AgentExportFormat;
|
|
1479
|
+
/** As sent, snake_case. */
|
|
1480
|
+
filters: Record<string, unknown>;
|
|
1481
|
+
status: AgentExportStatus;
|
|
1482
|
+
rows: number;
|
|
1483
|
+
/** More than 1,000,000 rows matched. */
|
|
1484
|
+
truncated: boolean;
|
|
1485
|
+
bytes: number;
|
|
1486
|
+
error: string | null;
|
|
1487
|
+
requested_by: {
|
|
1488
|
+
user_id: string | null;
|
|
1489
|
+
api_key_id: string | null;
|
|
1490
|
+
};
|
|
1491
|
+
/** A signed link (24 h), once completed; `exports.get` signs a fresh one. */
|
|
1492
|
+
download: {
|
|
1493
|
+
url: string;
|
|
1494
|
+
expires_at: string;
|
|
1495
|
+
} | null;
|
|
1496
|
+
created_at: string;
|
|
1497
|
+
started_at: string | null;
|
|
1498
|
+
completed_at: string | null;
|
|
1499
|
+
}
|
|
1500
|
+
interface StartAgentExportInput {
|
|
1501
|
+
kind: AgentExportKind;
|
|
1502
|
+
/** Default `csv`. */
|
|
1503
|
+
format?: AgentExportFormat;
|
|
1504
|
+
filters?: AgentExportFilters;
|
|
1505
|
+
}
|
|
1506
|
+
interface StartAgentExportResult {
|
|
1507
|
+
exportId: string;
|
|
1508
|
+
status: AgentExportStatus;
|
|
1509
|
+
export: AgentExport;
|
|
1510
|
+
}
|
|
1511
|
+
/** A `messages` row of the JSON export (and of the telemetry webhook). */
|
|
1512
|
+
interface AgentExportMessageRow extends AgentMessage {
|
|
1513
|
+
channel: {
|
|
1514
|
+
id: string;
|
|
1515
|
+
slug: string | null;
|
|
1516
|
+
};
|
|
1517
|
+
sender_agent: {
|
|
1518
|
+
slug: string;
|
|
1519
|
+
name: string;
|
|
1520
|
+
} | null;
|
|
1521
|
+
}
|
|
1522
|
+
/** A `tasks` row. */
|
|
1523
|
+
interface AgentExportTaskRow extends AgentTask {
|
|
1524
|
+
channel: {
|
|
1525
|
+
id: string;
|
|
1526
|
+
slug: string | null;
|
|
1527
|
+
};
|
|
1528
|
+
assignee: {
|
|
1529
|
+
slug: string;
|
|
1530
|
+
name: string;
|
|
1531
|
+
} | null;
|
|
1532
|
+
events: AgentTaskEvent[];
|
|
1533
|
+
}
|
|
1534
|
+
/** A `questions` row. */
|
|
1535
|
+
interface AgentExportQuestionRow extends AgentQuestion {
|
|
1536
|
+
channel: {
|
|
1537
|
+
id: string;
|
|
1538
|
+
slug: string | null;
|
|
1539
|
+
} | null;
|
|
1540
|
+
agent: {
|
|
1541
|
+
slug: string;
|
|
1542
|
+
name: string;
|
|
1543
|
+
} | null;
|
|
1544
|
+
}
|
|
1545
|
+
interface TelemetrySinkStatus {
|
|
1546
|
+
last_run_at: string | null;
|
|
1547
|
+
last_success_at: string | null;
|
|
1548
|
+
last_error: string | null;
|
|
1549
|
+
last_error_at: string | null;
|
|
1550
|
+
consecutive_failures: number;
|
|
1551
|
+
items_sent: number;
|
|
1552
|
+
/** `failing`: the last run failed; `idle`: never ran. */
|
|
1553
|
+
health: 'ok' | 'failing' | 'idle' | 'disabled';
|
|
1554
|
+
}
|
|
1555
|
+
interface OtelSink {
|
|
1556
|
+
enabled: boolean;
|
|
1557
|
+
/** The OTLP/HTTP traces URL. */
|
|
1558
|
+
endpoint_url: string | null;
|
|
1559
|
+
protocol: 'http/json';
|
|
1560
|
+
/** Header values are write-only: only their names come back. */
|
|
1561
|
+
header_names: string[];
|
|
1562
|
+
headers_configured: boolean;
|
|
1563
|
+
status: TelemetrySinkStatus;
|
|
1564
|
+
updated_at: string | null;
|
|
1565
|
+
}
|
|
1566
|
+
interface SetOtelSinkInput {
|
|
1567
|
+
enabled?: boolean;
|
|
1568
|
+
/** An OTLP/HTTP traces URL; a bare origin gets `/v1/traces`. null clears it. */
|
|
1569
|
+
endpointUrl?: string | null;
|
|
1570
|
+
/**
|
|
1571
|
+
* Sent with every export (`Authorization`, `x-honeycomb-team`,
|
|
1572
|
+
* `DD-API-KEY`, at most 10). Replaces them all; null clears them; leave it
|
|
1573
|
+
* out to keep them.
|
|
1574
|
+
*/
|
|
1575
|
+
headers?: Record<string, string> | null;
|
|
1576
|
+
}
|
|
1577
|
+
interface WebhookSink {
|
|
1578
|
+
enabled: boolean;
|
|
1579
|
+
url: string | null;
|
|
1580
|
+
secret_configured: boolean;
|
|
1581
|
+
status: TelemetrySinkStatus;
|
|
1582
|
+
updated_at: string | null;
|
|
1583
|
+
}
|
|
1584
|
+
interface SetWebhookSinkInput {
|
|
1585
|
+
enabled?: boolean;
|
|
1586
|
+
url?: string | null;
|
|
1587
|
+
/** Generate a new signing secret (returned once). */
|
|
1588
|
+
rotateSecret?: boolean;
|
|
1589
|
+
}
|
|
1590
|
+
interface SetWebhookSinkResult {
|
|
1591
|
+
webhook: WebhookSink;
|
|
1592
|
+
/** The `whsec_…` signing secret: only on the first save with a URL or a rotation. Store it now. */
|
|
1593
|
+
secret?: string;
|
|
1594
|
+
}
|
|
1595
|
+
interface TelemetryTestResult {
|
|
1596
|
+
ok: boolean;
|
|
1597
|
+
/** The endpoint's HTTP status. */
|
|
1598
|
+
status?: number;
|
|
1599
|
+
error?: string;
|
|
1600
|
+
/** OpenTelemetry: the test span's trace id. */
|
|
1601
|
+
trace_id?: string;
|
|
1602
|
+
}
|
|
1603
|
+
/** `X-Webhook-Event` of a telemetry batch. */
|
|
1604
|
+
type TelemetryWebhookEvent = 'agent.activity' | 'agent.test';
|
|
1605
|
+
/**
|
|
1606
|
+
* The body of a telemetry webhook batch (`version: 1`): the rows of the
|
|
1607
|
+
* JSON export. `agent.test` batches are empty.
|
|
1608
|
+
*/
|
|
1609
|
+
interface TelemetryWebhookBatch {
|
|
1610
|
+
version: 1;
|
|
1611
|
+
event: TelemetryWebhookEvent;
|
|
1612
|
+
/** `X-Webhook-Delivery-ID`; the same when a batch is retried. */
|
|
1613
|
+
batch_id: string;
|
|
1614
|
+
organization_id: string;
|
|
1615
|
+
sent_at: string;
|
|
1616
|
+
messages: AgentExportMessageRow[];
|
|
1617
|
+
/** Tasks closed in this batch, with their history. */
|
|
1618
|
+
tasks: AgentExportTaskRow[];
|
|
1619
|
+
task_events: Array<AgentTaskEvent & {
|
|
1620
|
+
task_id: string;
|
|
1621
|
+
}>;
|
|
1622
|
+
/** Questions closed (answered, expired, canceled) in this batch. */
|
|
1623
|
+
questions: Array<AgentExportQuestionRow & {
|
|
1624
|
+
status: QuestionStatus;
|
|
1625
|
+
}>;
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1
1628
|
/**
|
|
2
1629
|
* Helpers shared by `@channlize/core`, `@channlize/react` and
|
|
3
1630
|
* `@channlize/mcp`: defaults, key detection, environment variables, event
|
|
@@ -37,6 +1664,8 @@ interface ChannlizeEnv {
|
|
|
37
1664
|
baseUrl?: string;
|
|
38
1665
|
/** `CHANNLIZE_TIMEOUT` (milliseconds, unparsed) */
|
|
39
1666
|
timeout?: string;
|
|
1667
|
+
/** `CHANNLIZE_AGENT_ID` (Channlize for Agents: the agent to act as) */
|
|
1668
|
+
agentId?: string;
|
|
40
1669
|
}
|
|
41
1670
|
/**
|
|
42
1671
|
* Reads the `CHANNLIZE_*` environment variables. Safe in browsers and edge
|
|
@@ -271,6 +1900,12 @@ declare class ChannlizeError extends Error {
|
|
|
271
1900
|
* `upgradeUrl` on a plan-limit 429. Undefined for network errors.
|
|
272
1901
|
*/
|
|
273
1902
|
details?: Record<string, unknown>;
|
|
1903
|
+
/**
|
|
1904
|
+
* ISO time the call may succeed again: the body's `retryAt` (agent
|
|
1905
|
+
* policies, human takeovers), else derived from a `Retry-After` header.
|
|
1906
|
+
* See `retryAfter(error)`.
|
|
1907
|
+
*/
|
|
1908
|
+
retryAt?: string;
|
|
274
1909
|
constructor(message: string, statusCode?: number | undefined, code?: string | undefined);
|
|
275
1910
|
}
|
|
276
1911
|
declare class ValidationError extends ChannlizeError {
|
|
@@ -301,6 +1936,202 @@ interface TrackEventResult {
|
|
|
301
1936
|
dropped?: 'plan_limit' | 'rate_limit';
|
|
302
1937
|
}
|
|
303
1938
|
|
|
1939
|
+
/**
|
|
1940
|
+
* Channlize for Agents, Phase 4 on the agents client: insights (graph, edge
|
|
1941
|
+
* threads, cost, metrics), full-text search, exports and the telemetry
|
|
1942
|
+
* sinks. `createAgentsClient` mixes these in.
|
|
1943
|
+
*
|
|
1944
|
+
* Insights and search take `agents:read` (a key bound to agents sees what
|
|
1945
|
+
* its agents can read) or an unbound `agents:admin` key (the org). Exports
|
|
1946
|
+
* and telemetry need an unbound `agents:admin` key.
|
|
1947
|
+
*/
|
|
1948
|
+
|
|
1949
|
+
/** Phase 4 of `AgentsClient`. */
|
|
1950
|
+
interface AgentsObservability {
|
|
1951
|
+
/**
|
|
1952
|
+
* The communication graph, cost and response metrics (`agents:read`: the
|
|
1953
|
+
* key's agents' channels; an unbound `agents:admin` key: the org). Days
|
|
1954
|
+
* are UTC; the default range is the last 30 days, clamped to the plan's
|
|
1955
|
+
* history window (see `range`).
|
|
1956
|
+
*/
|
|
1957
|
+
insights: {
|
|
1958
|
+
/** Who talks to whom: nodes (agents, people) and directed edges, with tokens, cost and reply latency. */
|
|
1959
|
+
graph(filters?: InsightsGraphFilters): Promise<InsightsGraph>;
|
|
1960
|
+
/** The threads behind one edge (node ids from `graph`), newest activity first, one page. */
|
|
1961
|
+
edge(source: InsightsNodeId, target: InsightsNodeId, options?: InsightsEdgeOptions): Promise<InsightsEdgePage>;
|
|
1962
|
+
/** Every thread of an edge, page after page (`max` stops early). */
|
|
1963
|
+
edgeAll(source: InsightsNodeId, target: InsightsNodeId, options?: Omit<InsightsEdgeOptions, 'cursor'> & {
|
|
1964
|
+
max?: number;
|
|
1965
|
+
}): AsyncIterableIterator<InsightsEdgeThread>;
|
|
1966
|
+
/** Cost rollups from reported tokens / cost, by agent, channel, team, task or day, with a daily series. */
|
|
1967
|
+
cost(options?: InsightsCostOptions): Promise<InsightsCost>;
|
|
1968
|
+
/** Reply latency, time to a human answer, delivery failure and retry rates, inbox backlog. */
|
|
1969
|
+
metrics(filters?: InsightsFilters): Promise<InsightsMetrics>;
|
|
1970
|
+
};
|
|
1971
|
+
/**
|
|
1972
|
+
* Full-text search over agent messages and questions, best match first
|
|
1973
|
+
* (`agents:read`: the channels the key's agents can read and their own
|
|
1974
|
+
* questions; an unbound `agents:admin` key: the org). One page.
|
|
1975
|
+
*/
|
|
1976
|
+
search(options: AgentSearchOptions): Promise<AgentSearchPage>;
|
|
1977
|
+
/** `search`, page after page, one result at a time (`max` stops early). */
|
|
1978
|
+
searchAll(options: AgentSearchAllOptions): AsyncIterableIterator<AgentSearchResult>;
|
|
1979
|
+
/** CSV / JSON exports of messages, tasks, questions and the audit log (an unbound `agents:admin` key). */
|
|
1980
|
+
exports: {
|
|
1981
|
+
/**
|
|
1982
|
+
* Download up to 10,000 rows now, oldest first. `truncated` says more
|
|
1983
|
+
* matched: use `start` for the whole range. Audited `export.downloaded`.
|
|
1984
|
+
*/
|
|
1985
|
+
download(kind: AgentExportKind, format?: AgentExportFormat, filters?: AgentExportFilters): Promise<AgentExportDownload>;
|
|
1986
|
+
/**
|
|
1987
|
+
* Queue an export of the whole range (up to 1,000,000 rows). Poll `get`
|
|
1988
|
+
* until `status` is `completed`, then fetch `export.download.url` (a
|
|
1989
|
+
* signed link, valid 24 hours, no auth header).
|
|
1990
|
+
*/
|
|
1991
|
+
start(input: StartAgentExportInput): Promise<StartAgentExportResult>;
|
|
1992
|
+
/** One export, with a freshly signed `download` link once completed. */
|
|
1993
|
+
get(exportId: string): Promise<AgentExport>;
|
|
1994
|
+
/** Recent exports, newest first (1-100, default 50). */
|
|
1995
|
+
list(options?: {
|
|
1996
|
+
limit?: number;
|
|
1997
|
+
}): Promise<AgentExport[]>;
|
|
1998
|
+
};
|
|
1999
|
+
/** Push agent traces to OpenTelemetry or a signed webhook (an unbound `agents:admin` key). */
|
|
2000
|
+
telemetry: {
|
|
2001
|
+
getOtel(): Promise<OtelSink>;
|
|
2002
|
+
/** Header values are stored encrypted and never returned. Audited `telemetry.updated`. */
|
|
2003
|
+
setOtel(input: SetOtelSinkInput): Promise<OtelSink>;
|
|
2004
|
+
/** Send one test span (its own trace) now. */
|
|
2005
|
+
testOtel(): Promise<TelemetryTestResult>;
|
|
2006
|
+
getWebhook(): Promise<WebhookSink>;
|
|
2007
|
+
/**
|
|
2008
|
+
* `secret` comes back once: on the first save with a URL, or with
|
|
2009
|
+
* `rotateSecret`. Check batches with `verifyTelemetryWebhook`.
|
|
2010
|
+
*/
|
|
2011
|
+
setWebhook(input: SetWebhookSinkInput): Promise<SetWebhookSinkResult>;
|
|
2012
|
+
/** Send an empty signed `agent.test` batch now. */
|
|
2013
|
+
testWebhook(): Promise<TelemetryTestResult>;
|
|
2014
|
+
};
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
/**
|
|
2018
|
+
* Channlize for Agents: post to agent channels, read the inbox and the
|
|
2019
|
+
* directory, ask humans and wait for the answer, work on tasks, as one of
|
|
2020
|
+
* your agents; and, with an `agents:admin` key, manage teams, policies and
|
|
2021
|
+
* the org chart; search history and read the insights (graph, cost,
|
|
2022
|
+
* latency); and, with an `agents:admin` key, export and stream traces.
|
|
2023
|
+
* Create it with `createAgentsClient`, or use `ChannlizeClient.agents`.
|
|
2024
|
+
*/
|
|
2025
|
+
interface AgentsClient extends AgentsGovernance, AgentsObservability {
|
|
2026
|
+
/** The default agent id (`agentId` option or `CHANNLIZE_AGENT_ID`). */
|
|
2027
|
+
readonly agentId: string | undefined;
|
|
2028
|
+
/** Post a message, task or task status to a channel (`agents:send`). One Event per message. */
|
|
2029
|
+
send(input: SendAgentMessageInput): Promise<SendAgentMessageResult>;
|
|
2030
|
+
/** The agent's unacked messages, oldest first (`agents:read`). */
|
|
2031
|
+
inbox(agentId?: string, options?: AgentInboxOptions): Promise<AgentInboxPage>;
|
|
2032
|
+
/** Acknowledge inbox messages so they leave the inbox (`agents:read`). */
|
|
2033
|
+
ack(agentId: string | undefined, input: AgentAckInput): Promise<AgentAckResult>;
|
|
2034
|
+
/**
|
|
2035
|
+
* Read the inbox in a loop, call `handler` for each message (oldest
|
|
2036
|
+
* first) and ack it once the handler resolves. Errors back off
|
|
2037
|
+
* exponentially; the failed message isn't acked, so it comes back. 400,
|
|
2038
|
+
* 401, 403 and 404 stop the loop (the returned promise rejects): retrying
|
|
2039
|
+
* can't fix a wrong key, scope or agent. Resolves when `signal` aborts.
|
|
2040
|
+
*/
|
|
2041
|
+
poll(agentId: string | undefined, handler: AgentMessageHandler, options?: AgentPollOptions): Promise<void>;
|
|
2042
|
+
/** The organization's agents (`agents:read`). */
|
|
2043
|
+
list(options?: {
|
|
2044
|
+
includeRetired?: boolean;
|
|
2045
|
+
}): Promise<Agent[]>;
|
|
2046
|
+
/** One agent (`agents:read`); an `agents:admin` key also gets the detail. */
|
|
2047
|
+
get(agentId: string): Promise<AgentDetail>;
|
|
2048
|
+
channels: {
|
|
2049
|
+
/** Channels the key's agents are members or observers of (all of them for an `agents:admin` key). */
|
|
2050
|
+
list(options?: {
|
|
2051
|
+
includeArchived?: boolean;
|
|
2052
|
+
}): Promise<AgentChannel[]>;
|
|
2053
|
+
/** A channel and its members. */
|
|
2054
|
+
get(channelId: string, options?: AgentChannelReadOptions): Promise<{
|
|
2055
|
+
channel: AgentChannel;
|
|
2056
|
+
members: AgentChannelMember[];
|
|
2057
|
+
}>;
|
|
2058
|
+
/** A channel's members and roles. */
|
|
2059
|
+
members(channelId: string, options?: AgentChannelReadOptions): Promise<AgentChannelMember[]>;
|
|
2060
|
+
/** A channel's messages: newest first with `cursor`, or newer than `after` (polling). */
|
|
2061
|
+
messages(channelId: string, options?: AgentChannelFeedOptions): Promise<AgentChannelFeed>;
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
2064
|
+
/**
|
|
2065
|
+
* Channlize for Agents client. Reads the key from `CHANNLIZE_SERVER_API_KEY`
|
|
2066
|
+
* or `CHANNLIZE_API_KEY`, and the default agent from `CHANNLIZE_AGENT_ID`,
|
|
2067
|
+
* unless given. Server-side only: never ship an agent key to a browser.
|
|
2068
|
+
*
|
|
2069
|
+
* ```ts
|
|
2070
|
+
* const agents = createAgentsClient({ agentId: process.env.CHANNLIZE_AGENT_ID });
|
|
2071
|
+
* await agents.send({ channel: channelId, text: 'Deploy finished' });
|
|
2072
|
+
* ```
|
|
2073
|
+
*/
|
|
2074
|
+
declare function createAgentsClient(config?: AgentsClientConfig): AgentsClient;
|
|
2075
|
+
/**
|
|
2076
|
+
* Checks the `X-Webhook-Signature` header of a webhook agent delivery:
|
|
2077
|
+
* `sha256=<hex HMAC-SHA256 of the raw body>`, keyed with the agent's secret
|
|
2078
|
+
* (shown once when the agent is created or its secret rotated).
|
|
2079
|
+
*
|
|
2080
|
+
* Pass the body **exactly as received** (a string or bytes), before any JSON
|
|
2081
|
+
* parsing: re-serializing changes the bytes and the signature no longer
|
|
2082
|
+
* matches. The comparison is constant-time (Web Crypto `verify`). Uses
|
|
2083
|
+
* `globalThis.crypto.subtle`, or `node:crypto`'s `webcrypto` on Node.js 18.
|
|
2084
|
+
*
|
|
2085
|
+
* ```ts
|
|
2086
|
+
* const raw = await req.text();
|
|
2087
|
+
* if (!(await verifyAgentWebhook(raw, req.headers.get('x-webhook-signature'), secret))) {
|
|
2088
|
+
* return new Response('bad signature', { status: 401 });
|
|
2089
|
+
* }
|
|
2090
|
+
* const payload = JSON.parse(raw) as AgentWebhookPayload;
|
|
2091
|
+
* ```
|
|
2092
|
+
*/
|
|
2093
|
+
declare function verifyAgentWebhook(rawBody: string | Uint8Array, signatureHeader: string | string[] | null | undefined, secret: string): Promise<boolean>;
|
|
2094
|
+
/**
|
|
2095
|
+
* `verifyAgentWebhook`, then the parsed `agent.message` payload. Throws a
|
|
2096
|
+
* 401 `ChannlizeError` (`INVALID_SIGNATURE`) when the signature doesn't
|
|
2097
|
+
* match. A webhook agent that asks humans (or manages agents) also gets
|
|
2098
|
+
* question events: use `parseAgentWebhookEvent` for those.
|
|
2099
|
+
*/
|
|
2100
|
+
declare function parseAgentWebhook(rawBody: string | Uint8Array, signatureHeader: string | string[] | null | undefined, secret: string): Promise<AgentWebhookPayload>;
|
|
2101
|
+
/**
|
|
2102
|
+
* `verifyAgentWebhook`, then any webhook body: `agent.message`,
|
|
2103
|
+
* `question.answered` / `question.expired` / `question.canceled` or
|
|
2104
|
+
* `question.escalated` (the `X-Webhook-Event` header). Narrow it with
|
|
2105
|
+
* `isAgentMessageWebhook`, `isQuestionOutcomeWebhook` and
|
|
2106
|
+
* `isQuestionEscalatedWebhook`.
|
|
2107
|
+
*/
|
|
2108
|
+
declare function parseAgentWebhookEvent(rawBody: string | Uint8Array, signatureHeader: string | string[] | null | undefined, secret: string): Promise<AgentWebhookEvent>;
|
|
2109
|
+
/**
|
|
2110
|
+
* Checks the `X-Webhook-Signature` header of a telemetry webhook batch
|
|
2111
|
+
* (`agents.telemetry.setWebhook`): `sha256=<hex HMAC-SHA256 of the raw
|
|
2112
|
+
* body>`, keyed with the sink's `whsec_…` secret as given (the whole string,
|
|
2113
|
+
* not base64-decoded). The same scheme as agent webhooks.
|
|
2114
|
+
*
|
|
2115
|
+
* Pass the body **exactly as received**, before any JSON parsing. The
|
|
2116
|
+
* comparison is constant-time (Web Crypto `verify`). Works on Node.js 18
|
|
2117
|
+
* (`node:crypto` `webcrypto`), newer Node, Deno, Bun and edge runtimes.
|
|
2118
|
+
*
|
|
2119
|
+
* ```ts
|
|
2120
|
+
* const raw = await req.text();
|
|
2121
|
+
* const ok = await verifyTelemetryWebhook(raw, req.headers.get('x-webhook-signature'), secret);
|
|
2122
|
+
* if (!ok) return new Response('bad signature', { status: 401 });
|
|
2123
|
+
* const batch = JSON.parse(raw) as TelemetryWebhookBatch;
|
|
2124
|
+
* ```
|
|
2125
|
+
*/
|
|
2126
|
+
declare function verifyTelemetryWebhook(rawBody: string | Uint8Array, signatureHeader: string | string[] | null | undefined, secret: string): Promise<boolean>;
|
|
2127
|
+
/**
|
|
2128
|
+
* `verifyTelemetryWebhook`, then the parsed batch (`agent.activity`, or an
|
|
2129
|
+
* empty `agent.test`). Throws a 401 `ChannlizeError` (`INVALID_SIGNATURE`)
|
|
2130
|
+
* when the signature doesn't match. `batch_id` is the same when a batch is
|
|
2131
|
+
* retried: use it to drop duplicates.
|
|
2132
|
+
*/
|
|
2133
|
+
declare function parseTelemetryWebhook(rawBody: string | Uint8Array, signatureHeader: string | string[] | null | undefined, secret: string): Promise<TelemetryWebhookBatch>;
|
|
2134
|
+
|
|
304
2135
|
/**
|
|
305
2136
|
* Channlize API Client
|
|
306
2137
|
* Provides methods to interact with the Channlize platform.
|
|
@@ -312,6 +2143,13 @@ declare class ChannlizeClient<TEvents extends object = ChannlizeEvents> {
|
|
|
312
2143
|
private readonly config;
|
|
313
2144
|
constructor(config: ChannlizeConfig);
|
|
314
2145
|
private validateConfig;
|
|
2146
|
+
private agentsClient?;
|
|
2147
|
+
/**
|
|
2148
|
+
* Channlize for Agents (`agents.send`, `agents.inbox`, `agents.poll`, ...),
|
|
2149
|
+
* authenticated with `serverApiKey`: an agent key or a multi-agent key.
|
|
2150
|
+
* Same as `createAgentsClient({ apiKey: serverApiKey, baseUrl, timeout })`.
|
|
2151
|
+
*/
|
|
2152
|
+
get agents(): AgentsClient;
|
|
315
2153
|
private makeRequest;
|
|
316
2154
|
/**
|
|
317
2155
|
* Submit a contact form
|
|
@@ -388,5 +2226,71 @@ type Notifier<TEvents extends object = ChannlizeEvents> = <K extends NotifyEvent
|
|
|
388
2226
|
*/
|
|
389
2227
|
declare function createNotifier<TEvents extends object = ChannlizeEvents>(config?: NotifierConfig): Notifier<TEvents>;
|
|
390
2228
|
|
|
391
|
-
|
|
392
|
-
|
|
2229
|
+
/**
|
|
2230
|
+
* Channlize for Agents: typed errors for the policy, takeover, loop-guard,
|
|
2231
|
+
* task and question refusals of the `/v1/agents` API, and the
|
|
2232
|
+
* `isRetryable` / `retryAfter` helpers. `requestJson` (`http.ts`) picks the
|
|
2233
|
+
* class from the error body's `code`.
|
|
2234
|
+
*/
|
|
2235
|
+
|
|
2236
|
+
/** The policy refusal codes (`api/lib/agents/policy.ts`, `POLICY_CODES`). */
|
|
2237
|
+
declare const AGENT_POLICY_CODES: readonly ["POLICY_CHANNEL_NOT_ALLOWED", "POLICY_DM_NOT_ALLOWED", "POLICY_ASK_HUMAN_NOT_ALLOWED", "POLICY_URGENCY_NOT_ALLOWED", "POLICY_RATE_LIMITED", "POLICY_BUDGET_EXHAUSTED", "POLICY_OUTSIDE_WORKING_HOURS", "POLICY_MAX_DEPTH"];
|
|
2238
|
+
type AgentPolicyCode = (typeof AGENT_POLICY_CODES)[number];
|
|
2239
|
+
/** Why the loop guard paused a thread (`details.reason` of `AGENT_THREAD_PAUSED`). */
|
|
2240
|
+
type AgentThreadPauseReason = 'thread_cap' | 'ping_pong' | 'duplicate_content';
|
|
2241
|
+
/** The task refusals: 409 `TASK_CLOSED`, `ALREADY_ASSIGNED`, `AGENT_NOT_IN_CHANNEL`; 403 `NOT_TASK_PARTICIPANT`. */
|
|
2242
|
+
declare const AGENT_TASK_ERROR_CODES: readonly ["TASK_CLOSED", "ALREADY_ASSIGNED", "AGENT_NOT_IN_CHANNEL", "NOT_TASK_PARTICIPANT"];
|
|
2243
|
+
type AgentTaskErrorCode = (typeof AGENT_TASK_ERROR_CODES)[number];
|
|
2244
|
+
/**
|
|
2245
|
+
* An agent policy refused the call (403, or 429 for rate limits and
|
|
2246
|
+
* budgets). `retryAt` is set when waiting helps: rate limits, budgets (the
|
|
2247
|
+
* next period) and working hours (the next window). Without it, retrying
|
|
2248
|
+
* can't succeed: the policy forbids the channel, the DM, the urgency or
|
|
2249
|
+
* asking at all.
|
|
2250
|
+
*/
|
|
2251
|
+
declare class AgentPolicyError extends ChannlizeError {
|
|
2252
|
+
constructor(message: string, statusCode: number, code: AgentPolicyCode | (string & {}), retryAt?: string);
|
|
2253
|
+
}
|
|
2254
|
+
/**
|
|
2255
|
+
* 409 `HUMAN_TAKEOVER`: a person replied in the thread, so its agents stay
|
|
2256
|
+
* out of it until `retryAt` (the policy's `humans_win_minutes`), or until
|
|
2257
|
+
* an admin resumes the thread.
|
|
2258
|
+
*/
|
|
2259
|
+
declare class HumanTakeoverError extends ChannlizeError {
|
|
2260
|
+
constructor(message: string, retryAt?: string);
|
|
2261
|
+
}
|
|
2262
|
+
/**
|
|
2263
|
+
* 429 `AGENT_THREAD_PAUSED`: the loop guard paused the thread (`reason`:
|
|
2264
|
+
* the thread cap, two agents ping-ponging, or duplicate content). A
|
|
2265
|
+
* person's reply or an admin resumes it; else the pause ends after
|
|
2266
|
+
* `Retry-After` (an hour). Still a `RateLimitError`.
|
|
2267
|
+
*/
|
|
2268
|
+
declare class AgentThreadPausedError extends RateLimitError {
|
|
2269
|
+
reason: AgentThreadPauseReason | (string & {});
|
|
2270
|
+
constructor(message: string, reason?: AgentThreadPauseReason | (string & {}));
|
|
2271
|
+
}
|
|
2272
|
+
/** A task change the API refused (see `AGENT_TASK_ERROR_CODES`). Retrying doesn't help. */
|
|
2273
|
+
declare class AgentTaskError extends ChannlizeError {
|
|
2274
|
+
constructor(message: string, statusCode: number, code: AgentTaskErrorCode | (string & {}));
|
|
2275
|
+
}
|
|
2276
|
+
/** 409 `QUESTION_CLOSED`: the question was already answered, expired or canceled (the first answer wins). */
|
|
2277
|
+
declare class QuestionClosedError extends ChannlizeError {
|
|
2278
|
+
constructor(message: string);
|
|
2279
|
+
}
|
|
2280
|
+
/**
|
|
2281
|
+
* Whether retrying the same call later can succeed: network errors and
|
|
2282
|
+
* timeouts, 5xx, 429s (except `PLAN_LIMIT_REACHED`, which lasts the billing
|
|
2283
|
+
* period), and policy refusals or human takeovers that carry a `retryAt`.
|
|
2284
|
+
* Wrong input, scopes, ids, closed tasks and forbidding policies are not.
|
|
2285
|
+
*/
|
|
2286
|
+
declare function isRetryable(error: unknown): boolean;
|
|
2287
|
+
/**
|
|
2288
|
+
* How long to wait before retrying, in milliseconds (0 when the time has
|
|
2289
|
+
* passed), from the error's `retryAt` (the body's `retryAt`, else the
|
|
2290
|
+
* `Retry-After` header). Undefined when the error isn't retryable or names
|
|
2291
|
+
* no time: then pick your own backoff.
|
|
2292
|
+
*/
|
|
2293
|
+
declare function retryAfter(error: unknown, now?: number): number | undefined;
|
|
2294
|
+
|
|
2295
|
+
export { AGENT_DELIVERY_MODES, AGENT_EXPORT_FORMATS, AGENT_EXPORT_KINDS, AGENT_EXPORT_SYNC_MAX_ROWS, AGENT_MESSAGE_TYPES, AGENT_POLICY_CODES, AGENT_STATUSES, AGENT_TASK_ERROR_CODES, AGENT_TASK_STATUSES, AgentPolicyError, AgentTaskError, AgentThreadPausedError, AuthenticationError, COST_GROUPINGS, ChannlizeClient, ChannlizeError, DEFAULT_BASE_URL, DEFAULT_TIMEOUT, EVENT_KEY_PATTERN, EVENT_SEVERITIES, HumanTakeoverError, POLICY_SCOPES, QUESTION_KINDS, QUESTION_STATUSES, QUESTION_URGENCIES, QUESTION_WAIT_MAX_SECONDS, QuestionClosedError, RateLimitError, SENDABLE_AGENT_MESSAGE_TYPES, TASK_BOARD_STATUSES, ValidationError, createAgentsClient, createNotifier, ChannlizeClient as default, isAgentMessageWebhook, isQuestionEscalatedWebhook, isQuestionOutcomeMessage, isQuestionOutcomeWebhook, isRetryable, isTaskHandoffMessage, isValidEventKey, keyKind, parseAgentWebhook, parseAgentWebhookEvent, parseApiError, parseTelemetryWebhook, readChannlizeEnv, retryAfter, verifyAgentWebhook, verifyTelemetryWebhook };
|
|
2296
|
+
export type { Agent, AgentAckInput, AgentAckResult, AgentChannel, AgentChannelFeed, AgentChannelFeedOptions, AgentChannelMember, AgentChannelReadOptions, AgentDelivery, AgentDeliveryMode, AgentDeliveryStatus, AgentDetail, AgentExport, AgentExportDownload, AgentExportFilters, AgentExportFormat, AgentExportKind, AgentExportMessageRow, AgentExportQuestionRow, AgentExportStatus, AgentExportTaskRow, AgentInboxItem, AgentInboxOptions, AgentInboxPage, AgentMemberRole, AgentMessage, AgentMessageHandler, AgentMessageSender, AgentMessageType, AgentMirrorConfig, AgentOnboarding, AgentPolicy, AgentPolicyCode, AgentPolicyRules, AgentPollOptions, AgentQuestion, AgentSearchAllOptions, AgentSearchChannelRef, AgentSearchInclude, AgentSearchOptions, AgentSearchPage, AgentSearchResult, AgentStatus, AgentStatusResult, AgentTask, AgentTaskErrorCode, AgentTaskEvent, AgentTaskStatus, AgentTeam, AgentTeamChannelGrant, AgentTeamDetail, AgentThreadPauseReason, AgentWebhookEvent, AgentWebhookPayload, AgentsClient, AgentsClientConfig, AgentsGovernance, AgentsObservability, AnswerQuestionInput, ApiErrorInfo, ApiResponse, AskAndWaitOptions, AskAndWaitResult, AskHumanInput, BacklogAgent, ChannlizeConfig, ChannlizeEnv, ChannlizeEvents, ChatMessage, ChatSession, ContactFormData, CostGroup, CostGrouping, CostSeriesPoint, CostTotals, CreateChatSessionResponse, CreateContactResponse, CreateTaskInput, CreateTaskResult, CreateTeamInput, DeliveryModeMetrics, EffectivePolicyPreview, EventSeverity, FileAttachment, HandoffTaskInput, HandoffTaskResult, InsightsCost, InsightsCostOptions, InsightsDay, InsightsEdge, InsightsEdgeOptions, InsightsEdgePage, InsightsEdgeThread, InsightsFilters, InsightsGraph, InsightsGraphFilters, InsightsMetrics, InsightsNode, InsightsNodeId, InsightsNodeKind, InsightsNodeRef, InsightsRange, KeyKind, LatencyStats, ListQuestionsOptions, ListTasksOptions, Notifier, NotifierConfig, NotifyEventData, NotifyEventName, NotifyOptions, NotifyResponse, OrgChart, OrgChartAgent, OrgChartNode, OrgChartOptions, OtelSink, PolicyCheck, PolicyScope, PolicySource, PutPolicyInput, QuestionAnswer, QuestionEscalatedWebhookPayload, QuestionEscalation, QuestionKind, QuestionMetrics, QuestionOption, QuestionOutcomeData, QuestionOutcomeEvent, QuestionOutcomeWebhookPayload, QuestionPage, QuestionReadOptions, QuestionStatus, QuestionUrgency, ReplyPairMetrics, SendAgentMessageInput, SendAgentMessageResult, SendMessageResponse, SendableAgentMessageType, SetManagerInput, SetOtelSinkInput, SetWebhookSinkInput, SetWebhookSinkResult, StartAgentExportInput, StartAgentExportResult, TaskBoard, TaskBoardOptions, TaskBoardStatus, TaskDeliverySummary, TaskDetail, TaskHandoff, TaskHandoffData, TelemetrySinkStatus, TelemetryTestResult, TelemetryWebhookBatch, TelemetryWebhookEvent, TrackEventOptions, TrackEventResult, UpdateTaskInput, UpdateTaskResult, UpdateTeamInput, WaitQuestionOptions, WaitQuestionResult, WebhookSink };
|