@actuarial-ts/agents 0.5.0 → 0.6.1

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
@@ -1,156 +1,60 @@
1
1
  # @actuarial-ts/agents
2
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 four-gate study-promotion chain (`promoteStudy`), a remote-engine bridge (`defineRemoteMethod`) with a referee divergence explainer, a fail-closed MCP tenant seam, a reserving advisor factory, and a golden-prompt eval harness.
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
- 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
- # plus @mastra/mcp if you use the MCP surface:
14
- npm install @mastra/mcp
15
- ```
16
-
17
- `@mastra/core` (>= 1.49, < 2), `zod` (^3.25), and `@mastra/mcp` (>= 1.14, < 2) are peer dependencies: the HOST application owns the Mastra version. `@mastra/mcp` is only needed if you use the MCP surface. `@actuarial-ts/core`, `@actuarial-ts/interchange`, `@actuarial-ts/data`, and `@actuarial-ts/compliance` are regular dependencies, installed for you.
18
-
19
- ## Security model
20
-
21
- 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:
22
-
23
- - `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.
24
- - `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.
25
-
26
- Tools never throw into the model. Anything the tool body throws becomes:
27
-
28
- ```ts
29
- { success: false, error: { code: string, message: string } }
30
- ```
31
-
32
- 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.
33
-
34
- ```ts
35
- import { defineActuarialTool, tenantOf, toolRegistry } from "@actuarial-ts/agents";
36
- import { z } from "zod";
37
-
38
- const getOverview = defineActuarialTool({
39
- id: "get_workspace_overview",
40
- description: "Orient yourself in the workspace",
41
- kind: "read", // or "action" for state-mutating tools
42
- inputSchema: z.object({}),
43
- execute: async (_input, context) => {
44
- const projectId = tenantOf(context);
45
- return { success: true, ...loadOverview(projectId) };
46
- },
47
- });
48
-
49
- const { tools, actionToolIds } = toolRegistry([getOverview /* , ... */]);
50
- // tools -> Record keyed by id, ready for new Agent({ tools })
51
- // actionToolIds -> the host client refreshes after these run
5
+ ```bash
6
+ npm install @actuarial-ts/agents@0.6.1 @actuarial-ts/core@0.6.1 @actuarial-ts/data@0.6.1 @actuarial-ts/interchange@0.6.1 @actuarial-ts/compliance@0.6.1 @mastra/core@^1.51.0 @mastra/mcp@^1.14.0 zod@^3.25.76
52
7
  ```
53
8
 
54
- ## Judgment chains: propose, justify, approve, record
55
-
56
- `createJudgmentChain` turns an ordered list of `JudgmentGateSpec`s into a committed Mastra workflow that pauses at EVERY actuarial judgment:
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`.
57
10
 
58
- 1. **Propose.** The gate gathers evidence through your service layer and suspends with `{ stage, recommendation, evidence }`.
59
- 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).
60
- 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).
11
+ ## Trusted diagnostic selection
61
12
 
62
- 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.
13
+ `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.
63
14
 
64
15
  ```ts
65
- import { createJudgmentChain } from "@actuarial-ts/agents";
66
- import { generateDisclosure } from "@actuarial-ts/compliance";
67
- import { Mastra } from "@mastra/core/mastra";
68
-
69
- const chain = createJudgmentChain({
70
- id: "derive-expected-losses",
71
- gates: [capGate, ilfGate, trendGate, elrGate],
72
- now: () => new Date().toISOString(), // the host owns the clock
73
- onComplete: async ({ trail, ledger }, ctx) => {
74
- persistTrailNote(tenantOf(ctx), trail, ledger);
75
- },
76
- });
77
-
78
- // Register for snapshot storage (suspend/resume state lives there; durable
79
- // storage keeps paused chains resumable across restarts).
80
- const mastra = new Mastra({ workflows: { chain }, storage });
81
-
82
- const run = await mastra.getWorkflow("chain").createRun();
83
- let state = await run.start({ inputData: {}, requestContext }); // suspended at gate 1
84
- state = await run.resume({
85
- step: "cap-gate",
86
- resumeData: { decision: "accept", cap: 150_000, rationale: "volatile large losses distort development" },
87
- requestContext,
16
+ import { createDiagnosticSelectionTool } from "@actuarial-ts/agents";
17
+
18
+ const tool = createDiagnosticSelectionTool({
19
+ definition: compiledDefinition,
20
+ runPresets: [{
21
+ id: "annual-review-v1",
22
+ definitionIntegrity: compiledDefinition.definitionIntegrity,
23
+ allowedInstanceIds: ["casualty/count/reported-frequency"],
24
+ execute: ({ tenantId, instanceIds }) => runApprovedPreset({ tenantId, instanceIds }),
25
+ }],
88
26
  });
89
- // ... resume each gate; the final result is { trail, ledger }
90
27
  ```
