@actuarial-ts/agents 0.7.0 → 0.8.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/README.md CHANGED
@@ -3,11 +3,16 @@
3
3
  Mastra tools and human-gated workflows for actuarial-ts. It is an orchestration boundary around the other four packages, not an autonomous actuary.
4
4
 
5
5
  ```bash
6
- npm install @actuarial-ts/agents@0.7.0 @actuarial-ts/core@0.7.0 @actuarial-ts/data@0.7.0 @actuarial-ts/interchange@0.7.0 @actuarial-ts/compliance@0.7.0 @mastra/core@^1.51.0 @mastra/mcp@^1.14.0 zod@^3.25.76
6
+ npm install @actuarial-ts/agents@0.8.0 @actuarial-ts/core@0.8.0 @actuarial-ts/data@0.8.0 @actuarial-ts/interchange@0.8.0 @actuarial-ts/compliance@0.8.0 @mastra/core@^1.51.0 @mastra/mcp@^1.14.0 zod@^3.25.76
7
7
  ```
8
8
 
9
9
  Requires Node 22.13+. Peer ranges are `@mastra/core >=1.51.0 <2`, `@mastra/mcp >=1.14.0 <2`, and Zod `^3.25.76`.
10
10
 
11
+ SDK 0.8 adds a closed customization selection tool: the model selects only a
12
+ host-approved preset and allowlisted scenario IDs, while tenant identity stays
13
+ in trusted request context. See the [0.8 adoption guide](https://github.com/yerromnitsuj/actng/blob/v0.8.0/docs/migrations/0.8-reusable-customization.md)
14
+ and [customization reference](https://github.com/yerromnitsuj/actng/blob/v0.8.0/docs/reference/reusable-customization.md).
15
+
11
16
  ## Trusted diagnostic selection
12
17
 
13
18
  `createDiagnosticSelectionTool` lets a model choose only reviewed instance IDs, one host-approved run preset, and a display view. The host owns the authentic compiled definition, allowable instance catalog, cutoff/filter/grouping policy, tenant, data access, and executor.
@@ -38,6 +43,17 @@ type DiagnosticAgentToolInput = {
38
43
 
39
44
  It cannot contain formulas, measures, count populations, amount/exposure bases, missingness, period axes, arbitrary filters, provenance, or project/tenant IDs. The executor must return owner-authenticated `VerifiedDiagnosticRunProvenance` stamped for the exact definition, preset, and sorted selection; a cached superset is rejected rather than display-filtered into an apparent run.
40
45
 
46
+ This executor remains **eager-only** in SDK 0.8. The compact diagnostics APIs
47
+ introduced in 0.7.0 do not change its return contract:
48
+ `VerifiedCompactDiagnosticRunProvenance` and streamed replay receipts cannot be
49
+ returned in place of eager verified provenance. Keep this tool's approved
50
+ executor on the eager validated-run/provenance path. Compact analysis and
51
+ paged evidence can be hosted separately through the public core/data/compliance
52
+ APIs; casting or display-filtering a compact result does not authorize a tool
53
+ response. See the [compact adoption guide](https://github.com/yerromnitsuj/actng/blob/v0.8.0/docs/migrations/0.7-compact-diagnostics.md)
54
+ for the distinct workflows and [replay reference](https://github.com/yerromnitsuj/actng/blob/v0.8.0/docs/reference/diagnostic-replay-stream.md)
55
+ for evidence verification and its SDK-version requirements.
56
+
41
57
  Success returns `{ success: true, data: { ... } }`. The `data` object contains formula/calculation/definition identities, run/result/binding fingerprints, the full review receipt (including triggered and not-evaluated rules), and one explicitly display-only projection. `data.display.points` holds emergence or latest-diagonal points; `data.display.triangles` holds the triangle view. Display points retain reviewed metric evaluations and findings while omitting the raw aggregate `components` field. Failures remain `{ success: false, error: { code, message } }`.
42
58
 
43
59
  The v0.6.1 correction uses `runPresets` in the host catalog and `tenantId` in the host executor input. Migrate the earlier `presets`, `tenant`, flattened success fields, and `display.value` names to the contract above. There is no definition-editing path; changing a basis or rule requires a separate human-governed workflow.
@@ -54,7 +70,7 @@ In 0.6 the public `DefinedActuarialTool<TInput, TOutput>` execute accepts raw `z
54
70
 
55
71
  The package’s offline test suite covers trusted catalog selection, direct/Mastra-shaped execution, tenant failure, once-only transforms, provenance coherence, judgment gates, remote sidecar behavior, promotion, and golden-prompt tool selection.
56
72
 
57
- See the [formula catalog](https://github.com/yerromnitsuj/actng/blob/v0.7.0/docs/reference/diagnostic-formulas.md) and [migration guide](https://github.com/yerromnitsuj/actng/blob/v0.7.0/docs/migrations/0.6-generalized-diagnostics.md).
73
+ See the [formula catalog](https://github.com/yerromnitsuj/actng/blob/v0.8.0/docs/reference/diagnostic-formulas.md) and [migration guide](https://github.com/yerromnitsuj/actng/blob/v0.8.0/docs/migrations/0.6-generalized-diagnostics.md).
58
74
 
59
75
  ## License
60
76
 
@@ -0,0 +1,122 @@
1
+ import { type AnalysisResult } from "@actuarial-ts/core";
2
+ import { z } from "zod";
3
+ import { type DefinedActuarialTool } from "./tools.js";
4
+ export declare const customizationAgentToolInputSchema: z.ZodObject<{
5
+ runPresetId: z.ZodEffects<z.ZodString, string, string>;
6
+ scenarioIds: z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">;
7
+ }, "strict", z.ZodTypeAny, {
8
+ runPresetId: string;
9
+ scenarioIds: string[];
10
+ }, {
11
+ runPresetId: string;
12
+ scenarioIds: string[];
13
+ }>;
14
+ export interface CustomizationAgentPresetResult {
15
+ readonly scenarioId: string;
16
+ readonly result: AnalysisResult;
17
+ }
18
+ export interface CustomizationAgentRunPreset {
19
+ readonly id: string;
20
+ readonly recipeId: string;
21
+ readonly allowedScenarioIds: readonly string[];
22
+ readonly execute: (input: {
23
+ readonly tenantId: string;
24
+ readonly scenarioIds: readonly string[];
25
+ }) => Promise<readonly CustomizationAgentPresetResult[]>;
26
+ }
27
+ export interface CustomizationAgentToolSuccess {
28
+ readonly success: true;
29
+ readonly data: {
30
+ readonly runPresetId: string;
31
+ readonly recipeId: string;
32
+ readonly scenarioIds: readonly string[];
33
+ readonly results: readonly CustomizationAgentPresetResult[];
34
+ };
35
+ }
36
+ export declare const customizationAgentToolResultSchema: z.ZodUnion<[z.ZodObject<{
37
+ success: z.ZodLiteral<true>;
38
+ data: z.ZodObject<{
39
+ runPresetId: z.ZodEffects<z.ZodString, string, string>;
40
+ recipeId: z.ZodEffects<z.ZodString, string, string>;
41
+ scenarioIds: z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">;
42
+ results: z.ZodArray<z.ZodObject<{
43
+ scenarioId: z.ZodEffects<z.ZodString, string, string>;
44
+ result: z.ZodType<AnalysisResult, z.ZodTypeDef, AnalysisResult>;
45
+ }, "strict", z.ZodTypeAny, {
46
+ scenarioId: string;
47
+ result: AnalysisResult;
48
+ }, {
49
+ scenarioId: string;
50
+ result: AnalysisResult;
51
+ }>, "many">;
52
+ }, "strict", z.ZodTypeAny, {
53
+ runPresetId: string;
54
+ scenarioIds: string[];
55
+ recipeId: string;
56
+ results: {
57
+ scenarioId: string;
58
+ result: AnalysisResult;
59
+ }[];
60
+ }, {
61
+ runPresetId: string;
62
+ scenarioIds: string[];
63
+ recipeId: string;
64
+ results: {
65
+ scenarioId: string;
66
+ result: AnalysisResult;
67
+ }[];
68
+ }>;
69
+ }, "strict", z.ZodTypeAny, {
70
+ data: {
71
+ runPresetId: string;
72
+ scenarioIds: string[];
73
+ recipeId: string;
74
+ results: {
75
+ scenarioId: string;
76
+ result: AnalysisResult;
77
+ }[];
78
+ };
79
+ success: true;
80
+ }, {
81
+ data: {
82
+ runPresetId: string;
83
+ scenarioIds: string[];
84
+ recipeId: string;
85
+ results: {
86
+ scenarioId: string;
87
+ result: AnalysisResult;
88
+ }[];
89
+ };
90
+ success: true;
91
+ }>, z.ZodObject<{
92
+ success: z.ZodLiteral<false>;
93
+ error: z.ZodObject<{
94
+ code: z.ZodString;
95
+ message: z.ZodString;
96
+ }, "strict", z.ZodTypeAny, {
97
+ code: string;
98
+ message: string;
99
+ }, {
100
+ code: string;
101
+ message: string;
102
+ }>;
103
+ }, "strict", z.ZodTypeAny, {
104
+ error: {
105
+ code: string;
106
+ message: string;
107
+ };
108
+ success: false;
109
+ }, {
110
+ error: {
111
+ code: string;
112
+ message: string;
113
+ };
114
+ success: false;
115
+ }>]>;
116
+ export declare function createCustomizationSelectionTool(input: {
117
+ readonly runPresets: readonly CustomizationAgentRunPreset[];
118
+ readonly id?: string;
119
+ readonly description?: string;
120
+ readonly tenantContextKey?: string;
121
+ }): DefinedActuarialTool<z.input<typeof customizationAgentToolInputSchema>, z.output<typeof customizationAgentToolResultSchema>>;
122
+ //# sourceMappingURL=customization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customization.d.ts","sourceRoot":"","sources":["../src/customization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE5E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,iCAAiC;;;;;;;;;EAGnC,CAAC;AAEZ,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;CACjC;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE;QACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;KACzC,KAAK,OAAO,CAAC,SAAS,8BAA8B,EAAE,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE;QACb,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;QACxC,QAAQ,CAAC,OAAO,EAAE,SAAS,8BAA8B,EAAE,CAAC;KAC7D,CAAC;CACH;AAMD,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAW7C,CAAC;AAEH,wBAAgB,gCAAgC,CAAC,KAAK,EAAE;IACtD,QAAQ,CAAC,UAAU,EAAE,SAAS,2BAA2B,EAAE,CAAC;IAC5D,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC,GAAG,oBAAoB,CACtB,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,EACjD,CAAC,CAAC,MAAM,CAAC,OAAO,kCAAkC,CAAC,CACpD,CAmDA"}
@@ -0,0 +1,79 @@
1
+ import { isDiagnosticToken } from "@actuarial-ts/core";
2
+ import { analysisResultSchema, parseAnalysisResult } from "@actuarial-ts/data";
3
+ import { z } from "zod";
4
+ import { AgentsError } from "./errors.js";
5
+ import { defineActuarialTool, } from "./tools.js";
6
+ const token = z.string().refine(isDiagnosticToken);
7
+ export const customizationAgentToolInputSchema = z.object({
8
+ runPresetId: token,
9
+ scenarioIds: z.array(token).max(32),
10
+ }).strict();
11
+ const failureSchema = z.object({
12
+ success: z.literal(false),
13
+ error: z.object({ code: z.string(), message: z.string() }).strict(),
14
+ }).strict();
15
+ export const customizationAgentToolResultSchema = z.union([
16
+ z.object({
17
+ success: z.literal(true),
18
+ data: z.object({
19
+ runPresetId: token,
20
+ recipeId: token,
21
+ scenarioIds: z.array(token),
22
+ results: z.array(z.object({ scenarioId: token, result: analysisResultSchema }).strict()),
23
+ }).strict(),
24
+ }).strict(),
25
+ failureSchema,
26
+ ]);
27
+ export function createCustomizationSelectionTool(input) {
28
+ const catalog = new Map();
29
+ for (const preset of input.runPresets) {
30
+ if (!isDiagnosticToken(preset.id) || !isDiagnosticToken(preset.recipeId))
31
+ throw new AgentsError("BAD_CUSTOMIZATION_CATALOG", "Customization preset id and recipeId must be valid tokens");
32
+ if (catalog.has(preset.id))
33
+ throw new AgentsError("BAD_CUSTOMIZATION_CATALOG", `Duplicate customization preset ${preset.id}`);
34
+ if (new Set(preset.allowedScenarioIds).size !== preset.allowedScenarioIds.length || preset.allowedScenarioIds.some((id) => !isDiagnosticToken(id)))
35
+ throw new AgentsError("BAD_CUSTOMIZATION_CATALOG", `Preset ${preset.id} has invalid or duplicate scenario IDs`);
36
+ catalog.set(preset.id, Object.freeze({ ...preset, allowedScenarioIds: Object.freeze([...preset.allowedScenarioIds].sort()) }));
37
+ }
38
+ return defineActuarialTool({
39
+ id: input.id ?? "run-approved-customization",
40
+ description: input.description ?? "Run a host-approved actuarial recipe and approved scenarios",
41
+ kind: "read",
42
+ tenant: "required",
43
+ tenantKey: input.tenantContextKey ?? "projectId",
44
+ inputSchema: customizationAgentToolInputSchema,
45
+ outputSchema: customizationAgentToolResultSchema,
46
+ execute: async (request, tenant) => {
47
+ const preset = catalog.get(request.runPresetId);
48
+ if (preset === undefined)
49
+ throw new AgentsError("UNKNOWN_CUSTOMIZATION_PRESET", `Unknown customization preset ${request.runPresetId}`);
50
+ if (new Set(request.scenarioIds).size !== request.scenarioIds.length)
51
+ throw new AgentsError("CUSTOMIZATION_RUN_MISMATCH", "Requested scenario IDs must be unique");
52
+ const scenarioIds = [...request.scenarioIds].sort();
53
+ if (scenarioIds.some((id) => !preset.allowedScenarioIds.includes(id)))
54
+ throw new AgentsError("UNAPPROVED_CUSTOMIZATION_SCENARIO", "One or more requested scenarios are not approved by the selected preset");
55
+ const rawResults = await preset.execute({ tenantId: tenant, scenarioIds });
56
+ const byId = new Map();
57
+ for (const item of rawResults) {
58
+ if (!scenarioIds.includes(item.scenarioId) || byId.has(item.scenarioId))
59
+ throw new AgentsError("CUSTOMIZATION_RUN_MISMATCH", "Preset executor returned an unexpected or duplicate scenario result");
60
+ const result = parseAnalysisResult(item.result);
61
+ if (result.recipeId !== preset.recipeId)
62
+ throw new AgentsError("CUSTOMIZATION_RUN_MISMATCH", "Preset executor returned a result for another recipe");
63
+ byId.set(item.scenarioId, result);
64
+ }
65
+ if (byId.size !== scenarioIds.length)
66
+ throw new AgentsError("CUSTOMIZATION_RUN_MISMATCH", "Preset executor omitted an exact requested scenario result");
67
+ return {
68
+ success: true,
69
+ data: {
70
+ runPresetId: preset.id,
71
+ recipeId: preset.recipeId,
72
+ scenarioIds,
73
+ results: scenarioIds.map((scenarioId) => ({ scenarioId, result: byId.get(scenarioId) })),
74
+ },
75
+ };
76
+ },
77
+ });
78
+ }
79
+ //# sourceMappingURL=customization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customization.js","sourceRoot":"","sources":["../src/customization.ts"],"names":[],"mappings":"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"}
package/dist/errors.d.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  * thrown during tool execution into a { success: false, error } envelope.
11
11
  */
12
12
  /** Every machine-readable code an AgentsError can carry. */
13
- export declare const AGENTS_ERROR_CODES: readonly ["NO_TENANT_CONTEXT", "TENANT_IN_SCHEMA", "BAD_INPUT_SCHEMA", "BAD_GATE", "MISSING_RATIONALE", "DUPLICATE_TOOL_ID", "BAD_PROMOTION_OPTIONS", "EMPTY_STUDY", "TOLERANCE_CEILING_EXCEEDED", "SEGMENT_UNRESOLVED", "SEGMENT_AMBIGUOUS", "VERDICT_NOT_DISAGREE", "DIVERGENCE_INPUT_MISMATCH", "NO_DIVERGENCE_EVIDENCE", "REMOTE_RESULT_INVALID", "MCP_SELF_TEST_FAILED", "BAD_DIAGNOSTIC_CATALOG", "UNKNOWN_DIAGNOSTIC_PRESET", "UNAPPROVED_DIAGNOSTIC_INSTANCE", "DIAGNOSTIC_RUN_MISMATCH", "BAD_OUTPUT_SCHEMA", "TOOL_INPUT_INVALID", "TOOL_OUTPUT_INVALID"];
13
+ export declare const AGENTS_ERROR_CODES: readonly ["NO_TENANT_CONTEXT", "TENANT_IN_SCHEMA", "BAD_INPUT_SCHEMA", "BAD_GATE", "MISSING_RATIONALE", "DUPLICATE_TOOL_ID", "BAD_PROMOTION_OPTIONS", "EMPTY_STUDY", "TOLERANCE_CEILING_EXCEEDED", "SEGMENT_UNRESOLVED", "SEGMENT_AMBIGUOUS", "VERDICT_NOT_DISAGREE", "DIVERGENCE_INPUT_MISMATCH", "NO_DIVERGENCE_EVIDENCE", "REMOTE_RESULT_INVALID", "MCP_SELF_TEST_FAILED", "BAD_DIAGNOSTIC_CATALOG", "UNKNOWN_DIAGNOSTIC_PRESET", "UNAPPROVED_DIAGNOSTIC_INSTANCE", "DIAGNOSTIC_RUN_MISMATCH", "BAD_CUSTOMIZATION_CATALOG", "UNKNOWN_CUSTOMIZATION_PRESET", "UNAPPROVED_CUSTOMIZATION_SCENARIO", "CUSTOMIZATION_RUN_MISMATCH", "BAD_OUTPUT_SCHEMA", "TOOL_INPUT_INVALID", "TOOL_OUTPUT_INVALID"];
14
14
  export type AgentsErrorCode = (typeof AGENTS_ERROR_CODES)[number];
15
15
  /**
16
16
  * Thrown for invalid agent-toolkit input: tenant-seam violations, malformed
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,qiBAuCrB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;gBACnB,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM;CAKnD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,qqBA2CrB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;gBACnB,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM;CAKnD"}
package/dist/errors.js CHANGED
@@ -46,6 +46,10 @@ export const AGENTS_ERROR_CODES = [
46
46
  "UNKNOWN_DIAGNOSTIC_PRESET",
47
47
  "UNAPPROVED_DIAGNOSTIC_INSTANCE",
48
48
  "DIAGNOSTIC_RUN_MISMATCH",
49
+ "BAD_CUSTOMIZATION_CATALOG",
50
+ "UNKNOWN_CUSTOMIZATION_PRESET",
51
+ "UNAPPROVED_CUSTOMIZATION_SCENARIO",
52
+ "CUSTOMIZATION_RUN_MISMATCH",
49
53
  "BAD_OUTPUT_SCHEMA",
50
54
  "TOOL_INPUT_INVALID",
51
55
  "TOOL_OUTPUT_INVALID",
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,sFAAsF;IACtF,mBAAmB;IACnB,sHAAsH;IACtH,kBAAkB;IAClB,kBAAkB;IAClB,2EAA2E;IAC3E,UAAU;IACV,iEAAiE;IACjE,mBAAmB;IACnB,8DAA8D;IAC9D,mBAAmB;IACnB,8EAA8E;IAC9E,uBAAuB;IACvB,kEAAkE;IAClE,aAAa;IACb,mFAAmF;IACnF,4BAA4B;IAC5B,6FAA6F;IAC7F,oBAAoB;IACpB,kGAAkG;IAClG,mBAAmB;IACnB,wIAAwI;IACxI,sBAAsB;IACtB,0IAA0I;IAC1I,2BAA2B;IAC3B,sIAAsI;IACtI,wBAAwB;IACxB,yIAAyI;IACzI,uBAAuB;IACvB,iLAAiL;IACjL,sBAAsB;IACtB,wBAAwB;IACxB,2BAA2B;IAC3B,gCAAgC;IAChC,yBAAyB;IACzB,mBAAmB;IACnB,oBAAoB;IACpB,qBAAqB;CACb,CAAC;AAIX;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,IAAI,CAAkB;IAC/B,YAAY,IAAqB,EAAE,OAAe;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,sFAAsF;IACtF,mBAAmB;IACnB,sHAAsH;IACtH,kBAAkB;IAClB,kBAAkB;IAClB,2EAA2E;IAC3E,UAAU;IACV,iEAAiE;IACjE,mBAAmB;IACnB,8DAA8D;IAC9D,mBAAmB;IACnB,8EAA8E;IAC9E,uBAAuB;IACvB,kEAAkE;IAClE,aAAa;IACb,mFAAmF;IACnF,4BAA4B;IAC5B,6FAA6F;IAC7F,oBAAoB;IACpB,kGAAkG;IAClG,mBAAmB;IACnB,wIAAwI;IACxI,sBAAsB;IACtB,0IAA0I;IAC1I,2BAA2B;IAC3B,sIAAsI;IACtI,wBAAwB;IACxB,yIAAyI;IACzI,uBAAuB;IACvB,iLAAiL;IACjL,sBAAsB;IACtB,wBAAwB;IACxB,2BAA2B;IAC3B,gCAAgC;IAChC,yBAAyB;IACzB,2BAA2B;IAC3B,8BAA8B;IAC9B,mCAAmC;IACnC,4BAA4B;IAC5B,mBAAmB;IACnB,oBAAoB;IACpB,qBAAqB;CACb,CAAC;AAIX;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,IAAI,CAAkB;IAC/B,YAAY,IAAqB,EAAE,OAAe;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
package/dist/index.d.ts CHANGED
@@ -8,4 +8,5 @@ export * from "./divergence.js";
8
8
  export * from "./remote.js";
9
9
  export * from "./mcp.js";
10
10
  export * from "./diagnostics.js";
11
+ export * from "./customization.js";
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -8,4 +8,5 @@ export * from "./divergence.js";
8
8
  export * from "./remote.js";
9
9
  export * from "./mcp.js";
10
10
  export * from "./diagnostics.js";
11
+ export * from "./customization.js";
11
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actuarial-ts/agents",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Mastra agent toolkit for actuarial-ts: exact validated tools with a hard tenant seam, human-gated judgment, trusted-catalog diagnostic selection, reserving advice, and evals.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -47,17 +47,17 @@
47
47
  "prepublishOnly": "node ../../tools/release/verify-release-attestation.mjs @actuarial-ts/agents"
48
48
  },
49
49
  "dependencies": {
50
- "@actuarial-ts/compliance": "^0.7.0",
51
- "@actuarial-ts/core": "^0.7.0",
52
- "@actuarial-ts/data": "^0.7.0",
53
- "@actuarial-ts/interchange": "^0.7.0"
50
+ "@actuarial-ts/compliance": "^0.8.0",
51
+ "@actuarial-ts/core": "^0.8.0",
52
+ "@actuarial-ts/data": "^0.8.0",
53
+ "@actuarial-ts/interchange": "^0.8.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@mastra/core": "^1.51.0",
57
57
  "@mastra/mcp": "^1.14.0",
58
58
  "@types/node": "^22.10.5",
59
59
  "typescript": "^5.7.3",
60
- "vitest": "^3.0.5",
60
+ "vitest": "^5.0.1",
61
61
  "zod": "^3.25.76"
62
62
  },
63
63
  "peerDependencies": {
@@ -0,0 +1,117 @@
1
+ import { isDiagnosticToken, type AnalysisResult } from "@actuarial-ts/core";
2
+ import { analysisResultSchema, parseAnalysisResult } from "@actuarial-ts/data";
3
+ import { z } from "zod";
4
+ import { AgentsError } from "./errors.js";
5
+ import {
6
+ defineActuarialTool,
7
+ type DefinedActuarialTool,
8
+ } from "./tools.js";
9
+
10
+ const token = z.string().refine(isDiagnosticToken);
11
+ export const customizationAgentToolInputSchema = z.object({
12
+ runPresetId: token,
13
+ scenarioIds: z.array(token).max(32),
14
+ }).strict();
15
+
16
+ export interface CustomizationAgentPresetResult {
17
+ readonly scenarioId: string;
18
+ readonly result: AnalysisResult;
19
+ }
20
+
21
+ export interface CustomizationAgentRunPreset {
22
+ readonly id: string;
23
+ readonly recipeId: string;
24
+ readonly allowedScenarioIds: readonly string[];
25
+ readonly execute: (input: {
26
+ readonly tenantId: string;
27
+ readonly scenarioIds: readonly string[];
28
+ }) => Promise<readonly CustomizationAgentPresetResult[]>;
29
+ }
30
+
31
+ export interface CustomizationAgentToolSuccess {
32
+ readonly success: true;
33
+ readonly data: {
34
+ readonly runPresetId: string;
35
+ readonly recipeId: string;
36
+ readonly scenarioIds: readonly string[];
37
+ readonly results: readonly CustomizationAgentPresetResult[];
38
+ };
39
+ }
40
+
41
+ const failureSchema = z.object({
42
+ success: z.literal(false),
43
+ error: z.object({ code: z.string(), message: z.string() }).strict(),
44
+ }).strict();
45
+ export const customizationAgentToolResultSchema = z.union([
46
+ z.object({
47
+ success: z.literal(true),
48
+ data: z.object({
49
+ runPresetId: token,
50
+ recipeId: token,
51
+ scenarioIds: z.array(token),
52
+ results: z.array(z.object({ scenarioId: token, result: analysisResultSchema }).strict()),
53
+ }).strict(),
54
+ }).strict(),
55
+ failureSchema,
56
+ ]);
57
+
58
+ export function createCustomizationSelectionTool(input: {
59
+ readonly runPresets: readonly CustomizationAgentRunPreset[];
60
+ readonly id?: string;
61
+ readonly description?: string;
62
+ readonly tenantContextKey?: string;
63
+ }): DefinedActuarialTool<
64
+ z.input<typeof customizationAgentToolInputSchema>,
65
+ z.output<typeof customizationAgentToolResultSchema>
66
+ > {
67
+ const catalog = new Map<string, CustomizationAgentRunPreset>();
68
+ for (const preset of input.runPresets) {
69
+ if (!isDiagnosticToken(preset.id) || !isDiagnosticToken(preset.recipeId))
70
+ throw new AgentsError("BAD_CUSTOMIZATION_CATALOG", "Customization preset id and recipeId must be valid tokens");
71
+ if (catalog.has(preset.id))
72
+ throw new AgentsError("BAD_CUSTOMIZATION_CATALOG", `Duplicate customization preset ${preset.id}`);
73
+ if (new Set(preset.allowedScenarioIds).size !== preset.allowedScenarioIds.length || preset.allowedScenarioIds.some((id) => !isDiagnosticToken(id)))
74
+ throw new AgentsError("BAD_CUSTOMIZATION_CATALOG", `Preset ${preset.id} has invalid or duplicate scenario IDs`);
75
+ catalog.set(preset.id, Object.freeze({ ...preset, allowedScenarioIds: Object.freeze([...preset.allowedScenarioIds].sort()) }));
76
+ }
77
+ return defineActuarialTool({
78
+ id: input.id ?? "run-approved-customization",
79
+ description: input.description ?? "Run a host-approved actuarial recipe and approved scenarios",
80
+ kind: "read",
81
+ tenant: "required",
82
+ tenantKey: input.tenantContextKey ?? "projectId",
83
+ inputSchema: customizationAgentToolInputSchema,
84
+ outputSchema: customizationAgentToolResultSchema,
85
+ execute: async (request, tenant) => {
86
+ const preset = catalog.get(request.runPresetId);
87
+ if (preset === undefined)
88
+ throw new AgentsError("UNKNOWN_CUSTOMIZATION_PRESET", `Unknown customization preset ${request.runPresetId}`);
89
+ if (new Set(request.scenarioIds).size !== request.scenarioIds.length)
90
+ throw new AgentsError("CUSTOMIZATION_RUN_MISMATCH", "Requested scenario IDs must be unique");
91
+ const scenarioIds = [...request.scenarioIds].sort();
92
+ if (scenarioIds.some((id) => !preset.allowedScenarioIds.includes(id)))
93
+ throw new AgentsError("UNAPPROVED_CUSTOMIZATION_SCENARIO", "One or more requested scenarios are not approved by the selected preset");
94
+ const rawResults = await preset.execute({ tenantId: tenant, scenarioIds });
95
+ const byId = new Map<string, AnalysisResult>();
96
+ for (const item of rawResults) {
97
+ if (!scenarioIds.includes(item.scenarioId) || byId.has(item.scenarioId))
98
+ throw new AgentsError("CUSTOMIZATION_RUN_MISMATCH", "Preset executor returned an unexpected or duplicate scenario result");
99
+ const result = parseAnalysisResult(item.result);
100
+ if (result.recipeId !== preset.recipeId)
101
+ throw new AgentsError("CUSTOMIZATION_RUN_MISMATCH", "Preset executor returned a result for another recipe");
102
+ byId.set(item.scenarioId, result);
103
+ }
104
+ if (byId.size !== scenarioIds.length)
105
+ throw new AgentsError("CUSTOMIZATION_RUN_MISMATCH", "Preset executor omitted an exact requested scenario result");
106
+ return {
107
+ success: true,
108
+ data: {
109
+ runPresetId: preset.id,
110
+ recipeId: preset.recipeId,
111
+ scenarioIds,
112
+ results: scenarioIds.map((scenarioId) => ({ scenarioId, result: byId.get(scenarioId)! })),
113
+ },
114
+ };
115
+ },
116
+ });
117
+ }
package/src/errors.ts CHANGED
@@ -47,6 +47,10 @@ export const AGENTS_ERROR_CODES = [
47
47
  "UNKNOWN_DIAGNOSTIC_PRESET",
48
48
  "UNAPPROVED_DIAGNOSTIC_INSTANCE",
49
49
  "DIAGNOSTIC_RUN_MISMATCH",
50
+ "BAD_CUSTOMIZATION_CATALOG",
51
+ "UNKNOWN_CUSTOMIZATION_PRESET",
52
+ "UNAPPROVED_CUSTOMIZATION_SCENARIO",
53
+ "CUSTOMIZATION_RUN_MISMATCH",
50
54
  "BAD_OUTPUT_SCHEMA",
51
55
  "TOOL_INPUT_INVALID",
52
56
  "TOOL_OUTPUT_INVALID",
package/src/index.ts CHANGED
@@ -8,3 +8,4 @@ export * from "./divergence.js";
8
8
  export * from "./remote.js";
9
9
  export * from "./mcp.js";
10
10
  export * from "./diagnostics.js";
11
+ export * from "./customization.js";