@voicelayer/sdk 0.1.11 → 0.2.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.ts CHANGED
@@ -1,8 +1,11 @@
1
- import { A as AgentDTO, a as AgentStatus, b as AgentEnvironment, P as ProcessSchemaDTO, c as AgentContext, d as Participant, C as CallInfo } from './text-session-D1j8nQac.js';
2
- export { e as AgentTurnEvent, f as AudioProfile, g as AudioSurface, h as ChannelKind, D as DtmfEvent, i as DtmfHandler, E as EndCallControllerHandle, j as EndCallOutcome, F as FakeSessionAdapter, k as FloorControlConfig, I as InboundOptions, L as LK_AGENT_STATE_MAP, M as MemoryHandle, l as MetricsEvent, N as NON_BUSY_STATES, m as ParticipantId, n as ParticipantKind, o as ParticipantSet, p as ProcessSnapshot, R as RespondOptions, q as Room, r as RouteEntry, s as RoutingRule, t as RoutingSnapshot, u as RunTextSessionOptions, v as RunTextTranscriptOptions, S as SayOptions, w as SendDtmfOptions, x as SessionAdapter, y as SessionCapabilities, z as SessionErrorEvent, B as SessionEvent, G as SessionEventMap, H as SessionFactory, J as SessionFactoryInput, K as SessionOutbound, O as SessionState, Q as SpeechResult, T as SpeechTarget, U as StateChangeEvent, V as TextSession, W as TextTranscriptResult, X as TtsVoiceConfig, Y as TurnEvent, Z as Unsubscribe, _ as UserInputEvent, $ as UserTurn, a0 as applySpeechTurnHandling, a1 as dtmfCodeToDigit, a2 as dtmfDigitToCode, a3 as duck, a4 as mute, a5 as normalizeState, m as participantId, a6 as passthrough, a7 as runTextSession, a8 as runTextTranscript, a9 as transform } from './text-session-D1j8nQac.js';
3
- import { z, ZodType } from 'zod';
1
+ import { A as AgentDTO, a as AgentStatus, b as AgentEnvironment, c as AgentContext, P as Participant, C as CallInfo, d as ProcessSchemaDTO } from './text-session-BqMWaNsN.js';
2
+ export { e as AgentTurnEvent, f as AudioProfile, g as AudioSurface, h as ChannelKind, D as DtmfEvent, i as DtmfHandler, E as EndCallControllerHandle, j as EndCallOutcome, F as FakeSessionAdapter, k as FloorControlConfig, I as InboundOptions, L as LK_AGENT_STATE_MAP, M as MemoryHandle, l as MetricsEvent, N as NON_BUSY_STATES, m as ParticipantId, n as ParticipantKind, o as ParticipantSet, p as ProcessSnapshot, R as RespondOptions, q as Room, r as RouteEntry, s as RoutingRule, t as RoutingSnapshot, u as RunTextSessionOptions, v as RunTextTranscriptOptions, S as SayOptions, w as SendDtmfOptions, x as SessionAdapter, y as SessionCapabilities, z as SessionErrorEvent, B as SessionEvent, G as SessionEventMap, H as SessionFactory, J as SessionFactoryInput, K as SessionOutbound, O as SessionState, Q as SpeechResult, T as SpeechTarget, U as StateChangeEvent, V as TextSession, W as TextTranscriptResult, X as TtsVoiceConfig, Y as TurnEvent, Z as Unsubscribe, _ as UserInputEvent, $ as UserStateEvent, a0 as UserTurn, a1 as applySpeechTurnHandling, a2 as dtmfCodeToDigit, a3 as dtmfDigitToCode, a4 as duck, a5 as mute, a6 as normalizeState, m as participantId, a7 as passthrough, a8 as runTextSession, a9 as runTextTranscript, aa as transform } from './text-session-BqMWaNsN.js';
4
3
  import { llm } from '@livekit/agents';
5
- import { Redis } from 'ioredis';
4
+ import { z, ZodType } from 'zod';
5
+ import { OnQuery, BrainTransport } from './brain/index.js';
6
+ export { BrainCallMetadata, BrainCapabilities, BrainChunk, BrainConfigError, BrainEndpointConfig, BrainMessage, BrainPubSub, BrainRequest, BrainRequestError, ConnectorChatModel, ConnectorChatModelOptions, ConnectorLLMOptions, IncomingBrainRequest, OnQueryContext, OnQueryResult, RedisBrainPubSub, SseDelta, TunnelBrainTransportOptions, assertPublicHttpsUrl, buildRedisBrainPubSub, callbackTransport, createConnectorLLM, httpBrainTransport, parseChatCompletionSse, runBrainRequest, tunnelBrainTransport } from './brain/index.js';
7
+ import 'openai';
8
+ import 'ioredis';
6
9
 
