@alvera-ai/platform-sdk 0.21.1 → 0.21.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/action_status_updaters.md +14 -14
- package/.agent/advanced_migrations.md +8 -0
- package/.agent/async.md +4 -3
- package/.agent/cookbook/organic-marketing.md +307 -31
- package/.agent/cookbook/subscription-saas.md +7 -2
- package/.agent/data_activation_clients.md +79 -33
- package/.agent/generic_tables.md +39 -10
- package/.agent/interoperability_contracts.md +4 -4
- package/.agent/mock-services.md +4 -2
- package/.agent/templates.md +6 -1
- package/.agent/tools.md +16 -8
- package/.agent/workflows.md +60 -2
- package/dist/index.d.mts +64 -17
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +8 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -389,7 +389,7 @@ const { data } = await api.dataActivationClients.ingest(
|
|
|
389
389
|
tenantSlug, datalakeSlug, activationClientSlug,
|
|
390
390
|
{ data: rowAsJson }, // a single row, shaped per the CSV/JSON the contracts expect
|
|
391
391
|
)
|
|
392
|
-
// data.batch_id — UUID; the
|
|
392
|
+
// data.batch_id — UUID; the run's batch identifier (use to find the run's log rows)
|
|
393
393
|
// data.key — storage key for the row's archived ndjson
|
|
394
394
|
// data.jobs_count — number of downstream jobs the platform enqueued
|
|
395
395
|
```
|
|
@@ -400,8 +400,11 @@ been written, poll the logs (§6.4) or use the verification
|
|
|
400
400
|
pattern (§6.6).
|
|
401
401
|
|
|
402
402
|
The `batch_id` is the most important field on the response —
|
|
403
|
-
every
|
|
404
|
-
|
|
403
|
+
every log row the run writes carries it, and every dataset row the
|
|
404
|
+
run writes points at one of those log rows through
|
|
405
|
+
`alvera_data_activation_log_id`. A dataset row carries no
|
|
406
|
+
`batch_id` of its own, so the batch reaches the rows through the
|
|
407
|
+
log rows: that is the join for run-specific verification.
|
|
405
408
|
|
|
406
409
|
### 6.2 Bulk file ingestion — `.ingestFile`
|
|
407
410
|
|
|
@@ -490,8 +493,9 @@ batch_id UUID — the run's batch identifier
|
|
|
490
493
|
dataset_table string — the target dataset/table name
|
|
491
494
|
rows_ingested number — count of top-level rows the contract emitted
|
|
492
495
|
(cascade rows carry 0)
|
|
493
|
-
dataset_updated number — count of dataset rows
|
|
494
|
-
(
|
|
496
|
+
dataset_updated number — count of dataset rows that point at this log row
|
|
497
|
+
(each row the run writes carries its log row's id in
|
|
498
|
+
alvera_data_activation_log_id; load-bearing: see Gotcha 7)
|
|
495
499
|
output_files { object_key, mode }[] — merged ndjson archive refs, one per
|
|
496
500
|
bucket; mode is 'raw' | 'tokenized' | 'redacted'
|
|
497
501
|
(empty until the post-batch merge worker commits).
|
|
@@ -639,29 +643,32 @@ spends its full timeout and then reports nothing about the cause.
|
|
|
639
643
|
|
|
640
644
|
### 6.6 Verifying ingestion: the two-step dataset search
|
|
641
645
|
|
|
642
|
-
> **Simplest landing check —
|
|
643
|
-
> commits a moment after the `202`). When you just need to know
|
|
644
|
-
> *landed*,
|
|
645
|
-
> batch_id
|
|
646
|
-
>
|
|
647
|
-
> the
|
|
648
|
-
>
|
|
649
|
-
>
|
|
646
|
+
> **Simplest landing check — the run's own log rows.** Ingestion is async
|
|
647
|
+
> (the row commits a moment after the `202`). When you just need to know
|
|
648
|
+
> rows *landed*, read the run's log rows (§6.4) filtered by its
|
|
649
|
+
> `batch_id`. Every dataset row the run writes points at the log row for
|
|
650
|
+
> its table, and that log row's `dataset_updated` counts it — so the log
|
|
651
|
+
> rows answer the question with no query on the dataset table and no
|
|
652
|
+
> table name to know. A dataset row carries no `batch_id` of its own to
|
|
653
|
+
> filter on. **Each call is a fresh read, so there is no stale snapshot to
|
|
654
|
+
> recover from** — unlike a `createUserSearch` created before the row
|
|
655
|
+
> commits, which captures nothing and never updates. Gate on it, then run
|
|
656
|
+
> the two-step `createUserSearch` below **once** (race-free) only if you
|
|
657
|
+
> need the dataset's alias-join + tokenization semantics.
|
|
650
658
|
>
|
|
651
659
|
> ```typescript
|
|
652
|
-
> const { data:
|
|
653
|
-
>
|
|
654
|
-
>
|
|
655
|
-
>
|
|
656
|
-
> //
|
|
657
|
-
> //
|
|
658
|
-
>
|
|
659
|
-
> const landed = typeof probe !== 'string' && probe.data.length > 0
|
|
660
|
+
> const { data: logs } = await api.dataActivationClients.logs.list(
|
|
661
|
+
> tenantSlug, datalakeSlug, activationClientSlug,
|
|
662
|
+
> { filters: [{ field: 'batch_id', op: '==', value: batchId }] },
|
|
663
|
+
> )
|
|
664
|
+
> // One log row per dataset table the run wrote into; each counts the rows
|
|
665
|
+
> // that point at it. A sum above zero proves the batch landed.
|
|
666
|
+
> const landed = (logs.data ?? []).reduce((n, log) => n + (log.dataset_updated ?? 0), 0) > 0
|
|
660
667
|
> ```
|
|
661
668
|
>
|
|
662
669
|
> `createUserSearch` is the heavier, workflow-oriented surface — reach for
|
|
663
|
-
> it when you need its alias joins
|
|
664
|
-
> for a plain "did it land" check.
|
|
670
|
+
> it when you need the rows themselves: its alias joins, tokenized
|
|
671
|
+
> read-back. Not for a plain "did it land" check.
|
|
665
672
|
|
|
666
673
|
The canonical way to **prove a row landed in the datalake** is
|
|
667
674
|
to query the dataset directly. This is a two-step pattern:
|
|
@@ -683,7 +690,8 @@ const { data: search } = await api.datasets.createUserSearch(
|
|
|
683
690
|
'patient', // dataset name
|
|
684
691
|
{
|
|
685
692
|
search_query: `ri.value = '${externalPatientId}'` // SQL WHERE-clause fragment
|
|
686
|
-
+ ` AND le.
|
|
693
|
+
+ ` AND le.alvera_data_activation_log_id IN`
|
|
694
|
+
+ ` (SELECT id FROM data_activation_logs WHERE batch_id = '${batchId}')`,
|
|
687
695
|
},
|
|
688
696
|
)
|
|
689
697
|
// search.id — UUID of the materialised result set
|
|
@@ -736,8 +744,46 @@ a patient or an appointment is now a generic table you declare, plus
|
|
|
736
744
|
the legal entity its rows resolve to**; there is no dataset of that
|
|
737
745
|
name to search. The four cookbooks all take this shape.
|
|
738
746
|
|
|
739
|
-
|
|
740
|
-
|
|
747
|
+
Scoping a search to one run is the usual reason to reach for this
|
|
748
|
+
surface at all, and it goes **through the log row**. A row carries no
|
|
749
|
+
`batch_id`, `client_id`, `user_id` or `source_uri` of its own: it
|
|
750
|
+
carries `alvera_data_activation_log_id`, the `data_activation_logs` row
|
|
751
|
+
of the ingest that wrote it, and the batch lives there. So the
|
|
752
|
+
predicate is
|
|
753
|
+
|
|
754
|
+
```
|
|
755
|
+
<alias>.alvera_data_activation_log_id IN
|
|
756
|
+
(SELECT id FROM data_activation_logs WHERE batch_id = '<batch_id>')
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
The search runs with read access across the whole lake, so
|
|
760
|
+
`data_activation_logs` is readable from inside it. The pointer is null
|
|
761
|
+
on a row nothing ingested (a row an app wrote itself), so such a row
|
|
762
|
+
never matches a batch predicate.
|
|
763
|
+
|
|
764
|
+
#### Where a row came from, coming back
|
|
765
|
+
|
|
766
|
+
A searched row carries the pointer **and** the log row it points at,
|
|
767
|
+
loaded. Measured on a live run — one legal entity, one generic-table row
|
|
768
|
+
— the platform columns that come back are:
|
|
769
|
+
|
|
770
|
+
```
|
|
771
|
+
id string
|
|
772
|
+
inserted_at / updated_at string
|
|
773
|
+
checksum string
|
|
774
|
+
checksum_changed? boolean (the key has the question mark)
|
|
775
|
+
legal_entity_id string (generic-table rows)
|
|
776
|
+
alvera_data_activation_log_id string (null on a row no ingest wrote)
|
|
777
|
+
alvera_data_activation_log object — the log row itself:
|
|
778
|
+
id, batch_id, client_id, user_id, source_uri, dataset_table,
|
|
779
|
+
rows_ingested, dataset_updated, status, error, input_files,
|
|
780
|
+
output_files, inserted_at, updated_at
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
So "which batch wrote this row?" is `row.alvera_data_activation_log.batch_id`,
|
|
784
|
+
and "where did it come from?" is `row.alvera_data_activation_log.source_uri` —
|
|
785
|
+
there is no top-level `batch_id`, `client_id`, `user_id` or `source_uri` on
|
|
786
|
+
the row unless the table declared a column of that name itself.
|
|
741
787
|
|
|
742
788
|
#### What a masked column looks like coming back
|
|
743
789
|
|
|
@@ -807,13 +853,13 @@ screen. Pick the mode by which of those two readers you are serving.
|
|
|
807
853
|
pattern in §6.6) before treating the row as ingested.
|
|
808
854
|
|
|
809
855
|
7. **`dataset_updated > 0` is the load-bearing freshness
|
|
810
|
-
gate.** `rows_ingested`
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
`.createUserSearch`
|
|
814
|
-
BEFORE
|
|
815
|
-
and there's no way to refresh the materialised
|
|
816
|
-
you'd have to POST a new search. Poll for
|
|
856
|
+
gate.** `rows_ingested` counts rows the contract emitted —
|
|
857
|
+
received, not persisted. `dataset_updated` counts the dataset
|
|
858
|
+
rows that point at the log row, so it moves only when a row
|
|
859
|
+
has been written. A `.createUserSearch` scoped to the batch
|
|
860
|
+
(§6.6) issued BEFORE the rows are written returns an empty
|
|
861
|
+
result set, and there's no way to refresh the materialised
|
|
862
|
+
result — you'd have to POST a new search. Poll for
|
|
817
863
|
`dataset_updated > 0` before issuing the search.
|
|
818
864
|
|
|
819
865
|
8. **`output_files` empty ≠ batch failed.** A log row with
|
package/.agent/generic_tables.md
CHANGED
|
@@ -168,6 +168,7 @@ On a `none` column it is documentation and costs nothing.
|
|
|
168
168
|
datetime timestamp with timezone
|
|
169
169
|
time time of day (no date component)
|
|
170
170
|
jsonb arbitrary JSON document
|
|
171
|
+
uuid identifier; reads back as a uuid string, not raw bytes
|
|
171
172
|
```
|
|
172
173
|
|
|
173
174
|
`decimal` and `float` are distinct on purpose: `decimal` emits a
|
|
@@ -297,21 +298,49 @@ data activation clients use as the upsert key.
|
|
|
297
298
|
|
|
298
299
|
### Reserved column names
|
|
299
300
|
|
|
300
|
-
The platform
|
|
301
|
-
in
|
|
301
|
+
The platform creates every generic table with the same seven base
|
|
302
|
+
columns, and they are yours to read but never to declare in
|
|
303
|
+
`columns[N].name`:
|
|
302
304
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
+
```
|
|
306
|
+
id uuid primary key
|
|
307
|
+
inserted_at timestamp
|
|
308
|
+
updated_at timestamp
|
|
309
|
+
checksum the row's content fingerprint
|
|
310
|
+
checksum_changed whether the last write changed it
|
|
311
|
+
legal_entity_id the subject the contract's MDM resolve stamped
|
|
312
|
+
alvera_data_activation_log_id the data_activation_logs row of the
|
|
313
|
+
ingest that wrote the row
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Where the batch, the client, the user and the source went.** A row
|
|
317
|
+
does not carry them. It carries `alvera_data_activation_log_id`, a
|
|
318
|
+
pointer to the `data_activation_logs` row of the ingest that wrote it,
|
|
319
|
+
and the batch, the client, the user and the source live on that log
|
|
320
|
+
row. The pointer is **null on a row nothing ingested** — a row an app
|
|
321
|
+
wrote straight into the table. To pick out one ingest's rows in SQL, go
|
|
322
|
+
through the log row:
|
|
305
323
|
|
|
306
324
|
```
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
updated_at timestamp
|
|
310
|
-
batch_id the ingest run that wrote the row
|
|
311
|
-
client_id the activation client that wrote it
|
|
312
|
-
legal_entity_id the subject the contract's MDM resolve stamped
|
|
325
|
+
<table>.alvera_data_activation_log_id IN
|
|
326
|
+
(SELECT id FROM data_activation_logs WHERE batch_id = '<batch_id>')
|
|
313
327
|
```
|
|
314
328
|
|
|
329
|
+
Because those four are no longer platform columns, they are no longer
|
|
330
|
+
reserved: a table may declare its own `batch_id`, `client_id`,
|
|
331
|
+
`user_id` or `source_uri`, and it is plain data like any other column.
|
|
332
|
+
|
|
333
|
+
**`id` may be named once: inside the unique combination.** A
|
|
334
|
+
definition must name a unique combination, and a table is sometimes
|
|
335
|
+
unique only together with its id — say `(organization_id, id)`.
|
|
336
|
+
Declaring `id` with `is_unique: true` puts it in that combination and
|
|
337
|
+
adds no column (every table already has one). Declared any other way,
|
|
338
|
+
`id` is a reserved name like the rest. And it may join the combination,
|
|
339
|
+
never be the whole of it: create accepts a table whose only unique
|
|
340
|
+
column is `id`, but the column sync drops reserved names before it
|
|
341
|
+
reads the unique columns, finds none, and fails every migrate of the
|
|
342
|
+
lake, which stays at `new`. Mark a column of the table's own unique.
|
|
343
|
+
|
|
315
344
|
**`legal_entity_id` is the one that catches people.** It is not a
|
|
316
345
|
column you declare and fill — a contract's `mdm_input_config`
|
|
317
346
|
resolves the subject and the platform stamps it. Declaring a column
|
|
@@ -298,8 +298,8 @@ in the datalake and there is nothing to search afterwards. The
|
|
|
298
298
|
`upsert_into_datalake` step (the DB insert, routed by the
|
|
299
299
|
contract's `resource_type` destination) runs only when the DAC
|
|
300
300
|
worker ingests a row — i.e. on `dataActivationClients.ingest`, not
|
|
301
|
-
on `.run`. To prove a row *landed*, ingest and then
|
|
302
|
-
`batch_id` (see `data_activation_clients.md` §6.6).
|
|
301
|
+
on `.run`. To prove a row *landed*, ingest and then read the run's
|
|
302
|
+
log rows for its `batch_id` (see `data_activation_clients.md` §6.6).
|
|
303
303
|
|
|
304
304
|
```typescript
|
|
305
305
|
const { data: result } = await api.interoperabilityContracts.run(
|
|
@@ -592,8 +592,8 @@ surface, and `workflows.md` for the workflow side of the same join.
|
|
|
592
592
|
`'checking'` PASSES `.run(slug, row)` — the sandbox renders
|
|
593
593
|
JSON without casting the enum — but is rejected at live
|
|
594
594
|
ingest: the batch reports `rows_ingested` yet the row never
|
|
595
|
-
persists (`dataset_updated` stays `0`;
|
|
596
|
-
|
|
595
|
+
persists (`dataset_updated` stays `0`; no row points at the
|
|
596
|
+
batch's log row). Sandbox-run (§7.4) proves the shape, not the
|
|
597
597
|
enum domain — ground every enum value against the platform
|
|
598
598
|
schema or a known-good fixture, never intuition.
|
|
599
599
|
|
package/.agent/mock-services.md
CHANGED
|
@@ -14,9 +14,11 @@ third-party APIs the platform integrates with — Athenahealth, Twilio, Mailgun,
|
|
|
14
14
|
Stripe, SendGrid, HubSpot, QuickBooks, Airtable, Atomic FI, the LLM providers,
|
|
15
15
|
and a small set of AWS endpoints MiniStack cannot serve.
|
|
16
16
|
|
|
17
|
-
**MiniStack** serves AWS itself: `s3,lambda,sns,ssm,sqs,sts,logs,secretsmanager,cloudformation`
|
|
17
|
+
**MiniStack** serves AWS itself: `s3,lambda,sns,ssm,sqs,sts,logs,secretsmanager,cloudformation,rds,ses`
|
|
18
18
|
(`local-dependencies.yml`). See [Datalakes](datalakes.md) for how datalake
|
|
19
|
-
provisioning uses it.
|
|
19
|
+
provisioning uses it. An SES email tool whose endpoint URL is `http://localhost:4566`
|
|
20
|
+
sends into MiniStack, which lists every message it received at
|
|
21
|
+
`http://localhost:4566/_ministack/ses/messages`.
|
|
20
22
|
|
|
21
23
|
The division is not arbitrary. No AWS emulator here serves
|
|
22
24
|
`pinpoint-sms-voice-v2` — LocalStack Community answered 501 (Ultimate tier
|
package/.agent/templates.md
CHANGED
|
@@ -90,7 +90,12 @@ trying to add to the catalog.
|
|
|
90
90
|
sub-directories under that prefix ship the same basename (e.g.
|
|
91
91
|
two vendors under `data_activation/interoperability/`),
|
|
92
92
|
`metadataDetails` returns `409 Conflict` with the candidate
|
|
93
|
-
paths; a missing basename returns `404`.
|
|
93
|
+
paths; a missing basename returns `404`. This bites status
|
|
94
|
+
templates: Mailgun and SES both ship an `email_message_status`
|
|
95
|
+
under `status_poller`, so the bare `email_message_status`
|
|
96
|
+
answers 409 — name the provider's path
|
|
97
|
+
(`status_poller/aws_ses/email_message_status`), as the bare
|
|
98
|
+
`sms_message_status` already required.
|
|
94
99
|
|
|
95
100
|
2. **`output_schema` may be `null`.** Some templates render plain
|
|
96
101
|
strings without structured output. Test for null before
|
package/.agent/tools.md
CHANGED
|
@@ -92,8 +92,9 @@ the discriminator. Each branch is its own TypeScript type:
|
|
|
92
92
|
tool_body_type = 'email' → dedicated email-provider body
|
|
93
93
|
(Mailgun, SendGrid, SES,
|
|
94
94
|
SMTP-bridge; optional
|
|
95
|
-
endpoint_url
|
|
96
|
-
|
|
95
|
+
endpoint_url: for SES the
|
|
96
|
+
whole request URL, for
|
|
97
|
+
Mailgun the API base URL)
|
|
97
98
|
— alternative to using
|
|
98
99
|
rest_api for email intents
|
|
99
100
|
```
|
|
@@ -274,6 +275,15 @@ Each branch has its own required-list. Common patterns:
|
|
|
274
275
|
probe; blank ⇒ each service resolves to
|
|
275
276
|
its own regional AWS host)
|
|
276
277
|
|
|
278
|
+
email body, provider ses from_email, region, access_key_id +
|
|
279
|
+
secret_access_key (a long-lived IAM key:
|
|
280
|
+
there is no session-token field, so
|
|
281
|
+
temporary credentials cannot send);
|
|
282
|
+
optional endpoint_url — the WHOLE request
|
|
283
|
+
URL, e.g. a local AWS stand-in at
|
|
284
|
+
http://localhost:4566; blank ⇒
|
|
285
|
+
https://email.<region>.amazonaws.com
|
|
286
|
+
|
|
277
287
|
sql_database body db_type, db_host, db_port, db_name,
|
|
278
288
|
auth_method, db_username,
|
|
279
289
|
db_password (or iam_role)
|
|
@@ -788,12 +798,10 @@ usable as a proof — three things to get right:
|
|
|
788
798
|
asynchronously, so the response carries the PREVIOUS run's stamps.
|
|
789
799
|
Capture `last_run_at` as a baseline BEFORE calling it, then poll the
|
|
790
800
|
row until `last_run_at` advances past that baseline.
|
|
791
|
-
- **`last_run_status` has
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
`last_run_status === 'ok'` proves a complete reconciliation — a
|
|
796
|
-
`!== 'error'` check silently accepts a truncated `partial`.
|
|
801
|
+
- **`last_run_status` has two values.** `'ok'` means the run read its
|
|
802
|
+
whole time window; `'error'` means it stopped, and `last_run_error`
|
|
803
|
+
says why. There is no partial run: every page of the window is read,
|
|
804
|
+
one job per page, with no page cap.
|
|
797
805
|
`last_run_events_found` counts the current run's events, and because
|
|
798
806
|
`refresh` is async an early read can show an in-progress figure.
|
|
799
807
|
- **`status` is the halt flag.** It is `'active'` normally and the
|
package/.agent/workflows.md
CHANGED
|
@@ -441,6 +441,17 @@ variable. Field paths match the columns of the workflow's
|
|
|
441
441
|
For generic-table-bound workflows, `event_dataset` carries the
|
|
442
442
|
table's columns directly (no separate `row` indirection).
|
|
443
443
|
|
|
444
|
+
**Where the row came from is on its log row, not on the row.** A row
|
|
445
|
+
carries no `batch_id`, `client_id`, `user_id` or `source_uri` of its
|
|
446
|
+
own: it points at the `data_activation_logs` row of the ingest that
|
|
447
|
+
wrote it, and templates read that log row loaded on the event —
|
|
448
|
+
`event_dataset.alvera_data_activation_log.source_uri`,
|
|
449
|
+
`event_dataset.alvera_data_activation_log.batch_id`. It is null when
|
|
450
|
+
the row came from no ingest (an app wrote it straight into its table),
|
|
451
|
+
so guard a template that reads it. A generic table may declare its
|
|
452
|
+
own column called `source_uri` or `batch_id`; then
|
|
453
|
+
`event_dataset.source_uri` is that column, plain data.
|
|
454
|
+
|
|
444
455
|
### `skip_mdm_resolution` is a deliberate choice, not a generic-table default
|
|
445
456
|
|
|
446
457
|
`skip_mdm_resolution` (default `false`) opts the workflow out of the
|
|
@@ -566,8 +577,12 @@ reads as "leave it alone" on the wire and as "remove it" in the author's head.
|
|
|
566
577
|
Caller-supplied fields **inside each `actions[*]`** row:
|
|
567
578
|
|
|
568
579
|
```
|
|
569
|
-
action_type required enum — 'sms' | '
|
|
570
|
-
|
|
580
|
+
action_type required enum — 'sms' | 'mms' | 'email' | 'voice'
|
|
581
|
+
| 'data_exchange' | 'data_activation'
|
|
582
|
+
tool_id UUID — tool.intent must match action_type. Required
|
|
583
|
+
for every action type EXCEPT
|
|
584
|
+
data_activation, which refuses one
|
|
585
|
+
(its client carries its own tool)
|
|
571
586
|
decision_key required string — unique within the workflow
|
|
572
587
|
trigger_template required string — schedule; 'now'/'' = immediate,
|
|
573
588
|
else local ISO 8601 in datalake tz (§2)
|
|
@@ -585,6 +600,49 @@ Inside `tool_call`, the `sms_request`, `mms_request` and `email_request`
|
|
|
585
600
|
variants also take `link_prefix` (**required**) and `link_validity_days`
|
|
586
601
|
(optional, default 365) — see §7.
|
|
587
602
|
|
|
603
|
+
### The `data_activation` action runs a client for the row
|
|
604
|
+
|
|
605
|
+
An action of type `data_activation` sends nothing. It runs a data
|
|
606
|
+
activation client — the one `client_slug` names, in the workflow's own
|
|
607
|
+
datalake — for the row that started the workflow. Its tool call is
|
|
608
|
+
`run_data_activation_client`, and it names no tool: the client carries
|
|
609
|
+
its own, so an action with a `tool_id` is refused.
|
|
610
|
+
|
|
611
|
+
```typescript
|
|
612
|
+
import { ActionType } from '@alvera-ai/platform-sdk'
|
|
613
|
+
|
|
614
|
+
const fetchMemberAction = {
|
|
615
|
+
action_type: ActionType.DATA_ACTIVATION, // no tool_id: the client carries its own tool
|
|
616
|
+
decision_key: 'fetch_member',
|
|
617
|
+
trigger_template: 'now',
|
|
618
|
+
idempotency_template: '{{ event_dataset.message_id }}-fetch',
|
|
619
|
+
tool_call: {
|
|
620
|
+
tool_call_type: 'run_data_activation_client',
|
|
621
|
+
client_slug: 'fetch-member',
|
|
622
|
+
tool_call_override_template:
|
|
623
|
+
`{"tool_call_type": "sql_query", "query": {"type": "custom", "body": "SELECT * FROM inbound_messages WHERE message_id = '{{ event_dataset.message_id }}'"}}`,
|
|
624
|
+
},
|
|
625
|
+
}
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
The questions a builder asks about it:
|
|
629
|
+
|
|
630
|
+
- **What does the override do?** `tool_call_override_template` is
|
|
631
|
+
Liquid rendered against the row (`event_dataset`) to the client's
|
|
632
|
+
WHOLE tool call as JSON — the same shape `.runManually` takes as its
|
|
633
|
+
one-shot override (`data_activation_clients.md` §6.3). An override of
|
|
634
|
+
the same `tool_call_type` as the client's stored call is merged over
|
|
635
|
+
it; one of another type replaces it.
|
|
636
|
+
- **Does it change the client?** No. The override applies to that one
|
|
637
|
+
run; the client's stored tool call — a scheduled query, say — is
|
|
638
|
+
untouched.
|
|
639
|
+
- **Two rows at once?** Each row's action is its own run of the client,
|
|
640
|
+
with its own rendered override, and runs beside any scheduled run
|
|
641
|
+
rather than merging into it.
|
|
642
|
+
- **How do I see what it did?** The client's run is an ordinary data
|
|
643
|
+
activation run: read it back through the client's runs and log rows
|
|
644
|
+
(`data_activation_clients.md` §6.4–§6.5).
|
|
645
|
+
|
|
588
646
|
**Write-only (Request-only).** None.
|
|
589
647
|
|
|
590
648
|
## 5. Lifecycle
|
package/dist/index.d.mts
CHANGED
|
@@ -679,7 +679,7 @@ type ActionStatusUpdaterResponse = {
|
|
|
679
679
|
*/
|
|
680
680
|
readonly last_run_at?: string | null;
|
|
681
681
|
/**
|
|
682
|
-
* Why the last poll run failed
|
|
682
|
+
* Why the last poll run failed; null when the run completed and read its whole window
|
|
683
683
|
*/
|
|
684
684
|
readonly last_run_error?: string | null;
|
|
685
685
|
/**
|
|
@@ -687,9 +687,9 @@ type ActionStatusUpdaterResponse = {
|
|
|
687
687
|
*/
|
|
688
688
|
readonly last_run_events_found?: number | null;
|
|
689
689
|
/**
|
|
690
|
-
* Outcome of the last poll run
|
|
690
|
+
* Outcome of the last poll run: `ok` when the run read its whole window, `error` when it stopped — read `last_run_error` for why. A run is never partial: every page of the window is read, one job per page.
|
|
691
691
|
*/
|
|
692
|
-
readonly last_run_status?: 'ok' | '
|
|
692
|
+
readonly last_run_status?: 'ok' | 'error';
|
|
693
693
|
message_config: SimpleTemplateConfigResponse;
|
|
694
694
|
/**
|
|
695
695
|
* Updater name
|
|
@@ -990,6 +990,7 @@ declare enum ActionType {
|
|
|
990
990
|
EMAIL = "email",
|
|
991
991
|
VOICE = "voice",
|
|
992
992
|
DATA_EXCHANGE = "data_exchange",
|
|
993
|
+
DATA_ACTIVATION = "data_activation",
|
|
993
994
|
}
|
|
994
995
|
/**
|
|
995
996
|
* MDMVerifyRequest
|
|
@@ -1185,11 +1186,13 @@ type ActionResponse = {
|
|
|
1185
1186
|
tool_call_type: 'aws_lambda_request';
|
|
1186
1187
|
} & ActionAwsLambdaCallResponse) | ({
|
|
1187
1188
|
tool_call_type: 'manual_upload';
|
|
1188
|
-
} & ActionManualUploadCallResponse)
|
|
1189
|
+
} & ActionManualUploadCallResponse) | ({
|
|
1190
|
+
tool_call_type: 'run_data_activation_client';
|
|
1191
|
+
} & ActionRunDataActivationClientCallResponse);
|
|
1189
1192
|
/**
|
|
1190
|
-
* Tool that executes this action
|
|
1193
|
+
* Tool that executes this action. Required for every action type except data_activation, which refuses one: its client carries its own tool.
|
|
1191
1194
|
*/
|
|
1192
|
-
tool_id
|
|
1195
|
+
tool_id?: string | null;
|
|
1193
1196
|
/**
|
|
1194
1197
|
* Liquid template that determines when this action executes
|
|
1195
1198
|
*/
|
|
@@ -1663,6 +1666,21 @@ type SystemTemplateListResponse = {
|
|
|
1663
1666
|
type DataActivationClientS3CallResponse = S3CallResponse & {
|
|
1664
1667
|
tool_call_type: 's3_request';
|
|
1665
1668
|
};
|
|
1669
|
+
/**
|
|
1670
|
+
* RunDataActivationClientCallRequest
|
|
1671
|
+
*
|
|
1672
|
+
* Runs a data activation client for the row that started the workflow, with the tool call the template renders for that row in place of the client's stored one. Request
|
|
1673
|
+
*/
|
|
1674
|
+
type RunDataActivationClientCallRequest = {
|
|
1675
|
+
/**
|
|
1676
|
+
* Slug of the data activation client to run, in the workflow's datalake
|
|
1677
|
+
*/
|
|
1678
|
+
client_slug: string;
|
|
1679
|
+
/**
|
|
1680
|
+
* Liquid template rendered against the row that started the workflow, to the client's whole tool call as JSON — the shape the run-manually endpoint takes. It replaces the client's stored tool call for this run only.
|
|
1681
|
+
*/
|
|
1682
|
+
tool_call_override_template: string;
|
|
1683
|
+
};
|
|
1666
1684
|
/**
|
|
1667
1685
|
* EmailCallResponse
|
|
1668
1686
|
*
|
|
@@ -1786,10 +1804,10 @@ type GenericTableListResponse = {
|
|
|
1786
1804
|
/**
|
|
1787
1805
|
* MMSCallResponse
|
|
1788
1806
|
*
|
|
1789
|
-
* MMS tool-call config — Liquid-templated recipient
|
|
1807
|
+
* MMS tool-call config — Liquid-templated recipient, optional caption, plain public media URL, and the prefix its links go out on.
|
|
1790
1808
|
*/
|
|
1791
1809
|
type MmsCallResponse = {
|
|
1792
|
-
body
|
|
1810
|
+
body?: SimpleTemplateConfigResponse;
|
|
1793
1811
|
/**
|
|
1794
1812
|
* Address of the host that serves this action's links. Every URL in the body goes out as <link_prefix>/<token>. An absolute http or https URL, path allowed, with no query, fragment or trailing slash.
|
|
1795
1813
|
*/
|
|
@@ -2232,7 +2250,7 @@ type GenericTableColumnResponse = {
|
|
|
2232
2250
|
/**
|
|
2233
2251
|
* Column data type
|
|
2234
2252
|
*/
|
|
2235
|
-
type: 'string' | 'integer' | 'float' | 'boolean' | 'date' | 'datetime' | 'time' | 'decimal' | 'jsonb';
|
|
2253
|
+
type: 'string' | 'integer' | 'float' | 'boolean' | 'date' | 'datetime' | 'time' | 'decimal' | 'jsonb' | 'uuid';
|
|
2236
2254
|
};
|
|
2237
2255
|
/**
|
|
2238
2256
|
* DatasetSearchResponse
|
|
@@ -2373,6 +2391,12 @@ type AuthenticatedLinkUpdateMessageTrackingRequest = {
|
|
|
2373
2391
|
type DataActivationClientSftpCallResponse = SftpCallResponse & {
|
|
2374
2392
|
tool_call_type: 'sftp_request';
|
|
2375
2393
|
};
|
|
2394
|
+
/**
|
|
2395
|
+
* ActionRunDataActivationClientCallResponse
|
|
2396
|
+
*/
|
|
2397
|
+
type ActionRunDataActivationClientCallResponse = RunDataActivationClientCallResponse & {
|
|
2398
|
+
tool_call_type: 'run_data_activation_client';
|
|
2399
|
+
};
|
|
2376
2400
|
/**
|
|
2377
2401
|
* DataSourceRequest
|
|
2378
2402
|
*
|
|
@@ -2615,6 +2639,21 @@ type AlveraApiError = {
|
|
|
2615
2639
|
*/
|
|
2616
2640
|
mode?: string | null;
|
|
2617
2641
|
};
|
|
2642
|
+
/**
|
|
2643
|
+
* RunDataActivationClientCallResponse
|
|
2644
|
+
*
|
|
2645
|
+
* Runs a data activation client for the row that started the workflow, with the tool call the template renders for that row in place of the client's stored one.
|
|
2646
|
+
*/
|
|
2647
|
+
type RunDataActivationClientCallResponse = {
|
|
2648
|
+
/**
|
|
2649
|
+
* Slug of the data activation client to run, in the workflow's datalake
|
|
2650
|
+
*/
|
|
2651
|
+
client_slug: string;
|
|
2652
|
+
/**
|
|
2653
|
+
* Liquid template rendered against the row that started the workflow, to the client's whole tool call as JSON — the shape the run-manually endpoint takes. It replaces the client's stored tool call for this run only.
|
|
2654
|
+
*/
|
|
2655
|
+
tool_call_override_template: string;
|
|
2656
|
+
};
|
|
2618
2657
|
/**
|
|
2619
2658
|
* CloudStorageAwsResponse
|
|
2620
2659
|
*
|
|
@@ -3438,7 +3477,7 @@ type EmailResponse = {
|
|
|
3438
3477
|
*/
|
|
3439
3478
|
domain?: string;
|
|
3440
3479
|
/**
|
|
3441
|
-
* Custom Mailgun API base URL (e.g., https://api.eu.mailgun.net/v3 for EU domains, or a WireMock endpoint for integration tests)
|
|
3480
|
+
* Custom provider endpoint; leave blank for the real provider. For SES, the whole request URL (e.g., http://localhost:4566 for MiniStack); blank means https://email.<region>.amazonaws.com. For Mailgun, the API base URL (e.g., https://api.eu.mailgun.net/v3 for EU domains, or a WireMock endpoint for integration tests)
|
|
3442
3481
|
*/
|
|
3443
3482
|
endpoint_url?: string | null;
|
|
3444
3483
|
/**
|
|
@@ -4205,7 +4244,7 @@ type GenericTableColumnRequest = {
|
|
|
4205
4244
|
/**
|
|
4206
4245
|
* Column data type
|
|
4207
4246
|
*/
|
|
4208
|
-
type: 'string' | 'integer' | 'float' | 'boolean' | 'date' | 'datetime' | 'time' | 'decimal' | 'jsonb';
|
|
4247
|
+
type: 'string' | 'integer' | 'float' | 'boolean' | 'date' | 'datetime' | 'time' | 'decimal' | 'jsonb' | 'uuid';
|
|
4209
4248
|
};
|
|
4210
4249
|
/**
|
|
4211
4250
|
* CloudWatchQueryResponse
|
|
@@ -4738,10 +4777,10 @@ type InteroperabilityContractAiAgentRequestWritable = {
|
|
|
4738
4777
|
/**
|
|
4739
4778
|
* MMSCallRequest
|
|
4740
4779
|
*
|
|
4741
|
-
* MMS tool-call config — Liquid-templated recipient
|
|
4780
|
+
* MMS tool-call config — Liquid-templated recipient, optional caption, plain public media URL, and the prefix its links go out on. Request
|
|
4742
4781
|
*/
|
|
4743
4782
|
type MmsCallRequestWritable = {
|
|
4744
|
-
body
|
|
4783
|
+
body?: SimpleTemplateConfigRequest;
|
|
4745
4784
|
/**
|
|
4746
4785
|
* Address of the host that serves this action's links. Every URL in the body goes out as <link_prefix>/<token>. An absolute http or https URL, path allowed, with no query, fragment or trailing slash.
|
|
4747
4786
|
*/
|
|
@@ -4973,11 +5012,13 @@ type ActionRequestWritable = {
|
|
|
4973
5012
|
tool_call_type: 'aws_lambda_request';
|
|
4974
5013
|
} & ActionAwsLambdaCallRequestWritable) | ({
|
|
4975
5014
|
tool_call_type: 'manual_upload';
|
|
4976
|
-
} & ActionManualUploadCallRequest)
|
|
5015
|
+
} & ActionManualUploadCallRequest) | ({
|
|
5016
|
+
tool_call_type: 'run_data_activation_client';
|
|
5017
|
+
} & ActionRunDataActivationClientCallRequestWritable);
|
|
4977
5018
|
/**
|
|
4978
|
-
* Tool that executes this action
|
|
5019
|
+
* Tool that executes this action. Required for every action type except data_activation, which refuses one: its client carries its own tool.
|
|
4979
5020
|
*/
|
|
4980
|
-
tool_id
|
|
5021
|
+
tool_id?: string | null;
|
|
4981
5022
|
/**
|
|
4982
5023
|
* Liquid template that determines when this action executes
|
|
4983
5024
|
*/
|
|
@@ -5098,7 +5139,7 @@ type EmailRequestWritable = {
|
|
|
5098
5139
|
*/
|
|
5099
5140
|
domain?: string;
|
|
5100
5141
|
/**
|
|
5101
|
-
* Custom Mailgun API base URL (e.g., https://api.eu.mailgun.net/v3 for EU domains, or a WireMock endpoint for integration tests)
|
|
5142
|
+
* Custom provider endpoint; leave blank for the real provider. For SES, the whole request URL (e.g., http://localhost:4566 for MiniStack); blank means https://email.<region>.amazonaws.com. For Mailgun, the API base URL (e.g., https://api.eu.mailgun.net/v3 for EU domains, or a WireMock endpoint for integration tests)
|
|
5102
5143
|
*/
|
|
5103
5144
|
endpoint_url?: string | null;
|
|
5104
5145
|
/**
|
|
@@ -5794,6 +5835,12 @@ type SftpRequestWritable = {
|
|
|
5794
5835
|
*/
|
|
5795
5836
|
user_name: string;
|
|
5796
5837
|
};
|
|
5838
|
+
/**
|
|
5839
|
+
* ActionRunDataActivationClientCallRequest
|
|
5840
|
+
*/
|
|
5841
|
+
type ActionRunDataActivationClientCallRequestWritable = RunDataActivationClientCallRequest & {
|
|
5842
|
+
tool_call_type: 'run_data_activation_client';
|
|
5843
|
+
};
|
|
5797
5844
|
/**
|
|
5798
5845
|
* CloudStorageCustomRequest
|
|
5799
5846
|
*
|