91
28
 
92
- ### The ledger fusion
93
-
94
- 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:
29
+ The strict model input contains only:
95
30
 
96
31
  ```ts
97
- const { trail, ledger } = finalResult;
98
- const disclosure = generateDisclosure({
99
- metadata, // EstimateMetadata for the analysis
100
- methods, // MethodUse[]
101
- ledger, // the chain's fused ledger, judgments and rationales included
102
- sdkVersion,
103
- generatedAt: now(),
104
- });
32
+ type DiagnosticAgentToolInput = {
33
+ runPresetId: string;
34
+ instanceIds: string[];
35
+ view: "emergence" | "triangles" | "latest-diagonal";
36
+ };
105
37
  ```
106
38
 
107
- ASOP 41 assumptions-and-judgments documentation as a side effect of running the analysis.
108
-
109
- ### Footgun: workflows are accidental thenables
39
+ 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.
110
40
 
111
- 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.
41
+ 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 } }`.
112
42
 
113
- ## Reserving advisor factory
43
+ 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.
114
44
 
115
- `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.
45
+ ## Tool boundary
116
46
 
117
- 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.
47
+ `defineActuarialTool` enforces two shared rules. First, required tenant identity is resolved from trusted request context before the body runs; the model schema cannot express a project/tenant key. Second, every failure is a recursively readonly `{ success: false, error: { code, message } }` result rather than a thrown model-visible exception.
118
48
 
119
- ```ts
120
- import { createReservingAdvisor, assembleInstructions } from "@actuarial-ts/agents";
121
-
122
- const advisor = createReservingAdvisor({
123
- model: anthropic("claude-sonnet-4-5"),
124
- tools,
125
- memory,
126
- domainInstructions: [ldfSelectionGuide, cappingGuide, tailGuide],
127
- });
128
-
129
- // What is this agent actually running on? Byte-inspect it:
130
- const prompt = assembleInstructions({ domainInstructions: [ldfSelectionGuide, cappingGuide, tailGuide] });
131
- ```
49
+ In 0.6 the public `DefinedActuarialTool<TInput, TOutput>` execute accepts raw `z.input`, parses exactly once, gives the body `z.output`, and returns only the body result or `ToolEnvelopeFailure`. Input/output schemas remain attached through identity-validation metadata bridges whose JSON Schema matches the private real Zod schema, so Mastra cannot run transforms twice. Invalid input is `TOOL_INPUT_INVALID`; malformed/undefined output is `TOOL_OUTPUT_INVALID`. A supplied output schema must accept and preserve the complete failure union or construction throws `BAD_OUTPUT_SCHEMA`. Failure envelopes cannot be rewritten by conditional transforms.
132
50
 
133
- ## Eval harness
51
+ ## Human judgment and remote engines
134
52
 