7
10
  /**
8
11
  * The plan itself. Everything the agent needs to run the call without the
@@ -27,6 +30,60 @@ declare const CallPlan: z.ZodObject<{
27
30
  displayName?: string | undefined;
28
31
  }>;
29
32
  draftConfig: z.ZodDefault<z.ZodObject<{
33
+ stt: z.ZodOptional<z.ZodOptional<z.ZodObject<{
34
+ provider: z.ZodEnum<["deepgram", "cartesia", "assemblyai"]>;
35
+ model: z.ZodOptional<z.ZodString>;
36
+ language: z.ZodOptional<z.ZodString>;
37
+ endOfTurnConfidence: z.ZodOptional<z.ZodNumber>;
38
+ endOfTurnTimeoutMs: z.ZodOptional<z.ZodNumber>;
39
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
40
+ }, "strip", z.ZodTypeAny, {
41
+ provider: "deepgram" | "cartesia" | "assemblyai";
42
+ model?: string | undefined;
43
+ language?: string | undefined;
44
+ endOfTurnConfidence?: number | undefined;
45
+ endOfTurnTimeoutMs?: number | undefined;
46
+ keywords?: string[] | undefined;
47
+ }, {
48
+ provider: "deepgram" | "cartesia" | "assemblyai";
49
+ model?: string | undefined;
50
+ language?: string | undefined;
51
+ endOfTurnConfidence?: number | undefined;
52
+ endOfTurnTimeoutMs?: number | undefined;
53
+ keywords?: string[] | undefined;
54
+ }>>>;
55
+ realtime: z.ZodOptional<z.ZodOptional<z.ZodObject<{
56
+ provider: z.ZodEnum<["openai", "google"]>;
57
+ model: z.ZodString;
58
+ voice: z.ZodOptional<z.ZodString>;
59
+ temperature: z.ZodOptional<z.ZodNumber>;
60
+ }, "strip", z.ZodTypeAny, {
61
+ provider: "openai" | "google";
62
+ model: string;
63
+ voice?: string | undefined;
64
+ temperature?: number | undefined;
65
+ }, {
66
+ provider: "openai" | "google";
67
+ model: string;
68
+ voice?: string | undefined;
69
+ temperature?: number | undefined;
70
+ }>>>;
71
+ voice: z.ZodOptional<z.ZodObject<{
72
+ provider: z.ZodEnum<["deepgram", "elevenlabs", "openai", "cartesia"]>;
73
+ voiceId: z.ZodString;
74
+ model: z.ZodOptional<z.ZodString>;
75
+ rate: z.ZodOptional<z.ZodNumber>;
76
+ }, "strip", z.ZodTypeAny, {
77
+ provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
78
+ voiceId: string;
79
+ model?: string | undefined;
80
+ rate?: number | undefined;
81
+ }, {
82
+ provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
83
+ voiceId: string;
84
+ model?: string | undefined;
85
+ rate?: number | undefined;
86
+ }>>;
30
87
  source: z.ZodOptional<z.ZodOptional<z.ZodEnum<["sdk", "flow", "playbook", "connector"]>>>;
31
88
  name: z.ZodOptional<z.ZodString>;
32
89
  triggers: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -68,11 +125,11 @@ declare const CallPlan: z.ZodObject<{
68
125
  kind: z.ZodLiteral<"say">;
69
126
  text: z.ZodString;
70
127
  }, "strip", z.ZodTypeAny, {
71
- kind: "say";
72
128
  text: string;
73
- }, {
74
129
  kind: "say";
130
+ }, {
75
131
  text: string;
132
+ kind: "say";
76
133
  }>]>;
77
134
  onlyWhile: z.ZodOptional<z.ZodString>;
78
135
  }, "strip", z.ZodTypeAny, {
@@ -81,8 +138,8 @@ declare const CallPlan: z.ZodObject<{
81
138
  } | {
82
139
  kind: "endCall";
83
140
  } | {
84
- kind: "say";
85
141
  text: string;
142
+ kind: "say";
86
143
  };
87
144
  on: {
88
145
  kind: "regex";
@@ -99,8 +156,8 @@ declare const CallPlan: z.ZodObject<{
99
156
  } | {
100
157
  kind: "endCall";
101
158
  } | {
102
- kind: "say";
103
159
  text: string;
160
+ kind: "say";
104
161
  };
105
162
  on: {
106
163
  kind: "regex";
@@ -143,62 +200,8 @@ declare const CallPlan: z.ZodObject<{
143
200
  topP?: number | undefined;
144
201
  }>>;
145
202
  language: z.ZodOptional<z.ZodDefault<z.ZodString>>;
146
- voice: z.ZodOptional<z.ZodObject<{
147
- provider: z.ZodEnum<["deepgram", "elevenlabs", "openai", "cartesia"]>;
148
- voiceId: z.ZodString;
149
- model: z.ZodOptional<z.ZodString>;
150
- rate: z.ZodOptional<z.ZodNumber>;
151
- }, "strip", z.ZodTypeAny, {
152
- provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
153
- voiceId: string;
154
- model?: string | undefined;
155
- rate?: number | undefined;
156
- }, {
157
- provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
158
- voiceId: string;
159
- model?: string | undefined;
160
- rate?: number | undefined;
161
- }>>;
162
- realtime: z.ZodOptional<z.ZodOptional<z.ZodObject<{
163
- provider: z.ZodEnum<["openai", "google"]>;
164
- model: z.ZodString;
165
- voice: z.ZodOptional<z.ZodString>;
166
- temperature: z.ZodOptional<z.ZodNumber>;
167
- }, "strip", z.ZodTypeAny, {
168
- provider: "openai" | "google";
169
- model: string;
170
- temperature?: number | undefined;
171
- voice?: string | undefined;
172
- }, {
173
- provider: "openai" | "google";
174
- model: string;
175
- temperature?: number | undefined;
176
- voice?: string | undefined;
177
- }>>>;
178
203
  systemPrompt: z.ZodOptional<z.ZodOptional<z.ZodString>>;
179
204
  routingInstructions: z.ZodOptional<z.ZodOptional<z.ZodString>>;
180
- stt: z.ZodOptional<z.ZodOptional<z.ZodObject<{
181
- provider: z.ZodEnum<["deepgram", "cartesia", "assemblyai"]>;
182
- model: z.ZodOptional<z.ZodString>;
183
- language: z.ZodOptional<z.ZodString>;
184
- endOfTurnConfidence: z.ZodOptional<z.ZodNumber>;
185
- endOfTurnTimeoutMs: z.ZodOptional<z.ZodNumber>;
186
- keywords: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
187
- }, "strip", z.ZodTypeAny, {
188
- provider: "deepgram" | "cartesia" | "assemblyai";
189
- model?: string | undefined;
190
- language?: string | undefined;
191
- endOfTurnConfidence?: number | undefined;
192
- endOfTurnTimeoutMs?: number | undefined;
193
- keywords?: string[] | undefined;
194
- }, {
195
- provider: "deepgram" | "cartesia" | "assemblyai";
196
- model?: string | undefined;
197
- language?: string | undefined;
198
- endOfTurnConfidence?: number | undefined;
199
- endOfTurnTimeoutMs?: number | undefined;
200
- keywords?: string[] | undefined;
201
- }>>>;
202
205
  consultation: z.ZodOptional<z.ZodObject<{
203
206
  enabled: z.ZodDefault<z.ZodBoolean>;
204
207
  defaultTimeoutMs: z.ZodDefault<z.ZodNumber>;
@@ -348,6 +351,26 @@ declare const CallPlan: z.ZodObject<{
348
351
  description?: string | undefined;
349
352
  }>, "many">>>;
350
353
  }, "strip", z.ZodTypeAny, {
354
+ stt?: {
355
+ provider: "deepgram" | "cartesia" | "assemblyai";
356
+ model?: string | undefined;
357
+ language?: string | undefined;
358
+ endOfTurnConfidence?: number | undefined;
359
+ endOfTurnTimeoutMs?: number | undefined;
360
+ keywords?: string[] | undefined;
361
+ } | undefined;
362
+ realtime?: {
363
+ provider: "openai" | "google";
364
+ model: string;
365
+ voice?: string | undefined;
366
+ temperature?: number | undefined;
367
+ } | undefined;
368
+ voice?: {
369
+ provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
370
+ voiceId: string;
371
+ model?: string | undefined;
372
+ rate?: number | undefined;
373
+ } | undefined;
351
374
  source?: "playbook" | "sdk" | "flow" | "connector" | undefined;
352
375
  name?: string | undefined;
353
376
  triggers?: Record<string, {
@@ -356,8 +379,8 @@ declare const CallPlan: z.ZodObject<{
356
379
  } | {
357
380
  kind: "endCall";
358
381
  } | {
359
- kind: "say";
360
382
  text: string;
383
+ kind: "say";
361
384
  };
362
385
  on: {
363
386
  kind: "regex";
@@ -373,7 +396,7 @@ declare const CallPlan: z.ZodObject<{
373
396
  toolName: string;
374
397
  defaultArgs?: Record<string, unknown> | undefined;
375
398
  }[] | undefined;
376
- mode?: "cascade" | "realtime" | undefined;
399
+ mode?: "realtime" | "cascade" | undefined;
377
400
  model?: {
378
401
  provider: "openai" | "anthropic" | "gemini";
379
402
  model: string;
@@ -382,28 +405,8 @@ declare const CallPlan: z.ZodObject<{
382
405
  topP?: number | undefined;
383
406
  } | undefined;
384
407
  language?: string | undefined;
385
- voice?: {
386
- provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
387
- voiceId: string;
388
- model?: string | undefined;
389
- rate?: number | undefined;
390
- } | undefined;
391
- realtime?: {
392
- provider: "openai" | "google";
393
- model: string;
394
- temperature?: number | undefined;
395
- voice?: string | undefined;
396
- } | undefined;
397
408
  systemPrompt?: string | undefined;
398
409
  routingInstructions?: string | undefined;
399
- stt?: {
400
- provider: "deepgram" | "cartesia" | "assemblyai";
401
- model?: string | undefined;
402
- language?: string | undefined;
403
- endOfTurnConfidence?: number | undefined;
404
- endOfTurnTimeoutMs?: number | undefined;
405
- keywords?: string[] | undefined;
406
- } | undefined;
407
410
  consultation?: {
408
411
  enabled: boolean;
409
412
  defaultTimeoutMs: number;
@@ -447,6 +450,26 @@ declare const CallPlan: z.ZodObject<{
447
450
  description?: string | undefined;
448
451
  }[] | undefined;
449
452
  }, {
453
+ stt?: {
454
+ provider: "deepgram" | "cartesia" | "assemblyai";
455
+ model?: string | undefined;
456
+ language?: string | undefined;
457
+ endOfTurnConfidence?: number | undefined;
458
+ endOfTurnTimeoutMs?: number | undefined;
459
+ keywords?: string[] | undefined;
460
+ } | undefined;
461
+ realtime?: {
462
+ provider: "openai" | "google";
463
+ model: string;
464
+ voice?: string | undefined;
465
+ temperature?: number | undefined;
466
+ } | undefined;
467
+ voice?: {
468
+ provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
469
+ voiceId: string;
470
+ model?: string | undefined;
471
+ rate?: number | undefined;
472
+ } | undefined;
450
473
  source?: "playbook" | "sdk" | "flow" | "connector" | undefined;
451
474
  name?: string | undefined;
452
475
  triggers?: Record<string, {
@@ -455,8 +478,8 @@ declare const CallPlan: z.ZodObject<{
455
478
  } | {
456
479
  kind: "endCall";
457
480
  } | {
458
- kind: "say";
459
481
  text: string;
482
+ kind: "say";
460
483
  };
461
484
  on: {
462
485
  kind: "regex";
@@ -472,7 +495,7 @@ declare const CallPlan: z.ZodObject<{
472
495
  toolName: string;
473
496
  defaultArgs?: Record<string, unknown> | undefined;
474
497
  }[] | undefined;
475
- mode?: "cascade" | "realtime" | undefined;
498
+ mode?: "realtime" | "cascade" | undefined;
476
499
  model?: {
477
500
  provider: "openai" | "anthropic" | "gemini";
478
501
  model: string;
@@ -481,28 +504,8 @@ declare const CallPlan: z.ZodObject<{
481
504
  topP?: number | undefined;
482
505
  } | undefined;
483
506
  language?: string | undefined;
484
- voice?: {
485
- provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
486
- voiceId: string;
487
- model?: string | undefined;
488
- rate?: number | undefined;
489
- } | undefined;
490
- realtime?: {
491
- provider: "openai" | "google";
492
- model: string;
493
- temperature?: number | undefined;
494
- voice?: string | undefined;
495
- } | undefined;
496
507
  systemPrompt?: string | undefined;
497
508
  routingInstructions?: string | undefined;
498
- stt?: {
499
- provider: "deepgram" | "cartesia" | "assemblyai";
500
- model?: string | undefined;
501
- language?: string | undefined;
502
- endOfTurnConfidence?: number | undefined;
503
- endOfTurnTimeoutMs?: number | undefined;
504
- keywords?: string[] | undefined;
505
- } | undefined;
506
509
  consultation?: {
507
510
  enabled?: boolean | undefined;
508
511
  defaultTimeoutMs?: number | undefined;
@@ -617,6 +620,26 @@ declare const CallPlan: z.ZodObject<{
617
620
  displayName?: string | undefined;
618
621
  };
619
622
  draftConfig: {
623
+ stt?: {
624
+ provider: "deepgram" | "cartesia" | "assemblyai";
625
+ model?: string | undefined;
626
+ language?: string | undefined;
627
+ endOfTurnConfidence?: number | undefined;
628
+ endOfTurnTimeoutMs?: number | undefined;
629
+ keywords?: string[] | undefined;
630
+ } | undefined;
631
+ realtime?: {
632
+ provider: "openai" | "google";
633
+ model: string;
634
+ voice?: string | undefined;
635
+ temperature?: number | undefined;
636
+ } | undefined;
637
+ voice?: {
638
+ provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
639
+ voiceId: string;
640
+ model?: string | undefined;
641
+ rate?: number | undefined;
642
+ } | undefined;
620
643
  source?: "playbook" | "sdk" | "flow" | "connector" | undefined;
621
644
  name?: string | undefined;
622
645
  triggers?: Record<string, {
@@ -625,8 +648,8 @@ declare const CallPlan: z.ZodObject<{
625
648
  } | {
626
649
  kind: "endCall";
627
650
  } | {
628
- kind: "say";
629
651
  text: string;
652
+ kind: "say";
630
653
  };
631
654
  on: {
632
655
  kind: "regex";
@@ -642,7 +665,7 @@ declare const CallPlan: z.ZodObject<{
642
665
  toolName: string;
643
666
  defaultArgs?: Record<string, unknown> | undefined;
644
667
  }[] | undefined;
645
- mode?: "cascade" | "realtime" | undefined;
668
+ mode?: "realtime" | "cascade" | undefined;
646
669
  model?: {
647
670
  provider: "openai" | "anthropic" | "gemini";
648
671
  model: string;
@@ -651,28 +674,8 @@ declare const CallPlan: z.ZodObject<{
651
674
  topP?: number | undefined;
652
675
  } | undefined;
653
676
  language?: string | undefined;
654
- voice?: {
655
- provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
656
- voiceId: string;
657
- model?: string | undefined;
658
- rate?: number | undefined;
659
- } | undefined;
660
- realtime?: {
661
- provider: "openai" | "google";
662
- model: string;
663
- temperature?: number | undefined;
664
- voice?: string | undefined;
665
- } | undefined;
666
677
  systemPrompt?: string | undefined;
667
678
  routingInstructions?: string | undefined;
668
- stt?: {
669
- provider: "deepgram" | "cartesia" | "assemblyai";
670
- model?: string | undefined;
671
- language?: string | undefined;
672
- endOfTurnConfidence?: number | undefined;
673
- endOfTurnTimeoutMs?: number | undefined;
674
- keywords?: string[] | undefined;
675
- } | undefined;
676
679
  consultation?: {
677
680
  enabled: boolean;
678
681
  defaultTimeoutMs: number;
@@ -757,18 +760,38 @@ declare const CallPlan: z.ZodObject<{
757
760
  secondary?: "ask_callee" | "fallback_phrase" | undefined;
758
761
  };
759
762
  draftConfig?: {
760
- source?: "playbook" | "sdk" | "flow" | "connector" | undefined;
761
- name?: string | undefined;
762
- triggers?: Record<string, {
763
- then: {
764
- kind: "handoff";
765
- } | {
766
- kind: "endCall";
767
- } | {
768
- kind: "say";
769
- text: string;
770
- };
771
- on: {
763
+ stt?: {
764
+ provider: "deepgram" | "cartesia" | "assemblyai";
765
+ model?: string | undefined;
766
+ language?: string | undefined;
767
+ endOfTurnConfidence?: number | undefined;
768
+ endOfTurnTimeoutMs?: number | undefined;
769
+ keywords?: string[] | undefined;
770
+ } | undefined;
771
+ realtime?: {
772
+ provider: "openai" | "google";
773
+ model: string;
774
+ voice?: string | undefined;
775
+ temperature?: number | undefined;
776
+ } | undefined;
777
+ voice?: {
778
+ provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
779
+ voiceId: string;
780
+ model?: string | undefined;
781
+ rate?: number | undefined;
782
+ } | undefined;
783
+ source?: "playbook" | "sdk" | "flow" | "connector" | undefined;
784
+ name?: string | undefined;
785
+ triggers?: Record<string, {
786
+ then: {
787
+ kind: "handoff";
788
+ } | {
789
+ kind: "endCall";
790
+ } | {
791
+ text: string;
792
+ kind: "say";
793
+ };
794
+ on: {
772
795
  kind: "regex";
773
796
  pattern: string;
774
797
  flags?: string | undefined;
@@ -782,7 +805,7 @@ declare const CallPlan: z.ZodObject<{
782
805
  toolName: string;
783
806
  defaultArgs?: Record<string, unknown> | undefined;
784
807
  }[] | undefined;
785
- mode?: "cascade" | "realtime" | undefined;
808
+ mode?: "realtime" | "cascade" | undefined;
786
809
  model?: {
787
810
  provider: "openai" | "anthropic" | "gemini";
788
811
  model: string;
@@ -791,28 +814,8 @@ declare const CallPlan: z.ZodObject<{
791
814
  topP?: number | undefined;
792
815
  } | undefined;
793
816
  language?: string | undefined;
794
- voice?: {
795
- provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
796
- voiceId: string;
797
- model?: string | undefined;
798
- rate?: number | undefined;
799
- } | undefined;
800
- realtime?: {
801
- provider: "openai" | "google";
802
- model: string;
803
- temperature?: number | undefined;
804
- voice?: string | undefined;
805
- } | undefined;
806
817
  systemPrompt?: string | undefined;
807
818
  routingInstructions?: string | undefined;
808
- stt?: {
809
- provider: "deepgram" | "cartesia" | "assemblyai";
810
- model?: string | undefined;
811
- language?: string | undefined;
812
- endOfTurnConfidence?: number | undefined;
813
- endOfTurnTimeoutMs?: number | undefined;
814
- keywords?: string[] | undefined;
815
- } | undefined;
816
819
  consultation?: {
817
820
  enabled?: boolean | undefined;
818
821
  defaultTimeoutMs?: number | undefined;
@@ -1077,13 +1080,13 @@ declare const AgentConfig$1: z.ZodObject<{
1077
1080
  }, "strip", z.ZodTypeAny, {
1078
1081
  provider: "openai" | "google";
1079
1082
  model: string;
1080
- temperature?: number | undefined;
1081
1083
  voice?: string | undefined;
1084
+ temperature?: number | undefined;
1082
1085
  }, {
1083
1086
  provider: "openai" | "google";
1084
1087
  model: string;
1085
- temperature?: number | undefined;
1086
1088
  voice?: string | undefined;
1089
+ temperature?: number | undefined;
1087
1090
  }>>;
1088
1091
  language: z.ZodDefault<z.ZodString>;
1089
1092
  tools: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -1261,11 +1264,11 @@ declare const AgentConfig$1: z.ZodObject<{
1261
1264
  kind: z.ZodLiteral<"say">;
1262
1265
  text: z.ZodString;
1263
1266
  }, "strip", z.ZodTypeAny, {
1264
- kind: "say";
1265
1267
  text: string;
1266
- }, {
1267
1268
  kind: "say";
1269
+ }, {
1268
1270
  text: string;
1271
+ kind: "say";
1269
1272
  }>]>;
1270
1273
  onlyWhile: z.ZodOptional<z.ZodString>;
1271
1274
  }, "strip", z.ZodTypeAny, {
@@ -1274,8 +1277,8 @@ declare const AgentConfig$1: z.ZodObject<{
1274
1277
  } | {
1275
1278
  kind: "endCall";
1276
1279
  } | {
1277
- kind: "say";
1278
1280
  text: string;
1281
+ kind: "say";
1279
1282
  };
1280
1283
  on: {
1281
1284
  kind: "regex";
@@ -1292,8 +1295,8 @@ declare const AgentConfig$1: z.ZodObject<{
1292
1295
  } | {
1293
1296
  kind: "endCall";
1294
1297
  } | {
1295
- kind: "say";
1296
1298
  text: string;
1299
+ kind: "say";
1297
1300
  };
1298
1301
  on: {
1299
1302
  kind: "regex";
@@ -1331,6 +1334,12 @@ declare const AgentConfig$1: z.ZodObject<{
1331
1334
  createdAt: z.ZodString;
1332
1335
  updatedAt: z.ZodString;
1333
1336
  }, "strip", z.ZodTypeAny, {
1337
+ voice: {
1338
+ provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
1339
+ voiceId: string;
1340
+ model?: string | undefined;
1341
+ rate?: number | undefined;
1342
+ };
1334
1343
  id: string;
1335
1344
  projectId: string;
1336
1345
  name: string;
@@ -1340,7 +1349,7 @@ declare const AgentConfig$1: z.ZodObject<{
1340
1349
  toolName: string;
1341
1350
  defaultArgs?: Record<string, unknown> | undefined;
1342
1351
  }[];
1343
- mode: "cascade" | "realtime";
1352
+ mode: "realtime" | "cascade";
1344
1353
  model: {
1345
1354
  provider: "openai" | "anthropic" | "gemini";
1346
1355
  model: string;
@@ -1349,12 +1358,6 @@ declare const AgentConfig$1: z.ZodObject<{
1349
1358
  topP?: number | undefined;
1350
1359
  };
1351
1360
  language: string;
1352
- voice: {
1353
- provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
1354
- voiceId: string;
1355
- model?: string | undefined;
1356
- rate?: number | undefined;
1357
- };
1358
1361
  consultation: {
1359
1362
  enabled: boolean;
1360
1363
  defaultTimeoutMs: number;
@@ -1376,6 +1379,20 @@ declare const AgentConfig$1: z.ZodObject<{
1376
1379
  enum?: string[] | undefined;
1377
1380
  description?: string | undefined;
1378
1381
  }[];
1382
+ stt?: {
1383
+ provider: "deepgram" | "cartesia" | "assemblyai";
1384
+ model?: string | undefined;
1385
+ language?: string | undefined;
1386
+ endOfTurnConfidence?: number | undefined;
1387
+ endOfTurnTimeoutMs?: number | undefined;
1388
+ keywords?: string[] | undefined;
1389
+ } | undefined;
1390
+ realtime?: {
1391
+ provider: "openai" | "google";
1392
+ model: string;
1393
+ voice?: string | undefined;
1394
+ temperature?: number | undefined;
1395
+ } | undefined;
1379
1396
  source?: "playbook" | "sdk" | "flow" | "connector" | undefined;
1380
1397
  triggers?: Record<string, {
1381
1398
  then: {
@@ -1383,8 +1400,8 @@ declare const AgentConfig$1: z.ZodObject<{
1383
1400
  } | {
1384
1401
  kind: "endCall";
1385
1402
  } | {
1386
- kind: "say";
1387
1403
  text: string;
1404
+ kind: "say";
1388
1405
  };
1389
1406
  on: {
1390
1407
  kind: "regex";
@@ -1396,22 +1413,8 @@ declare const AgentConfig$1: z.ZodObject<{
1396
1413
  };
1397
1414
  onlyWhile?: string | undefined;
1398
1415
  }> | undefined;
1399
- realtime?: {
1400
- provider: "openai" | "google";
1401
- model: string;
1402
- temperature?: number | undefined;
1403
- voice?: string | undefined;
1404
- } | undefined;
1405
1416
  systemPrompt?: string | undefined;
1406
1417
  routingInstructions?: string | undefined;
1407
- stt?: {
1408
- provider: "deepgram" | "cartesia" | "assemblyai";
1409
- model?: string | undefined;
1410
- language?: string | undefined;
1411
- endOfTurnConfidence?: number | undefined;
1412
- endOfTurnTimeoutMs?: number | undefined;
1413
- keywords?: string[] | undefined;
1414
- } | undefined;
1415
1418
  process?: {
1416
1419
  collect: Record<string, {
1417
1420
  type: "string" | "number" | "boolean" | "string[]" | "datetime" | "email" | "phone";
@@ -1434,6 +1437,12 @@ declare const AgentConfig$1: z.ZodObject<{
1434
1437
  brainConnectorId?: string | null | undefined;
1435
1438
  modeLocked?: boolean | undefined;
1436
1439
  }, {
1440
+ voice: {
1441
+ provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
1442
+ voiceId: string;
1443
+ model?: string | undefined;
1444
+ rate?: number | undefined;
1445
+ };
1437
1446
  id: string;
1438
1447
  projectId: string;
1439
1448
  name: string;
@@ -1446,12 +1455,6 @@ declare const AgentConfig$1: z.ZodObject<{
1446
1455
  maxOutputTokens?: number | undefined;
1447
1456
  topP?: number | undefined;
1448
1457
  };
1449
- voice: {
1450
- provider: "deepgram" | "elevenlabs" | "openai" | "cartesia";
1451
- voiceId: string;
1452
- model?: string | undefined;
1453
- rate?: number | undefined;
1454
- };
1455
1458
  consultation: {
1456
1459
  enabled?: boolean | undefined;
1457
1460
  defaultTimeoutMs?: number | undefined;
@@ -1466,6 +1469,20 @@ declare const AgentConfig$1: z.ZodObject<{
1466
1469
  normal?: number | undefined;
1467
1470
  } | undefined;
1468
1471
  };
1472
+ stt?: {
1473
+ provider: "deepgram" | "cartesia" | "assemblyai";
1474
+ model?: string | undefined;
1475
+ language?: string | undefined;
1476
+ endOfTurnConfidence?: number | undefined;
1477
+ endOfTurnTimeoutMs?: number | undefined;
1478
+ keywords?: string[] | undefined;
1479
+ } | undefined;
1480
+ realtime?: {
1481
+ provider: "openai" | "google";
1482
+ model: string;
1483
+ voice?: string | undefined;
1484
+ temperature?: number | undefined;
1485
+ } | undefined;
1469
1486
  source?: "playbook" | "sdk" | "flow" | "connector" | undefined;
1470
1487
  triggers?: Record<string, {
1471
1488
  then: {
@@ -1473,8 +1490,8 @@ declare const AgentConfig$1: z.ZodObject<{
1473
1490
  } | {
1474
1491
  kind: "endCall";
1475
1492
  } | {
1476
- kind: "say";
1477
1493
  text: string;
1494
+ kind: "say";
1478
1495
  };
1479
1496
  on: {
1480
1497
  kind: "regex";
@@ -1490,24 +1507,10 @@ declare const AgentConfig$1: z.ZodObject<{
1490
1507
  toolName: string;
1491
1508
  defaultArgs?: Record<string, unknown> | undefined;
1492
1509
  }[] | undefined;
1493
- mode?: "cascade" | "realtime" | undefined;
1510
+ mode?: "realtime" | "cascade" | undefined;
1494
1511
  language?: string | undefined;
1495
- realtime?: {
1496
- provider: "openai" | "google";
1497
- model: string;
1498
- temperature?: number | undefined;
1499
- voice?: string | undefined;
1500
- } | undefined;
1501
1512
  systemPrompt?: string | undefined;
1502
1513
  routingInstructions?: string | undefined;
1503
- stt?: {
1504
- provider: "deepgram" | "cartesia" | "assemblyai";
1505
- model?: string | undefined;
1506
- language?: string | undefined;
1507
- endOfTurnConfidence?: number | undefined;
1508
- endOfTurnTimeoutMs?: number | undefined;
1509
- keywords?: string[] | undefined;
1510
- } | undefined;
1511
1514
  process?: {
1512
1515
  backendAck?: {
1513
1516
  url: string;
@@ -1539,124 +1542,6 @@ declare const AgentConfig$1: z.ZodObject<{
1539
1542
  }>;
1540
1543
  type AgentConfig$1 = z.infer<typeof AgentConfig$1>;
1541
1544
 
1542
- /** Frames a daemon sends up to the relay. */
1543
- declare const ConnectorUpFrame: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
1544
- kind: z.ZodLiteral<"hello">;
1545
- token: z.ZodString;
1546
- replicaId: z.ZodString;
1547
- version: z.ZodString;
1548
- caps: z.ZodObject<{
1549
- streaming: z.ZodBoolean;
1550
- tools: z.ZodBoolean;
1551
- litellm: z.ZodBoolean;
1552
- }, "strip", z.ZodTypeAny, {
1553
- tools: boolean;
1554
- streaming: boolean;
1555
- litellm: boolean;
1556
- }, {
1557
- tools: boolean;
1558
- streaming: boolean;
1559
- litellm: boolean;
1560
- }>;
1561
- }, "strip", z.ZodTypeAny, {
1562
- kind: "hello";
1563
- version: string;
1564
- token: string;
1565
- replicaId: string;
1566
- caps: {
1567
- tools: boolean;
1568
- streaming: boolean;
1569
- litellm: boolean;
1570
- };
1571
- }, {
1572
- kind: "hello";
1573
- version: string;
1574
- token: string;
1575
- replicaId: string;
1576
- caps: {
1577
- tools: boolean;
1578
- streaming: boolean;
1579
- litellm: boolean;
1580
- };
1581
- }>, z.ZodObject<{
1582
- kind: z.ZodLiteral<"pong">;
1583
- ts: z.ZodNumber;
1584
- }, "strip", z.ZodTypeAny, {
1585
- kind: "pong";
1586
- ts: number;
1587
- }, {
1588
- kind: "pong";
1589
- ts: number;
1590
- }>, z.ZodObject<{
1591
- kind: z.ZodLiteral<"brain.delta">;
1592
- streamId: z.ZodString;
1593
- content: z.ZodString;
1594
- }, "strip", z.ZodTypeAny, {
1595
- kind: "brain.delta";
1596
- content: string;
1597
- streamId: string;
1598
- }, {
1599
- kind: "brain.delta";
1600
- content: string;
1601
- streamId: string;
1602
- }>, z.ZodObject<{
1603
- kind: z.ZodLiteral<"brain.done">;
1604
- streamId: z.ZodString;
1605
- finishReason: z.ZodString;
1606
- }, "strip", z.ZodTypeAny, {
1607
- kind: "brain.done";
1608
- streamId: string;
1609
- finishReason: string;
1610
- }, {
1611
- kind: "brain.done";
1612
- streamId: string;
1613
- finishReason: string;
1614
- }>, z.ZodObject<{
1615
- kind: z.ZodLiteral<"brain.error">;
1616
- streamId: z.ZodString;
1617
- code: z.ZodEnum<["upstream_timeout", "upstream_error", "bad_response", "normalize_failed", "unreachable"]>;
1618
- message: z.ZodString;
1619
- }, "strip", z.ZodTypeAny, {
1620
- message: string;
1621
- kind: "brain.error";
1622
- code: "upstream_timeout" | "upstream_error" | "bad_response" | "normalize_failed" | "unreachable";
1623
- streamId: string;
1624
- }, {
1625
- message: string;
1626
- kind: "brain.error";
1627
- code: "upstream_timeout" | "upstream_error" | "bad_response" | "normalize_failed" | "unreachable";
1628
- streamId: string;
1629
- }>]>;
1630
- type ConnectorUpFrame = z.infer<typeof ConnectorUpFrame>;
1631
-
1632
- interface TransportOptions {
1633
- readonly apiKey: string;
1634
- readonly baseUrl: string;
1635
- readonly fetch?: typeof fetch;
1636
- readonly maxRetries?: number;
1637
- readonly initialBackoffMs?: number;
1638
- readonly userAgent?: string;
1639
- }
1640
- interface RequestOptions {
1641
- readonly method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
1642
- readonly path: string;
1643
- readonly body?: unknown;
1644
- readonly query?: Record<string, string | undefined>;
1645
- readonly signal?: AbortSignal;
1646
- /** Extra request headers, merged on top of the defaults (auth/content-type
1647
- * etc). Lowercase keys recommended. */
1648
- readonly headers?: Record<string, string>;
1649
- }
1650
- declare class Transport {
1651
- private readonly options;
1652
- private readonly fetchImpl;
1653
- private readonly maxRetries;
1654
- private readonly initialBackoffMs;
1655
- constructor(options: TransportOptions);
1656
- request<T>(opts: RequestOptions, schema: ZodType<T>): Promise<T>;
1657
- private backoffMs;
1658
- }
1659
-
1660
1545
  interface ReadinessResult {
1661
1546
  readonly ok: boolean;
1662
1547
  /** Human-readable explanation when ok=false. Surfaced in metadata. */
@@ -1758,1150 +1643,1441 @@ interface AgentEventEmitter {
1758
1643
  emit(event: AgentLifecycleEvent): void;
1759
1644
  }
1760
1645
 
1761
- interface RegisterInput {
1762
- readonly name: string;
1763
- readonly version: string;
1764
- readonly environment: AgentEnvironment;
1765
- /** Capability tags (e.g. ['fnol', 'es-MX']). Surfaced in the dashboard. */
1766
- readonly capabilities?: readonly string[];
1767
- /**
1768
- * JSON-serializable process schema for the dashboard "what this agent does"
1769
- * view. Built by `buildProcessSchemaDTO` from the agent's ProcessDefinition.
1770
- */
1771
- readonly processSchema?: ProcessSchemaDTO | null;
1772
- /**
1773
- * Opt this agent into MCP exposure. When true, the API upserts a matching
1774
- * agent_config row keyed by (project_id, name, environment) so MCP /
1775
- * dashboard / REST can list and inspect this agent. Default false — pure
1776
- * SDK agents that don't need MCP visibility stay invisible to it. See
1777
- * docs/architecture/contracts-design.md §2b.
1778
- */
1779
- readonly mcpExposed?: boolean;
1780
- /**
1781
- * Self-checks run before sending the register request. Each result is
1782
- * recorded on the agent. See RegisterOptions.requireReady for failure
1783
- * policy.
1784
- */
1785
- readonly readiness?: readonly ReadinessProbe[];
1786
- /** User metadata. Merged on top of default metadata (user wins on conflict). */
1787
- readonly metadata?: Record<string, unknown>;
1788
- /**
1789
- * Whether to auto-collect host/runtime/build metadata. Default true. Set
1790
- * false to send exactly what you pass in `metadata`.
1791
- */
1792
- readonly collectDefaults?: boolean;
1646
+ /** Primitive field types accepted in a process definition. */
1647
+ type ProcessFieldType = 'string' | 'string[]' | 'number' | 'boolean' | 'datetime' | 'email' | 'phone';
1648
+ interface ProcessField {
1649
+ readonly type: ProcessFieldType;
1650
+ readonly required?: boolean;
1651
+ /** Regex pattern for `string` / `string[]` items. */
1652
+ readonly pattern?: RegExp;
1653
+ /** Inclusive lower bound on a number or array length. */
1654
+ readonly min?: number;
1655
+ /** Inclusive upper bound on a number or array length. */
1656
+ readonly max?: number;
1657
+ /** One of N — restricts the captured value to this set. */
1658
+ readonly enum?: readonly string[];
1659
+ /** Override the auto-generated prompt for capturing this field. */
1660
+ readonly ask?: string;
1661
+ /** Override the field-extraction hint shown to the LLM. */
1662
+ readonly extract?: string;
1793
1663
  }
1794
- interface RegisterOptions {
1795
- /**
1796
- * Override server-suggested heartbeat cadence (ms). When omitted, the SDK
1797
- * uses the value returned by /v1/agents/register, falling back to
1798
- * AGENT_HEARTBEAT_INTERVAL_MS.
1799
- */
1800
- readonly heartbeatIntervalMs?: number;
1801
- /**
1802
- * Disable signal handlers (SIGTERM/SIGINT). Useful in tests and in hosts
1803
- * that own their own shutdown lifecycle.
1804
- */
1805
- readonly attachSignalHandlers?: boolean;
1806
- /**
1807
- * On SIGTERM/SIGINT, call DELETE /v1/agents/:id before exiting so the
1808
- * dashboard reflects "gone" immediately instead of waiting for offline
1809
- * timeout. Default true. Best-effort: errors are swallowed.
1664
+ type CompletionStrategy = 'all-required-captured' | 'all-captured' | {
1665
+ custom: (data: Record<string, unknown>, ctx: AgentContext) => boolean | Promise<boolean>;
1666
+ };
1667
+ interface ProcessBackendAck {
1668
+ /** URL to POST captured data to. The call cannot complete until this 2xx's. */
1669
+ readonly url: string;
1670
+ readonly timeoutMs?: number;
1671
+ readonly headers?: Readonly<Record<string, string>>;
1672
+ }
1673
+ interface ProcessDefinition<T extends Record<string, ProcessField> = Record<string, ProcessField>> {
1674
+ /** Field schema. Order is preserved when the SDK auto-asks for fields. */
1675
+ readonly collect: T;
1676
+ /** When the call can end. Defaults to 'all-required-captured'. */
1677
+ readonly completeWhen?: CompletionStrategy;
1678
+ /** Optional external system that must ACK before completion. */
1679
+ readonly backendAck?: ProcessBackendAck;
1680
+ /** Fires once all completion conditions are met. */
1681
+ readonly onComplete?: (data: InferProcessData<T>, ctx: AgentContext) => Promise<void> | void;
1682
+ /** Fires whenever a field is captured (good for live CRM updates). */
1683
+ readonly onField?: <K extends keyof T>(field: K, value: InferFieldValue<T[K]>, ctx: AgentContext) => Promise<void> | void;
1684
+ }
1685
+ /** Inferred TS type for the data bag a process produces. */
1686
+ type InferProcessData<T extends Record<string, ProcessField>> = {
1687
+ [K in keyof T]: T[K]['required'] extends true ? InferFieldValue<T[K]> : InferFieldValue<T[K]> | undefined;
1688
+ };
1689
+ type InferFieldValue<F extends ProcessField> = F['type'] extends 'string' ? string : F['type'] extends 'string[]' ? string[] : F['type'] extends 'number' ? number : F['type'] extends 'boolean' ? boolean : F['type'] extends 'datetime' ? Date : F['type'] extends 'email' ? string : F['type'] extends 'phone' ? string : never;
1690
+ type TriggerCondition = RegExp | `signal:${string}` | ((text: string, ctx: AgentContext) => boolean | Promise<boolean>);
1691
+ type TriggerAction = 'handoff' | 'endCall' | {
1692
+ say: string;
1693
+ } | {
1694
+ run: (ctx: AgentContext) => Promise<void> | void;
1695
+ }
1696
+ /** Jump the flow-graph cursor to a node id. Only meaningful under the graph
1697
+ * interpreter (the flat goals+rails path has no cursor and ignores it). */
1698
+ | {
1699
+ goto: string;
1700
+ };
1701
+ interface TriggerDefinition {
1702
+ readonly on: TriggerCondition;
1703
+ readonly then: TriggerAction;
1704
+ /** If set, the trigger only fires while the named field is uncaptured. */
1705
+ readonly onlyWhile?: string;
1706
+ }
1707
+ interface HandoffConfig {
1708
+ /** Default human number when a trigger says { then: 'handoff' }. */
1709
+ readonly fallback: string;
1710
+ /** Map signal/trigger names to specific destinations. */
1711
+ readonly routes?: Readonly<Record<string, string>>;
1712
+ /** Build the briefing text passed to the human agent (or PSTN whisper). */
1713
+ readonly briefing?: (args: {
1714
+ readonly data: Record<string, unknown>;
1715
+ readonly transcript: TranscriptHandle;
1716
+ readonly call: AgentContext['call'];
1717
+ }) => string | Promise<string>;
1718
+ /**
1719
+ * 'warm' (default) dials the human into the room as a conference, lets the
1720
+ * agent brief them live, then drops the agent — caller + human stay
1721
+ * connected. 'cold' is a blind SIP REFER: the caller is transferred away
1722
+ * immediately. Warm falls back to cold when no outbound trunk is configured.
1810
1723
  */
1811
- readonly deregisterOnSignal?: boolean;
1724
+ readonly mode?: 'warm' | 'cold';
1725
+ }
1726
+ interface TranscriptHandle {
1727
+ /** Last N turns as `speaker: text` lines. */
1728
+ tail(n: number): string;
1729
+ full(): string;
1730
+ }
1731
+ /**
1732
+ * Memory scope. `'participant'` and `'caller'` are synonyms — `'caller'`
1733
+ * is the historical name from the 1:1 era; new code should prefer
1734
+ * `'participant'`, which makes the multi-party semantics explicit.
1735
+ */
1736
+ type MemoryScope = 'call' | 'caller' | 'participant' | 'account' | 'platform';
1737
+ interface MemoryConfig {
1738
+ /** Which scope to persist to. Defaults to 'caller'. */
1739
+ readonly scope?: MemoryScope;
1740
+ readonly retentionDays?: number;
1741
+ /** Fields auto-redacted on write. Recognized: ssn, dob, email, phone, ccn. */
1742
+ readonly piiFields?: readonly string[];
1743
+ /** Opt in to cross-tenant aggregate memory (anonymized). */
1744
+ readonly platformOptIn?: boolean;
1745
+ }
1746
+ /**
1747
+ * Multi-participant configuration. Optional — when omitted, the agent runs
1748
+ * in 1:1 mode (one human + one agent) and the SDK still populates
1749
+ * `ctx.room.participants` so participant-aware code paths work.
1750
+ */
1751
+ interface ParticipantsConfig {
1812
1752
  /**
1813
- * If any readiness probe reports !ok, throw before calling register.
1814
- * Default false: probes that fail mark the agent as `degraded` instead.
1753
+ * Fires when a human participant joins the room. In 1:1 calls this
1754
+ * fires once at session start for the caller. In multi-party calls it
1755
+ * fires per join.
1815
1756
  */
1816
- readonly requireReady?: boolean;
1757
+ readonly onJoin?: (participant: Participant, ctx: AgentContext) => Promise<void> | void;
1758
+ /** Fires when a participant disconnects (hangup, transfer, kick). */
1759
+ readonly onLeave?: (participant: Participant, ctx: AgentContext) => Promise<void> | void;
1817
1760
  /**
1818
- * Listener for lifecycle events. Equivalent to `agent.events.on(fn)` after
1819
- * register; register-time events (readiness, registered) are also delivered.
1761
+ * Synchronously enrich a participant's attribute bag before `onJoin`
1762
+ * fires. Useful for phone-number → language lookups, etc. The returned
1763
+ * map is merged into `participant.attributes`.
1820
1764
  */
1821
- readonly onEvent?: (event: AgentLifecycleEvent) => void;
1765
+ readonly attributes?: (participant: Participant) => Readonly<Record<string, string>> | Promise<Readonly<Record<string, string>>>;
1766
+ /**
1767
+ * Reject participants beyond this count. Default: unlimited. The cap
1768
+ * is enforced by the worker when wiring participant lifecycle.
1769
+ */
1770
+ readonly max?: number;
1822
1771
  }
1823
- interface RegisteredAgent {
1824
- readonly agent: AgentDTO;
1825
- readonly events: AgentEventEmitter;
1826
- /** Push a status change immediately (next heartbeat carries it too). */
1827
- setStatus(status: 'online' | 'degraded', detail?: string): Promise<void>;
1828
- /** Replace metadata on the next heartbeat. Pass {} to clear. */
1829
- updateMetadata(metadata: Record<string, unknown>): Promise<void>;
1830
- /** Best-effort DELETE; safe to call multiple times. */
1831
- deregister(): Promise<void>;
1832
- /** Stop the heartbeat ticker without deleting the row. Idempotent. */
1833
- stop(): Promise<void>;
1772
+ /**
1773
+ * A connector instance. Created by per-system factories like `salesforce()`,
1774
+ * `twilio()`, etc. The factory returns an opaque handle that the SDK wires
1775
+ * into `ctx.connectors` and (when `expose: true`) into the LLM tool list.
1776
+ */
1777
+ interface ConnectorInstance<TName extends string = string, TApi = unknown> {
1778
+ readonly __connector: true;
1779
+ readonly name: TName;
1780
+ readonly api: TApi;
1781
+ /** If true, every method on `api` becomes an LLM-callable tool. */
1782
+ readonly expose?: boolean;
1834
1783
  }
1835
- interface SchedulerLike {
1836
- setTimeout(cb: () => void, ms: number): NodeJS.Timeout | number;
1837
- clearTimeout(handle: NodeJS.Timeout | number | undefined): void;
1784
+ type ComplianceTag = 'tcpa' | 'hipaa' | 'pci' | 'gdpr' | 'soc2';
1785
+ /**
1786
+ * Duck-typed pipeline component markers. The SDK never inspects these — they
1787
+ * are passed through to LiveKit's AgentSession as-is. Three ways to satisfy:
1788
+ *
1789
+ * 1. SDK factory: `deepgram.tts({ model: 'aura-2' })`
1790
+ * 2. Wrapped LK: `wrap(new TTS({...}), { trace: true })`
1791
+ * 3. User-built: class MyTTS extends BaseTTS { ... } // BaseTTS
1792
+ * // re-exported
1793
+ * // from the SDK
1794
+ *
1795
+ * Anything implementing the duck-type — even a plain object — is accepted.
1796
+ */
1797
+ interface STTProvider {
1798
+ readonly __vlPipeline?: 'stt';
1838
1799
  }
1839
- interface AgentsClientOptions {
1840
- readonly scheduler?: SchedulerLike;
1841
- readonly attachSignalHandlers?: boolean;
1800
+ interface LLMProvider {
1801
+ readonly __vlPipeline?: 'llm';
1842
1802
  }
1843
- declare class AgentsClient {
1844
- private readonly transport;
1845
- private readonly options;
1846
- constructor(transport: Transport, options?: AgentsClientOptions);
1803
+ interface TTSProvider {
1804
+ readonly __vlPipeline?: 'tts';
1805
+ }
1806
+ interface VADProvider {
1807
+ readonly __vlPipeline?: 'vad';
1808
+ }
1809
+ interface TurnDetectorProvider {
1810
+ readonly __vlPipeline?: 'turn';
1811
+ }
1812
+ /**
1813
+ * Speech-to-speech / realtime model marker (OpenAI Realtime, Gemini Live).
1814
+ * A realtime model handles STT + LLM + TTS + turn-taking server-side, so when
1815
+ * `models.realtime` is set the SDK builds the AgentSession around it and
1816
+ * ignores the stt/llm/tts slots.
1817
+ */
1818
+ interface RealtimeProvider {
1819
+ readonly __vlPipeline?: 'realtime';
1820
+ }
1821
+ /**
1822
+ * Lazy form so users can pick a provider per call (e.g. by caller locale).
1823
+ * The factory runs once per call, before AgentSession is constructed, so it
1824
+ * receives the call envelope (callerId, to, metadata) rather than the full
1825
+ * AgentContext (which depends on AgentSession existing).
1826
+ */
1827
+ type ProviderFactory<T> = (call: CallInfo) => T | Promise<T>;
1828
+ interface ModelConfig {
1847
1829
  /**
1848
- * Fetch a deployed agent's compiled process_schema. A flow-runtime worker
1849
- * calls this per dispatched call to boot a visually-built flow. Returns
1850
- * null on 404 or when the agent has no schema.
1830
+ * String form: 'openai/gpt-4o' (resolves via SDK defaults).
1831
+ * Instance form: any LLMProvider (LK plugin, wrap()-ed, or user-built).
1832
+ * Factory form: `(ctx) => provider` for per-call selection.
1851
1833
  */
1852
- getProcessSchema(agentId: string): Promise<ProcessSchemaDTO | null>;
1834
+ readonly llm?: string | LLMProvider | ProviderFactory<LLMProvider>;
1835
+ readonly stt?: string | STTProvider | ProviderFactory<STTProvider>;
1836
+ readonly tts?: string | TTSProvider | ProviderFactory<TTSProvider>;
1837
+ /** VAD has no string form — always pass an instance or factory. */
1838
+ readonly vad?: VADProvider | ProviderFactory<VADProvider>;
1839
+ readonly turnDetector?: TurnDetectorProvider | ProviderFactory<TurnDetectorProvider>;
1853
1840
  /**
1854
- * Fetch a deployed agent's stored AgentConfig — the pipeline the dashboard
1855
- * set (model / voice / stt / mode / realtime). A flow-runtime worker reads
1856
- * this per call so the no-code agent's runtime matches the builder. Returns
1857
- * null on 404 (agent not MCP-exposed or absent).
1841
+ * Speech-to-speech / realtime model. When set, the STT→LLM→TTS pipeline is
1842
+ * bypassed: the realtime model drives the whole turn. No string form — pass
1843
+ * an instance (`openai.realtime({ voice: 'alloy' })`) or a per-call factory.
1858
1844
  */
1859
- getConfig(agentId: string): Promise<AgentConfig$1 | null>;
1860
- register(input: RegisterInput, opts?: RegisterOptions): Promise<RegisteredAgent>;
1861
- list(query?: {
1862
- environment?: AgentEnvironment;
1863
- }): Promise<{
1864
- agents: {
1865
- status: "online" | "offline" | "degraded";
1866
- id: string;
1867
- projectId: string;
1868
- name: string;
1869
- createdAt: string;
1870
- updatedAt: string;
1871
- version: string;
1872
- environment: "dev" | "stg" | "prd";
1873
- statusDetail: string | null;
1874
- capabilities: string[];
1875
- readiness: {
1876
- probe: string;
1877
- ok: boolean;
1878
- detail?: string | undefined;
1879
- }[];
1880
- metadata: Record<string, unknown>;
1881
- lastSeenAt: string | null;
1882
- processSchema?: {
1883
- id: string;
1884
- completionGate: {
1885
- requiredFields: string[];
1886
- backendAck?: {
1887
- url: string;
1888
- timeoutMs: number;
1889
- } | undefined;
1890
- };
1891
- fields: {
1892
- type: "string" | "number" | "boolean" | "string[]" | "datetime" | "email" | "phone";
1893
- name: string;
1894
- required: boolean;
1895
- ask?: string | undefined;
1896
- pattern?: string | undefined;
1897
- min?: number | undefined;
1898
- max?: number | undefined;
1899
- enum?: string[] | undefined;
1900
- }[];
1901
- handoff?: {
1902
- fallback?: string | undefined;
1903
- routes?: Record<string, string> | undefined;
1904
- } | undefined;
1905
- memory?: {
1906
- scope?: "caller" | "call" | "account" | "participant" | "platform" | undefined;
1907
- retentionDays?: number | undefined;
1908
- piiFields?: string[] | undefined;
1909
- } | undefined;
1910
- speech?: {
1911
- interruption?: {
1912
- enabled?: boolean | undefined;
1913
- minWords?: number | undefined;
1914
- minDuration?: number | undefined;
1915
- } | undefined;
1916
- endpointing?: {
1917
- minDelay?: number | undefined;
1918
- maxDelay?: number | undefined;
1919
- } | undefined;
1920
- } | undefined;
1921
- prompts?: {
1922
- id: string;
1923
- text: string;
1924
- }[] | undefined;
1925
- triggers?: {
1926
- then: string;
1927
- name: string;
1928
- on: string;
1929
- onlyWhile?: string | undefined;
1930
- }[] | undefined;
1931
- tools?: {
1932
- name: string;
1933
- description: string;
1934
- input: Record<string, "string" | "number" | "boolean">;
1935
- url: string;
1936
- method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
1937
- auth: "none" | "connection";
1938
- headers?: Record<string, string> | undefined;
1939
- connectionRef?: string | undefined;
1940
- }[] | undefined;
1941
- program?: {
1942
- v: 1;
1943
- id: string;
1944
- nodes: Record<string, {
1945
- type: "code" | "start" | "say" | "ask" | "confirm" | "tool" | "decision" | "handoff" | "end" | "trigger" | "gate" | "playbook" | "menu" | "set" | "subflow" | "llm" | "rag" | "memory" | "speech" | "classify" | "router" | "note";
1946
- id: string;
1947
- config: Record<string, unknown>;
1948
- out: {
1949
- to: string;
1950
- sourceHandle?: string | undefined;
1951
- label?: string | undefined;
1952
- condition?: string | undefined;
1953
- }[];
1954
- }>;
1955
- entry: string[];
1956
- completionGate: {
1957
- requiredFields: string[];
1958
- };
1959
- diagnostics?: {
1960
- acyclic: boolean;
1961
- droppedEdges: string[];
1962
- unsupportedNodes: string[];
1963
- } | undefined;
1964
- } | undefined;
1965
- } | null | undefined;
1966
- }[];
1967
- }>;
1968
- delete(agentId: string): Promise<{
1969
- ok: true;
1970
- }>;
1845
+ readonly realtime?: RealtimeProvider | ProviderFactory<RealtimeProvider>;
1846
+ /** Spoken language; defaults to 'en-US'. Used by string-form defaults. */
1847
+ readonly language?: string;
1971
1848
  }
1972
-
1973
- interface ContextInput {
1974
- readonly callerId: string;
1975
- readonly scopes?: readonly MemoryScope$1[];
1849
+ /**
1850
+ * Answering-machine detection mode for outbound calls. Mirrors
1851
+ * `OutboundConfig.amd` in @voicelayer/agent-spec.
1852
+ *
1853
+ * 'off' — never run AMD; treat every answer as a human.
1854
+ * 'detect' — leave the voicemail message (or hang up) the moment
1855
+ * a machine greeting is recognised.
1856
+ * 'detectMessageEnd' — recognise the machine, then wait for the greeting to
1857
+ * finish (an explicit "after the tone"-style cue or the
1858
+ * greeting going quiet) before leaving the message.
1859
+ */
1860
+ type AmdMode = 'off' | 'detect' | 'detectMessageEnd';
1861
+ /**
1862
+ * Outbound-only behavior. AMD never runs on inbound calls (the runtime gates
1863
+ * on the dispatch-metadata `direction`), so these knobs are inert unless the
1864
+ * call was placed via the outbound path.
1865
+ */
1866
+ interface OutboundCallConfig {
1867
+ /** Answering-machine detection mode. Defaults to 'off'. */
1868
+ readonly amd?: AmdMode;
1869
+ /**
1870
+ * Spoken (via TTS) when a machine is detected. When unset, the agent hangs
1871
+ * up on detection instead of leaving a message.
1872
+ */
1873
+ readonly voicemailScript?: string;
1976
1874
  }
1977
- interface WriteInput {
1978
- readonly scope: MemoryScope$1;
1979
- readonly callerId: string;
1980
- readonly delta: Record<string, unknown>;
1981
- readonly callId?: string;
1875
+ /**
1876
+ * Barge-in tuning. The pipeline allows interruptions by default (LK defaults:
1877
+ * any speech ≥500ms cuts the agent off). These knobs tune that behavior per
1878
+ * agent WITHOUT switching to puppet/hostControlled mode — e.g. a senior-living
1879
+ * help desk wants `minWords: 2` so backchannels ("mm-hm", "okay") don't
1880
+ * truncate the agent mid-sentence, while a fast-paced escalation desk keeps
1881
+ * the zero-word default. Set `enabled: false` to make the agent
1882
+ * non-interruptible (kiosk / broadcast announcements).
1883
+ */
1884
+ interface InterruptionConfig {
1885
+ /** Allow the caller to barge in over agent speech. Default true. */
1886
+ readonly enabled?: boolean;
1887
+ /** Words the caller must say before it counts as an interruption. Default 0
1888
+ * (any speech interrupts). 2–3 filters out backchannels. */
1889
+ readonly minWords?: number;
1890
+ /** Minimum caller speech duration (ms) to count as an interruption. Default 500. */
1891
+ readonly minDuration?: number;
1982
1892
  }
1983
- interface SnapshotInput {
1984
- readonly callId: string;
1985
- readonly stage: string;
1986
- readonly snapshot: Record<string, unknown>;
1893
+ /**
1894
+ * End-of-turn detection tuning: how long the pipeline waits after the caller
1895
+ * stops speaking before treating the turn as finished. Raise `minDelay` for
1896
+ * callers who pause mid-thought (e.g. elderly speakers); lower it for
1897
+ * fast-paced lines.
1898
+ */
1899
+ interface EndpointingConfig {
1900
+ /** Minimum silence (ms) before the caller's turn is considered done. Default 500. */
1901
+ readonly minDelay?: number;
1902
+ /** Hard ceiling (ms) after which the turn ends regardless. Default 3000. */
1903
+ readonly maxDelay?: number;
1987
1904
  }
1988
- interface ResolveInput {
1989
- readonly externalKey: string;
1990
- readonly displayName?: string;
1991
- readonly identifiers?: ReadonlyArray<{
1992
- type: string;
1993
- value: string;
1994
- }>;
1905
+ /**
1906
+ * Speech polish. `pronunciations` rewrites brand names / acronyms / jargon to
1907
+ * a spoken form before TTS (e.g. `{ VoiceLayer: 'Voice Layer', API: 'A P I' }`)
1908
+ * via applyPronunciations(). `backgroundAudio` plays ambient room tone under
1909
+ * the agent so silence feels less dead (a URL or a named preset).
1910
+ * `interruption` + `endpointing` tune barge-in and turn-taking per agent.
1911
+ */
1912
+ interface SpeechConfig {
1913
+ readonly pronunciations?: Readonly<Record<string, string>>;
1914
+ readonly backgroundAudio?: string | {
1915
+ readonly url?: string;
1916
+ readonly volume?: number;
1917
+ };
1918
+ readonly interruption?: InterruptionConfig;
1919
+ readonly endpointing?: EndpointingConfig;
1995
1920
  }
1996
- declare class MemoryClient {
1997
- private readonly transport;
1998
- constructor(transport: Transport);
1999
- context(input: ContextInput): Promise<RelevantContext>;
2000
- write(input: WriteInput): Promise<void>;
2001
- snapshot(input: SnapshotInput): Promise<{
2002
- id: string;
2003
- }>;
2004
- resolveCaller(input: ResolveInput): Promise<ResolveCallerResponse['caller']>;
2005
- deleteCaller(callerId: string): Promise<DeleteCallerResponse>;
1921
+ /** What caused the call to end. Surfaced to `endCall.onEnd` + logs. */
1922
+ type EndCallTrigger =
1923
+ /** The LLM invoked the built-in `end_call` tool. */
1924
+ 'tool'
1925
+ /** An external controller (MCP host) sent a `hangup` command. */
1926
+ | 'host'
1927
+ /** The dead-air backstop fired (`idleHangupMs` of silence while idle). */
1928
+ | 'idle'
1929
+ /** The hard per-call ceiling fired (`maxCallDurationMs` elapsed). */
1930
+ | 'max_duration'
1931
+ /** The last non-agent participant left the room. */
1932
+ | 'participant-left'
1933
+ /** A flow/graph run finished and asked to hang up. */
1934
+ | 'flow'
1935
+ /** The realtime engine closed / disconnected under the session. */
1936
+ | 'engine-closed'
1937
+ /** `ctx.endCall()` called directly from user code. */
1938
+ | 'user';
1939
+ /** Passed to `endCall.onEnd` describing the teardown about to happen. */
1940
+ interface EndCallInfo {
1941
+ /** Why the call is ending (e.g. the `end_call` tool's `reason`). */
1942
+ readonly reason?: string;
1943
+ /** What triggered the hang-up. */
1944
+ readonly trigger: EndCallTrigger;
1945
+ /** The teardown strategy that will run (after the policy is resolved). */
1946
+ readonly teardown: 'room' | 'agent';
2006
1947
  }
2007
-
2008
- type CallStatus = 'in_progress' | 'completed' | 'failed';
2009
- type CallAttributeValue = string | number | boolean;
2010
- type CallParticipantRole = 'caller' | 'agent' | 'callee' | 'supervisor' | 'observer' | 'unknown';
2011
- type CallParticipantKind = 'human' | 'agent' | 'phone' | 'sip' | 'system';
2012
- type CallLegKind = 'sip-inbound' | 'sip-outbound' | 'agent-session' | 'conference' | 'transfer' | 'unknown';
2013
- type CallLegStatus = 'starting' | 'active' | 'ended';
2014
- interface CallSummary {
2015
- readonly id: string;
2016
- readonly projectId: string;
2017
- readonly livekitRoom: string;
2018
- readonly phoneNumberId: string | null;
2019
- readonly agentId: string | null;
2020
- readonly bindingId: string | null;
2021
- readonly callerE164: string | null;
2022
- readonly toE164: string | null;
2023
- readonly status: CallStatus;
2024
- readonly startedAt: string;
1948
+ /**
1949
+ * Controls how the agent ENDS a call. The SDK — not the agent prompt or an
1950
+ * external puppet driver — owns teardown, so a hang-up is reliable even when
1951
+ * the realtime transport has died mid-wrap.
1952
+ *
1953
+ * Defaults are "best case" and active without opt-in: the whole LiveKit room
1954
+ * is deleted (which drops the SIP/PSTN leg too, so the carrier gets a BYE),
1955
+ * a guarantee-watchdog re-attempts teardown if the first try doesn't land, and
1956
+ * a dead-air backstop hangs up after the line has been silent too long. Every
1957
+ * knob is overridable; set a field to `false` to disable that guard.
1958
+ */
1959
+ interface EndCallPolicy {
1960
+ /**
1961
+ * Teardown strategy. `'room'` (default) deletes the LiveKit room via the
1962
+ * room service — this removes the SIP participant too, so the call actually
1963
+ * disconnects on the carrier side. `'agent'` only drops the agent's own
1964
+ * participant (leaves any SIP leg up); use it only when something else owns
1965
+ * the room lifecycle.
1966
+ */
1967
+ readonly teardown?: 'room' | 'agent';
1968
+ /**
1969
+ * After a hang-up is requested, keep re-attempting teardown until the room
1970
+ * is actually gone or this many ms elapse. Guards against a teardown call
1971
+ * that silently doesn't land (transport race, transient room-service error).
1972
+ * Default 4000. `false` disables (single best-effort attempt).
1973
+ */
1974
+ readonly guaranteeMs?: number | false;
1975
+ /**
1976
+ * Dead-air backstop: when the agent is idle (waiting on the caller) and the
1977
+ * line stays silent — no agent turn, no caller speech — for this many ms,
1978
+ * end the call. Catches a wedged session whose normal `end_call` never ran.
1979
+ * Only armed while the agent is idle, so it never interrupts agent speech or
1980
+ * a long tool call. Default 20000. `false` disables.
1981
+ */
1982
+ readonly idleHangupMs?: number | false;
1983
+ /**
1984
+ * Hard call ceiling: hang up once the call has run this many ms from when
1985
+ * the session becomes ready, regardless of activity. Catches runaway calls
1986
+ * that never end naturally (stuck loops, hijacked keys dialing premium
1987
+ * numbers). Fires with trigger `'max_duration'`. Default 3600000 (60
1988
+ * minutes). `false` disables.
1989
+ */
1990
+ readonly maxCallDurationMs?: number | false;
1991
+ /**
1992
+ * Hook fired the moment a hang-up is decided, just before teardown — for
1993
+ * every trigger (tool, host, idle, max_duration, engine-closed, …). Return
1994
+ * `false` to take over teardown yourself (the SDK then does nothing — the
1995
+ * call will NOT end unless you end it). Returning anything else (or nothing)
1996
+ * runs the default teardown. Throwing is caught + logged, then the default
1997
+ * teardown still runs (safe by default).
1998
+ *
1999
+ * EXCEPT a host hangup (`trigger: 'host'` — MCP `call_hangup`): the host is
2000
+ * the operator, so the hook is told (with the host's reason) and given 2
2001
+ * seconds, but can't keep the call open; the room is always deleted, even
2002
+ * after an earlier hang-up was vetoed and whatever `teardown` says (0.2.0).
2003
+ */
2004
+ readonly onEnd?: (ctx: AgentContext, info: EndCallInfo) => boolean | void | Promise<boolean | void>;
2025
2005
  }
2026
- interface CallUsageReport {
2027
- readonly durationMs: number;
2028
- readonly llm: readonly {
2029
- readonly provider: string;
2030
- readonly model: string;
2031
- readonly inputTokens: number;
2032
- readonly outputTokens: number;
2033
- }[];
2034
- readonly tts: readonly {
2035
- readonly provider: string;
2036
- readonly chars: number;
2037
- }[];
2038
- readonly stt: readonly {
2039
- readonly provider: string;
2040
- readonly seconds: number;
2041
- }[];
2042
- }
2043
- interface AppendTranscriptInput {
2044
- readonly speaker: 'caller' | 'agent';
2045
- readonly text: string;
2046
- readonly startMs: number;
2047
- readonly endMs: number;
2048
- readonly final?: boolean;
2049
- }
2050
- type DtmfDirection = 'received' | 'sent';
2051
- interface AppendDtmfEventInput {
2052
- readonly direction: DtmfDirection;
2053
- readonly digit: string;
2054
- readonly code: number;
2055
- readonly participantId?: string;
2056
- }
2057
- interface EnsureCallByRoomInput {
2058
- readonly roomName: string;
2059
- readonly phoneNumberId?: string;
2060
- readonly agentId?: string;
2061
- readonly bindingId?: string;
2062
- readonly callerE164?: string;
2063
- readonly toE164?: string;
2064
- readonly attributes?: Record<string, CallAttributeValue>;
2065
- readonly participants?: CallParticipantInput[];
2066
- readonly legs?: CallLegInput[];
2067
- readonly startedAt?: string;
2006
+ type ShorthandPrimitive$1 = 'string' | 'number' | 'boolean';
2007
+ type ToolInputShape$1 = Record<string, ShorthandPrimitive$1> | z.ZodTypeAny;
2008
+ interface ToolDefinition$1<I = unknown, R = unknown> {
2009
+ readonly description: string;
2010
+ readonly input: ToolInputShape$1;
2011
+ readonly run: (input: I, ctx: AgentContext) => Promise<R> | R;
2012
+ /**
2013
+ * Capability this tool requires. Action Guard hard-blocks the call if not
2014
+ * declared (PRD §B.5 — "no soft failures, ever"). Defaults to
2015
+ * `tool.<name>` when omitted; passing a domain-scoped string
2016
+ * (`crm.write`, `payment.refund`) lets multiple tools share a capability
2017
+ * for centralised policy.
2018
+ */
2019
+ readonly capability?: string;
2068
2020
  }
2069
- interface CallParticipantInput {
2070
- readonly participantKey: string;
2071
- readonly role: CallParticipantRole;
2072
- readonly kind: CallParticipantKind;
2073
- readonly identity?: string | null;
2074
- readonly address?: string | null;
2075
- readonly displayName?: string | null;
2076
- readonly joinedAt?: string;
2077
- readonly leftAt?: string | null;
2078
- readonly metadata?: Record<string, unknown>;
2021
+ /**
2022
+ * Optional security adapters. The SDK always enforces the local-only synchronous
2023
+ * guards (PRD §B.2 input regex, §B.3 system seal + PII tokenisation, §B.4
2024
+ * markdown strip + PII partial-mask, §B.5 capability check). Setting any of
2025
+ * these augments the local floor with external services. Each is independently
2026
+ * optional — none has to be live for the floor guards to function.
2027
+ *
2028
+ * URLs can also come from env (`SECURITY_LLM_GUARD_URL`,
2029
+ * `SECURITY_PRESIDIO_ANALYZER_URL`, `SECURITY_PRESIDIO_ANONYMIZER_URL`,
2030
+ * `SECURITY_OPA_URL`, `SECURITY_OPA_DECISION_PATH`); explicit config wins.
2031
+ */
2032
+ interface SecurityConfig {
2033
+ /** Disable the primitive entirely. Use only for tests. Production code MUST NOT set this. */
2034
+ readonly disabled?: boolean;
2035
+ /** External LLM-Guard adapter for richer injection detection. */
2036
+ readonly llmGuardUrl?: string;
2037
+ /** Presidio analyzer URL for PII detection beyond local regex. */
2038
+ readonly presidioAnalyzerUrl?: string;
2039
+ /** Presidio anonymizer URL — if set, output is redacted before TTS. */
2040
+ readonly presidioAnonymizerUrl?: string;
2041
+ /** OPA decision API base URL (e.g. `http://opa:8181`). */
2042
+ readonly opaUrl?: string;
2043
+ /** OPA decision path (e.g. `voicelayer/security/decision`). */
2044
+ readonly opaDecisionPath?: string;
2045
+ /** Per-request timeout for security adapter calls. */
2046
+ readonly adapterTimeoutMs?: number;
2079
2047
  }
2080
- interface CallLegInput {
2081
- readonly legKey: string;
2082
- readonly kind: CallLegKind;
2083
- readonly status: CallLegStatus;
2084
- readonly fromParticipantKey?: string | null;
2085
- readonly toParticipantKey?: string | null;
2086
- readonly fromAddress?: string | null;
2087
- readonly toAddress?: string | null;
2088
- readonly startedAt?: string;
2089
- readonly endedAt?: string | null;
2090
- readonly metadata?: Record<string, unknown>;
2048
+ /**
2049
+ * Marks an agent as a *flow-runtime* worker: instead of a fixed process it
2050
+ * resolves the deployed flow from the dispatch metadata (`agentId`) at call
2051
+ * time, fetches that agent's compiled process_schema, and boots from it. One
2052
+ * process serves many flows (the shared pool). See defineFlowRuntime().
2053
+ */
2054
+ interface FlowRuntimeConfig {
2055
+ /** Prepended to the flow's compiled say/confirm prompt fragments. */
2056
+ readonly basePrompt?: string;
2057
+ /** Spoken (verbatim) before hanging up when a flow call's schema cannot be
2058
+ * loaded. A failed flow boot NEVER silently answers as a generic assistant. */
2059
+ readonly bootFailureMessage?: string;
2091
2060
  }
2092
- interface SyncCallStateInput {
2093
- readonly attributes?: Record<string, CallAttributeValue>;
2094
- readonly participants?: CallParticipantInput[];
2095
- readonly legs?: CallLegInput[];
2061
+ /** Output content-moderation guard config (P5). Mirrors @voicelayer/plugin-guard's
2062
+ * GuardConfig; the pure inspector lives in runtime/guard.ts. */
2063
+ interface GuardConfig {
2064
+ /** Flag content longer than this many characters. Default 8000. */
2065
+ readonly maxLength?: number;
2066
+ /** Substrings that flag content (case-insensitive). Default none. */
2067
+ readonly bannedSubstrings?: readonly string[];
2096
2068
  }
2097
- declare class CallsClient {
2098
- private readonly transport;
2099
- constructor(transport: Transport);
2100
- getByRoom(roomName: string): Promise<CallSummary>;
2101
- ensureByRoom(input: EnsureCallByRoomInput): Promise<CallSummary>;
2102
- syncState(callId: string, input: SyncCallStateInput): Promise<void>;
2103
- appendTranscriptSegment(callId: string, input: AppendTranscriptInput): Promise<void>;
2104
- reportUsage(callId: string, report: CallUsageReport): Promise<void>;
2105
- appendDtmfEvent(callId: string, input: AppendDtmfEventInput): Promise<void>;
2069
+ interface AgentConfig<TProcess extends Record<string, ProcessField> = Record<string, ProcessField>> {
2070
+ /** Lowercase, kebab-case identifier. Used for LiveKit dispatch + presence. */
2071
+ readonly name: string;
2072
+ /** System prompt the LLM sees. */
2073
+ readonly prompt: string;
2074
+ /** Fixed opening line, spoken instantly via TTS at the start of the default
2075
+ * conversation flow — NO LLM. Eliminates the dead air of an LLM-generated
2076
+ * greeting (the first generateReply must process the whole system prompt).
2077
+ * Absent → the SDK falls back to an LLM-generated greeting. */
2078
+ readonly greeting?: string;
2079
+ /** Agent-level Instructions (the routing/decision layer): plain-language guidance
2080
+ * for WHEN the agent acts, appended below the persona under a `# Routing` header.
2081
+ * Interpolated with {{ }} by the process runtime. Optional. */
2082
+ readonly routingInstructions?: string;
2083
+ /** Capability tags surfaced in the dashboard. */
2084
+ readonly capabilities?: readonly string[];
2085
+ /** Semantic version. Defaults to AGENT_VERSION env or '0.0.0'. */
2086
+ readonly version?: string;
2087
+ /** dev / stg / prd. Defaults to AGENT_ENVIRONMENT env or 'dev'. */
2088
+ readonly environment?: AgentEnvironment;
2089
+ readonly process?: ProcessDefinition<TProcess>;
2090
+ readonly triggers?: Readonly<Record<string, TriggerDefinition>>;
2091
+ readonly handoff?: HandoffConfig;
2092
+ readonly memory?: MemoryConfig;
2093
+ readonly participants?: ParticipantsConfig;
2094
+ readonly connectors?: Readonly<Record<string, ConnectorInstance>>;
2095
+ readonly compliance?: readonly ComplianceTag[];
2096
+ readonly models?: ModelConfig;
2097
+ readonly outbound?: OutboundCallConfig;
2098
+ readonly speech?: SpeechConfig;
2099
+ readonly endCall?: EndCallPolicy;
2100
+ readonly tools?: Readonly<Record<string, ToolDefinition$1>>;
2101
+ /** Per-agent registry-tool scoping (stored ToolBinding names, applied at
2102
+ * boot). Non-empty → only these dashboard HTTP tools attach; absent/[] →
2103
+ * every enabled registry tool attaches (the historical default). */
2104
+ readonly toolBindings?: readonly string[];
2105
+ readonly security?: SecurityConfig;
2106
+ /** Output content-moderation guard (P5). When set, each assistant turn is
2107
+ * inspected and a violation is recorded as an engine.guard.blocked event on
2108
+ * the call timeline. OBSERVE-ONLY on voice — it audits, it does not unsay a
2109
+ * spoken turn. Absent → no guard. */
2110
+ readonly guard?: GuardConfig;
2106
2111
  /**
2107
- * Append a structured call event — consultation lifecycle kinds, or the
2108
- * operational vocabulary the call-detail Timeline renders between
2109
- * transcript rows (tool.* / handoff.* / lookup.* / record.* / notify.*).
2110
- * See apps/api/src/routes/calls.ts AppendEventBody for the accepted shapes.
2112
+ * Per-call ConsultationPolicy used by the built-in `ask_host` tool. When
2113
+ * omitted the SDK uses the contract defaults (30s per-consult, 120s
2114
+ * cumulative). Plan-first calls override this at boot from
2115
+ * `plan.draftConfig.consultation`. See
2116
+ * packages/contracts/src/consultation.ts for the schema + semantics.
2117
+ */
2118
+ readonly consultation?: ConsultationPolicy;
2119
+ /**
2120
+ * Use your existing text agent as the LLM. When set (and `models.llm` is
2121
+ * unset), defineAgent wires the pipeline's LLM slot to this function: the
2122
+ * caller's STT transcript is passed to `onQuery`, and its returned text (or
2123
+ * streamed pieces) is spoken by TTS. The "two lines, keep your stack" path.
2111
2124
  *
2112
- * The agent SDK's built-in `ask_host` tool calls this on consultation start
2113
- * / end; the handoff runtime and graph interpreter emit op events through it
2114
- * so the operational story (dial → answered → briefed → dropped, tool calls)
2115
- * is visible in the dashboard, not just the spoken transcript.
2125
+ * Equivalent to `models: { llm: connector.llm({ onQuery }) }`. For a remote
2126
+ * brain instead, use `connector.llm({ url })` (direct) or a tunnel transport.
2127
+ * See docs/specs/voice-brain-connector/.
2116
2128
  */
2117
- appendEvent(callId: string, input: {
2118
- readonly kind: 'consultation.requested' | 'consultation.resolved' | `tool.${string}` | `handoff.${string}` | `lookup.${string}` | `record.${string}` | `notify.${string}`;
2119
- readonly payload: Record<string, unknown>;
2120
- }): Promise<void>;
2121
- }
2122
-
2123
- interface CreateFormSessionInput {
2124
- readonly formId: string;
2125
- readonly recipientPhone: string;
2126
- readonly recipientName?: string;
2127
- readonly prefill?: Record<string, unknown>;
2128
- readonly webhookUrl?: string;
2129
- readonly callbackFromNumber?: string;
2130
- readonly ttlSeconds?: number;
2129
+ readonly onQuery?: OnQuery;
2130
+ readonly onUtterance?: (text: string, ctx: AgentContext) => Promise<void> | void;
2131
+ readonly onFieldCaptured?: (field: string, value: unknown, ctx: AgentContext) => Promise<void> | void;
2132
+ readonly onCallEnd?: (outcome: CallOutcomeSummary, ctx: AgentContext) => Promise<void> | void;
2133
+ readonly onEvent?: (event: AgentLifecycleEvent) => void;
2134
+ /** Replace the default conversation loop. The SDK does NOT auto-greet. */
2135
+ readonly onCall?: (ctx: AgentContext) => Promise<void>;
2136
+ readonly readiness?: readonly ReadinessProbe[];
2131
2137
  /**
2132
- * When set, the API will SMS the link from this phone number immediately
2133
- * after creating the session. This is the common case for agent-led use:
2134
- * the agent calls sendFormLink during a conversation and the recipient
2135
- * gets a text right away.
2138
+ * Run as a remote-controlled (puppet) agent: no autonomous LLM loop, no
2139
+ * process/triggers pipeline. STT utterances are still published to
2140
+ * `call-events:{callId}` via the existing transcript-segments sync, and
2141
+ * the SDK subscribes to `call-control:{room}` to receive `say`,
2142
+ * `hangup`, `dtmf` commands from an external driver (typically the MCP
2143
+ * server invoked by a coding agent).
2144
+ *
2145
+ * When this is on, `process`, `triggers`, `onUtterance`, `onCall` are
2146
+ * ignored. `tools`, `connectors`, `memory` still work.
2136
2147
  */
2137
- readonly sendSms?: {
2138
- readonly phoneNumberId: string;
2139
- readonly bodyPrefix?: string;
2140
- };
2148
+ readonly puppetMode?: boolean;
2141
2149
  /**
2142
- * When set, the API will email the link to `to` immediately after creating
2143
- * the session. Independent from sendSms — set both for belt-and-braces
2144
- * delivery, set neither to just receive the URL back. Use this when SMS is
2145
- * blocked by toll-fraud / 10DLC registration.
2150
+ * Host-controlled autonomous agent (the "smart puppet"). UNLIKE puppetMode,
2151
+ * the agent keeps its REAL LLM and drives the conversation itself from its
2152
+ * prompt (the per-call `intent` is appended at boot). Since 0.2.0 EVERY
2153
+ * agent listens on its call's control channel (the MCP host can interject
2154
+ * with `say`, `hangup` or send `dtmf`, and answer `ask_host`), so this flag
2155
+ * now only shapes turn handling for a host-driven call. Use this for an agent that takes a customer's
2156
+ * intent and runs the call like a human secretary, asking the host for any
2157
+ * info it's missing. Mutually exclusive in spirit with puppetMode (which is
2158
+ * the older NoOp "dumb mouth").
2146
2159
  */
2147
- readonly sendEmail?: {
2148
- readonly to: string;
2149
- readonly subject?: string;
2150
- readonly bodyPrefix?: string;
2151
- };
2152
- }
2153
- interface CreatedFormSession {
2154
- readonly sessionId: string;
2155
- readonly token: string;
2156
- readonly url: string;
2157
- readonly smsId: string | null;
2158
- readonly emailId: string | null;
2159
- readonly expiresAt: string;
2160
- }
2161
- interface PublicFormSessionView {
2162
- readonly schema: {
2163
- readonly id: string;
2164
- readonly version: number;
2165
- readonly title: string;
2166
- readonly description?: string | undefined;
2167
- readonly survey: Record<string, unknown>;
2168
- };
2169
- readonly values: Record<string, unknown>;
2170
- readonly status: 'pending' | 'active' | 'live' | 'submitted' | 'expired';
2171
- readonly recipientPhoneMasked: string;
2172
- readonly hasActiveCall: boolean;
2173
- readonly submittedAt: string | null;
2174
- readonly expiresAt: string;
2160
+ readonly hostControlled?: boolean;
2161
+ /** When set, this agent boots each call from a deployed flow's process_schema. */
2162
+ readonly flowRuntime?: FlowRuntimeConfig;
2163
+ /**
2164
+ * Opt a hand-coded (non-flow) agent into the dashboard-driven pipeline: on
2165
+ * each call the SDK fetches this agent's PUBLISHED configuration (a saved
2166
+ * dashboard draft applies only once the owner publishes it) and applies
2167
+ * the operator-selected voice / model / STT over the coded defaults. The
2168
+ * pipeline *mode* (cascade vs realtime) stays pinned to what the code
2169
+ * declares — a stale `mode=realtime` in the dashboard can't flip a
2170
+ * cascade-only worker. Flow agents (`flowRuntime`) get this implicitly and
2171
+ * may additionally switch mode; this flag is the SDK opt-in. The agent id is
2172
+ * read from dispatch metadata (the inbound router injects it from
2173
+ * phone_numbers.agentId), so it's a no-op for calls without one.
2174
+ */
2175
+ readonly pipelineFromConfig?: boolean;
2176
+ /**
2177
+ * Opt this agent into MCP-layer visibility. When true, on register the API
2178
+ * also writes an `agent_config` row keyed by (project_id, name,
2179
+ * environment) so MCP / dashboard / REST can list and inspect this agent
2180
+ * (and, post-step-7, drive call_say / call_send_guidance / etc against
2181
+ * its live calls).
2182
+ *
2183
+ * Defaults to true so newly-registered agents show up in dashboards and
2184
+ * MCP-host listings without opt-in. Pass `false` for autonomous-only
2185
+ * agents that should stay invisible to MCP. See
2186
+ * docs/architecture/contracts-design.md §2b.
2187
+ */
2188
+ readonly mcpExposed?: boolean;
2175
2189
  }
2176
- declare class FormsClient {
2177
- private readonly transport;
2178
- constructor(transport: Transport);
2179
- createSession(input: CreateFormSessionInput): Promise<CreatedFormSession>;
2180
- getByToken(token: string): Promise<PublicFormSessionView>;
2181
- patchValues(token: string, values: Record<string, unknown>): Promise<{
2182
- values: Record<string, unknown>;
2183
- updatedAt: string;
2184
- }>;
2185
- submit(token: string, values: Record<string, unknown>): Promise<{
2186
- responseId: string;
2187
- submittedAt: string;
2188
- }>;
2190
+ interface CallOutcomeSummary {
2191
+ readonly reason: 'completed' | 'handoff' | 'caller_hung_up' | 'agent_hung_up' | 'error';
2192
+ readonly durationMs: number;
2193
+ readonly processCompleted: boolean;
2194
+ readonly fieldsCaptured: number;
2195
+ readonly handoffOccurred: boolean;
2189
2196
  }
2197
+ /**
2198
+ * Identity helper that gives users a typed `defineProcess` entry point with
2199
+ * full inference on `onComplete`'s `data` argument.
2200
+ *
2201
+ * defineProcess({
2202
+ * collect: { name: { type: 'string', required: true } },
2203
+ * onComplete: (data) => { data.name // string },
2204
+ * })
2205
+ */
2206
+ declare function defineProcess<T extends Record<string, ProcessField>>(def: ProcessDefinition<T>): ProcessDefinition<T>;
2190
2207
 
2191
- interface SendEmailInput {
2192
- readonly to: string;
2193
- readonly subject: string;
2194
- readonly text: string;
2195
- readonly html?: string;
2196
- }
2197
- interface SentEmail {
2198
- readonly emailId: string;
2208
+ interface RunAgentTextTranscriptOptions {
2209
+ /** The agent's system prompt / instructions (its code-defined behavior). */
2210
+ readonly instructions: string;
2211
+ /** The LLM that generates replies — injected so this stays provider-agnostic and
2212
+ * unit-testable (real inference/openai LLM in prod; a scripted fake in tests). */
2213
+ readonly llm: llm.LLM;
2214
+ /** Scripted caller turns, run in order; each produces the agent's reply turn(s). */
2215
+ readonly messages: readonly string[];
2216
+ /** Optional id surfaced on the Agent (for traceability). */
2217
+ readonly agentId?: string;
2199
2218
  }
2200
- declare class EmailClient {
2201
- private readonly transport;
2202
- constructor(transport: Transport);
2203
- send(input: SendEmailInput): Promise<SentEmail>;
2219
+ interface AgentTextTranscriptResult {
2220
+ readonly replies: string[];
2204
2221
  }
2205
-
2206
- declare class PlansClient {
2207
- private readonly transport;
2208
- constructor(transport: Transport);
2222
+ interface RunLiveAgentTextOptions {
2223
+ /** The agent's system prompt / instructions (its code-defined behavior). */
2224
+ readonly instructions: string;
2225
+ /** The LLM that generates replies (injected — real provider LLM or a fake). */
2226
+ readonly llm: llm.LLM;
2227
+ /** Optional id surfaced on the Agent (for traceability). */
2228
+ readonly agentId?: string;
2209
2229
  /**
2210
- * Fetch a plan by id. Project scoping is enforced by the API via the
2211
- * caller's VOICELAYER_API_KEY — a cross-project planId surfaces as 404.
2212
- * Returns `null` on 404 so the caller can fall back to legacy boot.
2230
+ * Labels for the model usage each turn reports (the surface that owns the reply meters it): which provider and
2231
+ * model this session's LLM is, and whether the workspace's own key (BYOK) serves it. Absent ⇒ turns report no usage.
2213
2232
  */
2214
- getById(planId: string): Promise<CallPlan | null>;
2215
- }
2216
-
2217
- declare const ProviderCredential: z.ZodObject<{
2218
- apiKey: z.ZodString;
2219
- baseUrl: z.ZodOptional<z.ZodString>;
2220
- }, "strip", z.ZodTypeAny, {
2221
- apiKey: string;
2222
- baseUrl?: string | undefined;
2223
- }, {
2224
- apiKey: string;
2225
- baseUrl?: string | undefined;
2226
- }>;
2227
- type ProviderCredential = z.infer<typeof ProviderCredential>;
2228
- declare const BrainConnectorConfig: z.ZodObject<{
2229
- connector: z.ZodObject<{
2230
- id: z.ZodString;
2231
- mode: z.ZodEnum<["tunnel", "direct"]>;
2232
- connectionId: z.ZodNullable<z.ZodString>;
2233
- defaultModel: z.ZodNullable<z.ZodString>;
2234
- normalize: z.ZodEnum<["auto", "on", "off"]>;
2235
- enabled: z.ZodBoolean;
2236
- credential: z.ZodOptional<z.ZodNullable<z.ZodObject<{
2237
- apiKey: z.ZodString;
2238
- baseUrl: z.ZodString;
2239
- }, "strip", z.ZodTypeAny, {
2240
- apiKey: string;
2241
- baseUrl: string;
2242
- }, {
2243
- apiKey: string;
2244
- baseUrl: string;
2245
- }>>>;
2246
- }, "strip", z.ZodTypeAny, {
2247
- id: string;
2248
- enabled: boolean;
2249
- mode: "tunnel" | "direct";
2250
- defaultModel: string | null;
2251
- connectionId: string | null;
2252
- normalize: "on" | "off" | "auto";
2253
- credential?: {
2254
- apiKey: string;
2255
- baseUrl: string;
2256
- } | null | undefined;
2257
- }, {
2258
- id: string;
2259
- enabled: boolean;
2260
- mode: "tunnel" | "direct";
2261
- defaultModel: string | null;
2262
- connectionId: string | null;
2263
- normalize: "on" | "off" | "auto";
2264
- credential?: {
2265
- apiKey: string;
2266
- baseUrl: string;
2267
- } | null | undefined;
2268
- }>;
2269
- }, "strip", z.ZodTypeAny, {
2270
- connector: {
2271
- id: string;
2272
- enabled: boolean;
2273
- mode: "tunnel" | "direct";
2274
- defaultModel: string | null;
2275
- connectionId: string | null;
2276
- normalize: "on" | "off" | "auto";
2277
- credential?: {
2278
- apiKey: string;
2279
- baseUrl: string;
2280
- } | null | undefined;
2281
- };
2282
- }, {
2283
- connector: {
2284
- id: string;
2285
- enabled: boolean;
2286
- mode: "tunnel" | "direct";
2287
- defaultModel: string | null;
2288
- connectionId: string | null;
2289
- normalize: "on" | "off" | "auto";
2290
- credential?: {
2291
- apiKey: string;
2292
- baseUrl: string;
2293
- } | null | undefined;
2233
+ readonly meter?: {
2234
+ readonly provider: string;
2235
+ readonly model: string;
2236
+ readonly byok: boolean;
2294
2237
  };
2295
- }>;
2296
- type BrainConnectorConfig = z.infer<typeof BrainConnectorConfig>['connector'];
2297
- declare class ConnectionsClient {
2298
- private readonly transport;
2299
- constructor(transport: Transport);
2300
- resolveProviderCredential(provider: string): Promise<ProviderCredential | null>;
2301
- resolveBrainConnectorConfig(id: string): Promise<BrainConnectorConfig | null>;
2302
2238
  }
2239
+ /** Model usage behind one turn (one entry per model request) — the host-sdk `TurnModelUsage` shape, structurally. */
2240
+ interface LiveAgentTurnUsage {
2241
+ readonly provider: string;
2242
+ readonly model: string;
2243
+ readonly inputTokens: number;
2244
+ readonly outputTokens: number;
2245
+ readonly byok: boolean;
2246
+ }
2247
+ /** One live turn of a code-first agent: the assistant text for that turn, and
2248
+ * whether the conversation ended (code-first sessions stay open until `end`). */
2249
+ interface LiveAgentTurn {
2250
+ readonly replies: string[];
2251
+ readonly done: boolean;
2252
+ /** The model requests this turn made (only when the session was given `meter` labels). */
2253
+ readonly usage?: readonly LiveAgentTurnUsage[];
2254
+ }
2255
+ /** A live, turn-by-turn conversation with a code-first agent — the AgentSession is
2256
+ * kept alive across turns (it carries chat history internally), so this is the
2257
+ * code-first analogue of `runLiveTextConversation` (the flow driver). Shape
2258
+ * matches the engine's AgentConversation so the agent-runner drives both alike. */
2259
+ interface LiveAgentTextSession {
2260
+ /** Start the session. Code-first agents don't auto-greet in no-room text mode,
2261
+ * so the opening turn is empty; the first user turn produces the first reply. */
2262
+ start(): Promise<LiveAgentTurn>;
2263
+ /** Feed one user message; resolves with the agent's replies for that turn. */
2264
+ turn(text: string): Promise<LiveAgentTurn>;
2265
+ /** Close the session. */
2266
+ end(): Promise<void>;
2267
+ }
2268
+ declare function runLiveAgentTextSession(opts: RunLiveAgentTextOptions): LiveAgentTextSession;
2269
+ /** Drive an instruction-based agent over text and collect its replies. Stateless
2270
+ * batch turn — built on the live driver (start → turn per message → end). */
2271
+ declare function runAgentTextTranscript(opts: RunAgentTextTranscriptOptions): Promise<AgentTextTranscriptResult>;
2303
2272
 
2304
- interface BrainMessage {
2305
- readonly role: 'system' | 'user' | 'assistant';
2306
- readonly content: string;
2307
- }
2308
- interface BrainCallMetadata {
2309
- readonly channel: 'voice' | 'text';
2310
- readonly callId?: string;
2311
- readonly projectId?: string;
2273
+ interface WrapOptions<T> {
2274
+ /** Emit OTel spans around each method call. Default: true. */
2275
+ readonly trace?: boolean;
2276
+ /** Tag spans with `vl.provider.label` for easy filtering. */
2277
+ readonly label?: string;
2278
+ /**
2279
+ * Fallback provider used if the primary throws. Accepts an instance OR a
2280
+ * ProviderFactory (so `deepgram.tts(...)` works directly). The fallback is
2281
+ * resolved lazily on first error.
2282
+ */
2283
+ readonly fallback?: T | ProviderFactory<T>;
2284
+ /**
2285
+ * Methods to instrument. By default the wrapper instruments every method
2286
+ * call. Pass an explicit list to limit overhead on hot paths.
2287
+ */
2288
+ readonly methods?: readonly string[];
2312
2289
  }
2313
- interface BrainRequest {
2314
- readonly messages: readonly BrainMessage[];
2315
- /** Upstream model id / alias. Omitted → the brain's own default. */
2316
- readonly model?: string;
2317
- readonly temperature?: number;
2318
- readonly metadata: BrainCallMetadata;
2319
- }
2320
- /** One streamed piece of the brain's reply. */
2321
- interface BrainChunk {
2322
- readonly content?: string;
2323
- }
2324
- interface BrainCapabilities {
2325
- readonly reachable: boolean;
2326
- readonly streaming: boolean;
2327
- }
2328
- interface BrainTransport {
2329
- readonly kind: 'callback' | 'http' | 'tunnel';
2330
- /** Stream the reply token-by-token (the voice path: first sentence → TTS ASAP). */
2331
- stream(req: BrainRequest, signal: AbortSignal): AsyncIterable<BrainChunk>;
2332
- /** Non-streaming convenience (the text path). */
2333
- complete(req: BrainRequest, signal: AbortSignal): Promise<string>;
2334
- }
2335
- /** Context handed to a customer's in-process `onQuery` brain. */
2336
- interface OnQueryContext {
2337
- /** Full conversation so far (system + prior turns + latest user message). */
2338
- readonly messages: readonly BrainMessage[];
2339
- /** Aborts when the caller barges in / the turn is cancelled. */
2340
- readonly signal: AbortSignal;
2341
- }
2342
- type OnQueryResult = string | AsyncIterable<string>;
2343
2290
  /**
2344
- * Bring-your-own brain, in-process. Receives the latest user utterance (and the
2345
- * full history via `ctx.messages`) and returns the reply — either a string or an
2346
- * async-iterable of string pieces for token streaming.
2291
+ * Returns either the wrapped instance directly (when called with one) or a
2292
+ * ProviderFactory that produces the wrapped instance (when called with one of
2293
+ * those). This keeps the lazy import story intact: `wrap(deepgram.tts(...))`
2294
+ * is itself a factory.
2347
2295
  */
2348
- type OnQuery = (text: string, ctx: OnQueryContext) => OnQueryResult | Promise<OnQueryResult>;
2296
+ declare function wrap<T extends object>(target: T | ProviderFactory<T>, options?: WrapOptions<T>): T | ProviderFactory<T>;
2349
2297
 
2350
- /** Primitive field types accepted in a process definition. */
2351
- type ProcessFieldType = 'string' | 'string[]' | 'number' | 'boolean' | 'datetime' | 'email' | 'phone';
2352
- interface ProcessField {
2353
- readonly type: ProcessFieldType;
2354
- readonly required?: boolean;
2355
- /** Regex pattern for `string` / `string[]` items. */
2356
- readonly pattern?: RegExp;
2357
- /** Inclusive lower bound on a number or array length. */
2358
- readonly min?: number;
2359
- /** Inclusive upper bound on a number or array length. */
2360
- readonly max?: number;
2361
- /** One of N — restricts the captured value to this set. */
2362
- readonly enum?: readonly string[];
2363
- /** Override the auto-generated prompt for capturing this field. */
2364
- readonly ask?: string;
2365
- /** Override the field-extraction hint shown to the LLM. */
2366
- readonly extract?: string;
2298
+ interface ProviderCreds {
2299
+ readonly apiKey?: string;
2300
+ readonly baseURL?: string;
2367
2301
  }
2368
- type CompletionStrategy = 'all-required-captured' | 'all-captured' | {
2369
- custom: (data: Record<string, unknown>, ctx: AgentContext) => boolean | Promise<boolean>;
2302
+ declare const deepgram: {
2303
+ stt(options?: {
2304
+ model?: string;
2305
+ language?: string;
2306
+ apiKey?: string;
2307
+ baseURL?: string;
2308
+ }): ProviderFactory<STTProvider>;
2309
+ tts(options?: {
2310
+ model?: string;
2311
+ apiKey?: string;
2312
+ baseURL?: string;
2313
+ }): ProviderFactory<TTSProvider>;
2370
2314
  };
2371
- interface ProcessBackendAck {
2372
- /** URL to POST captured data to. The call cannot complete until this 2xx's. */
2373
- readonly url: string;
2374
- readonly timeoutMs?: number;
2375
- readonly headers?: Readonly<Record<string, string>>;
2376
- }
2377
- interface ProcessDefinition<T extends Record<string, ProcessField> = Record<string, ProcessField>> {
2378
- /** Field schema. Order is preserved when the SDK auto-asks for fields. */
2379
- readonly collect: T;
2380
- /** When the call can end. Defaults to 'all-required-captured'. */
2381
- readonly completeWhen?: CompletionStrategy;
2382
- /** Optional external system that must ACK before completion. */
2383
- readonly backendAck?: ProcessBackendAck;
2384
- /** Fires once all completion conditions are met. */
2385
- readonly onComplete?: (data: InferProcessData<T>, ctx: AgentContext) => Promise<void> | void;
2386
- /** Fires whenever a field is captured (good for live CRM updates). */
2387
- readonly onField?: <K extends keyof T>(field: K, value: InferFieldValue<T[K]>, ctx: AgentContext) => Promise<void> | void;
2388
- }
2389
- /** Inferred TS type for the data bag a process produces. */
2390
- type InferProcessData<T extends Record<string, ProcessField>> = {
2391
- [K in keyof T]: T[K]['required'] extends true ? InferFieldValue<T[K]> : InferFieldValue<T[K]> | undefined;
2315
+ declare const openai: {
2316
+ llm(options?: {
2317
+ model?: string;
2318
+ apiKey?: string;
2319
+ baseURL?: string;
2320
+ }): ProviderFactory<LLMProvider>;
2321
+ tts(options?: {
2322
+ model?: string;
2323
+ voice?: string;
2324
+ instructions?: string;
2325
+ apiKey?: string;
2326
+ baseURL?: string;
2327
+ }): ProviderFactory<TTSProvider>;
2328
+ realtime(options?: {
2329
+ model?: string;
2330
+ voice?: string;
2331
+ apiKey?: string;
2332
+ baseURL?: string;
2333
+ }): ProviderFactory<RealtimeProvider>;
2392
2334
  };
2393
- type InferFieldValue<F extends ProcessField> = F['type'] extends 'string' ? string : F['type'] extends 'string[]' ? string[] : F['type'] extends 'number' ? number : F['type'] extends 'boolean' ? boolean : F['type'] extends 'datetime' ? Date : F['type'] extends 'email' ? string : F['type'] extends 'phone' ? string : never;
2394
- type TriggerCondition = RegExp | `signal:${string}` | ((text: string, ctx: AgentContext) => boolean | Promise<boolean>);
2395
- type TriggerAction = 'handoff' | 'endCall' | {
2396
- say: string;
2397
- } | {
2398
- run: (ctx: AgentContext) => Promise<void> | void;
2399
- }
2400
- /** Jump the flow-graph cursor to a node id. Only meaningful under the graph
2401
- * interpreter (the flat goals+rails path has no cursor and ignores it). */
2402
- | {
2403
- goto: string;
2335
+ declare const cartesia: {
2336
+ tts(options?: {
2337
+ voice?: string;
2338
+ model?: string;
2339
+ apiKey?: string;
2340
+ baseURL?: string;
2341
+ }): ProviderFactory<TTSProvider>;
2342
+ stt(options?: {
2343
+ model?: string;
2344
+ language?: string;
2345
+ apiKey?: string;
2346
+ baseURL?: string;
2347
+ }): ProviderFactory<STTProvider>;
2404
2348
  };
2405
- interface TriggerDefinition {
2406
- readonly on: TriggerCondition;
2407
- readonly then: TriggerAction;
2408
- /** If set, the trigger only fires while the named field is uncaptured. */
2409
- readonly onlyWhile?: string;
2349
+ declare const elevenlabs: {
2350
+ tts(options?: {
2351
+ voice?: string;
2352
+ model?: string;
2353
+ apiKey?: string;
2354
+ baseURL?: string;
2355
+ }): ProviderFactory<TTSProvider>;
2356
+ };
2357
+ declare const assemblyai: {
2358
+ stt(options?: {
2359
+ language?: string;
2360
+ apiKey?: string;
2361
+ baseURL?: string;
2362
+ }): ProviderFactory<STTProvider>;
2363
+ };
2364
+ declare const google: {
2365
+ llm(options?: {
2366
+ model?: string;
2367
+ apiKey?: string;
2368
+ baseURL?: string;
2369
+ }): ProviderFactory<LLMProvider>;
2370
+ realtime(options?: {
2371
+ model?: string;
2372
+ voice?: string;
2373
+ apiKey?: string;
2374
+ baseURL?: string;
2375
+ }): ProviderFactory<RealtimeProvider>;
2376
+ };
2377
+ declare const silero: {
2378
+ vad(): ProviderFactory<VADProvider>;
2379
+ };
2380
+ declare const livekitTurn: {
2381
+ english(): ProviderFactory<TurnDetectorProvider>;
2382
+ multilingual(): ProviderFactory<TurnDetectorProvider>;
2383
+ };
2384
+ interface ConnectorLLMConfig {
2385
+ /** Upstream model id / alias (defaults to the brain's own default). */
2386
+ readonly model?: string;
2387
+ readonly temperature?: number;
2388
+ /** Spoken instead of dead air when the brain errors before replying. */
2389
+ readonly fallbackText?: string;
2390
+ /** In-process brain. */
2391
+ readonly onQuery?: OnQuery;
2392
+ /** Direct-egress brain — a public OpenAI-compatible base URL. */
2393
+ readonly url?: string;
2394
+ /** API key for the direct-egress endpoint. */
2395
+ readonly apiKey?: string;
2396
+ /** Hostnames that bypass the SSRF IP checks (direct mode). */
2397
+ readonly allowHosts?: readonly string[];
2398
+ /** Advanced: a custom transport (tunnel, etc.). */
2399
+ readonly transport?: BrainTransport;
2410
2400
  }
2411
- interface HandoffConfig {
2412
- /** Default human number when a trigger says { then: 'handoff' }. */
2413
- readonly fallback: string;
2414
- /** Map signal/trigger names to specific destinations. */
2415
- readonly routes?: Readonly<Record<string, string>>;
2416
- /** Build the briefing text passed to the human agent (or PSTN whisper). */
2417
- readonly briefing?: (args: {
2418
- readonly data: Record<string, unknown>;
2419
- readonly transcript: TranscriptHandle;
2420
- readonly call: AgentContext['call'];
2421
- }) => string | Promise<string>;
2422
- /**
2423
- * 'warm' (default) dials the human into the room as a conference, lets the
2424
- * agent brief them live, then drops the agent — caller + human stay
2425
- * connected. 'cold' is a blind SIP REFER: the caller is transferred away
2426
- * immediately. Warm falls back to cold when no outbound trunk is configured.
2427
- */
2428
- readonly mode?: 'warm' | 'cold';
2401
+ declare const connector: {
2402
+ llm(config?: ConnectorLLMConfig): ProviderFactory<LLMProvider>;
2403
+ };
2404
+
2405
+ /** The control-plane reads the resolver needs. Structural (not the full
2406
+ * VoiceLayerClient) so it stays trivially fakeable in tests — a real client
2407
+ * satisfies it. */
2408
+ interface AgentTextRuntimeClient {
2409
+ readonly agents: {
2410
+ getPrompt(agentId: string): Promise<string | null>;
2411
+ getConfig(agentId: string): Promise<{
2412
+ readonly model?: {
2413
+ readonly provider: string;
2414
+ readonly model: string;
2415
+ };
2416
+ readonly routingInstructions?: string | undefined;
2417
+ } | null>;
2418
+ };
2419
+ readonly connections: {
2420
+ resolveProviderCredential(provider: string): Promise<{
2421
+ readonly apiKey: string;
2422
+ readonly baseUrl?: string | undefined;
2423
+ } | null>;
2424
+ };
2429
2425
  }
2430
- interface TranscriptHandle {
2431
- /** Last N turns as `speaker: text` lines. */
2432
- tail(n: number): string;
2433
- full(): string;
2426
+ interface ResolvedAgentTextRuntime {
2427
+ /** The composed system prompt (persona + routing), ready for the AgentSession. */
2428
+ readonly instructions: string;
2429
+ /** The concrete provider LLM that generates replies. */
2430
+ readonly llm: llm.LLM;
2431
+ /** Which provider/model resolved — surfaced for traceability/logging. */
2432
+ readonly model: {
2433
+ readonly provider: string;
2434
+ readonly model: string;
2435
+ };
2436
+ /** True when a project BYOK key backed the LLM (vs the platform env key). */
2437
+ readonly byok: boolean;
2438
+ }
2439
+ /** Builds the concrete provider LLM from (provider, model, BYOK creds). Injectable
2440
+ * so tests can substitute a fake without loading a provider plugin. */
2441
+ type BuildTextLlm = (providerId: string, modelId: string, creds: ProviderCreds | undefined) => Promise<llm.LLM>;
2442
+ interface ResolveAgentTextRuntimeOptions {
2443
+ /** Override the LLM build (tests). Defaults to the real provider registry. */
2444
+ readonly buildLlm?: BuildTextLlm;
2445
+ }
2446
+ /** A code-first agent's resolved text runtime WITHOUT the built LLM — the cheap,
2447
+ * shareable part (instructions + which provider/model + BYOK creds). Cache THIS
2448
+ * and build a fresh LLM per session, never the LLM itself (an lk.LLM is a live
2449
+ * EventEmitter — sharing one across concurrent sessions cross-fires errors). */
2450
+ interface AgentTextPlan {
2451
+ readonly instructions: string;
2452
+ readonly provider: string;
2453
+ readonly model: string;
2454
+ readonly creds?: ProviderCreds;
2455
+ readonly byok: boolean;
2434
2456
  }
2435
2457
  /**
2436
- * Memory scope. `'participant'` and `'caller'` are synonyms — `'caller'`
2437
- * is the historical name from the 1:1 era; new code should prefer
2438
- * `'participant'`, which makes the multi-party semantics explicit.
2458
+ * Resolve a code-first agent's text PLAN (instructions + provider/model + BYOK),
2459
+ * or `null` when it isn't code-first-runnable (no synced prompt). No LLM built —
2460
+ * this is the cacheable part. Best-effort on the pipeline: a missing/blank config
2461
+ * falls back to the platform default model, mirroring the live path.
2439
2462
  */
2440
- type MemoryScope = 'call' | 'caller' | 'participant' | 'account' | 'platform';
2441
- interface MemoryConfig {
2442
- /** Which scope to persist to. Defaults to 'caller'. */
2443
- readonly scope?: MemoryScope;
2444
- readonly retentionDays?: number;
2445
- /** Fields auto-redacted on write. Recognized: ssn, dob, email, phone, ccn. */
2446
- readonly piiFields?: readonly string[];
2447
- /** Opt in to cross-tenant aggregate memory (anonymized). */
2448
- readonly platformOptIn?: boolean;
2449
- }
2463
+ declare function resolveAgentTextPlan(agentId: string, client: AgentTextRuntimeClient): Promise<AgentTextPlan | null>;
2464
+ /** Build a fresh provider LLM for a plan. Call once PER SESSION so no two live
2465
+ * sessions ever share an lk.LLM instance. */
2466
+ declare function buildTextLlm(plan: AgentTextPlan, buildLlm?: BuildTextLlm): Promise<llm.LLM>;
2450
2467
  /**
2451
- * Multi-participant configuration. Optional — when omitted, the agent runs
2452
- * in 1:1 mode (one human + one agent) and the SDK still populates
2453
- * `ctx.room.participants` so participant-aware code paths work.
2468
+ * Resolve a code-first agent's text runtime (plan + a freshly-built LLM), or
2469
+ * `null` when it isn't runnable. Convenience over resolveAgentTextPlan +
2470
+ * buildTextLlm — kept for callers that want a one-shot runtime (and tests).
2454
2471
  */
2455
- interface ParticipantsConfig {
2472
+ declare function resolveAgentTextRuntime(agentId: string, client: AgentTextRuntimeClient, opts?: ResolveAgentTextRuntimeOptions): Promise<ResolvedAgentTextRuntime | null>;
2473
+
2474
+ interface TransportOptions {
2475
+ readonly apiKey: string;
2476
+ readonly baseUrl: string;
2477
+ readonly fetch?: typeof fetch;
2478
+ readonly maxRetries?: number;
2479
+ readonly initialBackoffMs?: number;
2480
+ readonly userAgent?: string;
2481
+ }
2482
+ interface RequestOptions {
2483
+ readonly method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
2484
+ readonly path: string;
2485
+ readonly body?: unknown;
2486
+ readonly query?: Record<string, string | undefined>;
2487
+ readonly signal?: AbortSignal;
2488
+ /** Extra request headers, merged on top of the defaults (auth/content-type
2489
+ * etc). Lowercase keys recommended. */
2490
+ readonly headers?: Record<string, string>;
2491
+ }
2492
+ declare class Transport {
2493
+ private readonly options;
2494
+ private readonly fetchImpl;
2495
+ private readonly maxRetries;
2496
+ private readonly initialBackoffMs;
2497
+ constructor(options: TransportOptions);
2498
+ request<T>(opts: RequestOptions, schema: ZodType<T>): Promise<T>;
2499
+ private backoffMs;
2500
+ }
2501
+
2502
+ interface RegisterInput {
2503
+ readonly name: string;
2504
+ readonly version: string;
2505
+ readonly environment: AgentEnvironment;
2506
+ /** Capability tags (e.g. ['fnol', 'es-MX']). Surfaced in the dashboard. */
2507
+ readonly capabilities?: readonly string[];
2456
2508
  /**
2457
- * Fires when a human participant joins the room. In 1:1 calls this
2458
- * fires once at session start for the caller. In multi-party calls it
2459
- * fires per join.
2509
+ * JSON-serializable process schema for the dashboard "what this agent does"
2510
+ * view. Built by `buildProcessSchemaDTO` from the agent's ProcessDefinition.
2460
2511
  */
2461
- readonly onJoin?: (participant: Participant, ctx: AgentContext) => Promise<void> | void;
2462
- /** Fires when a participant disconnects (hangup, transfer, kick). */
2463
- readonly onLeave?: (participant: Participant, ctx: AgentContext) => Promise<void> | void;
2512
+ readonly processSchema?: ProcessSchemaDTO | null;
2464
2513
  /**
2465
- * Synchronously enrich a participant's attribute bag before `onJoin`
2466
- * fires. Useful for phone-number → language lookups, etc. The returned
2467
- * map is merged into `participant.attributes`.
2514
+ * A code-first agent's base prompt (its `defineAgent({ prompt })`). Synced to
2515
+ * the agent's record so a generic runner can run it over text by id (P2). Omit
2516
+ * for flow agents (their behavior lives in the compiled program).
2468
2517
  */
2469
- readonly attributes?: (participant: Participant) => Readonly<Record<string, string>> | Promise<Readonly<Record<string, string>>>;
2518
+ readonly prompt?: string | null;
2470
2519
  /**
2471
- * Reject participants beyond this count. Default: unlimited. The cap
2472
- * is enforced by the worker when wiring participant lifecycle.
2520
+ * Opt this agent into MCP exposure. When true, the API upserts a matching
2521
+ * agent_config row keyed by (project_id, name, environment) so MCP /
2522
+ * dashboard / REST can list and inspect this agent. Default false — pure
2523
+ * SDK agents that don't need MCP visibility stay invisible to it. See
2524
+ * docs/architecture/contracts-design.md §2b.
2473
2525
  */
2474
- readonly max?: number;
2475
- }
2476
- /**
2477
- * A connector instance. Created by per-system factories like `salesforce()`,
2478
- * `twilio()`, etc. The factory returns an opaque handle that the SDK wires
2479
- * into `ctx.connectors` and (when `expose: true`) into the LLM tool list.
2480
- */
2481
- interface ConnectorInstance<TName extends string = string, TApi = unknown> {
2482
- readonly __connector: true;
2483
- readonly name: TName;
2484
- readonly api: TApi;
2485
- /** If true, every method on `api` becomes an LLM-callable tool. */
2486
- readonly expose?: boolean;
2487
- }
2488
- type ComplianceTag = 'tcpa' | 'hipaa' | 'pci' | 'gdpr' | 'soc2';
2489
- /**
2490
- * Duck-typed pipeline component markers. The SDK never inspects these — they
2491
- * are passed through to LiveKit's AgentSession as-is. Three ways to satisfy:
2492
- *
2493
- * 1. SDK factory: `deepgram.tts({ model: 'aura-2' })`
2494
- * 2. Wrapped LK: `wrap(new TTS({...}), { trace: true })`
2495
- * 3. User-built: class MyTTS extends BaseTTS { ... } // BaseTTS
2496
- * // re-exported
2497
- * // from the SDK
2498
- *
2499
- * Anything implementing the duck-type — even a plain object — is accepted.
2500
- */
2501
- interface STTProvider {
2502
- readonly __vlPipeline?: 'stt';
2526
+ readonly mcpExposed?: boolean;
2527
+ /**
2528
+ * Self-checks run before sending the register request. Each result is
2529
+ * recorded on the agent. See RegisterOptions.requireReady for failure
2530
+ * policy.
2531
+ */
2532
+ readonly readiness?: readonly ReadinessProbe[];
2533
+ /** User metadata. Merged on top of default metadata (user wins on conflict). */
2534
+ readonly metadata?: Record<string, unknown>;
2535
+ /**
2536
+ * Whether to auto-collect host/runtime/build metadata. Default true. Set
2537
+ * false to send exactly what you pass in `metadata`.
2538
+ */
2539
+ readonly collectDefaults?: boolean;
2503
2540
  }
2504
- interface LLMProvider {
2505
- readonly __vlPipeline?: 'llm';
2506
- }
2507
- interface TTSProvider {
2508
- readonly __vlPipeline?: 'tts';
2509
- }
2510
- interface VADProvider {
2511
- readonly __vlPipeline?: 'vad';
2512
- }
2513
- interface TurnDetectorProvider {
2514
- readonly __vlPipeline?: 'turn';
2515
- }
2516
- /**
2517
- * Speech-to-speech / realtime model marker (OpenAI Realtime, Gemini Live).
2518
- * A realtime model handles STT + LLM + TTS + turn-taking server-side, so when
2519
- * `models.realtime` is set the SDK builds the AgentSession around it and
2520
- * ignores the stt/llm/tts slots.
2521
- */
2522
- interface RealtimeProvider {
2523
- readonly __vlPipeline?: 'realtime';
2524
- }
2525
- /**
2526
- * Lazy form so users can pick a provider per call (e.g. by caller locale).
2527
- * The factory runs once per call, before AgentSession is constructed, so it
2528
- * receives the call envelope (callerId, to, metadata) rather than the full
2529
- * AgentContext (which depends on AgentSession existing).
2530
- */
2531
- type ProviderFactory<T> = (call: CallInfo) => T | Promise<T>;
2532
- interface ModelConfig {
2533
- /**
2534
- * String form: 'openai/gpt-4o' (resolves via SDK defaults).
2535
- * Instance form: any LLMProvider (LK plugin, wrap()-ed, or user-built).
2536
- * Factory form: `(ctx) => provider` for per-call selection.
2537
- */
2538
- readonly llm?: string | LLMProvider | ProviderFactory<LLMProvider>;
2539
- readonly stt?: string | STTProvider | ProviderFactory<STTProvider>;
2540
- readonly tts?: string | TTSProvider | ProviderFactory<TTSProvider>;
2541
- /** VAD has no string form — always pass an instance or factory. */
2542
- readonly vad?: VADProvider | ProviderFactory<VADProvider>;
2543
- readonly turnDetector?: TurnDetectorProvider | ProviderFactory<TurnDetectorProvider>;
2541
+ interface RegisterOptions {
2544
2542
  /**
2545
- * Speech-to-speech / realtime model. When set, the STT→LLM→TTS pipeline is
2546
- * bypassed: the realtime model drives the whole turn. No string form — pass
2547
- * an instance (`openai.realtime({ voice: 'alloy' })`) or a per-call factory.
2543
+ * Override server-suggested heartbeat cadence (ms). When omitted, the SDK
2544
+ * uses the value returned by /v1/agents/register, falling back to
2545
+ * AGENT_HEARTBEAT_INTERVAL_MS.
2548
2546
  */
2549
- readonly realtime?: RealtimeProvider | ProviderFactory<RealtimeProvider>;
2550
- /** Spoken language; defaults to 'en-US'. Used by string-form defaults. */
2551
- readonly language?: string;
2552
- }
2553
- /**
2554
- * Answering-machine detection mode for outbound calls. Mirrors
2555
- * `OutboundConfig.amd` in @voicelayer/agent-spec.
2556
- *
2557
- * 'off' — never run AMD; treat every answer as a human.
2558
- * 'detect' — leave the voicemail message (or hang up) the moment
2559
- * a machine greeting is recognised.
2560
- * 'detectMessageEnd' — recognise the machine, then wait for the greeting to
2561
- * finish (an explicit "after the tone"-style cue or the
2562
- * greeting going quiet) before leaving the message.
2563
- */
2564
- type AmdMode = 'off' | 'detect' | 'detectMessageEnd';
2565
- /**
2566
- * Outbound-only behavior. AMD never runs on inbound calls (the runtime gates
2567
- * on the dispatch-metadata `direction`), so these knobs are inert unless the
2568
- * call was placed via the outbound path.
2569
- */
2570
- interface OutboundCallConfig {
2571
- /** Answering-machine detection mode. Defaults to 'off'. */
2572
- readonly amd?: AmdMode;
2547
+ readonly heartbeatIntervalMs?: number;
2573
2548
  /**
2574
- * Spoken (via TTS) when a machine is detected. When unset, the agent hangs
2575
- * up on detection instead of leaving a message.
2549
+ * Disable signal handlers (SIGTERM/SIGINT). Useful in tests and in hosts
2550
+ * that own their own shutdown lifecycle.
2576
2551
  */
2577
- readonly voicemailScript?: string;
2578
- }
2579
- /**
2580
- * Barge-in tuning. The pipeline allows interruptions by default (LK defaults:
2581
- * any speech ≥500ms cuts the agent off). These knobs tune that behavior per
2582
- * agent WITHOUT switching to puppet/hostControlled mode — e.g. a senior-living
2583
- * help desk wants `minWords: 2` so backchannels ("mm-hm", "okay") don't
2584
- * truncate the agent mid-sentence, while a fast-paced escalation desk keeps
2585
- * the zero-word default. Set `enabled: false` to make the agent
2586
- * non-interruptible (kiosk / broadcast announcements).
2587
- */
2588
- interface InterruptionConfig {
2589
- /** Allow the caller to barge in over agent speech. Default true. */
2590
- readonly enabled?: boolean;
2591
- /** Words the caller must say before it counts as an interruption. Default 0
2592
- * (any speech interrupts). 2–3 filters out backchannels. */
2593
- readonly minWords?: number;
2594
- /** Minimum caller speech duration (ms) to count as an interruption. Default 500. */
2595
- readonly minDuration?: number;
2596
- }
2597
- /**
2598
- * End-of-turn detection tuning: how long the pipeline waits after the caller
2599
- * stops speaking before treating the turn as finished. Raise `minDelay` for
2600
- * callers who pause mid-thought (e.g. elderly speakers); lower it for
2601
- * fast-paced lines.
2602
- */
2603
- interface EndpointingConfig {
2604
- /** Minimum silence (ms) before the caller's turn is considered done. Default 500. */
2605
- readonly minDelay?: number;
2606
- /** Hard ceiling (ms) after which the turn ends regardless. Default 3000. */
2607
- readonly maxDelay?: number;
2608
- }
2609
- /**
2610
- * Speech polish. `pronunciations` rewrites brand names / acronyms / jargon to
2611
- * a spoken form before TTS (e.g. `{ VoiceLayer: 'Voice Layer', API: 'A P I' }`)
2612
- * via applyPronunciations(). `backgroundAudio` plays ambient room tone under
2613
- * the agent so silence feels less dead (a URL or a named preset).
2614
- * `interruption` + `endpointing` tune barge-in and turn-taking per agent.
2615
- */
2616
- interface SpeechConfig {
2617
- readonly pronunciations?: Readonly<Record<string, string>>;
2618
- readonly backgroundAudio?: string | {
2619
- readonly url?: string;
2620
- readonly volume?: number;
2621
- };
2622
- readonly interruption?: InterruptionConfig;
2623
- readonly endpointing?: EndpointingConfig;
2624
- }
2625
- /** What caused the call to end. Surfaced to `endCall.onEnd` + logs. */
2626
- type EndCallTrigger =
2627
- /** The LLM invoked the built-in `end_call` tool. */
2628
- 'tool'
2629
- /** An external controller (MCP host) sent a `hangup` command. */
2630
- | 'host'
2631
- /** The dead-air backstop fired (`idleHangupMs` of silence while idle). */
2632
- | 'idle'
2633
- /** The hard per-call ceiling fired (`maxCallDurationMs` elapsed). */
2634
- | 'max_duration'
2635
- /** The last non-agent participant left the room. */
2636
- | 'participant-left'
2637
- /** A flow/graph run finished and asked to hang up. */
2638
- | 'flow'
2639
- /** The realtime engine closed / disconnected under the session. */
2640
- | 'engine-closed'
2641
- /** `ctx.endCall()` called directly from user code. */
2642
- | 'user';
2643
- /** Passed to `endCall.onEnd` describing the teardown about to happen. */
2644
- interface EndCallInfo {
2645
- /** Why the call is ending (e.g. the `end_call` tool's `reason`). */
2646
- readonly reason?: string;
2647
- /** What triggered the hang-up. */
2648
- readonly trigger: EndCallTrigger;
2649
- /** The teardown strategy that will run (after the policy is resolved). */
2650
- readonly teardown: 'room' | 'agent';
2651
- }
2652
- /**
2653
- * Controls how the agent ENDS a call. The SDK — not the agent prompt or an
2654
- * external puppet driver — owns teardown, so a hang-up is reliable even when
2655
- * the realtime transport has died mid-wrap.
2656
- *
2657
- * Defaults are "best case" and active without opt-in: the whole LiveKit room
2658
- * is deleted (which drops the SIP/PSTN leg too, so the carrier gets a BYE),
2659
- * a guarantee-watchdog re-attempts teardown if the first try doesn't land, and
2660
- * a dead-air backstop hangs up after the line has been silent too long. Every
2661
- * knob is overridable; set a field to `false` to disable that guard.
2662
- */
2663
- interface EndCallPolicy {
2552
+ readonly attachSignalHandlers?: boolean;
2664
2553
  /**
2665
- * Teardown strategy. `'room'` (default) deletes the LiveKit room via the
2666
- * room service — this removes the SIP participant too, so the call actually
2667
- * disconnects on the carrier side. `'agent'` only drops the agent's own
2668
- * participant (leaves any SIP leg up); use it only when something else owns
2669
- * the room lifecycle.
2554
+ * On SIGTERM/SIGINT, call DELETE /v1/agents/:id before exiting so the
2555
+ * dashboard reflects "gone" immediately instead of waiting for offline
2556
+ * timeout. Default true. Best-effort: errors are swallowed.
2670
2557
  */
2671
- readonly teardown?: 'room' | 'agent';
2558
+ readonly deregisterOnSignal?: boolean;
2672
2559
  /**
2673
- * After a hang-up is requested, keep re-attempting teardown until the room
2674
- * is actually gone or this many ms elapse. Guards against a teardown call
2675
- * that silently doesn't land (transport race, transient room-service error).
2676
- * Default 4000. `false` disables (single best-effort attempt).
2560
+ * If any readiness probe reports !ok, throw before calling register.
2561
+ * Default false: probes that fail mark the agent as `degraded` instead.
2677
2562
  */
2678
- readonly guaranteeMs?: number | false;
2563
+ readonly requireReady?: boolean;
2679
2564
  /**
2680
- * Dead-air backstop: when the agent is idle (waiting on the caller) and the
2681
- * line stays silent — no agent turn, no caller speech — for this many ms,
2682
- * end the call. Catches a wedged session whose normal `end_call` never ran.
2683
- * Only armed while the agent is idle, so it never interrupts agent speech or
2684
- * a long tool call. Default 20000. `false` disables.
2565
+ * Listener for lifecycle events. Equivalent to `agent.events.on(fn)` after
2566
+ * register; register-time events (readiness, registered) are also delivered.
2685
2567
  */
2686
- readonly idleHangupMs?: number | false;
2568
+ readonly onEvent?: (event: AgentLifecycleEvent) => void;
2569
+ }
2570
+ interface RegisteredAgent {
2571
+ readonly agent: AgentDTO;
2572
+ readonly events: AgentEventEmitter;
2573
+ /** Push a status change immediately (next heartbeat carries it too). */
2574
+ setStatus(status: 'online' | 'degraded', detail?: string): Promise<void>;
2575
+ /** Replace metadata on the next heartbeat. Pass {} to clear. */
2576
+ updateMetadata(metadata: Record<string, unknown>): Promise<void>;
2577
+ /** Best-effort DELETE; safe to call multiple times. */
2578
+ deregister(): Promise<void>;
2579
+ /** Stop the heartbeat ticker without deleting the row. Idempotent. */
2580
+ stop(): Promise<void>;
2581
+ }
2582
+ interface SchedulerLike {
2583
+ setTimeout(cb: () => void, ms: number): NodeJS.Timeout | number;
2584
+ clearTimeout(handle: NodeJS.Timeout | number | undefined): void;
2585
+ }
2586
+ interface AgentsClientOptions {
2587
+ readonly scheduler?: SchedulerLike;
2588
+ readonly attachSignalHandlers?: boolean;
2589
+ }
2590
+ declare class AgentsClient {
2591
+ private readonly transport;
2592
+ private readonly options;
2593
+ constructor(transport: Transport, options?: AgentsClientOptions);
2687
2594
  /**
2688
- * Hard call ceiling: hang up once the call has run this many ms from when
2689
- * the session becomes ready, regardless of activity. Catches runaway calls
2690
- * that never end naturally (stuck loops, hijacked keys dialing premium
2691
- * numbers). Fires with trigger `'max_duration'`. Default 3600000 (60
2692
- * minutes). `false` disables.
2595
+ * Fetch a deployed agent's compiled process_schema. A flow-runtime worker
2596
+ * calls this per dispatched call to boot a visually-built flow. Returns
2597
+ * null on 404 or when the agent has no schema.
2693
2598
  */
2694
- readonly maxCallDurationMs?: number | false;
2599
+ getProcessSchema(agentId: string): Promise<ProcessSchemaDTO | null>;
2695
2600
  /**
2696
- * Hook fired the moment a hang-up is decided, just before teardown — for
2697
- * every trigger (tool, host, idle, max_duration, engine-closed, …). Return
2698
- * `false` to take over teardown yourself (the SDK then does nothing — the
2699
- * call will NOT end unless you end it). Returning anything else (or nothing)
2700
- * runs the default teardown. Throwing is caught + logged, then the default
2701
- * teardown still runs (safe by default).
2601
+ * Fetch a code-first agent's synced base prompt (its `defineAgent({ prompt })`,
2602
+ * captured on register). The generic text runner reads this to run the agent
2603
+ * through the engine over text. Returns null on 404 or when the agent has no
2604
+ * synced prompt (flow agents, or agents registered before the sync landed).
2702
2605
  */
2703
- readonly onEnd?: (ctx: AgentContext, info: EndCallInfo) => boolean | void | Promise<boolean | void>;
2704
- }
2705
- type ShorthandPrimitive$1 = 'string' | 'number' | 'boolean';
2706
- type ToolInputShape$1 = Record<string, ShorthandPrimitive$1> | z.ZodTypeAny;
2707
- interface ToolDefinition$1<I = unknown, R = unknown> {
2708
- readonly description: string;
2709
- readonly input: ToolInputShape$1;
2710
- readonly run: (input: I, ctx: AgentContext) => Promise<R> | R;
2606
+ getPrompt(agentId: string): Promise<string | null>;
2711
2607
  /**
2712
- * Capability this tool requires. Action Guard hard-blocks the call if not
2713
- * declared (PRD §B.5 — "no soft failures, ever"). Defaults to
2714
- * `tool.<name>` when omitted; passing a domain-scoped string
2715
- * (`crm.write`, `payment.refund`) lets multiple tools share a capability
2716
- * for centralised policy.
2608
+ * Fetch a deployed agent's PUBLISHED AgentConfig — the pipeline the owner
2609
+ * published (model / voice / stt / mode / realtime). A flow-runtime worker
2610
+ * reads this per call so the no-code agent's runtime matches what was
2611
+ * published; a saved-but-unpublished dashboard draft is never returned here
2612
+ * (docs/specs/agents/draft-publish.md). Returns null on 404 (agent absent).
2717
2613
  */
2718
- readonly capability?: string;
2719
- }
2720
- /**
2721
- * Optional security adapters. The SDK always enforces the local-only synchronous
2722
- * guards (PRD §B.2 input regex, §B.3 system seal + PII tokenisation, §B.4
2723
- * markdown strip + PII partial-mask, §B.5 capability check). Setting any of
2724
- * these augments the local floor with external services. Each is independently
2725
- * optional — none has to be live for the floor guards to function.
2726
- *
2727
- * URLs can also come from env (`SECURITY_LLM_GUARD_URL`,
2728
- * `SECURITY_PRESIDIO_ANALYZER_URL`, `SECURITY_PRESIDIO_ANONYMIZER_URL`,
2729
- * `SECURITY_OPA_URL`, `SECURITY_OPA_DECISION_PATH`); explicit config wins.
2730
- */
2731
- interface SecurityConfig {
2732
- /** Disable the primitive entirely. Use only for tests. Production code MUST NOT set this. */
2733
- readonly disabled?: boolean;
2734
- /** External LLM-Guard adapter for richer injection detection. */
2735
- readonly llmGuardUrl?: string;
2736
- /** Presidio analyzer URL for PII detection beyond local regex. */
2737
- readonly presidioAnalyzerUrl?: string;
2738
- /** Presidio anonymizer URL — if set, output is redacted before TTS. */
2739
- readonly presidioAnonymizerUrl?: string;
2740
- /** OPA decision API base URL (e.g. `http://opa:8181`). */
2741
- readonly opaUrl?: string;
2742
- /** OPA decision path (e.g. `voicelayer/security/decision`). */
2743
- readonly opaDecisionPath?: string;
2744
- /** Per-request timeout for security adapter calls. */
2745
- readonly adapterTimeoutMs?: number;
2614
+ getConfig(agentId: string): Promise<AgentConfig$1 | null>;
2615
+ register(input: RegisterInput, opts?: RegisterOptions): Promise<RegisteredAgent>;
2616
+ list(query?: {
2617
+ environment?: AgentEnvironment;
2618
+ }): Promise<{
2619
+ agents: {
2620
+ status: "online" | "offline" | "degraded";
2621
+ id: string;
2622
+ projectId: string;
2623
+ name: string;
2624
+ createdAt: string;
2625
+ updatedAt: string;
2626
+ version: string;
2627
+ environment: "dev" | "stg" | "prd";
2628
+ statusDetail: string | null;
2629
+ capabilities: string[];
2630
+ readiness: {
2631
+ probe: string;
2632
+ ok: boolean;
2633
+ detail?: string | undefined;
2634
+ }[];
2635
+ metadata: Record<string, unknown>;
2636
+ lastSeenAt: string | null;
2637
+ processSchema?: {
2638
+ id: string;
2639
+ completionGate: {
2640
+ requiredFields: string[];
2641
+ backendAck?: {
2642
+ url: string;
2643
+ timeoutMs: number;
2644
+ } | undefined;
2645
+ };
2646
+ fields: {
2647
+ type: "string" | "number" | "boolean" | "string[]" | "datetime" | "email" | "phone";
2648
+ name: string;
2649
+ required: boolean;
2650
+ ask?: string | undefined;
2651
+ pattern?: string | undefined;
2652
+ min?: number | undefined;
2653
+ max?: number | undefined;
2654
+ enum?: string[] | undefined;
2655
+ }[];
2656
+ handoff?: {
2657
+ fallback?: string | undefined;
2658
+ routes?: Record<string, string> | undefined;
2659
+ } | undefined;
2660
+ memory?: {
2661
+ scope?: "caller" | "call" | "account" | "participant" | "platform" | undefined;
2662
+ retentionDays?: number | undefined;
2663
+ piiFields?: string[] | undefined;
2664
+ } | undefined;
2665
+ speech?: {
2666
+ interruption?: {
2667
+ enabled?: boolean | undefined;
2668
+ minWords?: number | undefined;
2669
+ minDuration?: number | undefined;
2670
+ } | undefined;
2671
+ endpointing?: {
2672
+ minDelay?: number | undefined;
2673
+ maxDelay?: number | undefined;
2674
+ } | undefined;
2675
+ } | undefined;
2676
+ prompts?: {
2677
+ text: string;
2678
+ id: string;
2679
+ }[] | undefined;
2680
+ triggers?: {
2681
+ then: string;
2682
+ name: string;
2683
+ on: string;
2684
+ onlyWhile?: string | undefined;
2685
+ }[] | undefined;
2686
+ tools?: {
2687
+ name: string;
2688
+ description: string;
2689
+ input: Record<string, "string" | "number" | "boolean">;
2690
+ url: string;
2691
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
2692
+ auth: "none" | "connection";
2693
+ headers?: Record<string, string> | undefined;
2694
+ connectionRef?: string | undefined;
2695
+ }[] | undefined;
2696
+ program?: {
2697
+ id: string;
2698
+ nodes: Record<string, {
2699
+ type: "llm" | "code" | "start" | "say" | "ask" | "confirm" | "tool" | "decision" | "handoff" | "end" | "trigger" | "gate" | "playbook" | "menu" | "set" | "subflow" | "rag" | "memory" | "speech" | "classify" | "router" | "note";
2700
+ id: string;
2701
+ config: Record<string, unknown>;
2702
+ out: {
2703
+ to: string;
2704
+ sourceHandle?: string | undefined;
2705
+ label?: string | undefined;
2706
+ condition?: string | undefined;
2707
+ }[];
2708
+ }>;
2709
+ v: 1;
2710
+ entry: string[];
2711
+ completionGate: {
2712
+ requiredFields: string[];
2713
+ };
2714
+ diagnostics?: {
2715
+ acyclic: boolean;
2716
+ droppedEdges: string[];
2717
+ unsupportedNodes: string[];
2718
+ labelOnlyEdges?: string[] | undefined;
2719
+ } | undefined;
2720
+ } | undefined;
2721
+ } | null | undefined;
2722
+ textRunnable?: boolean | undefined;
2723
+ }[];
2724
+ }>;
2725
+ delete(agentId: string): Promise<{
2726
+ ok: true;
2727
+ }>;
2746
2728
  }
2747
- /**
2748
- * Marks an agent as a *flow-runtime* worker: instead of a fixed process it
2749
- * resolves the deployed flow from the dispatch metadata (`agentId`) at call
2750
- * time, fetches that agent's compiled process_schema, and boots from it. One
2751
- * process serves many flows (the shared pool). See defineFlowRuntime().
2752
- */
2753
- interface FlowRuntimeConfig {
2754
- /** Prepended to the flow's compiled say/confirm prompt fragments. */
2755
- readonly basePrompt?: string;
2756
- /** Spoken (verbatim) before hanging up when a flow call's schema cannot be
2757
- * loaded. A failed flow boot NEVER silently answers as a generic assistant. */
2758
- readonly bootFailureMessage?: string;
2729
+
2730
+ interface ContextInput {
2731
+ readonly callerId: string;
2732
+ readonly scopes?: readonly MemoryScope$1[];
2759
2733
  }
2760
- interface AgentConfig<TProcess extends Record<string, ProcessField> = Record<string, ProcessField>> {
2761
- /** Lowercase, kebab-case identifier. Used for LiveKit dispatch + presence. */
2762
- readonly name: string;
2763
- /** System prompt the LLM sees. */
2764
- readonly prompt: string;
2765
- /** Agent-level Instructions (the routing/decision layer): plain-language guidance
2766
- * for WHEN the agent acts, appended below the persona under a `# Routing` header.
2767
- * Interpolated with {{ }} by the process runtime. Optional. */
2768
- readonly routingInstructions?: string;
2769
- /** Capability tags surfaced in the dashboard. */
2770
- readonly capabilities?: readonly string[];
2771
- /** Semantic version. Defaults to AGENT_VERSION env or '0.0.0'. */
2772
- readonly version?: string;
2773
- /** dev / stg / prd. Defaults to AGENT_ENVIRONMENT env or 'dev'. */
2774
- readonly environment?: AgentEnvironment;
2775
- readonly process?: ProcessDefinition<TProcess>;
2776
- readonly triggers?: Readonly<Record<string, TriggerDefinition>>;
2777
- readonly handoff?: HandoffConfig;
2778
- readonly memory?: MemoryConfig;
2779
- readonly participants?: ParticipantsConfig;
2780
- readonly connectors?: Readonly<Record<string, ConnectorInstance>>;
2781
- readonly compliance?: readonly ComplianceTag[];
2782
- readonly models?: ModelConfig;
2783
- readonly outbound?: OutboundCallConfig;
2784
- readonly speech?: SpeechConfig;
2785
- readonly endCall?: EndCallPolicy;
2786
- readonly tools?: Readonly<Record<string, ToolDefinition$1>>;
2787
- /** Per-agent registry-tool scoping (stored ToolBinding names, applied at
2788
- * boot). Non-empty → only these dashboard HTTP tools attach; absent/[] →
2789
- * every enabled registry tool attaches (the historical default). */
2790
- readonly toolBindings?: readonly string[];
2791
- readonly security?: SecurityConfig;
2792
- /**
2793
- * Per-call ConsultationPolicy used by the built-in `ask_host` tool. When
2794
- * omitted the SDK uses the contract defaults (30s per-consult, 120s
2795
- * cumulative). Plan-first calls override this at boot from
2796
- * `plan.draftConfig.consultation`. See
2797
- * packages/contracts/src/consultation.ts for the schema + semantics.
2798
- */
2799
- readonly consultation?: ConsultationPolicy;
2800
- /**
2801
- * Use your existing text agent as the LLM. When set (and `models.llm` is
2802
- * unset), defineAgent wires the pipeline's LLM slot to this function: the
2803
- * caller's STT transcript is passed to `onQuery`, and its returned text (or
2804
- * streamed pieces) is spoken by TTS. The "two lines, keep your stack" path.
2805
- *
2806
- * Equivalent to `models: { llm: connector.llm({ onQuery }) }`. For a remote
2807
- * brain instead, use `connector.llm({ url })` (direct) or a tunnel transport.
2808
- * See docs/specs/voice-brain-connector/.
2809
- */
2810
- readonly onQuery?: OnQuery;
2811
- readonly onUtterance?: (text: string, ctx: AgentContext) => Promise<void> | void;
2812
- readonly onFieldCaptured?: (field: string, value: unknown, ctx: AgentContext) => Promise<void> | void;
2813
- readonly onCallEnd?: (outcome: CallOutcomeSummary, ctx: AgentContext) => Promise<void> | void;
2814
- readonly onEvent?: (event: AgentLifecycleEvent) => void;
2815
- /** Replace the default conversation loop. The SDK does NOT auto-greet. */
2816
- readonly onCall?: (ctx: AgentContext) => Promise<void>;
2817
- readonly readiness?: readonly ReadinessProbe[];
2734
+ interface WriteInput {
2735
+ readonly scope: MemoryScope$1;
2736
+ readonly callerId: string;
2737
+ readonly delta: Record<string, unknown>;
2738
+ readonly callId?: string;
2739
+ }
2740
+ interface SnapshotInput {
2741
+ readonly callId: string;
2742
+ readonly stage: string;
2743
+ readonly snapshot: Record<string, unknown>;
2744
+ }
2745
+ interface ResolveInput {
2746
+ readonly externalKey: string;
2747
+ readonly displayName?: string;
2748
+ readonly identifiers?: ReadonlyArray<{
2749
+ type: string;
2750
+ value: string;
2751
+ }>;
2752
+ }
2753
+ declare class MemoryClient {
2754
+ private readonly transport;
2755
+ constructor(transport: Transport);
2756
+ context(input: ContextInput): Promise<RelevantContext>;
2757
+ write(input: WriteInput): Promise<void>;
2758
+ snapshot(input: SnapshotInput): Promise<{
2759
+ id: string;
2760
+ }>;
2761
+ resolveCaller(input: ResolveInput): Promise<ResolveCallerResponse['caller']>;
2762
+ deleteCaller(callerId: string): Promise<DeleteCallerResponse>;
2763
+ }
2764
+
2765
+ type CallStatus = 'in_progress' | 'completed' | 'failed';
2766
+ type CallAttributeValue = string | number | boolean;
2767
+ type CallParticipantRole = 'caller' | 'agent' | 'callee' | 'supervisor' | 'observer' | 'unknown';
2768
+ type CallParticipantKind = 'human' | 'agent' | 'phone' | 'sip' | 'system';
2769
+ type CallLegKind = 'sip-inbound' | 'sip-outbound' | 'agent-session' | 'conference' | 'transfer' | 'unknown';
2770
+ type CallLegStatus = 'starting' | 'active' | 'ended';
2771
+ interface CallSummary {
2772
+ readonly id: string;
2773
+ readonly projectId: string;
2774
+ readonly livekitRoom: string;
2775
+ readonly phoneNumberId: string | null;
2776
+ readonly agentId: string | null;
2777
+ readonly bindingId: string | null;
2778
+ readonly callerE164: string | null;
2779
+ readonly toE164: string | null;
2780
+ readonly status: CallStatus;
2781
+ readonly startedAt: string;
2782
+ }
2783
+ interface CallUsageReport {
2784
+ readonly durationMs: number;
2785
+ readonly llm: readonly {
2786
+ readonly provider: string;
2787
+ readonly model: string;
2788
+ readonly inputTokens: number;
2789
+ readonly outputTokens: number;
2790
+ }[];
2791
+ readonly tts: readonly {
2792
+ readonly provider: string;
2793
+ readonly chars: number;
2794
+ }[];
2795
+ readonly stt: readonly {
2796
+ readonly provider: string;
2797
+ readonly seconds: number;
2798
+ }[];
2799
+ }
2800
+ interface AppendTranscriptInput {
2801
+ readonly speaker: 'caller' | 'agent';
2802
+ readonly text: string;
2803
+ readonly startMs: number;
2804
+ readonly endMs: number;
2805
+ readonly final?: boolean;
2806
+ }
2807
+ type DtmfDirection = 'received' | 'sent';
2808
+ interface AppendDtmfEventInput {
2809
+ readonly direction: DtmfDirection;
2810
+ readonly digit: string;
2811
+ readonly code: number;
2812
+ readonly participantId?: string;
2813
+ }
2814
+ interface EnsureCallByRoomInput {
2815
+ readonly roomName: string;
2816
+ readonly phoneNumberId?: string;
2817
+ readonly agentId?: string;
2818
+ readonly bindingId?: string;
2819
+ readonly callerE164?: string;
2820
+ readonly toE164?: string;
2821
+ readonly attributes?: Record<string, CallAttributeValue>;
2822
+ readonly participants?: CallParticipantInput[];
2823
+ readonly legs?: CallLegInput[];
2824
+ readonly startedAt?: string;
2825
+ }
2826
+ interface CallParticipantInput {
2827
+ readonly participantKey: string;
2828
+ readonly role: CallParticipantRole;
2829
+ readonly kind: CallParticipantKind;
2830
+ readonly identity?: string | null;
2831
+ readonly address?: string | null;
2832
+ readonly displayName?: string | null;
2833
+ readonly joinedAt?: string;
2834
+ readonly leftAt?: string | null;
2835
+ readonly metadata?: Record<string, unknown>;
2836
+ }
2837
+ interface CallLegInput {
2838
+ readonly legKey: string;
2839
+ readonly kind: CallLegKind;
2840
+ readonly status: CallLegStatus;
2841
+ readonly fromParticipantKey?: string | null;
2842
+ readonly toParticipantKey?: string | null;
2843
+ readonly fromAddress?: string | null;
2844
+ readonly toAddress?: string | null;
2845
+ readonly startedAt?: string;
2846
+ readonly endedAt?: string | null;
2847
+ readonly metadata?: Record<string, unknown>;
2848
+ }
2849
+ interface SyncCallStateInput {
2850
+ readonly attributes?: Record<string, CallAttributeValue>;
2851
+ readonly participants?: CallParticipantInput[];
2852
+ readonly legs?: CallLegInput[];
2853
+ }
2854
+ declare class CallsClient {
2855
+ private readonly transport;
2856
+ constructor(transport: Transport);
2857
+ getByRoom(roomName: string): Promise<CallSummary>;
2858
+ ensureByRoom(input: EnsureCallByRoomInput): Promise<CallSummary>;
2859
+ syncState(callId: string, input: SyncCallStateInput): Promise<void>;
2860
+ appendTranscriptSegment(callId: string, input: AppendTranscriptInput): Promise<void>;
2861
+ reportUsage(callId: string, report: CallUsageReport): Promise<void>;
2862
+ appendDtmfEvent(callId: string, input: AppendDtmfEventInput): Promise<void>;
2818
2863
  /**
2819
- * Run as a remote-controlled (puppet) agent: no autonomous LLM loop, no
2820
- * process/triggers pipeline. STT utterances are still published to
2821
- * `call-events:{callId}` via the existing transcript-segments sync, and
2822
- * the SDK subscribes to `call-control:{callId}` to receive `say`,
2823
- * `hangup`, `dtmf` commands from an external driver (typically the MCP
2824
- * server invoked by a coding agent).
2864
+ * Append a structured call event — consultation lifecycle kinds, or the
2865
+ * operational vocabulary the call-detail Timeline renders between
2866
+ * transcript rows (tool.* / handoff.* / lookup.* / record.* / notify.*).
2867
+ * See apps/api/src/routes/calls.ts AppendEventBody for the accepted shapes.
2825
2868
  *
2826
- * When this is on, `process`, `triggers`, `onUtterance`, `onCall` are
2827
- * ignored. `tools`, `connectors`, `memory` still work.
2869
+ * The agent SDK's built-in `ask_host` tool calls this on consultation start
2870
+ * / end; the handoff runtime and graph interpreter emit op events through it
2871
+ * so the operational story (dial → answered → briefed → dropped, tool calls)
2872
+ * is visible in the dashboard, not just the spoken transcript.
2828
2873
  */
2829
- readonly puppetMode?: boolean;
2874
+ appendEvent(callId: string, input: {
2875
+ readonly kind: 'consultation.requested' | 'consultation.resolved' | `tool.${string}` | `handoff.${string}` | `lookup.${string}` | `record.${string}` | `notify.${string}`;
2876
+ readonly payload: Record<string, unknown>;
2877
+ }): Promise<void>;
2878
+ }
2879
+
2880
+ interface CreateFormSessionInput {
2881
+ readonly formId: string;
2882
+ readonly recipientPhone: string;
2883
+ readonly recipientName?: string;
2884
+ readonly prefill?: Record<string, unknown>;
2885
+ readonly webhookUrl?: string;
2886
+ readonly callbackFromNumber?: string;
2887
+ readonly ttlSeconds?: number;
2830
2888
  /**
2831
- * Host-controlled autonomous agent (the "smart puppet"). UNLIKE puppetMode,
2832
- * the agent keeps its REAL LLM and drives the conversation itself from its
2833
- * prompt (the per-call `intent` is appended at boot). This flag only wires
2834
- * the `call-control:{room}` channel so the MCP host can still interject
2835
- * (`say`), end the call (`hangup`), or send `dtmf` — and answer the agent's
2836
- * `ask_host` consultations. Use this for an agent that takes a customer's
2837
- * intent and runs the call like a human secretary, asking the host for any
2838
- * info it's missing. Mutually exclusive in spirit with puppetMode (which is
2839
- * the older NoOp "dumb mouth").
2889
+ * When set, the API will SMS the link from this phone number immediately
2890
+ * after creating the session. This is the common case for agent-led use:
2891
+ * the agent calls sendFormLink during a conversation and the recipient
2892
+ * gets a text right away.
2840
2893
  */
2841
- readonly hostControlled?: boolean;
2842
- /** When set, this agent boots each call from a deployed flow's process_schema. */
2843
- readonly flowRuntime?: FlowRuntimeConfig;
2894
+ readonly sendSms?: {
2895
+ readonly phoneNumberId: string;
2896
+ readonly bodyPrefix?: string;
2897
+ };
2844
2898
  /**
2845
- * Opt a hand-coded (non-flow) agent into the dashboard-driven pipeline: on
2846
- * each call the SDK fetches this agent's stored `agent_config` and applies
2847
- * the operator-selected voice / model / STT over the coded defaults. The
2848
- * pipeline *mode* (cascade vs realtime) stays pinned to what the code
2849
- * declares — a stale `mode=realtime` in the dashboard can't flip a
2850
- * cascade-only worker. Flow agents (`flowRuntime`) get this implicitly and
2851
- * may additionally switch mode; this flag is the SDK opt-in. The agent id is
2852
- * read from dispatch metadata (the inbound router injects it from
2853
- * phone_numbers.agentId), so it's a no-op for calls without one.
2899
+ * When set, the API will email the link to `to` immediately after creating
2900
+ * the session. Independent from sendSms — set both for belt-and-braces
2901
+ * delivery, set neither to just receive the URL back. Use this when SMS is
2902
+ * blocked by toll-fraud / 10DLC registration.
2854
2903
  */
2855
- readonly pipelineFromConfig?: boolean;
2904
+ readonly sendEmail?: {
2905
+ readonly to: string;
2906
+ readonly subject?: string;
2907
+ readonly bodyPrefix?: string;
2908
+ };
2909
+ }
2910
+ interface CreatedFormSession {
2911
+ readonly sessionId: string;
2912
+ readonly token: string;
2913
+ readonly url: string;
2914
+ readonly smsId: string | null;
2915
+ readonly emailId: string | null;
2916
+ readonly expiresAt: string;
2917
+ }
2918
+ interface PublicFormSessionView {
2919
+ readonly schema: {
2920
+ readonly id: string;
2921
+ readonly version: number;
2922
+ readonly title: string;
2923
+ readonly description?: string | undefined;
2924
+ readonly survey: Record<string, unknown>;
2925
+ };
2926
+ readonly values: Record<string, unknown>;
2927
+ readonly status: 'pending' | 'active' | 'live' | 'submitted' | 'expired';
2928
+ readonly recipientPhoneMasked: string;
2929
+ readonly hasActiveCall: boolean;
2930
+ readonly submittedAt: string | null;
2931
+ readonly expiresAt: string;
2932
+ }
2933
+ declare class FormsClient {
2934
+ private readonly transport;
2935
+ constructor(transport: Transport);
2936
+ createSession(input: CreateFormSessionInput): Promise<CreatedFormSession>;
2937
+ getByToken(token: string): Promise<PublicFormSessionView>;
2938
+ patchValues(token: string, values: Record<string, unknown>): Promise<{
2939
+ values: Record<string, unknown>;
2940
+ updatedAt: string;
2941
+ }>;
2942
+ submit(token: string, values: Record<string, unknown>): Promise<{
2943
+ responseId: string;
2944
+ submittedAt: string;
2945
+ }>;
2946
+ }
2947
+
2948
+ interface SendEmailInput {
2949
+ readonly to: string;
2950
+ readonly subject: string;
2951
+ readonly text: string;
2952
+ readonly html?: string;
2953
+ }
2954
+ interface SentEmail {
2955
+ readonly emailId: string;
2956
+ }
2957
+ declare class EmailClient {
2958
+ private readonly transport;
2959
+ constructor(transport: Transport);
2960
+ send(input: SendEmailInput): Promise<SentEmail>;
2961
+ }
2962
+
2963
+ declare class PlansClient {
2964
+ private readonly transport;
2965
+ constructor(transport: Transport);
2856
2966
  /**
2857
- * Opt this agent into MCP-layer visibility. When true, on register the API
2858
- * also writes an `agent_config` row keyed by (project_id, name,
2859
- * environment) so MCP / dashboard / REST can list and inspect this agent
2860
- * (and, post-step-7, drive call_say / call_send_guidance / etc against
2861
- * its live calls).
2862
- *
2863
- * Defaults to true so newly-registered agents show up in dashboards and
2864
- * MCP-host listings without opt-in. Pass `false` for autonomous-only
2865
- * agents that should stay invisible to MCP. See
2866
- * docs/architecture/contracts-design.md §2b.
2967
+ * Fetch a plan by id. Project scoping is enforced by the API via the
2968
+ * caller's VOICELAYER_API_KEY — a cross-project planId surfaces as 404.
2969
+ * Returns `null` on 404 so the caller can fall back to legacy boot.
2867
2970
  */
2868
- readonly mcpExposed?: boolean;
2971
+ getById(planId: string): Promise<CallPlan | null>;
2869
2972
  }
2870
- interface CallOutcomeSummary {
2871
- readonly reason: 'completed' | 'handoff' | 'caller_hung_up' | 'agent_hung_up' | 'error';
2872
- readonly durationMs: number;
2873
- readonly processCompleted: boolean;
2874
- readonly fieldsCaptured: number;
2875
- readonly handoffOccurred: boolean;
2973
+
2974
+ declare const ProviderCredential: z.ZodObject<{
2975
+ apiKey: z.ZodString;
2976
+ baseUrl: z.ZodOptional<z.ZodString>;
2977
+ }, "strip", z.ZodTypeAny, {
2978
+ apiKey: string;
2979
+ baseUrl?: string | undefined;
2980
+ }, {
2981
+ apiKey: string;
2982
+ baseUrl?: string | undefined;
2983
+ }>;
2984
+ type ProviderCredential = z.infer<typeof ProviderCredential>;
2985
+ declare const BrainConnectorConfig: z.ZodObject<{
2986
+ connector: z.ZodObject<{
2987
+ id: z.ZodString;
2988
+ mode: z.ZodEnum<["tunnel", "direct"]>;
2989
+ connectionId: z.ZodNullable<z.ZodString>;
2990
+ defaultModel: z.ZodNullable<z.ZodString>;
2991
+ normalize: z.ZodEnum<["auto", "on", "off"]>;
2992
+ enabled: z.ZodBoolean;
2993
+ credential: z.ZodOptional<z.ZodNullable<z.ZodObject<{
2994
+ apiKey: z.ZodString;
2995
+ baseUrl: z.ZodString;
2996
+ }, "strip", z.ZodTypeAny, {
2997
+ apiKey: string;
2998
+ baseUrl: string;
2999
+ }, {
3000
+ apiKey: string;
3001
+ baseUrl: string;
3002
+ }>>>;
3003
+ }, "strip", z.ZodTypeAny, {
3004
+ enabled: boolean;
3005
+ id: string;
3006
+ mode: "tunnel" | "direct";
3007
+ defaultModel: string | null;
3008
+ connectionId: string | null;
3009
+ normalize: "on" | "off" | "auto";
3010
+ credential?: {
3011
+ apiKey: string;
3012
+ baseUrl: string;
3013
+ } | null | undefined;
3014
+ }, {
3015
+ enabled: boolean;
3016
+ id: string;
3017
+ mode: "tunnel" | "direct";
3018
+ defaultModel: string | null;
3019
+ connectionId: string | null;
3020
+ normalize: "on" | "off" | "auto";
3021
+ credential?: {
3022
+ apiKey: string;
3023
+ baseUrl: string;
3024
+ } | null | undefined;
3025
+ }>;
3026
+ }, "strip", z.ZodTypeAny, {
3027
+ connector: {
3028
+ enabled: boolean;
3029
+ id: string;
3030
+ mode: "tunnel" | "direct";
3031
+ defaultModel: string | null;
3032
+ connectionId: string | null;
3033
+ normalize: "on" | "off" | "auto";
3034
+ credential?: {
3035
+ apiKey: string;
3036
+ baseUrl: string;
3037
+ } | null | undefined;
3038
+ };
3039
+ }, {
3040
+ connector: {
3041
+ enabled: boolean;
3042
+ id: string;
3043
+ mode: "tunnel" | "direct";
3044
+ defaultModel: string | null;
3045
+ connectionId: string | null;
3046
+ normalize: "on" | "off" | "auto";
3047
+ credential?: {
3048
+ apiKey: string;
3049
+ baseUrl: string;
3050
+ } | null | undefined;
3051
+ };
3052
+ }>;
3053
+ type BrainConnectorConfig = z.infer<typeof BrainConnectorConfig>['connector'];
3054
+ declare class ConnectionsClient {
3055
+ private readonly transport;
3056
+ constructor(transport: Transport);
3057
+ resolveProviderCredential(provider: string): Promise<ProviderCredential | null>;
3058
+ resolveBrainConnectorConfig(id: string): Promise<BrainConnectorConfig | null>;
2876
3059
  }
2877
- /**
2878
- * Identity helper that gives users a typed `defineProcess` entry point with
2879
- * full inference on `onComplete`'s `data` argument.
2880
- *
2881
- * defineProcess({
2882
- * collect: { name: { type: 'string', required: true } },
2883
- * onComplete: (data) => { data.name // string },
2884
- * })
2885
- */
2886
- declare function defineProcess<T extends Record<string, ProcessField>>(def: ProcessDefinition<T>): ProcessDefinition<T>;
2887
3060
 
2888
- interface RunAgentTextTranscriptOptions {
2889
- /** The agent's system prompt / instructions (its code-defined behavior). */
2890
- readonly instructions: string;
2891
- /** The LLM that generates replies — injected so this stays provider-agnostic and
2892
- * unit-testable (real inference/openai LLM in prod; a scripted fake in tests). */
2893
- readonly llm: llm.LLM;
2894
- /** Scripted caller turns, run in order; each produces the agent's reply turn(s). */
2895
- readonly messages: readonly string[];
2896
- /** Optional id surfaced on the Agent (for traceability). */
2897
- readonly agentId?: string;
3061
+ interface CreateClientOptions {
3062
+ readonly apiKey?: string;
3063
+ readonly baseUrl?: string;
3064
+ readonly fetch?: typeof fetch;
3065
+ readonly maxRetries?: number;
3066
+ readonly initialBackoffMs?: number;
3067
+ readonly userAgent?: string;
3068
+ readonly scheduler?: AgentsClientOptions['scheduler'];
3069
+ readonly attachSignalHandlers?: boolean;
2898
3070
  }
2899
- interface AgentTextTranscriptResult {
2900
- readonly replies: string[];
3071
+ interface VoiceLayerClient {
3072
+ readonly agents: AgentsClient;
3073
+ readonly memory: MemoryClient;
3074
+ readonly calls: CallsClient;
3075
+ readonly forms: FormsClient;
3076
+ readonly email: EmailClient;
3077
+ readonly plans: PlansClient;
3078
+ readonly connections: ConnectionsClient;
2901
3079
  }
2902
- /** Drive an instruction-based agent over text and collect its replies. Stateless
2903
- * batch turn — the request/response shape the text playground's agent path uses. */
2904
- declare function runAgentTextTranscript(opts: RunAgentTextTranscriptOptions): Promise<AgentTextTranscriptResult>;
3080
+ declare function createClient(options?: CreateClientOptions): VoiceLayerClient;
2905
3081
 
2906
3082
  interface DefaultMetadata {
2907
3083
  readonly hostname: string;
@@ -3049,9 +3225,13 @@ interface PuppetControlHandle {
3049
3225
  /** Stop listening for commands and tear down the Redis subscription. */
3050
3226
  close(): Promise<void>;
3051
3227
  }
3052
- /** True if we should run puppet wiring — REDIS_URL must be set. */
3228
+ /** @deprecated since 0.2.0 — see startPuppetControl. True if we should run puppet wiring — REDIS_URL must be set. */
3053
3229
  declare function puppetEnvAvailable(): boolean;
3054
3230
  /**
3231
+ * @deprecated since 0.2.0 (burn-down G-5): every agent now listens on its call's control channel and confirms each
3232
+ * command (runtime/call-control.ts + runtime/host-control.ts). This listener never confirms, so the API refuses its
3233
+ * commands. Kept for SDK consumers that call it directly; removed in the next major.
3234
+ *
3055
3235
  * Start a puppet-mode control listener for the given call. Returns a handle
3056
3236
  * the caller invokes when the call ends to release the Redis connection.
3057
3237
  *
@@ -3102,251 +3282,6 @@ declare function webhook(config: WebhookConfig): ConnectorInstance<'webhook', We
3102
3282
  /** Subset of ModelConfig the Agent class converts AgentConfig.models into. */
3103
3283
  type PipelineConfig = ModelConfig;
3104
3284
 
3105
- type ProviderKind = 'tts' | 'stt' | 'llm' | 'vad' | 'turn';
3106
- interface WrapOptions<T> {
3107
- /** Emit OTel spans around each method call. Default: true. */
3108
- readonly trace?: boolean;
3109
- /** Tag spans with `vl.provider.label` for easy filtering. */
3110
- readonly label?: string;
3111
- /**
3112
- * Provider role. When set, the wrapper additionally emits OTel Counters
3113
- * (vl.tts.chars / vl.llm.input_tokens / vl.stt.seconds) so /v1/calls/:id/
3114
- * metrics returns real per-call usage. The TTS path is wired today —
3115
- * chars are counted from the synthesize() text argument. LLM/STT counters
3116
- * still depend on the underlying adapter exposing usage on its response
3117
- * shape; see TODO below.
3118
- */
3119
- readonly kind?: ProviderKind;
3120
- /**
3121
- * Provider name surfaced in metric attributes (deepgram, openai, …).
3122
- * Falls back to `label` when omitted.
3123
- */
3124
- readonly provider?: string;
3125
- /**
3126
- * Fallback provider used if the primary throws. Accepts an instance OR a
3127
- * ProviderFactory (so `deepgram.tts(...)` works directly). The fallback is
3128
- * resolved lazily on first error.
3129
- */
3130
- readonly fallback?: T | ProviderFactory<T>;
3131
- /**
3132
- * Methods to instrument. By default the wrapper instruments every method
3133
- * call. Pass an explicit list to limit overhead on hot paths.
3134
- */
3135
- readonly methods?: readonly string[];
3136
- }
3137
- /**
3138
- * Returns either the wrapped instance directly (when called with one) or a
3139
- * ProviderFactory that produces the wrapped instance (when called with one of
3140
- * those). This keeps the lazy import story intact: `wrap(deepgram.tts(...))`
3141
- * is itself a factory.
3142
- */
3143
- declare function wrap<T extends object>(target: T | ProviderFactory<T>, options?: WrapOptions<T>): T | ProviderFactory<T>;
3144
-
3145
- declare const deepgram: {
3146
- stt(options?: {
3147
- model?: string;
3148
- language?: string;
3149
- apiKey?: string;
3150
- baseURL?: string;
3151
- }): ProviderFactory<STTProvider>;
3152
- tts(options?: {
3153
- model?: string;
3154
- apiKey?: string;
3155
- baseURL?: string;
3156
- }): ProviderFactory<TTSProvider>;
3157
- };
3158
- declare const openai: {
3159
- llm(options?: {
3160
- model?: string;
3161
- apiKey?: string;
3162
- baseURL?: string;
3163
- }): ProviderFactory<LLMProvider>;
3164
- tts(options?: {
3165
- model?: string;
3166
- voice?: string;
3167
- instructions?: string;
3168
- apiKey?: string;
3169
- baseURL?: string;
3170
- }): ProviderFactory<TTSProvider>;
3171
- realtime(options?: {
3172
- model?: string;
3173
- voice?: string;
3174
- apiKey?: string;
3175
- baseURL?: string;
3176
- }): ProviderFactory<RealtimeProvider>;
3177
- };
3178
- declare const cartesia: {
3179
- tts(options?: {
3180
- voice?: string;
3181
- model?: string;
3182
- apiKey?: string;
3183
- baseURL?: string;
3184
- }): ProviderFactory<TTSProvider>;
3185
- stt(options?: {
3186
- model?: string;
3187
- language?: string;
3188
- apiKey?: string;
3189
- baseURL?: string;
3190
- }): ProviderFactory<STTProvider>;
3191
- };
3192
- declare const elevenlabs: {
3193
- tts(options?: {
3194
- voice?: string;
3195
- model?: string;
3196
- apiKey?: string;
3197
- baseURL?: string;
3198
- }): ProviderFactory<TTSProvider>;
3199
- };
3200
- declare const assemblyai: {
3201
- stt(options?: {
3202
- language?: string;
3203
- apiKey?: string;
3204
- baseURL?: string;
3205
- }): ProviderFactory<STTProvider>;
3206
- };
3207
- declare const google: {
3208
- llm(options?: {
3209
- model?: string;
3210
- apiKey?: string;
3211
- baseURL?: string;
3212
- }): ProviderFactory<LLMProvider>;
3213
- realtime(options?: {
3214
- model?: string;
3215
- voice?: string;
3216
- apiKey?: string;
3217
- baseURL?: string;
3218
- }): ProviderFactory<RealtimeProvider>;
3219
- };
3220
- declare const silero: {
3221
- vad(): ProviderFactory<VADProvider>;
3222
- };
3223
- declare const livekitTurn: {
3224
- english(): ProviderFactory<TurnDetectorProvider>;
3225
- multilingual(): ProviderFactory<TurnDetectorProvider>;
3226
- };
3227
- interface ConnectorLLMConfig {
3228
- /** Upstream model id / alias (defaults to the brain's own default). */
3229
- readonly model?: string;
3230
- readonly temperature?: number;
3231
- /** Spoken instead of dead air when the brain errors before replying. */
3232
- readonly fallbackText?: string;
3233
- /** In-process brain. */
3234
- readonly onQuery?: OnQuery;
3235
- /** Direct-egress brain — a public OpenAI-compatible base URL. */
3236
- readonly url?: string;
3237
- /** API key for the direct-egress endpoint. */
3238
- readonly apiKey?: string;
3239
- /** Hostnames that bypass the SSRF IP checks (direct mode). */
3240
- readonly allowHosts?: readonly string[];
3241
- /** Advanced: a custom transport (tunnel, etc.). */
3242
- readonly transport?: BrainTransport;
3243
- }
3244
- declare const connector: {
3245
- llm(config?: ConnectorLLMConfig): ProviderFactory<LLMProvider>;
3246
- };
3247
-
3248
- declare function callbackTransport(onQuery: OnQuery): BrainTransport;
3249
-
3250
- interface ConnectorLLMOptions {
3251
- readonly model?: string;
3252
- readonly temperature?: number;
3253
- readonly callId?: string;
3254
- readonly projectId?: string;
3255
- /** Spoken instead of dead air when the brain errors before any reply. */
3256
- readonly fallbackText?: string;
3257
- }
3258
- /**
3259
- * Build a ConnectorLLM instance for the pipeline's `llm` slot. The returned
3260
- * object's chat() yields the brain reply and exposes close() for barge-in.
3261
- */
3262
- declare function createConnectorLLM(transport: BrainTransport, options?: ConnectorLLMOptions): Promise<unknown>;
3263
-
3264
- interface ConnectorChatModelOptions {
3265
- readonly model?: string;
3266
- }
3267
- interface ChatModelInput {
3268
- readonly messages: readonly {
3269
- readonly role: 'system' | 'user' | 'assistant';
3270
- readonly content: string;
3271
- }[];
3272
- readonly json?: boolean;
3273
- readonly temperature?: number;
3274
- readonly model?: string;
3275
- }
3276
- declare class ConnectorChatModel {
3277
- private readonly transport;
3278
- private readonly options;
3279
- constructor(transport: BrainTransport, options?: ConnectorChatModelOptions);
3280
- complete(input: ChatModelInput): Promise<string>;
3281
- }
3282
-
3283
- declare class BrainConfigError extends Error {
3284
- constructor(message: string);
3285
- }
3286
- /** Resolve a hostname to a list of IP strings. Injectable for tests. */
3287
- type HostLookup = (host: string) => Promise<readonly string[]>;
3288
- interface AssertUrlOptions {
3289
- /** Hostnames that bypass IP checks (explicit per-connector allowlist). */
3290
- readonly allowHosts?: readonly string[];
3291
- /** Override DNS resolution (tests). */
3292
- readonly lookup?: HostLookup;
3293
- }
3294
- /**
3295
- * Validate a brain URL for direct egress. Throws BrainConfigError on any
3296
- * violation; returns the parsed URL when safe.
3297
- */
3298
- declare function assertPublicHttpsUrl(raw: string, opts?: AssertUrlOptions): Promise<URL>;
3299
-
3300
- interface BrainPubSub {
3301
- publish(channel: string, message: string): Promise<void>;
3302
- /** Subscribe to a channel; returns an unsubscribe handle. */
3303
- subscribe(channel: string, handler: (raw: string) => void): Promise<() => Promise<void>>;
3304
- }
3305
- interface TunnelBrainTransportOptions {
3306
- readonly connectorId: string;
3307
- readonly pubsub: BrainPubSub;
3308
- /** Fail the turn if the daemon sends nothing within this window. Default 20s. */
3309
- readonly firstChunkTimeoutMs?: number;
3310
- }
3311
- declare function tunnelBrainTransport(options: TunnelBrainTransportOptions): BrainTransport;
3312
-
3313
- declare class RedisBrainPubSub implements BrainPubSub {
3314
- private readonly sub;
3315
- private readonly pub;
3316
- private readonly listeners;
3317
- constructor(sub: Redis, pub: Redis);
3318
- publish(channel: string, message: string): Promise<void>;
3319
- subscribe(channel: string, handler: (raw: string) => void): Promise<() => Promise<void>>;
3320
- close(): Promise<void>;
3321
- }
3322
- declare function buildRedisBrainPubSub(redisUrl: string | undefined): RedisBrainPubSub | null;
3323
-
3324
- interface SseDelta {
3325
- readonly content?: string;
3326
- readonly finishReason?: string;
3327
- }
3328
- declare function parseChatCompletionSse(source: AsyncIterable<Uint8Array> | ReadableStream<Uint8Array>): AsyncGenerator<SseDelta>;
3329
-
3330
- interface BrainEndpointConfig {
3331
- /** Base URL of the OpenAI-compatible endpoint, e.g. http://localhost:4000/v1. */
3332
- readonly brainUrl: string;
3333
- readonly apiKey?: string;
3334
- readonly defaultModel?: string;
3335
- /** Injectable for tests; defaults to global fetch. */
3336
- readonly fetchImpl?: typeof fetch;
3337
- }
3338
- interface IncomingBrainRequest {
3339
- readonly streamId: string;
3340
- readonly model?: string;
3341
- readonly temperature?: number;
3342
- readonly messages: ReadonlyArray<{
3343
- role: 'system' | 'user' | 'assistant';
3344
- content: string;
3345
- }>;
3346
- }
3347
- /** Run one brain.request and yield the reply frames. Never throws. */
3348
- declare function runBrainRequest(req: IncomingBrainRequest, cfg: BrainEndpointConfig, signal: AbortSignal): AsyncGenerator<ConnectorUpFrame>;
3349
-
3350
3285
  /**
3351
3286
  * Turn the persisted `agents.process_schema` (or a freshly-compiled flow) into a
3352
3287
  * ProcessDefinition. The completion gate drives the `required` flags so the
@@ -3377,6 +3312,26 @@ declare function processSchemaToAgentParts(schema: ProcessSchemaDTO, opts?: {
3377
3312
  readonly graphNodeIds?: ReadonlySet<string>;
3378
3313
  }): CompiledAgentParts;
3379
3314
 
3315
+ interface ExchangeWorkerTokenInput {
3316
+ readonly projectId: string;
3317
+ readonly callId?: string;
3318
+ readonly fetchImpl?: typeof fetch;
3319
+ }
3320
+ /** One mint per call (cheap in-cluster HMAC mint, ~ms) so every token is
3321
+ * attributable to a specific call in the API's audit log. Returns null when
3322
+ * the exchange isn't configured or fails — callers fall back to the env key. */
3323
+ declare function exchangeWorkerToken(input: ExchangeWorkerTokenInput): Promise<string | null>;
3324
+ /** Build a client directly from a PRE-MINTED worker token (W3-lite control-plane
3325
+ * mint). The authority (API for text, call-router for voice) minted the token
3326
+ * from the projectId it already holds and handed it to the worker — so the
3327
+ * worker never self-mints via /v1/internal/worker-token, closing the master-key
3328
+ * path where a worker asserts its own projectId. Returns null on a bad token so
3329
+ * callers can fall back to the self-mint chain (resolveWorkerClient). */
3330
+ declare function workerClientFromToken(token: string): VoiceLayerClient | null;
3331
+ /** Build the per-call SDK client under the calling project's identity, with
3332
+ * the env-key fallback chain above. `md` is the parsed dispatch metadata. */
3333
+ declare function resolveWorkerClient(md: Record<string, unknown>, fetchImpl?: typeof fetch): Promise<VoiceLayerClient | null>;
3334
+
3380
3335
  /**
3381
3336
  * Extend this to author a tool with the least ceremony. `run` receives the
3382
3337
  * parsed input and the live AgentContext; whatever it returns is handed back to
@@ -3428,25 +3383,4 @@ interface HttpToolSpec {
3428
3383
  */
3429
3384
  declare function httpTool(spec: HttpToolSpec): Record<string, ToolDefinition>;
3430
3385
 
3431
- interface CreateClientOptions {
3432
- readonly apiKey?: string;
3433
- readonly baseUrl?: string;
3434
- readonly fetch?: typeof fetch;
3435
- readonly maxRetries?: number;
3436
- readonly initialBackoffMs?: number;
3437
- readonly userAgent?: string;
3438
- readonly scheduler?: AgentsClientOptions['scheduler'];
3439
- readonly attachSignalHandlers?: boolean;
3440
- }
3441
- interface VoiceLayerClient {
3442
- readonly agents: AgentsClient;
3443
- readonly memory: MemoryClient;
3444
- readonly calls: CallsClient;
3445
- readonly forms: FormsClient;
3446
- readonly email: EmailClient;
3447
- readonly plans: PlansClient;
3448
- readonly connections: ConnectionsClient;
3449
- }
3450
- declare function createClient(options?: CreateClientOptions): VoiceLayerClient;
3451
-
3452
- export { Agent, type AgentConfig, AgentContext, type AgentEventEmitter, type AgentEventListener, type AgentLifecycleEvent, type AgentTextTranscriptResult, type AppendDtmfEventInput, type AppendTranscriptInput, BaseTool, type BrainCallMetadata, type BrainCapabilities, type BrainChunk, BrainConfigError, type BrainEndpointConfig, type BrainMessage, type BrainPubSub, type BrainRequest, type BrainTransport, type CallAttributeValue, CallInfo, type CallLegInput, type CallOutcomeSummary, type CallParticipantInput, type CallStatus, type CallSummary, CallsClient, type CompiledAgentParts, type CompletionStrategy, type ComplianceTag, ConnectorChatModel, type ConnectorChatModelOptions, type ConnectorInstance, type ConnectorLLMConfig, type ConnectorLLMOptions, ConsultationPolicy, type CreateClientOptions, type CreatedFormSession, type DefaultMetadata, type DtmfDirection, EmailClient, type SendEmailInput as EmailSendInput, type EndCallInfo, type EndCallPolicy, type EndCallTrigger, type EndpointingConfig, type EnsureCallByRoomInput, type CreateFormSessionInput as FormCreateInput, type FormToolsOptions, FormsClient, type HandoffConfig, type HttpToolResult, type HttpToolSpec, type IncomingBrainRequest, type InferProcessData, type InterruptionConfig, type LLMProvider, type MemoryConfig, type MemoryScope, type ModelConfig, type OnQuery, type OnQueryContext, type OnQueryResult, Participant, type ParticipantsConfig, type PipelineConfig, PlansClient, type ProcessBackendAck, type ProcessDefinition, type ProcessField, type ProcessFieldType, type PronunciationDict, type ProviderFactory, type PublicFormSessionView, type PuppetControlDeps, type PuppetControlHandle, type ReadinessProbe, type ReadinessReport, type ReadinessResult, type RealtimeProvider, RedisBrainPubSub, type RegisterInput, type RegisterOptions, type RegisteredAgent, type ResendCredentials, type ResendEmailToolOptions, type RunAgentTextTranscriptOptions, type STTProvider, type SecurityConfig, type SentEmail, type ShorthandPrimitive$1 as ShorthandPrimitive, type SpeechConfig, type SseDelta, type SyncCallStateInput, type TTSProvider, type ToolDefinition$1 as ToolDefinition, type ToolInputShape$1 as ToolInputShape, type TriggerAction, type TriggerCondition, type TriggerDefinition, type TunnelBrainTransportOptions, type TurnDetectorProvider, type VADProvider, VoiceLayerAuthError, type VoiceLayerClient, VoiceLayerError, VoiceLayerHttpError, VoiceLayerNetworkError, VoiceLayerValidationError, type WebhookApi, type WebhookConfig, type WrapOptions, applyPronunciations, assemblyai, assertPublicHttpsUrl, asyncProbe, buildRedisBrainPubSub, callbackTransport, cartesia, collectDefaultMetadata, connector, createClient, createConnectorLLM, createNoOpLLM, deepgram, defineAgent, defineFlowRuntime, defineProcess, defineTool, elevenlabs, envProbe, formTools, google, httpTool, livekitTurn, mergeMetadata, openai, parseChatCompletionSse, processSchemaToAgentParts, processSchemaToDefinition, puppetEnvAvailable, resendEmailTool, runAgentTextTranscript, runBrainRequest, runProbes, silero, startPuppetControl, tunnelBrainTransport, urlProbe, webhook, wrap };
3386
+ export { Agent, type AgentConfig, AgentContext, type AgentEventEmitter, type AgentEventListener, type AgentLifecycleEvent, type AgentTextPlan, type AgentTextRuntimeClient, type AgentTextTranscriptResult, type AppendDtmfEventInput, type AppendTranscriptInput, BaseTool, BrainTransport, type BuildTextLlm, type CallAttributeValue, CallInfo, type CallLegInput, type CallOutcomeSummary, type CallParticipantInput, type CallStatus, type CallSummary, CallsClient, type CompiledAgentParts, type CompletionStrategy, type ComplianceTag, type ConnectorInstance, type ConnectorLLMConfig, ConsultationPolicy, type CreateClientOptions, type CreatedFormSession, type DefaultMetadata, type DtmfDirection, EmailClient, type SendEmailInput as EmailSendInput, type EndCallInfo, type EndCallPolicy, type EndCallTrigger, type EndpointingConfig, type EnsureCallByRoomInput, type ExchangeWorkerTokenInput, type CreateFormSessionInput as FormCreateInput, type FormToolsOptions, FormsClient, type HandoffConfig, type HttpToolResult, type HttpToolSpec, type InferProcessData, type InterruptionConfig, type LLMProvider, type LiveAgentTextSession, type LiveAgentTurn, type LiveAgentTurnUsage, type MemoryConfig, type MemoryScope, type ModelConfig, OnQuery, Participant, type ParticipantsConfig, type PipelineConfig, PlansClient, type ProcessBackendAck, type ProcessDefinition, type ProcessField, type ProcessFieldType, type PronunciationDict, type ProviderFactory, type PublicFormSessionView, type PuppetControlDeps, type PuppetControlHandle, type ReadinessProbe, type ReadinessReport, type ReadinessResult, type RealtimeProvider, type RegisterInput, type RegisterOptions, type RegisteredAgent, type ResendCredentials, type ResendEmailToolOptions, type ResolveAgentTextRuntimeOptions, type ResolvedAgentTextRuntime, type RunAgentTextTranscriptOptions, type RunLiveAgentTextOptions, type STTProvider, type SecurityConfig, type SentEmail, type ShorthandPrimitive$1 as ShorthandPrimitive, type SpeechConfig, type SyncCallStateInput, type TTSProvider, type ToolDefinition$1 as ToolDefinition, type ToolInputShape$1 as ToolInputShape, type TriggerAction, type TriggerCondition, type TriggerDefinition, type TurnDetectorProvider, type VADProvider, VoiceLayerAuthError, type VoiceLayerClient, VoiceLayerError, VoiceLayerHttpError, VoiceLayerNetworkError, VoiceLayerValidationError, type WebhookApi, type WebhookConfig, type WrapOptions, applyPronunciations, assemblyai, asyncProbe, buildTextLlm, cartesia, collectDefaultMetadata, connector, createClient, createNoOpLLM, deepgram, defineAgent, defineFlowRuntime, defineProcess, defineTool, elevenlabs, envProbe, exchangeWorkerToken, formTools, google, httpTool, livekitTurn, mergeMetadata, openai, processSchemaToAgentParts, processSchemaToDefinition, puppetEnvAvailable, resendEmailTool, resolveAgentTextPlan, resolveAgentTextRuntime, resolveWorkerClient, runAgentTextTranscript, runLiveAgentTextSession, runProbes, silero, startPuppetControl, urlProbe, webhook, workerClientFromToken, wrap };