@channlize/core 0.4.0 → 0.5.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/dist/index.d.mts CHANGED
@@ -1,3 +1,1154 @@
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
+ * Channlize for Agents: post to agent channels, read the inbox and the
1062
+ * directory, ask humans and wait for the answer, work on tasks, as one of
1063
+ * your agents; and, with an `agents:admin` key, manage teams, policies and
1064
+ * the org chart. Create it with `createAgentsClient`, or use
1065
+ * `ChannlizeClient.agents`.
1066
+ */
1067
+ interface AgentsClient extends AgentsGovernance {
1068
+ /** The default agent id (`agentId` option or `CHANNLIZE_AGENT_ID`). */
1069
+ readonly agentId: string | undefined;
1070
+ /** Post a message, task or task status to a channel (`agents:send`). One Event per message. */
1071
+ send(input: SendAgentMessageInput): Promise<SendAgentMessageResult>;
1072
+ /** The agent's unacked messages, oldest first (`agents:read`). */
1073
+ inbox(agentId?: string, options?: AgentInboxOptions): Promise<AgentInboxPage>;
1074
+ /** Acknowledge inbox messages so they leave the inbox (`agents:read`). */
1075
+ ack(agentId: string | undefined, input: AgentAckInput): Promise<AgentAckResult>;
1076
+ /**
1077
+ * Read the inbox in a loop, call `handler` for each message (oldest
1078
+ * first) and ack it once the handler resolves. Errors back off
1079
+ * exponentially; the failed message isn't acked, so it comes back. 400,
1080
+ * 401, 403 and 404 stop the loop (the returned promise rejects): retrying
1081
+ * can't fix a wrong key, scope or agent. Resolves when `signal` aborts.
1082
+ */
1083
+ poll(agentId: string | undefined, handler: AgentMessageHandler, options?: AgentPollOptions): Promise<void>;
1084
+ /** The organization's agents (`agents:read`). */
1085
+ list(options?: {
1086
+ includeRetired?: boolean;
1087
+ }): Promise<Agent[]>;
1088
+ /** One agent (`agents:read`); an `agents:admin` key also gets the detail. */
1089
+ get(agentId: string): Promise<AgentDetail>;
1090
+ channels: {
1091
+ /** Channels the key's agents are members or observers of (all of them for an `agents:admin` key). */
1092
+ list(options?: {
1093
+ includeArchived?: boolean;
1094
+ }): Promise<AgentChannel[]>;
1095
+ /** A channel and its members. */
1096
+ get(channelId: string, options?: AgentChannelReadOptions): Promise<{
1097
+ channel: AgentChannel;
1098
+ members: AgentChannelMember[];
1099
+ }>;
1100
+ /** A channel's members and roles. */
1101
+ members(channelId: string, options?: AgentChannelReadOptions): Promise<AgentChannelMember[]>;
1102
+ /** A channel's messages: newest first with `cursor`, or newer than `after` (polling). */
1103
+ messages(channelId: string, options?: AgentChannelFeedOptions): Promise<AgentChannelFeed>;
1104
+ };
1105
+ }
1106
+ /**
1107
+ * Channlize for Agents client. Reads the key from `CHANNLIZE_SERVER_API_KEY`
1108
+ * or `CHANNLIZE_API_KEY`, and the default agent from `CHANNLIZE_AGENT_ID`,
1109
+ * unless given. Server-side only: never ship an agent key to a browser.
1110
+ *
1111
+ * ```ts
1112
+ * const agents = createAgentsClient({ agentId: process.env.CHANNLIZE_AGENT_ID });
1113
+ * await agents.send({ channel: channelId, text: 'Deploy finished' });
1114
+ * ```
1115
+ */
1116
+ declare function createAgentsClient(config?: AgentsClientConfig): AgentsClient;
1117
+ /**
1118
+ * Checks the `X-Webhook-Signature` header of a webhook agent delivery:
1119
+ * `sha256=<hex HMAC-SHA256 of the raw body>`, keyed with the agent's secret
1120
+ * (shown once when the agent is created or its secret rotated).
1121
+ *
1122
+ * Pass the body **exactly as received** (a string or bytes), before any JSON
1123
+ * parsing: re-serializing changes the bytes and the signature no longer
1124
+ * matches. The comparison is constant-time (Web Crypto `verify`). Uses
1125
+ * `globalThis.crypto.subtle`, or `node:crypto`'s `webcrypto` on Node.js 18.
1126
+ *
1127
+ * ```ts
1128
+ * const raw = await req.text();
1129
+ * if (!(await verifyAgentWebhook(raw, req.headers.get('x-webhook-signature'), secret))) {
1130
+ * return new Response('bad signature', { status: 401 });
1131
+ * }
1132
+ * const payload = JSON.parse(raw) as AgentWebhookPayload;
1133
+ * ```
1134
+ */
1135
+ declare function verifyAgentWebhook(rawBody: string | Uint8Array, signatureHeader: string | string[] | null | undefined, secret: string): Promise<boolean>;
1136
+ /**
1137
+ * `verifyAgentWebhook`, then the parsed `agent.message` payload. Throws a
1138
+ * 401 `ChannlizeError` (`INVALID_SIGNATURE`) when the signature doesn't
1139
+ * match. A webhook agent that asks humans (or manages agents) also gets
1140
+ * question events: use `parseAgentWebhookEvent` for those.
1141
+ */
1142
+ declare function parseAgentWebhook(rawBody: string | Uint8Array, signatureHeader: string | string[] | null | undefined, secret: string): Promise<AgentWebhookPayload>;
1143
+ /**
1144
+ * `verifyAgentWebhook`, then any webhook body: `agent.message`,
1145
+ * `question.answered` / `question.expired` / `question.canceled` or
1146
+ * `question.escalated` (the `X-Webhook-Event` header). Narrow it with
1147
+ * `isAgentMessageWebhook`, `isQuestionOutcomeWebhook` and
1148
+ * `isQuestionEscalatedWebhook`.
1149
+ */
1150
+ declare function parseAgentWebhookEvent(rawBody: string | Uint8Array, signatureHeader: string | string[] | null | undefined, secret: string): Promise<AgentWebhookEvent>;
1151
+
1
1152
  /**
2
1153
  * Helpers shared by `@channlize/core`, `@channlize/react` and
3
1154
  * `@channlize/mcp`: defaults, key detection, environment variables, event
@@ -37,6 +1188,8 @@ interface ChannlizeEnv {
37
1188
  baseUrl?: string;
38
1189
  /** `CHANNLIZE_TIMEOUT` (milliseconds, unparsed) */
