@voctiv/agent-sdk 0.2.4 → 0.2.6

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.
Files changed (2) hide show
  1. package/README.md +79 -8
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -79,7 +79,7 @@ export default defineScript(async ({ channel, logger, context }) => {
79
79
  - `channel` is the media channel for SIP, WS, ASR, TTS, audio playback, LLM, and structured data messages.
80
80
  - `logger` writes structured script logs and can stream logs to a debug endpoint.
81
81
  - `context` contains dialog identity, caller/called numbers, language, flags, params, entry point, persisted env, and runtime budget.
82
- - `platform` exposes legacy platform operations: NLU, dialog state, outbound call scheduling, messaging, and phrase records.
82
+ - `platform` exposes platform operations: NLU, dialog state, outbound call scheduling, messaging, and phrase records.
83
83
 
84
84
  `MediaChannel` is the main real-time API:
85
85
 
@@ -103,6 +103,28 @@ The important states are:
103
103
  - `active`: final 200 OK has been received or sent.
104
104
  - `terminated`: the call ended and no more audio is possible.
105
105
 
106
+ ### How Pre-Answer Works
107
+
108
+ Pre-answer means the SIP media path is open before the call is finally answered with `200 OK`. In this state the caller can already hear TTS, the script can already receive audio for ASR, and DTMF can be exchanged.
109
+
110
+ Use pre-answer when you need to do something before committing the call to the final answer state:
111
+
112
+ - play an informational greeting or disclaimer;
113
+ - collect a short value with ASR, such as account number or menu choice;
114
+ - detect and navigate an IVR that speaks before answering;
115
+ - delay `answer()` until the script is ready to transfer, bridge, or continue.
116
+
117
+ For inbound calls, the script controls this explicitly:
118
+
119
+ 1. Call `channel.sip.sendProgress()` to send `183 Session Progress` with SDP.
120
+ 2. Wait for `channel.sip.waitForEarly()` if your next logic step needs media to be ready.
121
+ 3. Use `channel.audio.say()`, `channel.audio.play()`, `channel.createAsr()`, or `channel.sip.sendDtmf()` normally.
122
+ 4. Call `channel.sip.answer()` when you want to send the final `200 OK`.
123
+
124
+ For outbound calls, pre-answer is controlled by the remote side. If the remote endpoint sends `183 Session Progress` with SDP, ScriptEngine moves the call to `early`. If it answers directly, `waitForEarly()` resolves when the call becomes `active`.
125
+
126
+ `early` is a media-ready state, not a final answer state. `answer()` is still the explicit transition that sends final `200 OK` for inbound calls. External billing behavior depends on the carrier.
127
+
106
128
  ### Outbound Pre-Answer
107
129
 
108
130
  For outbound calls, early media starts when the remote side sends a provisional response with SDP, usually `183 Session Progress`. This is useful for IVRs that speak before answering.
@@ -349,7 +371,7 @@ await channel.audio.say(
349
371
 
350
372
  ## Platform API
351
373
 
352
- `platform` exposes Voctiv legacy-compatible operations.
374
+ `platform` exposes Voctiv platform operations.
353
375
 
354
376
  `platform.nlu.extract(utterance, options?)` calls NLU v3 `/infer`. The runtime sends `phrase`, `context`, and `agent_id`. If `options.context` is omitted, current dialog params are serialized and used as NLU context.
355
377
 
@@ -361,7 +383,7 @@ const result = await platform.nlu.extract('I want to reschedule', {
361
383
  });
362
384
  ```
363
385
 
364
- Legacy platform APIs require `context.legacyV3Compat === true`. This includes NLU, outbound calls, dialog writes, messaging sends, and phrase records.
386
+ Platform APIs require `context.legacyV3Compat === true`. This includes NLU, outbound calls, dialog writes, messaging sends, and phrase records.
365
387
 
366
388
  ### Dialog State
367
389
 
@@ -372,19 +394,68 @@ platform.dialog.result = 'done';
372
394
 
373
395
  Setters update the local value immediately and ask the platform DB to persist asynchronously. They are not awaitable and should not be used as transactional writes.
374
396
 
375
- ### Outbound Calls
397
+ ### Platform-Scheduled Calls
398
+
399
+ Use `platform.call(msisdn, options?)` when the script needs to ask the platform to place an outbound SIP call. This is different from `channel.sip.makeCall()`: `makeCall()` creates a B-leg immediately inside the current live SIP session, while `platform.call()` schedules a separate platform-managed call that may happen now or later.
400
+
401
+ The destination number should be E.164 formatted.
402
+
403
+ ```ts
404
+ await platform.call('+12025551234');
405
+ ```
406
+
407
+ By default, the platform schedules the call for immediate processing. Use `date` to schedule it for the future:
376
408
 
377
409
  ```ts
378
410
  await platform.call('+12025551234', {
379
- date: new Date(Date.now() + 60_000),
411
+ date: new Date(Date.now() + 15 * 60_000),
380
412
  entryPoint: 'on_callback',
381
- recallCount: 2,
413
+ });
414
+ ```
415
+
416
+ `entryPoint` is passed to the script when the scheduled call starts. Use it to route the callback into a specific branch:
417
+
418
+ ```ts
419
+ export default defineScript(async ({ context, channel }) => {
420
+ if (context.entryPoint === 'on_callback') {
421
+ channel.sip.answer();
422
+ await channel.audio.say('Hello, this is your scheduled callback.');
423
+ return;
424
+ }
425
+
426
+ await channel.audio.say('I will call you back in fifteen minutes.');
427
+ });
428
+ ```
429
+
430
+ Use `dateEnd` to define the latest time when the call is still useful. If the platform cannot place the call before that deadline, it can skip the attempt.
431
+
432
+ ```ts
433
+ await platform.call('+12025551234', {
434
+ date: new Date('2026-04-29T10:00:00Z'),
435
+ dateEnd: new Date('2026-04-29T10:30:00Z'),
436
+ entryPoint: 'on_reminder',
437
+ });
438
+ ```
439
+
440
+ Retries are controlled with `recallCount` and `recallDelay`:
441
+
442
+ ```ts
443
+ await platform.call('+12025551234', {
444
+ entryPoint: 'on_follow_up',
445
+ recallCount: 3,
382
446
  recallDelay: 300,
383
- priority: 10,
384
447
  });
385
448
  ```
386
449
 
387
- This creates a row in the legacy `call` table. The dialer picks it up and originates the SIP call.
450
+ This means the platform may retry up to three times, waiting about five minutes between attempts.
451
+
452
+ Other scheduling options:
453
+
454
+ - `priority`: higher-priority calls can be processed earlier by the dialer.
455
+ - `timezone`: timezone offset used by the platform when interpreting scheduled dates.
456
+ - `onSuccessCall`: entry point to use after a successful call.
457
+ - `onFailedCall`: entry point to use after failed attempts.
458
+ - `protoAdditional`: extra protocol-level parameters, such as SIP headers expected by your telephony setup.
388
459
 
389
460
  ### Messaging
390
461
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voctiv/agent-sdk",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Voctiv TypeScript agent SDK: defineScript and platform types for the voice/dialog scripting runtime.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "",