@actuarial-ts/agents 0.1.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/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
package/NOTICE ADDED
@@ -0,0 +1,5 @@
1
+ actuarial-ts
2
+ Copyright 2026 Justin Morrey
3
+
4
+ This product includes software developed as part of the actuarial-ts project
5
+ (https://github.com/yerromnitsuj/actng).
package/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # @actuarial-ts/agents
2
+
3
+ Mastra agent toolkit for the actuarial-ts SDK: typed actuarial tools with a hard tenant seam, human-gated judgment workflows that write the compliance assumption ledger, a reserving advisor factory, and a golden-prompt eval harness.
4
+
5
+ The package generalizes the agent architecture proven in the ActNG reserving workbench. Its core idea: when an agent participates in an actuarial analysis, the documentation ASOP 41 asks for should fall out of RUNNING the analysis, not be reconstructed afterwards. Judgment chains built here write an `@actuarial-ts/compliance` assumption ledger as decisions are made, so a completed chain hands back a ledger ready for `generateDisclosure`.
6
+
7
+ These utilities are designed to support the actuary's compliance with the ASOPs; responsibility for compliance remains with the credentialed actuary.
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ npm install @actuarial-ts/agents @mastra/core zod
13
+ ```
14
+
15
+ `@mastra/core` (>= 1.49, < 2) and `zod` are peer dependencies: the HOST application owns the Mastra version. `@actuarial-ts/compliance` is a regular dependency (and brings `@actuarial-ts/core` with it).
16
+
17
+ ## Security model
18
+
19
+ The tenant id (project id) reaches tools ONLY via the server-set request context, never from the model. The package enforces the seam at both ends:
20
+
21
+ - `tenantOf(context, key = "projectId")` reads the tenant from `context.requestContext`, set server-side from the authenticated request. Missing, non-string, or empty ids throw a typed `AgentsError("NO_TENANT_CONTEXT")`, which the tool wrapper converts to a failure envelope.
22
+ - `defineActuarialTool` REJECTS, at definition time, any input schema declaring a tenant-id key (`projectId`, `tenantId`, `project_id`, ... in any casing) with `AgentsError("TENANT_IN_SCHEMA")`. The model must not even be able to express a tenant id.
23
+
24
+ Tools never throw into the model. Anything the tool body throws becomes:
25
+
26
+ ```ts
27
+ { success: false, error: { code: string, message: string } }
28
+ ```
29
+
30
+ Errors carrying a string `code` property (HTTP-style coded errors, `AgentsError`, `ComplianceError`) keep their code so the agent can recover deliberately: retry with adjusted parameters, suggest an alternative, or ask.
31
+
32
+ ```ts
33
+ import { defineActuarialTool, tenantOf, toolRegistry } from "@actuarial-ts/agents";
34
+ import { z } from "zod";
35
+
36
+ const getOverview = defineActuarialTool({
37
+ id: "get_workspace_overview",
38
+ description: "Orient yourself in the workspace",
39
+ kind: "read", // or "action" for state-mutating tools
40
+ inputSchema: z.object({}),
41
+ execute: async (_input, context) => {
42
+ const projectId = tenantOf(context);
43
+ return { success: true, ...loadOverview(projectId) };
44
+ },
45
+ });
46
+
47
+ const { tools, actionToolIds } = toolRegistry([getOverview /* , ... */]);
48
+ // tools -> Record keyed by id, ready for new Agent({ tools })
49
+ // actionToolIds -> the host client refreshes after these run
50
+ ```
51
+
52
+ ## Judgment chains: propose, justify, approve, record
53
+
54
+ `createJudgmentChain` turns an ordered list of `JudgmentGateSpec`s into a committed Mastra workflow that pauses at EVERY actuarial judgment:
55
+
56
+ 1. **Propose.** The gate gathers evidence through your service layer and suspends with `{ stage, recommendation, evidence }`.
57
+ 2. **Justify and approve.** A human decides; the resume payload carries the decision plus a VERBATIM rationale (schemas without a `rationale` key are rejected at definition time; blank rationales fail the gate at runtime).
58
+ 3. **Record.** `applyDecision` applies the decision through your service layer and returns the assumptions it fixed; the chain appends them to the threaded ledger with the rationale, the actor from the payload's optional `actor` field (default `"actuary"`), and a timestamp from the host-injected `now()` (the package never reads a clock).
59
+
60
+ A gate may also self-skip (`skipWhen`) based on earlier gates' decisions, recording a skip note in the trail - the shape the ActNG ELR derivation uses when the cap gate chose to stay unlimited and the restoration gate becomes moot.
61
+
62
+ ```ts
63
+ import { createJudgmentChain } from "@actuarial-ts/agents";
64
+ import { generateDisclosure } from "@actuarial-ts/compliance";
65
+ import { Mastra } from "@mastra/core/mastra";
66
+
67
+ const chain = createJudgmentChain({
68
+ id: "derive-expected-losses",
69
+ gates: [capGate, ilfGate, trendGate, elrGate],
70
+ now: () => new Date().toISOString(), // the host owns the clock
71
+ onComplete: async ({ trail, ledger }, ctx) => {
72
+ persistTrailNote(tenantOf(ctx), trail, ledger);
73
+ },
74
+ });
75
+
76
+ // Register for snapshot storage (suspend/resume state lives there; durable
77
+ // storage keeps paused chains resumable across restarts).
78
+ const mastra = new Mastra({ workflows: { chain }, storage });
79
+
80
+ const run = await mastra.getWorkflow("chain").createRun();
81
+ let state = await run.start({ inputData: {}, requestContext }); // suspended at gate 1
82
+ state = await run.resume({
83
+ step: "cap-gate",
84
+ resumeData: { decision: "accept", cap: 150_000, rationale: "volatile large losses distort development" },
85
+ requestContext,
86
+ });
87
+ // ... resume each gate; the final result is { trail, ledger }
88
+ ```
89
+
90
+ ### The ledger fusion
91
+
92
+ The completed chain's `ledger` is a real `@actuarial-ts/compliance` `AssumptionLedger`: every human decision is an `AssumptionEntry` with actor, verbatim rationale, and caller-supplied timestamp. Feed it straight into the disclosure pipeline:
93
+
94
+ ```ts
95
+ const { trail, ledger } = finalResult;
96
+ const disclosure = generateDisclosure({
97
+ metadata, // EstimateMetadata for the analysis
98
+ methods, // MethodUse[]
99
+ ledger, // the chain's fused ledger, judgments and rationales included
100
+ sdkVersion,
101
+ generatedAt: now(),
102
+ });
103
+ ```
104
+
105
+ ASOP 41 assumptions-and-judgments documentation as a side effect of running the analysis.
106
+
107
+ ### Footgun: workflows are accidental thenables
108
+
109
+ A Mastra `Workflow` exposes a `.then(step)` builder method, so `await chain` (or returning a workflow from an `async` function) makes JavaScript treat it as a thenable and the promise NEVER settles. Assign the chain synchronously and register it on your Mastra instance.
110
+
111
+ ## Reserving advisor factory
112
+
113
+ `createReservingAdvisor` assembles an `@mastra/core` Agent on a hardened base instruction template: professional grounding, every-number-from-a-tool-result, read-before-recommend ordering, action consent, failure recovery, and selection-of-ultimates weighting guidance. Host domain sections splice in between the base analytics and the conduct section.
114
+
115
+ The template is auditable by construction: `BASE_INSTRUCTIONS` exports the named sections and `assembleInstructions` is a pure deterministic string function, so hosts can byte-inspect (and snapshot-test) the exact prompt their agent runs on.
116
+
117
+ ```ts
118
+ import { createReservingAdvisor, assembleInstructions } from "@actuarial-ts/agents";
119
+
120
+ const advisor = createReservingAdvisor({
121
+ model: anthropic("claude-sonnet-4-5"),
122
+ tools,
123
+ memory,
124
+ domainInstructions: [ldfSelectionGuide, cappingGuide, tailGuide],
125
+ });
126
+
127
+ // What is this agent actually running on? Byte-inspect it:
128
+ const prompt = assembleInstructions({ domainInstructions: [ldfSelectionGuide, cappingGuide, tailGuide] });
129
+ ```
130
+
131
+ ## Eval harness
132
+
133
+ `runToolSelectionEvals` asserts tool SELECTION, not prose: each golden case lists the tools that must appear among the turn's calls. Running against a real agent costs live API tokens, so keep it opt-in (an env flag in a script, never in package tests).
134
+
135
+ ```ts
136
+ import { runToolSelectionEvals } from "@actuarial-ts/agents";
137
+
138
+ const report = await runToolSelectionEvals({
139
+ agent: advisor,
140
+ requestContext,
141
+ cases: [
142
+ { id: "cap-evidence", prompt: "Should we cap this book? Check the claim-size evidence first.", expectTools: ["analyze_claim_sizes"] },
143
+ { id: "elr-select", prompt: "Select an expected loss ratio of 65%.", expectTools: ["set_elr"] },
144
+ ],
145
+ timeoutMs: 180_000, // a stalled stream fails the case, not the suite
146
+ });
147
+ // report.results: per-case { id, pass, called, missing, error? }
148
+ // report.summary: { total, passed, failed }
149
+ ```
150
+
151
+ The `agent` parameter is typed structurally (anything with a `stream()` yielding a `fullStream`), so the harness itself is testable with a stubbed agent and canned chunks - no LLM, no network.
152
+
153
+ ## License
154
+
155
+ Apache-2.0. See LICENSE and NOTICE.
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Reserving advisor factory: assembles an @mastra/core Agent from the
3
+ * hardened base instruction template the ActNG server converged on, with
4
+ * host-supplied domain sections spliced in.
5
+ *
6
+ * The base sections are exported (BASE_INSTRUCTIONS) and the assembly is a
7
+ * pure, deterministic string function (assembleInstructions) so hosts and
8
+ * tests can byte-inspect exactly what their agent runs on - a load-bearing
9
+ * prompt should never be assembled somewhere you cannot audit.
10
+ *
11
+ * HOUSE GOTCHA honored throughout: no literal backtick characters anywhere in
12
+ * instruction content (a backtick inside a template literal once broke server
13
+ * boot). Section text uses quotes instead.
14
+ */
15
+ import { Agent } from "@mastra/core/agent";
16
+ export declare const BASE_INSTRUCTIONS: {
17
+ readonly role: "You are an embedded reserving advisor inside an actuarial analysis application, working alongside a credentialed actuary on one engagement at a time. You participate in the analysis rather than chatting about it: read tools ground every number you cite, and action tools change the working state through the exact same service layer as the application's own controls. You are expected to operate at the level of an experienced, credentialed reserving actuary.";
18
+ readonly professionalGrounding: "Your advice follows recognized actuarial practice: Friedland, \"Estimating Unpaid Claims Using Basic Techniques\" (method mechanics and adjustments); Werner and Modlin, \"Basic Ratemaking\" (exposure and trend concepts); ASOP 43 (unpaid claim estimates: intended purpose, materiality, methods appropriate to the data); and CAS reserving principles. When data violates a method's assumptions, say which assumption and why it matters, the way a reviewing actuary would.";
19
+ readonly workingRules: string;
20
+ readonly actionConsent: "You may change the working state when the user asks (or clearly implies) it - action tools are the same operations as the application's own controls and are reversible; do them rather than describing how the user could. A direct parameterized instruction is consent - apply it in the SAME turn, then confirm concisely what changed. Reserve ask-backs for genuinely ambiguous requests.";
21
+ readonly failureRecovery: "If a tool returns success: false, do not pretend it worked. Read the error, fix your parameters and retry once if the problem is yours, otherwise tell the user plainly what failed and offer the closest alternative. Never invent a result to cover a failed call.";
22
+ readonly selectionWeighting: "When blending method results into selected ultimates, weight like a reviewing actuary: lean toward methods whose assumptions the diagnostics support. Development methods earn weight on mature periods where the pattern is credible; expected-loss methods such as Bornhuetter-Ferguson earn weight on green, volatile periods where the a-priori is more credible than thin emerged experience; credibility blends such as Benktander are the natural compromise for middle-maturity periods. Never set custom weights or overrides without stating the rationale, and offer to record it.";
23
+ readonly conduct: "Be direct and technical; the user is an actuary, not a consumer. After returning search-like results or recommendations, ask whether they match what the user intended before charging ahead with actions, unless the user already told you to proceed end-to-end. When the user asks you to review, recommend, apply, and rerun in one instruction, do the full sequence without stopping to ask permission between steps, then summarize what changed. Keep a professional skeptic's tone: point out weak spots in the data, thin columns, and judgment calls that could move the answer materially.";
24
+ };
25
+ export type BaseInstructionSection = keyof typeof BASE_INSTRUCTIONS;
26
+ export interface AssembleInstructionsOptions {
27
+ /**
28
+ * Host domain sections (capping mechanics, tail conventions, named tool
29
+ * guidance, ...), spliced verbatim between the base analytical sections and
30
+ * the conduct section. Bring your own headers.
31
+ */
32
+ domainInstructions?: string | readonly string[];
33
+ /** Replaces the base conduct section wholesale when provided. */
34
+ conductOverrides?: string;
35
+ }
36
+ /**
37
+ * Deterministic assembly of the final instruction string: pure string
38
+ * concatenation with fixed headers, no clock, no randomness - identical
39
+ * inputs yield byte-identical output, so hosts can snapshot-test the exact
40
+ * prompt their agent runs on.
41
+ */
42
+ export declare function assembleInstructions(options?: AssembleInstructionsOptions): string;
43
+ /** Config slices lifted from the installed Agent constructor so the factory tracks the host's Mastra version. */
44
+ type AgentCtorConfig = ConstructorParameters<typeof Agent>[0];
45
+ export interface CreateReservingAdvisorOptions {
46
+ /** Defaults to "reserving-advisor". */
47
+ id?: string;
48
+ /** Defaults to "Reserving Advisor". */
49
+ name?: string;
50
+ description?: string;
51
+ /** The language model (same type the host's Agent constructor takes). */
52
+ model: AgentCtorConfig["model"];
53
+ /** The tool record, e.g. toolRegistry(...).tools. */
54
+ tools?: AgentCtorConfig["tools"];
55
+ /** Optional Mastra memory instance. */
56
+ memory?: AgentCtorConfig["memory"];
57
+ /** Host domain sections; see assembleInstructions. */
58
+ domainInstructions?: string | readonly string[];
59
+ /** Replaces the base conduct section wholesale. */
60
+ conductOverrides?: string;
61
+ }
62
+ /**
63
+ * Assembles a reserving advisor Agent on the hardened base template. The
64
+ * final instructions are exactly assembleInstructions({ domainInstructions,
65
+ * conductOverrides }) - byte-inspect them there.
66
+ */
67
+ export declare function createReservingAdvisor(options: CreateReservingAdvisorOptions): Agent;
68
+ export {};
69
+ //# sourceMappingURL=advisor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advisor.d.ts","sourceRoot":"","sources":["../src/advisor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAa3C,eAAO,MAAM,iBAAiB;;;;;;;;CAuBpB,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAAG,MAAM,OAAO,iBAAiB,CAAC;AAEpE,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IAChD,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,2BAAgC,GAAG,MAAM,CAkBtF;AAKD,iHAAiH;AACjH,KAAK,eAAe,GAAG,qBAAqB,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D,MAAM,WAAW,6BAA6B;IAC5C,uCAAuC;IACvC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAChC,qDAAqD;IACrD,KAAK,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACjC,uCAAuC;IACvC,MAAM,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC;IACnC,sDAAsD;IACtD,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IAChD,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,6BAA6B,GAAG,KAAK,CAepF"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Reserving advisor factory: assembles an @mastra/core Agent from the
3
+ * hardened base instruction template the ActNG server converged on, with
4
+ * host-supplied domain sections spliced in.
5
+ *
6
+ * The base sections are exported (BASE_INSTRUCTIONS) and the assembly is a
7
+ * pure, deterministic string function (assembleInstructions) so hosts and
8
+ * tests can byte-inspect exactly what their agent runs on - a load-bearing
9
+ * prompt should never be assembled somewhere you cannot audit.
10
+ *
11
+ * HOUSE GOTCHA honored throughout: no literal backtick characters anywhere in
12
+ * instruction content (a backtick inside a template literal once broke server
13
+ * boot). Section text uses quotes instead.
14
+ */
15
+ import { Agent } from "@mastra/core/agent";
16
+ // ---------------------------------------------------------------------------
17
+ // Base instruction sections
18
+ //
19
+ // Generalized from the server advisor's non-domain-specific rules: the
20
+ // professional grounding, tools-are-the-only-path-to-numbers,
21
+ // read-before-recommend ordering, no-table-recitation, action consent,
22
+ // failure recovery, selection-of-ultimates weighting, and conversational
23
+ // conduct. Workbench-specific exhibits (LDF vector conventions, capping
24
+ // mechanics, named tools) stay OUT: hosts splice those in as
25
+ // domainInstructions.
26
+ export const BASE_INSTRUCTIONS = {
27
+ role: "You are an embedded reserving advisor inside an actuarial analysis application, working alongside a credentialed actuary on one engagement at a time. You participate in the analysis rather than chatting about it: read tools ground every number you cite, and action tools change the working state through the exact same service layer as the application's own controls. You are expected to operate at the level of an experienced, credentialed reserving actuary.",
28
+ professionalGrounding: 'Your advice follows recognized actuarial practice: Friedland, "Estimating Unpaid Claims Using Basic Techniques" (method mechanics and adjustments); Werner and Modlin, "Basic Ratemaking" (exposure and trend concepts); ASOP 43 (unpaid claim estimates: intended purpose, materiality, methods appropriate to the data); and CAS reserving principles. When data violates a method\'s assumptions, say which assumption and why it matters, the way a reviewing actuary would.',
29
+ workingRules: [
30
+ "1. EVERY number you cite must come from a tool result in this conversation. Never estimate, recall, or invent figures. If you have not called the tool, you do not know the number.",
31
+ "2. Call read tools BEFORE forming recommendations: orient yourself in the current working state first, gather the relevant evidence before recommending a selection, and check data quality before opining on method reliability.",
32
+ "3. The application renders tool results as tables and cards next to this chat. Do NOT recite full tables into the conversation. Reference the handful of figures that carry your argument.",
33
+ ].join("\n"),
34
+ actionConsent: "You may change the working state when the user asks (or clearly implies) it - action tools are the same operations as the application's own controls and are reversible; do them rather than describing how the user could. A direct parameterized instruction is consent - apply it in the SAME turn, then confirm concisely what changed. Reserve ask-backs for genuinely ambiguous requests.",
35
+ failureRecovery: "If a tool returns success: false, do not pretend it worked. Read the error, fix your parameters and retry once if the problem is yours, otherwise tell the user plainly what failed and offer the closest alternative. Never invent a result to cover a failed call.",
36
+ selectionWeighting: "When blending method results into selected ultimates, weight like a reviewing actuary: lean toward methods whose assumptions the diagnostics support. Development methods earn weight on mature periods where the pattern is credible; expected-loss methods such as Bornhuetter-Ferguson earn weight on green, volatile periods where the a-priori is more credible than thin emerged experience; credibility blends such as Benktander are the natural compromise for middle-maturity periods. Never set custom weights or overrides without stating the rationale, and offer to record it.",
37
+ conduct: "Be direct and technical; the user is an actuary, not a consumer. After returning search-like results or recommendations, ask whether they match what the user intended before charging ahead with actions, unless the user already told you to proceed end-to-end. When the user asks you to review, recommend, apply, and rerun in one instruction, do the full sequence without stopping to ask permission between steps, then summarize what changed. Keep a professional skeptic's tone: point out weak spots in the data, thin columns, and judgment calls that could move the answer materially.",
38
+ };
39
+ /**
40
+ * Deterministic assembly of the final instruction string: pure string
41
+ * concatenation with fixed headers, no clock, no randomness - identical
42
+ * inputs yield byte-identical output, so hosts can snapshot-test the exact
43
+ * prompt their agent runs on.
44
+ */
45
+ export function assembleInstructions(options = {}) {
46
+ const domain = options.domainInstructions === undefined
47
+ ? []
48
+ : typeof options.domainInstructions === "string"
49
+ ? [options.domainInstructions]
50
+ : [...options.domainInstructions];
51
+ const sections = [
52
+ BASE_INSTRUCTIONS.role,
53
+ "## Professional grounding\n" + BASE_INSTRUCTIONS.professionalGrounding,
54
+ "## Non-negotiable working rules\n" + BASE_INSTRUCTIONS.workingRules,
55
+ "## Acting on the working state\n" + BASE_INSTRUCTIONS.actionConsent,
56
+ "## Failure recovery\n" + BASE_INSTRUCTIONS.failureRecovery,
57
+ "## Selection of ultimates\n" + BASE_INSTRUCTIONS.selectionWeighting,
58
+ ...domain,
59
+ "## Conversational conduct\n" + (options.conductOverrides ?? BASE_INSTRUCTIONS.conduct),
60
+ ];
61
+ return sections.join("\n\n");
62
+ }
63
+ /**
64
+ * Assembles a reserving advisor Agent on the hardened base template. The
65
+ * final instructions are exactly assembleInstructions({ domainInstructions,
66
+ * conductOverrides }) - byte-inspect them there.
67
+ */
68
+ export function createReservingAdvisor(options) {
69
+ return new Agent({
70
+ id: options.id ?? "reserving-advisor",
71
+ name: options.name ?? "Reserving Advisor",
72
+ description: options.description ??
73
+ "Embedded actuarial reserving advisor: analyzes loss development evidence, recommends and applies selections through host tools, and explains diagnostics.",
74
+ instructions: assembleInstructions({
75
+ domainInstructions: options.domainInstructions,
76
+ conductOverrides: options.conductOverrides,
77
+ }),
78
+ model: options.model,
79
+ ...(options.tools !== undefined ? { tools: options.tools } : {}),
80
+ ...(options.memory !== undefined ? { memory: options.memory } : {}),
81
+ });
82
+ }
83
+ //# sourceMappingURL=advisor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advisor.js","sourceRoot":"","sources":["../src/advisor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,8EAA8E;AAC9E,4BAA4B;AAC5B,EAAE;AACF,uEAAuE;AACvE,8DAA8D;AAC9D,uEAAuE;AACvE,yEAAyE;AACzE,wEAAwE;AACxE,6DAA6D;AAC7D,sBAAsB;AAEtB,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,6cAA6c;IAEnd,qBAAqB,EACnB,kdAAkd;IAEpd,YAAY,EAAE;QACZ,qLAAqL;QACrL,mOAAmO;QACnO,4LAA4L;KAC7L,CAAC,IAAI,CAAC,IAAI,CAAC;IAEZ,aAAa,EACX,iYAAiY;IAEnY,eAAe,EACb,sQAAsQ;IAExQ,kBAAkB,EAChB,+jBAA+jB;IAEjkB,OAAO,EACL,wkBAAwkB;CAClkB,CAAC;AAeX;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAAuC,EAAE;IAC5E,MAAM,MAAM,GACV,OAAO,CAAC,kBAAkB,KAAK,SAAS;QACtC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,OAAO,OAAO,CAAC,kBAAkB,KAAK,QAAQ;YAC9C,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC;YAC9B,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG;QACf,iBAAiB,CAAC,IAAI;QACtB,6BAA6B,GAAG,iBAAiB,CAAC,qBAAqB;QACvE,mCAAmC,GAAG,iBAAiB,CAAC,YAAY;QACpE,kCAAkC,GAAG,iBAAiB,CAAC,aAAa;QACpE,uBAAuB,GAAG,iBAAiB,CAAC,eAAe;QAC3D,6BAA6B,GAAG,iBAAiB,CAAC,kBAAkB;QACpE,GAAG,MAAM;QACT,6BAA6B,GAAG,CAAC,OAAO,CAAC,gBAAgB,IAAI,iBAAiB,CAAC,OAAO,CAAC;KACxF,CAAC;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AA0BD;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAsC;IAC3E,OAAO,IAAI,KAAK,CAAC;QACf,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,mBAAmB;QACrC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,mBAAmB;QACzC,WAAW,EACT,OAAO,CAAC,WAAW;YACnB,2JAA2J;QAC7J,YAAY,EAAE,oBAAoB,CAAC;YACjC,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;YAC9C,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;SAC3C,CAAC;QACF,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpE,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Error idiom for the agents package, mirroring core's ReservingError and
3
+ * compliance's ComplianceError: a typed Error subclass carrying a registered
4
+ * machine code. The registry below is the closed contract - add the code here
5
+ * when introducing a new throw.
6
+ *
7
+ * These errors are DEFINITION-TIME and SEAM errors (bad tool schemas, bad
8
+ * gate specs, missing tenant context, undocumented judgment). They are never
9
+ * allowed to reach the model: defineActuarialTool's wrapper converts anything
10
+ * thrown during tool execution into a { success: false, error } envelope.
11
+ */
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"];
14
+ export type AgentsErrorCode = (typeof AGENTS_ERROR_CODES)[number];
15
+ /**
16
+ * Thrown for invalid agent-toolkit input: tenant-seam violations, malformed
17
+ * gate specs, undocumented judgment. Carries a registered machine code so
18
+ * envelopes and tests can match on it without parsing messages.
19
+ */
20
+ export declare class AgentsError extends Error {
21
+ readonly code: AgentsErrorCode;
22
+ constructor(code: AgentsErrorCode, message: string);
23
+ }
24
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,8HAYrB,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 ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Error idiom for the agents package, mirroring core's ReservingError and
3
+ * compliance's ComplianceError: a typed Error subclass carrying a registered
4
+ * machine code. The registry below is the closed contract - add the code here
5
+ * when introducing a new throw.
6
+ *
7
+ * These errors are DEFINITION-TIME and SEAM errors (bad tool schemas, bad
8
+ * gate specs, missing tenant context, undocumented judgment). They are never
9
+ * allowed to reach the model: defineActuarialTool's wrapper converts anything
10
+ * thrown during tool execution into a { success: false, error } envelope.
11
+ */
12
+ /** Every machine-readable code an AgentsError can carry. */
13
+ export const AGENTS_ERROR_CODES = [
14
+ /** A tool read the request context and found no (or a non-string/empty) tenant id. */
15
+ "NO_TENANT_CONTEXT",
16
+ /** A tool's input schema declares a tenant-id key (projectId/tenantId); tenant ids travel only via RequestContext. */
17
+ "TENANT_IN_SCHEMA",
18
+ "BAD_INPUT_SCHEMA",
19
+ /** A judgment chain was defined with an invalid gate list or gate spec. */
20
+ "BAD_GATE",
21
+ /** A judgment gate was resumed without a non-blank rationale. */
22
+ "MISSING_RATIONALE",
23
+ /** Two tools with the same id were passed to toolRegistry. */
24
+ "DUPLICATE_TOOL_ID",
25
+ ];
26
+ /**
27
+ * Thrown for invalid agent-toolkit input: tenant-seam violations, malformed
28
+ * gate specs, undocumented judgment. Carries a registered machine code so
29
+ * envelopes and tests can match on it without parsing messages.
30
+ */
31
+ export class AgentsError extends Error {
32
+ code;
33
+ constructor(code, message) {
34
+ super(message);
35
+ this.name = "AgentsError";
36
+ this.code = code;
37
+ }
38
+ }
39
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +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;CACX,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"}