@loopstack/delegate-error-example-workflow 0.21.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/delegate-error-example.module.d.ts +3 -0
  2. package/dist/delegate-error-example.module.d.ts.map +1 -0
  3. package/dist/delegate-error-example.module.js +28 -0
  4. package/dist/delegate-error-example.module.js.map +1 -0
  5. package/dist/delegate-error.ui.yaml +22 -0
  6. package/dist/delegate-error.workflow.d.ts +27 -0
  7. package/dist/delegate-error.workflow.d.ts.map +1 -0
  8. package/dist/delegate-error.workflow.js +173 -0
  9. package/dist/delegate-error.workflow.js.map +1 -0
  10. package/dist/index.d.ts +3 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +19 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/tools/failing-sub-workflow.tool.d.ts +6 -0
  15. package/dist/tools/failing-sub-workflow.tool.d.ts.map +1 -0
  16. package/dist/tools/failing-sub-workflow.tool.js +40 -0
  17. package/dist/tools/failing-sub-workflow.tool.js.map +1 -0
  18. package/dist/tools/runtime-error.tool.d.ts +7 -0
  19. package/dist/tools/runtime-error.tool.d.ts.map +1 -0
  20. package/dist/tools/runtime-error.tool.js +34 -0
  21. package/dist/tools/runtime-error.tool.js.map +1 -0
  22. package/dist/tools/strict-schema.tool.d.ts +7 -0
  23. package/dist/tools/strict-schema.tool.d.ts.map +1 -0
  24. package/dist/tools/strict-schema.tool.js +32 -0
  25. package/dist/tools/strict-schema.tool.js.map +1 -0
  26. package/dist/workflows/failing.workflow.d.ts +5 -0
  27. package/dist/workflows/failing.workflow.d.ts.map +1 -0
  28. package/dist/workflows/failing.workflow.js +29 -0
  29. package/dist/workflows/failing.workflow.js.map +1 -0
  30. package/package.json +73 -0
  31. package/src/__tests__/delegate-error.workflow.spec.ts +216 -0
  32. package/src/delegate-error-example.module.ts +15 -0
  33. package/src/delegate-error.ui.yaml +22 -0
  34. package/src/delegate-error.workflow.ts +140 -0
  35. package/src/index.ts +2 -0
  36. package/src/tools/failing-sub-workflow.tool.ts +24 -0
  37. package/src/tools/runtime-error.tool.ts +24 -0
  38. package/src/tools/strict-schema.tool.ts +20 -0
  39. package/src/workflows/failing.workflow.ts +13 -0