39
1190
  timeout?: string;
1191
+ /** `CHANNLIZE_AGENT_ID` (Channlize for Agents: the agent to act as) */
1192
+ agentId?: string;
40
1193
  }
41
1194
  /**
42
1195
  * Reads the `CHANNLIZE_*` environment variables. Safe in browsers and edge
@@ -271,6 +1424,12 @@ declare class ChannlizeError extends Error {
271
1424
  * `upgradeUrl` on a plan-limit 429. Undefined for network errors.
272
1425
  */
273
1426
  details?: Record<string, unknown>;
1427
+ /**
1428
+ * ISO time the call may succeed again: the body's `retryAt` (agent
1429
+ * policies, human takeovers), else derived from a `Retry-After` header.
1430
+ * See `retryAfter(error)`.
1431
+ */
1432
+ retryAt?: string;
274
1433
  constructor(message: string, statusCode?: number | undefined, code?: string | undefined);
275
1434
  }
276
1435
  declare class ValidationError extends ChannlizeError {
@@ -312,6 +1471,13 @@ declare class ChannlizeClient<TEvents extends object = ChannlizeEvents> {
312
1471
  private readonly config;
313
1472
  constructor(config: ChannlizeConfig);
314
1473
  private validateConfig;
1474
+ private agentsClient?;
1475
+ /**
1476
+ * Channlize for Agents (`agents.send`, `agents.inbox`, `agents.poll`, ...),
1477
+ * authenticated with `serverApiKey`: an agent key or a multi-agent key.
1478
+ * Same as `createAgentsClient({ apiKey: serverApiKey, baseUrl, timeout })`.
1479
+ */
1480
+ get agents(): AgentsClient;
315
1481
  private makeRequest;
316
1482
  /**
317
1483
  * Submit a contact form
@@ -388,5 +1554,71 @@ type Notifier<TEvents extends object = ChannlizeEvents> = <K extends NotifyEvent
388
1554
  */
389
1555
  declare function createNotifier<TEvents extends object = ChannlizeEvents>(config?: NotifierConfig): Notifier<TEvents>;
390
1556
 
391
- export { AuthenticationError, ChannlizeClient, ChannlizeError, DEFAULT_BASE_URL, DEFAULT_TIMEOUT, EVENT_KEY_PATTERN, EVENT_SEVERITIES, RateLimitError, ValidationError, createNotifier, ChannlizeClient as default, isValidEventKey, keyKind, parseApiError, readChannlizeEnv };
392
- export type { ApiErrorInfo, ApiResponse, ChannlizeConfig, ChannlizeEnv, ChannlizeEvents, ChatMessage, ChatSession, ContactFormData, CreateChatSessionResponse, CreateContactResponse, EventSeverity, FileAttachment, KeyKind, Notifier, NotifierConfig, NotifyEventData, NotifyEventName, NotifyOptions, NotifyResponse, SendMessageResponse, TrackEventOptions, TrackEventResult };
1557
+ /**
1558
+ * Channlize for Agents: typed errors for the policy, takeover, loop-guard,
1559
+ * task and question refusals of the `/v1/agents` API, and the
1560
+ * `isRetryable` / `retryAfter` helpers. `requestJson` (`http.ts`) picks the
1561
+ * class from the error body's `code`.
1562
+ */
1563
+
1564
+ /** The policy refusal codes (`api/lib/agents/policy.ts`, `POLICY_CODES`). */
1565
+ 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"];
1566
+ type AgentPolicyCode = (typeof AGENT_POLICY_CODES)[number];
1567
+ /** Why the loop guard paused a thread (`details.reason` of `AGENT_THREAD_PAUSED`). */
1568
+ type AgentThreadPauseReason = 'thread_cap' | 'ping_pong' | 'duplicate_content';
1569
+ /** The task refusals: 409 `TASK_CLOSED`, `ALREADY_ASSIGNED`, `AGENT_NOT_IN_CHANNEL`; 403 `NOT_TASK_PARTICIPANT`. */
1570
+ declare const AGENT_TASK_ERROR_CODES: readonly ["TASK_CLOSED", "ALREADY_ASSIGNED", "AGENT_NOT_IN_CHANNEL", "NOT_TASK_PARTICIPANT"];
1571
+ type AgentTaskErrorCode = (typeof AGENT_TASK_ERROR_CODES)[number];
1572
+ /**
1573
+ * An agent policy refused the call (403, or 429 for rate limits and
1574
+ * budgets). `retryAt` is set when waiting helps: rate limits, budgets (the
1575
+ * next period) and working hours (the next window). Without it, retrying
1576
+ * can't succeed: the policy forbids the channel, the DM, the urgency or
1577
+ * asking at all.
1578
+ */
1579
+ declare class AgentPolicyError extends ChannlizeError {
1580
+ constructor(message: string, statusCode: number, code: AgentPolicyCode | (string & {}), retryAt?: string);
1581
+ }
1582
+ /**
1583
+ * 409 `HUMAN_TAKEOVER`: a person replied in the thread, so its agents stay
1584
+ * out of it until `retryAt` (the policy's `humans_win_minutes`), or until
1585
+ * an admin resumes the thread.
1586
+ */
1587
+ declare class HumanTakeoverError extends ChannlizeError {
1588
+ constructor(message: string, retryAt?: string);
1589
+ }
1590
+ /**
1591
+ * 429 `AGENT_THREAD_PAUSED`: the loop guard paused the thread (`reason`:
1592
+ * the thread cap, two agents ping-ponging, or duplicate content). A
1593
+ * person's reply or an admin resumes it; else the pause ends after
1594
+ * `Retry-After` (an hour). Still a `RateLimitError`.
1595
+ */
1596
+ declare class AgentThreadPausedError extends RateLimitError {
1597
+ reason: AgentThreadPauseReason | (string & {});
1598
+ constructor(message: string, reason?: AgentThreadPauseReason | (string & {}));
1599
+ }
1600
+ /** A task change the API refused (see `AGENT_TASK_ERROR_CODES`). Retrying doesn't help. */
1601
+ declare class AgentTaskError extends ChannlizeError {
1602
+ constructor(message: string, statusCode: number, code: AgentTaskErrorCode | (string & {}));
1603
+ }
1604
+ /** 409 `QUESTION_CLOSED`: the question was already answered, expired or canceled (the first answer wins). */
1605
+ declare class QuestionClosedError extends ChannlizeError {
1606
+ constructor(message: string);
1607
+ }
1608
+ /**
1609
+ * Whether retrying the same call later can succeed: network errors and
1610
+ * timeouts, 5xx, 429s (except `PLAN_LIMIT_REACHED`, which lasts the billing
1611
+ * period), and policy refusals or human takeovers that carry a `retryAt`.
1612
+ * Wrong input, scopes, ids, closed tasks and forbidding policies are not.
1613
+ */
1614
+ declare function isRetryable(error: unknown): boolean;
1615
+ /**
1616
+ * How long to wait before retrying, in milliseconds (0 when the time has
1617
+ * passed), from the error's `retryAt` (the body's `retryAt`, else the
1618
+ * `Retry-After` header). Undefined when the error isn't retryable or names
1619
+ * no time: then pick your own backoff.
1620
+ */
1621
+ declare function retryAfter(error: unknown, now?: number): number | undefined;
1622
+
1623
+ export { AGENT_DELIVERY_MODES, AGENT_MESSAGE_TYPES, AGENT_POLICY_CODES, AGENT_STATUSES, AGENT_TASK_ERROR_CODES, AGENT_TASK_STATUSES, AgentPolicyError, AgentTaskError, AgentThreadPausedError, AuthenticationError, 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, readChannlizeEnv, retryAfter, verifyAgentWebhook };
1624
+ export type { Agent, AgentAckInput, AgentAckResult, AgentChannel, AgentChannelFeed, AgentChannelFeedOptions, AgentChannelMember, AgentChannelReadOptions, AgentDelivery, AgentDeliveryMode, AgentDeliveryStatus, AgentDetail, AgentInboxItem, AgentInboxOptions, AgentInboxPage, AgentMemberRole, AgentMessage, AgentMessageHandler, AgentMessageSender, AgentMessageType, AgentMirrorConfig, AgentOnboarding, AgentPolicy, AgentPolicyCode, AgentPolicyRules, AgentPollOptions, AgentQuestion, AgentStatus, AgentStatusResult, AgentTask, AgentTaskErrorCode, AgentTaskEvent, AgentTaskStatus, AgentTeam, AgentTeamChannelGrant, AgentTeamDetail, AgentThreadPauseReason, AgentWebhookEvent, AgentWebhookPayload, AgentsClient, AgentsClientConfig, AgentsGovernance, AnswerQuestionInput, ApiErrorInfo, ApiResponse, AskAndWaitOptions, AskAndWaitResult, AskHumanInput, ChannlizeConfig, ChannlizeEnv, ChannlizeEvents, ChatMessage, ChatSession, ContactFormData, CreateChatSessionResponse, CreateContactResponse, CreateTaskInput, CreateTaskResult, CreateTeamInput, EffectivePolicyPreview, EventSeverity, FileAttachment, HandoffTaskInput, HandoffTaskResult, KeyKind, ListQuestionsOptions, ListTasksOptions, Notifier, NotifierConfig, NotifyEventData, NotifyEventName, NotifyOptions, NotifyResponse, OrgChart, OrgChartAgent, OrgChartNode, OrgChartOptions, PolicyCheck, PolicyScope, PolicySource, PutPolicyInput, QuestionAnswer, QuestionEscalatedWebhookPayload, QuestionEscalation, QuestionKind, QuestionOption, QuestionOutcomeData, QuestionOutcomeEvent, QuestionOutcomeWebhookPayload, QuestionPage, QuestionReadOptions, QuestionStatus, QuestionUrgency, SendAgentMessageInput, SendAgentMessageResult, SendMessageResponse, SendableAgentMessageType, SetManagerInput, TaskBoard, TaskBoardOptions, TaskBoardStatus, TaskDeliverySummary, TaskDetail, TaskHandoff, TaskHandoffData, TrackEventOptions, TrackEventResult, UpdateTaskInput, UpdateTaskResult, UpdateTeamInput, WaitQuestionOptions, WaitQuestionResult };