135
- `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).
53
+ `createJudgmentChain` suspends at declared gates, requires a rationale on resume, records the authenticated actor identity, and writes the compliance assumption ledger. `createReservingAdvisor` assembles a constrained Mastra advisor. `defineRemoteMethod` calls an authenticated interchange sidecar with timeouts, abort support, client-side document validation, and the same tenant/failure seam. Promotion workflows replay and referee imported studies before any selection can enter a workspace.
136
54
 
137
- ```ts
138
- import { runToolSelectionEvals } from "@actuarial-ts/agents";
139
-
140
- const report = await runToolSelectionEvals({
141
- agent: advisor,
142
- requestContext,
143
- cases: [
144
- { id: "cap-evidence", prompt: "Should we cap this book? Check the claim-size evidence first.", expectTools: ["analyze_claim_sizes"] },
145
- { id: "elr-select", prompt: "Select an expected loss ratio of 65%.", expectTools: ["set_elr"] },
146
- ],
147
- timeoutMs: 180_000, // a stalled stream fails the case, not the suite
148
- });
149
- // report.results: per-case { id, pass, called, missing, error? }
150
- // report.summary: { total, passed, failed }
151
- ```
55
+ 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.
152
56
 
153
- 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.
57
+ See the [formula catalog](https://github.com/yerromnitsuj/actng/blob/v0.6.1/docs/reference/diagnostic-formulas.md) and [migration guide](https://github.com/yerromnitsuj/actng/blob/v0.6.1/docs/migrations/0.6-generalized-diagnostics.md).
154
58
 
155
59
  ## License
156
60
 
@@ -0,0 +1,69 @@
1
+ import { type CompiledDiagnosticDefinition, type DiagnosticDeepReadonly } from "@actuarial-ts/core";
2
+ import { type VerifiedDiagnosticRunProvenance } from "@actuarial-ts/compliance";
3
+ import { z } from "zod";
4
+ import { type DefinedActuarialTool, type ToolEnvelopeFailure } from "./tools.js";
5
+ export declare const diagnosticAgentToolInputSchema: z.ZodObject<{
6
+ runPresetId: z.ZodEffects<z.ZodString, string, string>;
7
+ instanceIds: z.ZodType<readonly string[], z.ZodTypeDef, readonly string[]>;
8
+ view: z.ZodEnum<["emergence", "triangles", "latest-diagonal"]>;
9
+ }, "strict", z.ZodTypeAny, {
10
+ runPresetId: string;
11
+ instanceIds: readonly string[];
12
+ view: "emergence" | "triangles" | "latest-diagonal";
13
+ }, {
14
+ runPresetId: string;
15
+ instanceIds: readonly string[];
16
+ view: "emergence" | "triangles" | "latest-diagonal";
17
+ }>;
18
+ export type DiagnosticAgentView = "emergence" | "triangles" | "latest-diagonal";
19
+ export interface DiagnosticAgentToolInput {
20
+ readonly runPresetId: string;
21
+ readonly instanceIds: readonly string[];
22
+ readonly view: DiagnosticAgentView;
23
+ }
24
+ export interface DiagnosticAgentPresetExecutionInput {
25
+ readonly tenantId: string;
26
+ readonly instanceIds: readonly string[];
27
+ }
28
+ export interface DiagnosticAgentRunPreset {
29
+ readonly id: string;
30
+ readonly definitionIntegrity: string;
31
+ readonly allowedInstanceIds: readonly string[];
32
+ readonly execute: (input: DiagnosticAgentPresetExecutionInput) => Promise<VerifiedDiagnosticRunProvenance>;
33
+ }
34
+ export interface CreateDiagnosticSelectionToolInput {
35
+ readonly definition: CompiledDiagnosticDefinition;
36
+ readonly runPresets: readonly DiagnosticAgentRunPreset[];
37
+ readonly id?: string;
38
+ readonly description?: string;
39
+ readonly tenantContextKey?: string;
40
+ }
41
+ export type DiagnosticAgentDisplayProjection = {
42
+ readonly view: "emergence" | "latest-diagonal";
43
+ readonly points: readonly DiagnosticAgentDisplayPoint[];
44
+ } | {
45
+ readonly view: "triangles";
46
+ readonly triangles: VerifiedDiagnosticRunProvenance["result"]["triangles"];
47
+ };
48
+ export type DiagnosticAgentDisplayPoint = Omit<VerifiedDiagnosticRunProvenance["result"]["emergence"][number], "components">;
49
+ export interface DiagnosticAgentToolSuccess {
50
+ readonly success: true;
51
+ readonly data: {
52
+ readonly runPresetId: string;
53
+ readonly instanceIds: readonly string[];
54
+ readonly definitionIntegrity: string;
55
+ readonly formulaFingerprints: Readonly<Record<string, string>>;
56
+ readonly calculationFingerprints: Readonly<Record<string, string>>;
57
+ readonly runFingerprint: string;
58
+ readonly resultFingerprint: string;
59
+ readonly runResultFingerprint: string;
60
+ readonly review: VerifiedDiagnosticRunProvenance["review"];
61
+ readonly display: DiagnosticAgentDisplayProjection;
62
+ };
63
+ }
64
+ export type DiagnosticAgentToolResult = DiagnosticDeepReadonly<DiagnosticAgentToolSuccess> | ToolEnvelopeFailure;
65
+ /** Strict model-visible output schema, including the wrapper's failure branch. */
66
+ export declare const diagnosticAgentToolResultSchema: z.ZodType<DiagnosticAgentToolResult>;
67
+ export type DiagnosticSelectionTool = DefinedActuarialTool<DiagnosticAgentToolInput, DiagnosticAgentToolResult>;
68
+ export declare function createDiagnosticSelectionTool(input: CreateDiagnosticSelectionToolInput): DiagnosticSelectionTool;
69
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"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"}