@@ -0,0 +1,3 @@
1
+ export declare class DelegateErrorExampleModule {
2
+ }
3
+ //# sourceMappingURL=delegate-error-example.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate-error-example.module.d.ts","sourceRoot":"","sources":["../src/delegate-error-example.module.ts"],"names":[],"mappings":"AASA,qBAKa,0BAA0B;CAAG"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.DelegateErrorExampleModule = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ const claude_module_1 = require("@loopstack/claude-module");
12
+ const core_1 = require("@loopstack/core");
13
+ const delegate_error_workflow_1 = require("./delegate-error.workflow");
14
+ const failing_sub_workflow_tool_1 = require("./tools/failing-sub-workflow.tool");
15
+ const runtime_error_tool_1 = require("./tools/runtime-error.tool");
16
+ const strict_schema_tool_1 = require("./tools/strict-schema.tool");
17
+ const failing_workflow_1 = require("./workflows/failing.workflow");
18
+ let DelegateErrorExampleModule = class DelegateErrorExampleModule {
19
+ };
20
+ exports.DelegateErrorExampleModule = DelegateErrorExampleModule;
21
+ exports.DelegateErrorExampleModule = DelegateErrorExampleModule = __decorate([
22
+ (0, common_1.Module)({
23
+ imports: [core_1.LoopCoreModule, claude_module_1.ClaudeModule],
24
+ providers: [strict_schema_tool_1.StrictSchemaTool, runtime_error_tool_1.RuntimeErrorTool, failing_sub_workflow_tool_1.FailingSubWorkflowTool, failing_workflow_1.FailingWorkflow, delegate_error_workflow_1.DelegateErrorWorkflow],
25
+ exports: [delegate_error_workflow_1.DelegateErrorWorkflow],
26
+ })
27
+ ], DelegateErrorExampleModule);
28
+ //# sourceMappingURL=delegate-error-example.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate-error-example.module.js","sourceRoot":"","sources":["../src/delegate-error-example.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,4DAAwD;AACxD,0CAAiD;AACjD,uEAAkE;AAClE,iFAA2E;AAC3E,mEAA8D;AAC9D,mEAA8D;AAC9D,mEAA+D;AAOxD,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;CAAG,CAAA;AAA7B,gEAA0B;qCAA1B,0BAA0B;IALtC,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,qBAAc,EAAE,4BAAY,CAAC;QACvC,SAAS,EAAE,CAAC,qCAAgB,EAAE,qCAAgB,EAAE,kDAAsB,EAAE,kCAAe,EAAE,+CAAqB,CAAC;QAC/G,OAAO,EAAE,CAAC,+CAAqB,CAAC;KACjC,CAAC;GACW,0BAA0B,CAAG"}
@@ -0,0 +1,22 @@
1
+ title: 'Delegate Error Handling Example'
2
+
3
+ description: |
4
+ Demonstrates how tool errors (validation, runtime, and failed sub-workflows)
5
+ are handled by DelegateToolCalls and fed back to the LLM for self-correction.
6
+
7
+ The workflow instructs the LLM to:
8
+ 1. Call strictSchema with wrong args (triggers Zod validation error)
9
+ 2. Observe the error and retry with correct args
10
+ 3. Call runtimeError with shouldFail: true (triggers runtime error)
11
+ 4. Observe the error and retry with shouldFail: false
12
+ 5. Call failingSubWorkflow (launches a sub-workflow that fails)
13
+ 6. Observe the sub-workflow error and summarize
14
+
15
+ ui:
16
+ widgets:
17
+ - widget: button
18
+ showWhen:
19
+ - awaiting_tools
20
+ options:
21
+ transition: cancelPendingTools
22
+ label: Cancel pending tools
@@ -0,0 +1,27 @@
1
+ import { ClaudeGenerateText, ClaudeGenerateTextResult, DelegateToolCalls, DelegateToolCallsResult, UpdateToolResult } from '@loopstack/claude-module';
2
+ import { BaseWorkflow } from '@loopstack/common';
3
+ import { FailingSubWorkflowTool } from './tools/failing-sub-workflow.tool';
4
+ import { RuntimeErrorTool } from './tools/runtime-error.tool';
5
+ import { StrictSchemaTool } from './tools/strict-schema.tool';
6
+ export declare class DelegateErrorWorkflow extends BaseWorkflow {
7
+ claudeGenerateText: ClaudeGenerateText;
8
+ delegateToolCalls: DelegateToolCalls;
9
+ updateToolResult: UpdateToolResult;
10
+ strictSchema: StrictSchemaTool;
11
+ runtimeError: RuntimeErrorTool;
12
+ failingSubWorkflow: FailingSubWorkflowTool;
13
+ llmResult?: ClaudeGenerateTextResult;
14
+ delegateResult?: DelegateToolCallsResult;
15
+ turnCount: number;
16
+ setup(): Promise<void>;
17
+ llmTurn(): Promise<void>;
18
+ executeToolCalls(): Promise<void>;
19
+ toolResultReceived(payload: unknown): Promise<void>;
20
+ toolsComplete(): Promise<void>;
21
+ cancelPendingTools(): Promise<void>;
22
+ respond(): Promise<void>;
23
+ private hasToolCalls;
24
+ private allToolsComplete;
25
+ private isEndTurn;
26
+ }
27
+ //# sourceMappingURL=delegate-error.workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate-error.workflow.d.ts","sourceRoot":"","sources":["../src/delegate-error.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EAExB,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,YAAY,EASb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAU9D,qBAGa,qBAAsB,SAAQ,YAAY;IACvC,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,YAAY,EAAE,gBAAgB,CAAC;IAC/B,kBAAkB,EAAE,sBAAsB,CAAC;IAEzD,SAAS,CAAC,EAAE,wBAAwB,CAAC;IACrC,cAAc,CAAC,EAAE,uBAAuB,CAAC;IACzC,SAAS,EAAG,MAAM,CAAC;IAGb,KAAK;IAoBL,OAAO;IAwBP,gBAAgB;IAUhB,kBAAkB,CAAC,OAAO,EAAE,OAAO;IAWnC,aAAa;IAGb,kBAAkB;IASlB,OAAO;IAIb,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,SAAS;CAGlB"}
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DelegateErrorWorkflow = void 0;
13
+ const claude_module_1 = require("@loopstack/claude-module");
14
+ const common_1 = require("@loopstack/common");
15
+ const failing_sub_workflow_tool_1 = require("./tools/failing-sub-workflow.tool");
16
+ const runtime_error_tool_1 = require("./tools/runtime-error.tool");
17
+ const strict_schema_tool_1 = require("./tools/strict-schema.tool");
18
+ let DelegateErrorWorkflow = class DelegateErrorWorkflow extends common_1.BaseWorkflow {
19
+ claudeGenerateText;
20
+ delegateToolCalls;
21
+ updateToolResult;
22
+ strictSchema;
23
+ runtimeError;
24
+ failingSubWorkflow;
25
+ llmResult;
26
+ delegateResult;
27
+ turnCount;
28
+ async setup() {
29
+ this.turnCount = 0;
30
+ await this.repository.save(common_1.MessageDocument, {
31
+ role: 'assistant',
32
+ content: '# Delegate Error Handling Example\n\n' +
33
+ 'This workflow tests how tool errors are handled and fed back to the LLM.\n\n' +
34
+ 'The LLM will deliberately trigger errors, then self-correct.',
35
+ });
36
+ await this.repository.save(claude_module_1.ClaudeMessageDocument, {
37
+ role: 'user',
38
+ content: 'Follow the instructions in your system prompt exactly. ' +
39
+ 'Start with step 1: call strictSchema with no arguments.',
40
+ });
41
+ }
42
+ async llmTurn() {
43
+ this.turnCount++;
44
+ const result = await this.claudeGenerateText.call({
45
+ system: 'You are a test assistant that follows instructions precisely. ' +
46
+ 'You are fully autonomous — do NOT ask the user for input or confirmation. ' +
47
+ 'Just proceed through each step on your own.\n\n' +
48
+ 'Complete these steps IN ORDER. Do exactly one step per turn:\n\n' +
49
+ '1. Call the `strictSchema` tool with NO arguments (empty object {}). This will fail — that is expected.\n' +
50
+ '2. After seeing the validation error, call `strictSchema` correctly with { "name": "World" }.\n' +
51
+ '3. Call the `runtimeError` tool with { "shouldFail": true }. This will fail — that is expected.\n' +
52
+ '4. After seeing the runtime error, call `runtimeError` with { "shouldFail": false }.\n' +
53
+ '5. Call the `failingSubWorkflow` tool with {}. This launches a sub-workflow that will fail — that is expected.\n' +
54
+ '6. After seeing the sub-workflow error, respond with a brief summary of what happened (do NOT call any tools).\n\n' +
55
+ 'IMPORTANT: Only perform ONE step per turn. Do NOT skip steps. Do NOT wait for user input between steps.',
56
+ claude: { model: 'claude-sonnet-4-6' },
57
+ messagesSearchTag: 'message',
58
+ tools: ['strictSchema', 'runtimeError', 'failingSubWorkflow'],
59
+ });
60
+ this.llmResult = result.data;
61
+ }
62
+ async executeToolCalls() {
63
+ const result = await this.delegateToolCalls.call({
64
+ message: this.llmResult,
65
+ document: claude_module_1.ClaudeMessageDocument,
66
+ callback: { transition: 'toolResultReceived' },
67
+ });
68
+ this.delegateResult = result.data;
69
+ }
70
+ async toolResultReceived(payload) {
71
+ const result = await this.updateToolResult.call({
72
+ delegateResult: this.delegateResult,
73
+ completedTool: payload,
74
+ document: claude_module_1.ClaudeMessageDocument,
75
+ });
76
+ this.delegateResult = result.data;
77
+ }
78
+ async toolsComplete() { }
79
+ async cancelPendingTools() {
80
+ const workflowId = this.ctx.context.workflowId;
81
+ if (workflowId) {
82
+ await this.orchestrator.cancelChildren(workflowId);
83
+ }
84
+ }
85
+ async respond() {
86
+ await this.repository.save(claude_module_1.ClaudeMessageDocument, this.llmResult, { id: this.llmResult.id });
87
+ }
88
+ hasToolCalls() {
89
+ return this.llmResult?.stop_reason === 'tool_use';
90
+ }
91
+ allToolsComplete() {
92
+ return !!this.delegateResult?.allCompleted;
93
+ }
94
+ isEndTurn() {
95
+ return this.llmResult?.stop_reason === 'end_turn';
96
+ }
97
+ };
98
+ exports.DelegateErrorWorkflow = DelegateErrorWorkflow;
99
+ __decorate([
100
+ (0, common_1.InjectTool)(),
101
+ __metadata("design:type", claude_module_1.ClaudeGenerateText)
102
+ ], DelegateErrorWorkflow.prototype, "claudeGenerateText", void 0);
103
+ __decorate([
104
+ (0, common_1.InjectTool)(),
105
+ __metadata("design:type", claude_module_1.DelegateToolCalls)
106
+ ], DelegateErrorWorkflow.prototype, "delegateToolCalls", void 0);
107
+ __decorate([
108
+ (0, common_1.InjectTool)(),
109
+ __metadata("design:type", claude_module_1.UpdateToolResult)
110
+ ], DelegateErrorWorkflow.prototype, "updateToolResult", void 0);
111
+ __decorate([
112
+ (0, common_1.InjectTool)(),
113
+ __metadata("design:type", strict_schema_tool_1.StrictSchemaTool)
114
+ ], DelegateErrorWorkflow.prototype, "strictSchema", void 0);
115
+ __decorate([
116
+ (0, common_1.InjectTool)(),
117
+ __metadata("design:type", runtime_error_tool_1.RuntimeErrorTool)
118
+ ], DelegateErrorWorkflow.prototype, "runtimeError", void 0);
119
+ __decorate([
120
+ (0, common_1.InjectTool)(),
121
+ __metadata("design:type", failing_sub_workflow_tool_1.FailingSubWorkflowTool)
122
+ ], DelegateErrorWorkflow.prototype, "failingSubWorkflow", void 0);
123
+ __decorate([
124
+ (0, common_1.Initial)({ to: 'ready' }),
125
+ __metadata("design:type", Function),
126
+ __metadata("design:paramtypes", []),
127
+ __metadata("design:returntype", Promise)
128
+ ], DelegateErrorWorkflow.prototype, "setup", null);
129
+ __decorate([
130
+ (0, common_1.Transition)({ from: 'ready', to: 'prompt_executed' }),
131
+ __metadata("design:type", Function),
132
+ __metadata("design:paramtypes", []),
133
+ __metadata("design:returntype", Promise)
134
+ ], DelegateErrorWorkflow.prototype, "llmTurn", null);
135
+ __decorate([
136
+ (0, common_1.Transition)({ from: 'prompt_executed', to: 'awaiting_tools', priority: 10 }),
137
+ (0, common_1.Guard)('hasToolCalls'),
138
+ __metadata("design:type", Function),
139
+ __metadata("design:paramtypes", []),
140
+ __metadata("design:returntype", Promise)
141
+ ], DelegateErrorWorkflow.prototype, "executeToolCalls", null);
142
+ __decorate([
143
+ (0, common_1.Transition)({ from: 'awaiting_tools', to: 'awaiting_tools', wait: true }),
144
+ __metadata("design:type", Function),
145
+ __metadata("design:paramtypes", [Object]),
146
+ __metadata("design:returntype", Promise)
147
+ ], DelegateErrorWorkflow.prototype, "toolResultReceived", null);
148
+ __decorate([
149
+ (0, common_1.Transition)({ from: 'awaiting_tools', to: 'ready' }),
150
+ (0, common_1.Guard)('allToolsComplete'),
151
+ __metadata("design:type", Function),
152
+ __metadata("design:paramtypes", []),
153
+ __metadata("design:returntype", Promise)
154
+ ], DelegateErrorWorkflow.prototype, "toolsComplete", null);
155
+ __decorate([
156
+ (0, common_1.Transition)({ from: 'awaiting_tools', to: 'ready', wait: true }),
157
+ __metadata("design:type", Function),
158
+ __metadata("design:paramtypes", []),
159
+ __metadata("design:returntype", Promise)
160
+ ], DelegateErrorWorkflow.prototype, "cancelPendingTools", null);
161
+ __decorate([
162
+ (0, common_1.Final)({ from: 'prompt_executed' }),
163
+ (0, common_1.Guard)('isEndTurn'),
164
+ __metadata("design:type", Function),
165
+ __metadata("design:paramtypes", []),
166
+ __metadata("design:returntype", Promise)
167
+ ], DelegateErrorWorkflow.prototype, "respond", null);
168
+ exports.DelegateErrorWorkflow = DelegateErrorWorkflow = __decorate([
169
+ (0, common_1.Workflow)({
170
+ uiConfig: __dirname + '/delegate-error.ui.yaml',
171
+ })
172
+ ], DelegateErrorWorkflow);
173
+ //# sourceMappingURL=delegate-error.workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate-error.workflow.js","sourceRoot":"","sources":["../src/delegate-error.workflow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './delegate-error-example.module';
2
+ export * from './delegate-error.workflow';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,2BAA2B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./delegate-error-example.module"), exports);
18
+ __exportStar(require("./delegate-error.workflow"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kEAAgD;AAChD,4DAA0C"}
@@ -0,0 +1,6 @@
1
+ import { BaseTool, ToolCallOptions, ToolResult } from '@loopstack/common';
2
+ export declare class FailingSubWorkflowTool extends BaseTool {
3
+ private failingWorkflow;
4
+ call(_args: object, options?: ToolCallOptions): Promise<ToolResult>;
5
+ }
6
+ //# sourceMappingURL=failing-sub-workflow.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failing-sub-workflow.tool.d.ts","sourceRoot":"","sources":["../../src/tools/failing-sub-workflow.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAwB,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGhG,qBAQa,sBAAuB,SAAQ,QAAQ;IAChC,OAAO,CAAC,eAAe,CAAkB;IAErD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;CAQ1E"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.FailingSubWorkflowTool = void 0;
13
+ const zod_1 = require("zod");
14
+ const common_1 = require("@loopstack/common");
15
+ const failing_workflow_1 = require("../workflows/failing.workflow");
16
+ let FailingSubWorkflowTool = class FailingSubWorkflowTool extends common_1.BaseTool {
17
+ failingWorkflow;
18
+ async call(_args, options) {
19
+ const result = await this.failingWorkflow.run({}, { alias: 'failingWorkflow', callback: options?.callback });
20
+ return {
21
+ data: { workflowId: result.workflowId },
22
+ pending: { workflowId: result.workflowId },
23
+ };
24
+ }
25
+ };
26
+ exports.FailingSubWorkflowTool = FailingSubWorkflowTool;
27
+ __decorate([
28
+ (0, common_1.InjectWorkflow)(),
29
+ __metadata("design:type", failing_workflow_1.FailingWorkflow)
30
+ ], FailingSubWorkflowTool.prototype, "failingWorkflow", void 0);
31
+ exports.FailingSubWorkflowTool = FailingSubWorkflowTool = __decorate([
32
+ (0, common_1.Tool)({
33
+ uiConfig: {
34
+ description: 'Launch an async sub-workflow that always fails. ' +
35
+ 'Used to test that failed sub-workflow errors propagate back to the parent.',
36
+ },
37
+ schema: zod_1.z.object({}),
38
+ })
39
+ ], FailingSubWorkflowTool);
40
+ //# sourceMappingURL=failing-sub-workflow.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failing-sub-workflow.tool.js","sourceRoot":"","sources":["../../src/tools/failing-sub-workflow.tool.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6BAAwB;AACxB,8CAAgG;AAChG,oEAAgE;AAUzD,IAAM,sBAAsB,GAA5B,MAAM,sBAAuB,SAAQ,iBAAQ;IACxB,eAAe,CAAkB;IAE3D,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,OAAyB;QACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QAE7G,OAAO;YACL,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE;YACvC,OAAO,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE;SAC3C,CAAC;IACJ,CAAC;CACF,CAAA;AAXY,wDAAsB;AACP;IAAzB,IAAA,uBAAc,GAAE;8BAA0B,kCAAe;+DAAC;iCADhD,sBAAsB;IARlC,IAAA,aAAI,EAAC;QACJ,QAAQ,EAAE;YACR,WAAW,EACT,kDAAkD;gBAClD,4EAA4E;SAC/E;QACD,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC;KACrB,CAAC;GACW,sBAAsB,CAWlC"}
@@ -0,0 +1,7 @@
1
+ import { BaseTool, ToolResult } from '@loopstack/common';
2
+ export declare class RuntimeErrorTool extends BaseTool {
3
+ call(args: {
4
+ shouldFail: boolean;
5
+ }): Promise<ToolResult>;
6
+ }
7
+ //# sourceMappingURL=runtime-error.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-error.tool.d.ts","sourceRoot":"","sources":["../../src/tools/runtime-error.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAQ,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/D,qBAUa,gBAAiB,SAAQ,QAAQ;IAC5C,IAAI,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;CASzD"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.RuntimeErrorTool = void 0;
10
+ const zod_1 = require("zod");
11
+ const common_1 = require("@loopstack/common");
12
+ let RuntimeErrorTool = class RuntimeErrorTool extends common_1.BaseTool {
13
+ call(args) {
14
+ if (args.shouldFail) {
15
+ throw new Error('Simulated runtime error: external service unavailable.');
16
+ }
17
+ return Promise.resolve({
18
+ data: 'Action completed successfully.',
19
+ });
20
+ }
21
+ };
22
+ exports.RuntimeErrorTool = RuntimeErrorTool;
23
+ exports.RuntimeErrorTool = RuntimeErrorTool = __decorate([
24
+ (0, common_1.Tool)({
25
+ uiConfig: {
26
+ description: 'Perform an action that may fail at runtime. ' +
27
+ 'Pass shouldFail: true to simulate a runtime error, or false to succeed.',
28
+ },
29
+ schema: zod_1.z.object({
30
+ shouldFail: zod_1.z.boolean().describe('Whether the tool should simulate a runtime failure.'),
31
+ }),
32
+ })
33
+ ], RuntimeErrorTool);
34
+ //# sourceMappingURL=runtime-error.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-error.tool.js","sourceRoot":"","sources":["../../src/tools/runtime-error.tool.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6BAAwB;AACxB,8CAA+D;AAYxD,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,iBAAQ;IAC5C,IAAI,CAAC,IAA6B;QAChC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC5E,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,gCAAgC;SACvC,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAVY,4CAAgB;2BAAhB,gBAAgB;IAV5B,IAAA,aAAI,EAAC;QACJ,QAAQ,EAAE;YACR,WAAW,EACT,8CAA8C;gBAC9C,yEAAyE;SAC5E;QACD,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,UAAU,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;SACxF,CAAC;KACH,CAAC;GACW,gBAAgB,CAU5B"}
@@ -0,0 +1,7 @@
1
+ import { BaseTool, ToolResult } from '@loopstack/common';
2
+ export declare class StrictSchemaTool extends BaseTool {
3
+ call(args: {
4
+ name: string;
5
+ }): Promise<ToolResult>;
6
+ }
7
+ //# sourceMappingURL=strict-schema.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strict-schema.tool.d.ts","sourceRoot":"","sources":["../../src/tools/strict-schema.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAQ,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/D,qBAUa,gBAAiB,SAAQ,QAAQ;IAC5C,IAAI,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;CAKlD"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.StrictSchemaTool = void 0;
10
+ const zod_1 = require("zod");
11
+ const common_1 = require("@loopstack/common");
12
+ let StrictSchemaTool = class StrictSchemaTool extends common_1.BaseTool {
13
+ call(args) {
14
+ return Promise.resolve({
15
+ data: `Hello, ${args.name}! Nice to meet you.`,
16
+ });
17
+ }
18
+ };
19
+ exports.StrictSchemaTool = StrictSchemaTool;
20
+ exports.StrictSchemaTool = StrictSchemaTool = __decorate([
21
+ (0, common_1.Tool)({
22
+ uiConfig: {
23
+ description: 'Greet a person by name. Requires a name argument. ' + 'Returns a greeting message.',
24
+ },
25
+ schema: zod_1.z
26
+ .object({
27
+ name: zod_1.z.string().describe('The name of the person to greet.'),
28
+ })
29
+ .strict(),
30
+ })
31
+ ], StrictSchemaTool);
32
+ //# sourceMappingURL=strict-schema.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strict-schema.tool.js","sourceRoot":"","sources":["../../src/tools/strict-schema.tool.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6BAAwB;AACxB,8CAA+D;AAYxD,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,iBAAQ;IAC5C,IAAI,CAAC,IAAsB;QACzB,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,UAAU,IAAI,CAAC,IAAI,qBAAqB;SAC/C,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AANY,4CAAgB;2BAAhB,gBAAgB;IAV5B,IAAA,aAAI,EAAC;QACJ,QAAQ,EAAE;YACR,WAAW,EAAE,oDAAoD,GAAG,6BAA6B;SAClG;QACD,MAAM,EAAE,OAAC;aACN,MAAM,CAAC;YACN,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;SAC9D,CAAC;aACD,MAAM,EAAE;KACZ,CAAC;GACW,gBAAgB,CAM5B"}
@@ -0,0 +1,5 @@
1
+ import { BaseWorkflow } from '@loopstack/common';
2
+ export declare class FailingWorkflow extends BaseWorkflow {
3
+ start(): Promise<unknown>;
4
+ }
5
+ //# sourceMappingURL=failing.workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failing.workflow.d.ts","sourceRoot":"","sources":["../../src/workflows/failing.workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqB,MAAM,mBAAmB,CAAC;AAMpE,qBACa,eAAgB,SAAQ,YAAY;IAE/C,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;CAG1B"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.FailingWorkflow = void 0;
13
+ const common_1 = require("@loopstack/common");
14
+ let FailingWorkflow = class FailingWorkflow extends common_1.BaseWorkflow {
15
+ start() {
16
+ return Promise.reject(new Error('Simulated sub-workflow failure.'));
17
+ }
18
+ };
19
+ exports.FailingWorkflow = FailingWorkflow;
20
+ __decorate([
21
+ (0, common_1.Initial)({ to: 'done' }),
22
+ __metadata("design:type", Function),
23
+ __metadata("design:paramtypes", []),
24
+ __metadata("design:returntype", Promise)
25
+ ], FailingWorkflow.prototype, "start", null);
26
+ exports.FailingWorkflow = FailingWorkflow = __decorate([
27
+ (0, common_1.Workflow)({})
28
+ ], FailingWorkflow);
29
+ //# sourceMappingURL=failing.workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failing.workflow.js","sourceRoot":"","sources":["../../src/workflows/failing.workflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAAoE;AAO7D,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,qBAAY;IAE/C,KAAK;QACH,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;IACtE,CAAC;CACF,CAAA;AALY,0CAAe;AAE1B;IADC,IAAA,gBAAO,EAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;;;;4CAGvB;0BAJU,eAAe;IAD3B,IAAA,iBAAQ,EAAC,EAAE,CAAC;GACA,eAAe,CAK3B"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@loopstack/delegate-error-example-workflow",
3
+ "displayName": "Loopstack Delegate Error Example Workflow",
4
+ "description": "A workflow demonstrating how tool validation errors and runtime errors are handled by DelegateToolCalls and fed back to the LLM.",
5
+ "keywords": [
6
+ "error",
7
+ "delegate",
8
+ "tool calling",
9
+ "example",
10
+ "workflow"
11
+ ],
12
+ "version": "0.21.6",
13
+ "license": "MIT",
14
+ "author": {
15
+ "name": "Jakob Klippel",
16
+ "url": "https://www.linkedin.com/in/jakob-klippel/"
17
+ },
18
+ "main": "dist/index.js",
19
+ "types": "dist/index.d.ts",
20
+ "exports": {
21
+ ".": "./dist/index.js",
22
+ "./src/*": "./src/*"
23
+ },
24
+ "scripts": {
25
+ "build": "nest build",
26
+ "compile": "tsc --noEmit",
27
+ "format": "prettier --write .",
28
+ "lint": "eslint .",
29
+ "test": "jest --passWithNoTests",
30
+ "watch": "nest build --watch"
31
+ },
32
+ "dependencies": {
33
+ "@loopstack/claude-module": "^0.22.5",
34
+ "@loopstack/common": "^0.28.0",
35
+ "@loopstack/core": "^0.28.0",
36
+ "@nestjs/common": "^11.1.19",
37
+ "zod": "^4.3.6"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "src"
42
+ ],
43
+ "jest": {
44
+ "testEnvironment": "node",
45
+ "rootDir": "src",
46
+ "testRegex": ".*\\.spec\\.ts$",
47
+ "transform": {
48
+ "^.+\\.ts$": "ts-jest"
49
+ },
50
+ "testTimeout": 10000,
51
+ "forceExit": true,
52
+ "maxWorkers": 1
53
+ },
54
+ "loopstack": {
55
+ "modules": [
56
+ {
57
+ "path": "src/delegate-error-example.module.ts",
58
+ "className": "DelegateErrorExampleModule"
59
+ }
60
+ ],
61
+ "workflows": [
62
+ {
63
+ "path": "src/delegate-error.workflow.ts",
64
+ "className": "DelegateErrorWorkflow",
65
+ "propertyName": "delegateError"
66
+ }
67
+ ],
68
+ "installModes": [
69
+ "add",
70
+ "install"
71
+ ]
72
+ }
73
+ }
@@ -0,0 +1,216 @@
1
+ import { TestingModule } from '@nestjs/testing';
2
+ import { ClaudeGenerateText, ClaudeModule } from '@loopstack/claude-module';
3
+ import { LoopCoreModule, WorkflowProcessorService } from '@loopstack/core';
4
+ import { ToolMock, createStatelessContext, createWorkflowTest } from '@loopstack/testing';
5
+ import { DelegateErrorWorkflow } from '../delegate-error.workflow';
6
+ import { FailingSubWorkflowTool } from '../tools/failing-sub-workflow.tool';
7
+ import { RuntimeErrorTool } from '../tools/runtime-error.tool';
8
+ import { StrictSchemaTool } from '../tools/strict-schema.tool';
9
+ import { FailingWorkflow } from '../workflows/failing.workflow';
10
+
11
+ /**
12
+ * Helper to create a mock LLM response with a single tool_use block.
13
+ */
14
+ function mockToolUseResponse(toolName: string, input: Record<string, unknown>, toolUseId = 'toolu_test_1') {
15
+ return {
16
+ data: {
17
+ id: 'msg_test',
18
+ role: 'assistant',
19
+ stop_reason: 'tool_use',
20
+ content: [
21
+ { type: 'text', text: `Calling ${toolName}...` },
22
+ { type: 'tool_use', id: toolUseId, name: toolName, input },
23
+ ],
24
+ },
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Helper to create a mock LLM response with end_turn (no tool calls).
30
+ */
31
+ function mockEndTurnResponse(text: string) {
32
+ return {
33
+ data: {
34
+ id: 'msg_final',
35
+ role: 'assistant',
36
+ stop_reason: 'end_turn',
37
+ content: [{ type: 'text', text }],
38
+ },
39
+ };
40
+ }
41
+
42
+ describe('DelegateErrorWorkflow', () => {
43
+ let module: TestingModule;
44
+ let workflow: DelegateErrorWorkflow;
45
+ let processor: WorkflowProcessorService;
46
+ let mockClaude: ToolMock;
47
+
48
+ beforeEach(async () => {
49
+ module = await createWorkflowTest()
50
+ .forWorkflow(DelegateErrorWorkflow)
51
+ .withImports(LoopCoreModule, ClaudeModule)
52
+ .withToolOverride(ClaudeGenerateText)
53
+ // Real tools — we want to test actual validation and runtime errors
54
+ .withProviders(StrictSchemaTool, RuntimeErrorTool, FailingSubWorkflowTool, FailingWorkflow)
55
+ .compile();
56
+
57
+ workflow = module.get(DelegateErrorWorkflow);
58
+ processor = module.get(WorkflowProcessorService);
59
+ mockClaude = module.get(ClaudeGenerateText);
60
+ });
61
+
62
+ afterEach(async () => {
63
+ await module.close();
64
+ });
65
+
66
+ it('should be defined', () => {
67
+ expect(workflow).toBeDefined();
68
+ });
69
+
70
+ describe('validation error (bad schema args)', () => {
71
+ it('should capture validation error as is_error tool result and loop back to ready', async () => {
72
+ // LLM calls strictSchema with empty args — Zod validation will fail
73
+ mockClaude.call
74
+ .mockResolvedValueOnce(mockToolUseResponse('strictSchema', {}))
75
+ .mockResolvedValueOnce(mockEndTurnResponse('Done.'));
76
+
77
+ const context = createStatelessContext();
78
+ const result = await processor.process(workflow, {}, context);
79
+
80
+ expect(result.hasError).toBe(false);
81
+ expect(result.place).toBe('end');
82
+
83
+ // ClaudeGenerateText should have been called twice:
84
+ // 1st: LLM returns bad tool call → error fed back → loops to ready
85
+ // 2nd: LLM sees the error and responds with end_turn
86
+ expect(mockClaude.call).toHaveBeenCalledTimes(2);
87
+
88
+ // Should have tool result documents with is_error
89
+ const toolResultDocs = result.documents.filter((d) =>
90
+ d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
91
+ );
92
+ expect(toolResultDocs.length).toBeGreaterThan(0);
93
+ });
94
+ });
95
+
96
+ describe('runtime error (tool throws)', () => {
97
+ it('should capture runtime error as is_error tool result and loop back to ready', async () => {
98
+ // LLM calls runtimeError with shouldFail: true — tool will throw
99
+ mockClaude.call
100
+ .mockResolvedValueOnce(mockToolUseResponse('runtimeError', { shouldFail: true }))
101
+ .mockResolvedValueOnce(mockEndTurnResponse('Done.'));
102
+
103
+ const context = createStatelessContext();
104
+ const result = await processor.process(workflow, {}, context);
105
+
106
+ expect(result.hasError).toBe(false);
107
+ expect(result.place).toBe('end');
108
+ expect(mockClaude.call).toHaveBeenCalledTimes(2);
109
+
110
+ const toolResultDocs = result.documents.filter((d) =>
111
+ d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
112
+ );
113
+ expect(toolResultDocs.length).toBeGreaterThan(0);
114
+ });
115
+ });
116
+
117
+ describe('successful tool call', () => {
118
+ it('should process successful tool call without errors', async () => {
119
+ // LLM calls strictSchema with valid args
120
+ mockClaude.call
121
+ .mockResolvedValueOnce(mockToolUseResponse('strictSchema', { name: 'World' }))
122
+ .mockResolvedValueOnce(mockEndTurnResponse('Done.'));
123
+
124
+ const context = createStatelessContext();
125
+ const result = await processor.process(workflow, {}, context);
126
+
127
+ expect(result.hasError).toBe(false);
128
+ expect(result.place).toBe('end');
129
+ expect(mockClaude.call).toHaveBeenCalledTimes(2);
130
+
131
+ // No error tool results
132
+ const errorToolResults = result.documents.filter((d) =>
133
+ d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
134
+ );
135
+ expect(errorToolResults).toHaveLength(0);
136
+ });
137
+ });
138
+
139
+ describe('error metadata in tool result documents', () => {
140
+ it('should include validation error message in is_error tool result', async () => {
141
+ mockClaude.call
142
+ .mockResolvedValueOnce(mockToolUseResponse('strictSchema', {}))
143
+ .mockResolvedValueOnce(mockEndTurnResponse('Done.'));
144
+
145
+ const context = createStatelessContext();
146
+ const result = await processor.process(workflow, {}, context);
147
+
148
+ expect(result.hasError).toBe(false);
149
+
150
+ const toolResultDocs = result.documents.filter((d) =>
151
+ d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
152
+ );
153
+ expect(toolResultDocs.length).toBeGreaterThan(0);
154
+
155
+ const errorResult = toolResultDocs[0].content.toolResults.find((tr: { is_error?: boolean }) => tr.is_error);
156
+ expect(errorResult.content).toBeDefined();
157
+ // Zod v4 error message for missing required string field
158
+ expect(errorResult.content).toContain('invalid_type');
159
+ });
160
+
161
+ it('should include runtime error message in is_error tool result', async () => {
162
+ mockClaude.call
163
+ .mockResolvedValueOnce(mockToolUseResponse('runtimeError', { shouldFail: true }))
164
+ .mockResolvedValueOnce(mockEndTurnResponse('Done.'));
165
+
166
+ const context = createStatelessContext();
167
+ const result = await processor.process(workflow, {}, context);
168
+
169
+ expect(result.hasError).toBe(false);
170
+
171
+ const toolResultDocs = result.documents.filter((d) =>
172
+ d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
173
+ );
174
+ expect(toolResultDocs.length).toBeGreaterThan(0);
175
+
176
+ const errorResult = toolResultDocs[0].content.toolResults.find((tr: { is_error?: boolean }) => tr.is_error);
177
+ expect(errorResult.content).toContain('external service unavailable');
178
+ });
179
+ });
180
+
181
+ describe('validation and runtime errors produce identical structure', () => {
182
+ it('should produce the same is_error tool result shape for both error types', async () => {
183
+ // Run validation error
184
+ mockClaude.call.mockResolvedValueOnce(mockToolUseResponse('strictSchema', {}));
185
+ const context1 = createStatelessContext();
186
+ const result1 = await processor.process(workflow, {}, context1);
187
+
188
+ const validationErrorDoc = result1.documents.find((d) =>
189
+ d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
190
+ );
191
+ const validationError = validationErrorDoc?.content.toolResults.find((tr: { is_error?: boolean }) => tr.is_error);
192
+
193
+ // Run runtime error (fresh module needed for clean state)
194
+ mockClaude.call.mockResolvedValueOnce(mockToolUseResponse('runtimeError', { shouldFail: true }));
195
+ const context2 = createStatelessContext();
196
+ const result2 = await processor.process(workflow, {}, context2);
197
+
198
+ const runtimeErrorDoc = result2.documents.find((d) =>
199
+ d.content?.toolResults?.some((tr: { is_error?: boolean }) => tr.is_error),
200
+ );
201
+ const runtimeError = runtimeErrorDoc?.content.toolResults.find((tr: { is_error?: boolean }) => tr.is_error);
202
+
203
+ // Both should have the same structure
204
+ expect(validationError).toBeDefined();
205
+ expect(runtimeError).toBeDefined();
206
+ expect(validationError.type).toBe('tool_result');
207
+ expect(runtimeError.type).toBe('tool_result');
208
+ expect(validationError.is_error).toBe(true);
209
+ expect(runtimeError.is_error).toBe(true);
210
+ expect(typeof validationError.content).toBe('string');
211
+ expect(typeof runtimeError.content).toBe('string');
212
+ expect(typeof validationError.tool_use_id).toBe('string');
213
+ expect(typeof runtimeError.tool_use_id).toBe('string');
214
+ });
215
+ });
216
+ });
@@ -0,0 +1,15 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { ClaudeModule } from '@loopstack/claude-module';
3
+ import { LoopCoreModule } from '@loopstack/core';
4
+ import { DelegateErrorWorkflow } from './delegate-error.workflow';
5
+ import { FailingSubWorkflowTool } from './tools/failing-sub-workflow.tool';
6
+ import { RuntimeErrorTool } from './tools/runtime-error.tool';
7
+ import { StrictSchemaTool } from './tools/strict-schema.tool';
8
+ import { FailingWorkflow } from './workflows/failing.workflow';
9
+
10
+ @Module({
11
+ imports: [LoopCoreModule, ClaudeModule],
12
+ providers: [StrictSchemaTool, RuntimeErrorTool, FailingSubWorkflowTool, FailingWorkflow, DelegateErrorWorkflow],
13
+ exports: [DelegateErrorWorkflow],
14
+ })
15
+ export class DelegateErrorExampleModule {}
@@ -0,0 +1,22 @@
1
+ title: 'Delegate Error Handling Example'
2
+
3
+ description: |
4
+ Demonstrates how tool errors (validation, runtime, and failed sub-workflows)
5
+ are handled by DelegateToolCalls and fed back to the LLM for self-correction.
6
+
7
+ The workflow instructs the LLM to:
8
+ 1. Call strictSchema with wrong args (triggers Zod validation error)
9
+ 2. Observe the error and retry with correct args
10
+ 3. Call runtimeError with shouldFail: true (triggers runtime error)
11
+ 4. Observe the error and retry with shouldFail: false
12
+ 5. Call failingSubWorkflow (launches a sub-workflow that fails)
13
+ 6. Observe the sub-workflow error and summarize
14
+
15
+ ui:
16
+ widgets:
17
+ - widget: button
18
+ showWhen:
19
+ - awaiting_tools
20
+ options:
21
+ transition: cancelPendingTools
22
+ label: Cancel pending tools
@@ -0,0 +1,140 @@
1
+ import {
2
+ ClaudeGenerateText,
3
+ ClaudeGenerateTextResult,
4
+ ClaudeMessageDocument,
5
+ DelegateToolCalls,
6
+ DelegateToolCallsResult,
7
+ UpdateToolResult,
8
+ } from '@loopstack/claude-module';
9
+ import {
10
+ BaseWorkflow,
11
+ Final,
12
+ Guard,
13
+ Initial,
14
+ InjectTool,
15
+ MessageDocument,
16
+ ToolResult,
17
+ Transition,
18
+ Workflow,
19
+ } from '@loopstack/common';
20
+ import { FailingSubWorkflowTool } from './tools/failing-sub-workflow.tool';
21
+ import { RuntimeErrorTool } from './tools/runtime-error.tool';
22
+ import { StrictSchemaTool } from './tools/strict-schema.tool';
23
+
24
+ /**
25
+ * Demonstrates how tool errors (validation, runtime, and failed sub-workflows)
26
+ * are handled by DelegateToolCalls and fed back to the LLM for self-correction.
27
+ *
28
+ * The LLM is instructed to deliberately trigger errors first, then correct them.
29
+ * This verifies that all error types produce identical is_error tool results
30
+ * and that the LLM agent loop handles them correctly.
31
+ */
32
+ @Workflow({
33
+ uiConfig: __dirname + '/delegate-error.ui.yaml',
34
+ })
35
+ export class DelegateErrorWorkflow extends BaseWorkflow {
36
+ @InjectTool() claudeGenerateText: ClaudeGenerateText;
37
+ @InjectTool() delegateToolCalls: DelegateToolCalls;
38
+ @InjectTool() updateToolResult: UpdateToolResult;
39
+ @InjectTool() strictSchema: StrictSchemaTool;
40
+ @InjectTool() runtimeError: RuntimeErrorTool;
41
+ @InjectTool() failingSubWorkflow: FailingSubWorkflowTool;
42
+
43
+ llmResult?: ClaudeGenerateTextResult;
44
+ delegateResult?: DelegateToolCallsResult;
45
+ turnCount!: number;
46
+
47
+ @Initial({ to: 'ready' })
48
+ async setup() {
49
+ this.turnCount = 0;
50
+
51
+ await this.repository.save(MessageDocument, {
52
+ role: 'assistant',
53
+ content:
54
+ '# Delegate Error Handling Example\n\n' +
55
+ 'This workflow tests how tool errors are handled and fed back to the LLM.\n\n' +
56
+ 'The LLM will deliberately trigger errors, then self-correct.',
57
+ });
58
+
59
+ await this.repository.save(ClaudeMessageDocument, {
60
+ role: 'user',
61
+ content:
62
+ 'Follow the instructions in your system prompt exactly. ' +
63
+ 'Start with step 1: call strictSchema with no arguments.',
64
+ });
65
+ }
66
+
67
+ @Transition({ from: 'ready', to: 'prompt_executed' })
68
+ async llmTurn() {
69
+ this.turnCount++;
70
+ const result: ToolResult<ClaudeGenerateTextResult> = await this.claudeGenerateText.call({
71
+ system:
72
+ 'You are a test assistant that follows instructions precisely. ' +
73
+ 'You are fully autonomous — do NOT ask the user for input or confirmation. ' +
74
+ 'Just proceed through each step on your own.\n\n' +
75
+ 'Complete these steps IN ORDER. Do exactly one step per turn:\n\n' +
76
+ '1. Call the `strictSchema` tool with NO arguments (empty object {}). This will fail — that is expected.\n' +
77
+ '2. After seeing the validation error, call `strictSchema` correctly with { "name": "World" }.\n' +
78
+ '3. Call the `runtimeError` tool with { "shouldFail": true }. This will fail — that is expected.\n' +
79
+ '4. After seeing the runtime error, call `runtimeError` with { "shouldFail": false }.\n' +
80
+ '5. Call the `failingSubWorkflow` tool with {}. This launches a sub-workflow that will fail — that is expected.\n' +
81
+ '6. After seeing the sub-workflow error, respond with a brief summary of what happened (do NOT call any tools).\n\n' +
82
+ 'IMPORTANT: Only perform ONE step per turn. Do NOT skip steps. Do NOT wait for user input between steps.',
83
+ claude: { model: 'claude-sonnet-4-6' },
84
+ messagesSearchTag: 'message',
85
+ tools: ['strictSchema', 'runtimeError', 'failingSubWorkflow'],
86
+ });
87
+ this.llmResult = result.data;
88
+ }
89
+
90
+ @Transition({ from: 'prompt_executed', to: 'awaiting_tools', priority: 10 })
91
+ @Guard('hasToolCalls')
92
+ async executeToolCalls() {
93
+ const result: ToolResult<DelegateToolCallsResult> = await this.delegateToolCalls.call({
94
+ message: this.llmResult!,
95
+ document: ClaudeMessageDocument,
96
+ callback: { transition: 'toolResultReceived' },
97
+ });
98
+ this.delegateResult = result.data;
99
+ }
100
+
101
+ @Transition({ from: 'awaiting_tools', to: 'awaiting_tools', wait: true })
102
+ async toolResultReceived(payload: unknown) {
103
+ const result = await this.updateToolResult.call({
104
+ delegateResult: this.delegateResult!,
105
+ completedTool: payload,
106
+ document: ClaudeMessageDocument,
107
+ });
108
+ this.delegateResult = result.data as DelegateToolCallsResult;
109
+ }
110
+
111
+ @Transition({ from: 'awaiting_tools', to: 'ready' })
112
+ @Guard('allToolsComplete')
113
+ async toolsComplete() {}
114
+
115
+ @Transition({ from: 'awaiting_tools', to: 'ready', wait: true })
116
+ async cancelPendingTools() {
117
+ const workflowId = this.ctx.context.workflowId;
118
+ if (workflowId) {
119
+ await this.orchestrator.cancelChildren(workflowId);
120
+ }
121
+ }
122
+
123
+ @Final({ from: 'prompt_executed' })
124
+ @Guard('isEndTurn')
125
+ async respond() {
126
+ await this.repository.save(ClaudeMessageDocument, this.llmResult!, { id: this.llmResult!.id });
127
+ }
128
+
129
+ private hasToolCalls(): boolean {
130
+ return this.llmResult?.stop_reason === 'tool_use';
131
+ }
132
+
133
+ private allToolsComplete(): boolean {
134
+ return !!this.delegateResult?.allCompleted;
135
+ }
136
+
137
+ private isEndTurn(): boolean {
138
+ return this.llmResult?.stop_reason === 'end_turn';
139
+ }
140
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './delegate-error-example.module';
2
+ export * from './delegate-error.workflow';
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod';
2
+ import { BaseTool, InjectWorkflow, Tool, ToolCallOptions, ToolResult } from '@loopstack/common';
3
+ import { FailingWorkflow } from '../workflows/failing.workflow';
4
+
5
+ @Tool({
6
+ uiConfig: {
7
+ description:
8
+ 'Launch an async sub-workflow that always fails. ' +
9
+ 'Used to test that failed sub-workflow errors propagate back to the parent.',
10
+ },
11
+ schema: z.object({}),
12
+ })
13
+ export class FailingSubWorkflowTool extends BaseTool {
14
+ @InjectWorkflow() private failingWorkflow: FailingWorkflow;
15
+
16
+ async call(_args: object, options?: ToolCallOptions): Promise<ToolResult> {
17
+ const result = await this.failingWorkflow.run({}, { alias: 'failingWorkflow', callback: options?.callback });
18
+
19
+ return {
20
+ data: { workflowId: result.workflowId },
21
+ pending: { workflowId: result.workflowId },
22
+ };
23
+ }
24
+ }
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod';
2
+ import { BaseTool, Tool, ToolResult } from '@loopstack/common';
3
+
4
+ @Tool({
5
+ uiConfig: {
6
+ description:
7
+ 'Perform an action that may fail at runtime. ' +
8
+ 'Pass shouldFail: true to simulate a runtime error, or false to succeed.',
9
+ },
10
+ schema: z.object({
11
+ shouldFail: z.boolean().describe('Whether the tool should simulate a runtime failure.'),
12
+ }),
13
+ })
14
+ export class RuntimeErrorTool extends BaseTool {
15
+ call(args: { shouldFail: boolean }): Promise<ToolResult> {
16
+ if (args.shouldFail) {
17
+ throw new Error('Simulated runtime error: external service unavailable.');
18
+ }
19
+
20
+ return Promise.resolve({
21
+ data: 'Action completed successfully.',
22
+ });
23
+ }
24
+ }
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import { BaseTool, Tool, ToolResult } from '@loopstack/common';
3
+
4
+ @Tool({
5
+ uiConfig: {
6
+ description: 'Greet a person by name. Requires a name argument. ' + 'Returns a greeting message.',
7
+ },
8
+ schema: z
9
+ .object({
10
+ name: z.string().describe('The name of the person to greet.'),
11
+ })
12
+ .strict(),
13
+ })
14
+ export class StrictSchemaTool extends BaseTool {
15
+ call(args: { name: string }): Promise<ToolResult> {
16
+ return Promise.resolve({
17
+ data: `Hello, ${args.name}! Nice to meet you.`,
18
+ });
19
+ }
20
+ }
@@ -0,0 +1,13 @@
1
+ import { BaseWorkflow, Initial, Workflow } from '@loopstack/common';
2
+
3
+ /**
4
+ * A minimal sub-workflow that always fails on its initial transition.
5
+ * Used to verify that failed sub-workflow callbacks propagate errors to the parent.
6
+ */
7
+ @Workflow({})
8
+ export class FailingWorkflow extends BaseWorkflow {
9
+ @Initial({ to: 'done' })
10
+ start(): Promise<unknown> {
11
+ return Promise.reject(new Error('Simulated sub-workflow failure.'));
12
+ }
13
+ }