@strands-agents/sdk 1.3.0 → 1.4.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.
Files changed (174) hide show
  1. package/README.md +13 -13
  2. package/dist/src/__fixtures__/test-sandbox.node.d.ts +15 -0
  3. package/dist/src/__fixtures__/test-sandbox.node.d.ts.map +1 -0
  4. package/dist/src/__fixtures__/test-sandbox.node.js +22 -0
  5. package/dist/src/__fixtures__/test-sandbox.node.js.map +1 -0
  6. package/dist/src/__tests__/mcp.test.js +14 -14
  7. package/dist/src/__tests__/mcp.test.js.map +1 -1
  8. package/dist/src/agent/__tests__/agent.test.js +195 -0
  9. package/dist/src/agent/__tests__/agent.test.js.map +1 -1
  10. package/dist/src/agent/__tests__/tool-caller.test.d.ts +2 -0
  11. package/dist/src/agent/__tests__/tool-caller.test.d.ts.map +1 -0
  12. package/dist/src/agent/__tests__/tool-caller.test.js +459 -0
  13. package/dist/src/agent/__tests__/tool-caller.test.js.map +1 -0
  14. package/dist/src/agent/agent.d.ts +62 -2
  15. package/dist/src/agent/agent.d.ts.map +1 -1
  16. package/dist/src/agent/agent.js +122 -66
  17. package/dist/src/agent/agent.js.map +1 -1
  18. package/dist/src/agent/tool-caller.d.ts +149 -0
  19. package/dist/src/agent/tool-caller.d.ts.map +1 -0
  20. package/dist/src/agent/tool-caller.js +198 -0
  21. package/dist/src/agent/tool-caller.js.map +1 -0
  22. package/dist/src/errors.d.ts +17 -0
  23. package/dist/src/errors.d.ts.map +1 -1
  24. package/dist/src/errors.js +21 -0
  25. package/dist/src/errors.js.map +1 -1
  26. package/dist/src/index.d.ts +8 -3
  27. package/dist/src/index.d.ts.map +1 -1
  28. package/dist/src/index.js +4 -1
  29. package/dist/src/index.js.map +1 -1
  30. package/dist/src/interventions/handler.d.ts +1 -2
  31. package/dist/src/interventions/handler.d.ts.map +1 -1
  32. package/dist/src/interventions/registry.d.ts +2 -0
  33. package/dist/src/interventions/registry.d.ts.map +1 -1
  34. package/dist/src/interventions/registry.js +4 -0
  35. package/dist/src/interventions/registry.js.map +1 -1
  36. package/dist/src/mcp.d.ts +20 -15
  37. package/dist/src/mcp.d.ts.map +1 -1
  38. package/dist/src/mcp.js +15 -8
  39. package/dist/src/mcp.js.map +1 -1
  40. package/dist/src/models/__tests__/anthropic.test.js +21 -6
  41. package/dist/src/models/__tests__/anthropic.test.js.map +1 -1
  42. package/dist/src/models/__tests__/bedrock.test.js +142 -0
  43. package/dist/src/models/__tests__/bedrock.test.js.map +1 -1
  44. package/dist/src/models/anthropic.d.ts.map +1 -1
  45. package/dist/src/models/anthropic.js +5 -2
  46. package/dist/src/models/anthropic.js.map +1 -1
  47. package/dist/src/models/bedrock.d.ts +26 -1
  48. package/dist/src/models/bedrock.d.ts.map +1 -1
  49. package/dist/src/models/bedrock.js +22 -4
  50. package/dist/src/models/bedrock.js.map +1 -1
  51. package/dist/src/models/openai/__tests__/chat.test.js +2 -10
  52. package/dist/src/models/openai/__tests__/chat.test.js.map +1 -1
  53. package/dist/src/models/openai/__tests__/errors.test.d.ts +2 -0
  54. package/dist/src/models/openai/__tests__/errors.test.d.ts.map +1 -0
  55. package/dist/src/models/openai/__tests__/errors.test.js +30 -0
  56. package/dist/src/models/openai/__tests__/errors.test.js.map +1 -0
  57. package/dist/src/models/openai/__tests__/responses.test.js +0 -19
  58. package/dist/src/models/openai/__tests__/responses.test.js.map +1 -1
  59. package/dist/src/models/openai/errors.d.ts.map +1 -1
  60. package/dist/src/models/openai/errors.js +5 -3
  61. package/dist/src/models/openai/errors.js.map +1 -1
  62. package/dist/src/multiagent/__tests__/nodes.test.js +50 -0
  63. package/dist/src/multiagent/__tests__/nodes.test.js.map +1 -1
  64. package/dist/src/multiagent/nodes.d.ts +23 -2
  65. package/dist/src/multiagent/nodes.d.ts.map +1 -1
  66. package/dist/src/multiagent/nodes.js +18 -4
  67. package/dist/src/multiagent/nodes.js.map +1 -1
  68. package/dist/src/registry/__tests__/tool-registry.test.js +50 -1
  69. package/dist/src/registry/__tests__/tool-registry.test.js.map +1 -1
  70. package/dist/src/registry/tool-registry.d.ts +13 -0
  71. package/dist/src/registry/tool-registry.d.ts.map +1 -1
  72. package/dist/src/registry/tool-registry.js +35 -1
  73. package/dist/src/registry/tool-registry.js.map +1 -1
  74. package/dist/src/sandbox/__tests__/posix-shell.test.node.d.ts +2 -0
  75. package/dist/src/sandbox/__tests__/posix-shell.test.node.d.ts.map +1 -0
  76. package/dist/src/sandbox/__tests__/posix-shell.test.node.js +252 -0
  77. package/dist/src/sandbox/__tests__/posix-shell.test.node.js.map +1 -0
  78. package/dist/src/sandbox/base.d.ts +138 -0
  79. package/dist/src/sandbox/base.d.ts.map +1 -0
  80. package/dist/src/sandbox/base.js +84 -0
  81. package/dist/src/sandbox/base.js.map +1 -0
  82. package/dist/src/sandbox/constants.d.ts +7 -0
  83. package/dist/src/sandbox/constants.d.ts.map +1 -0
  84. package/dist/src/sandbox/constants.js +7 -0
  85. package/dist/src/sandbox/constants.js.map +1 -0
  86. package/dist/src/sandbox/posix-shell.d.ts +32 -0
  87. package/dist/src/sandbox/posix-shell.d.ts.map +1 -0
  88. package/dist/src/sandbox/posix-shell.js +78 -0
  89. package/dist/src/sandbox/posix-shell.js.map +1 -0
  90. package/dist/src/sandbox/stream-process.d.ts +32 -0
  91. package/dist/src/sandbox/stream-process.d.ts.map +1 -0
  92. package/dist/src/sandbox/stream-process.js +160 -0
  93. package/dist/src/sandbox/stream-process.js.map +1 -0
  94. package/dist/src/sandbox/types.d.ts +57 -0
  95. package/dist/src/sandbox/types.d.ts.map +1 -0
  96. package/dist/src/sandbox/types.js +8 -0
  97. package/dist/src/sandbox/types.js.map +1 -0
  98. package/dist/src/telemetry/__tests__/meter.test.js +11 -0
  99. package/dist/src/telemetry/__tests__/meter.test.js.map +1 -1
  100. package/dist/src/telemetry/meter.d.ts +10 -6
  101. package/dist/src/telemetry/meter.d.ts.map +1 -1
  102. package/dist/src/telemetry/meter.js +16 -3
  103. package/dist/src/telemetry/meter.js.map +1 -1
  104. package/dist/src/tsconfig.tsbuildinfo +1 -1
  105. package/dist/src/types/__tests__/messages.test.js +28 -0
  106. package/dist/src/types/__tests__/messages.test.js.map +1 -1
  107. package/dist/src/types/agent.d.ts +51 -0
  108. package/dist/src/types/agent.d.ts.map +1 -1
  109. package/dist/src/types/agent.js.map +1 -1
  110. package/dist/src/types/lifecycle-observer.d.ts +18 -0
  111. package/dist/src/types/lifecycle-observer.d.ts.map +1 -0
  112. package/dist/src/types/lifecycle-observer.js +2 -0
  113. package/dist/src/types/lifecycle-observer.js.map +1 -0
  114. package/dist/src/types/messages.d.ts +18 -2
  115. package/dist/src/types/messages.d.ts.map +1 -1
  116. package/dist/src/types/messages.js +9 -0
  117. package/dist/src/types/messages.js.map +1 -1
  118. package/dist/src/utils/shell-quote.d.ts +12 -0
  119. package/dist/src/utils/shell-quote.d.ts.map +1 -0
  120. package/dist/src/utils/shell-quote.js +14 -0
  121. package/dist/src/utils/shell-quote.js.map +1 -0
  122. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.d.ts +2 -0
  123. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.d.ts.map +1 -0
  124. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.js +358 -0
  125. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.js.map +1 -0
  126. package/dist/src/vended-interventions/hitl/hitl.d.ts +115 -0
  127. package/dist/src/vended-interventions/hitl/hitl.d.ts.map +1 -0
  128. package/dist/src/vended-interventions/hitl/hitl.js +138 -0
  129. package/dist/src/vended-interventions/hitl/hitl.js.map +1 -0
  130. package/dist/src/vended-interventions/hitl/index.d.ts +24 -0
  131. package/dist/src/vended-interventions/hitl/index.d.ts.map +1 -0
  132. package/dist/src/vended-interventions/hitl/index.js +23 -0
  133. package/dist/src/vended-interventions/hitl/index.js.map +1 -0
  134. package/dist/src/vended-interventions/steering/__tests__/handler.test.d.ts +2 -0
  135. package/dist/src/vended-interventions/steering/__tests__/handler.test.d.ts.map +1 -0
  136. package/dist/src/vended-interventions/steering/__tests__/handler.test.js +163 -0
  137. package/dist/src/vended-interventions/steering/__tests__/handler.test.js.map +1 -0
  138. package/dist/src/vended-interventions/steering/__tests__/llm.test.d.ts +2 -0
  139. package/dist/src/vended-interventions/steering/__tests__/llm.test.d.ts.map +1 -0
  140. package/dist/src/vended-interventions/steering/__tests__/llm.test.js +60 -0
  141. package/dist/src/vended-interventions/steering/__tests__/llm.test.js.map +1 -0
  142. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.d.ts +2 -0
  143. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.d.ts.map +1 -0
  144. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.js +94 -0
  145. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.js.map +1 -0
  146. package/dist/src/vended-interventions/steering/handlers/handler.d.ts +64 -0
  147. package/dist/src/vended-interventions/steering/handlers/handler.d.ts.map +1 -0
  148. package/dist/src/vended-interventions/steering/handlers/handler.js +71 -0
  149. package/dist/src/vended-interventions/steering/handlers/handler.js.map +1 -0
  150. package/dist/src/vended-interventions/steering/handlers/llm.d.ts +72 -0
  151. package/dist/src/vended-interventions/steering/handlers/llm.d.ts.map +1 -0
  152. package/dist/src/vended-interventions/steering/handlers/llm.js +177 -0
  153. package/dist/src/vended-interventions/steering/handlers/llm.js.map +1 -0
  154. package/dist/src/vended-interventions/steering/index.d.ts +31 -0
  155. package/dist/src/vended-interventions/steering/index.d.ts.map +1 -0
  156. package/dist/src/vended-interventions/steering/index.js +32 -0
  157. package/dist/src/vended-interventions/steering/index.js.map +1 -0
  158. package/dist/src/vended-interventions/steering/providers/context-provider.d.ts +55 -0
  159. package/dist/src/vended-interventions/steering/providers/context-provider.d.ts.map +1 -0
  160. package/dist/src/vended-interventions/steering/providers/context-provider.js +8 -0
  161. package/dist/src/vended-interventions/steering/providers/context-provider.js.map +1 -0
  162. package/dist/src/vended-interventions/steering/providers/tool-ledger.d.ts +49 -0
  163. package/dist/src/vended-interventions/steering/providers/tool-ledger.d.ts.map +1 -0
  164. package/dist/src/vended-interventions/steering/providers/tool-ledger.js +75 -0
  165. package/dist/src/vended-interventions/steering/providers/tool-ledger.js.map +1 -0
  166. package/dist/src/vended-plugins/index.d.ts +11 -0
  167. package/dist/src/vended-plugins/index.d.ts.map +1 -0
  168. package/dist/src/vended-plugins/index.js +11 -0
  169. package/dist/src/vended-plugins/index.js.map +1 -0
  170. package/dist/src/vended-tools/index.d.ts +17 -0
  171. package/dist/src/vended-tools/index.d.ts.map +1 -0
  172. package/dist/src/vended-tools/index.js +17 -0
  173. package/dist/src/vended-tools/index.js.map +1 -0
  174. package/package.json +31 -15
@@ -0,0 +1,358 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { HumanInTheLoop } from '../hitl.js';
3
+ import { Agent } from '../../../agent/agent.js';
4
+ import { MockMessageModel } from '../../../__fixtures__/mock-message-model.js';
5
+ import { createMockTool } from '../../../__fixtures__/tool-helpers.js';
6
+ describe('HumanInTheLoop', () => {
7
+ describe('default config (interrupt/resume)', () => {
8
+ it('pauses agent with interrupt on any tool call', async () => {
9
+ const model = new MockMessageModel()
10
+ .addTurn({ type: 'toolUseBlock', name: 'anyTool', toolUseId: 'tool-1', input: { x: 1 } })
11
+ .addTurn({ type: 'textBlock', text: 'Done' });
12
+ let toolExecuted = false;
13
+ const tool = createMockTool('anyTool', () => {
14
+ toolExecuted = true;
15
+ return 'result';
16
+ });
17
+ const agent = new Agent({
18
+ model,
19
+ tools: [tool],
20
+ interventions: [new HumanInTheLoop()],
21
+ printer: false,
22
+ });
23
+ const result = await agent.invoke('Do something');
24
+ expect(result.stopReason).toBe('interrupt');
25
+ expect(result.interrupts).toEqual([
26
+ expect.objectContaining({
27
+ name: 'strands:human-in-the-loop',
28
+ reason: expect.stringContaining('anyTool'),
29
+ }),
30
+ ]);
31
+ expect(toolExecuted).toBe(false);
32
+ });
33
+ });
34
+ describe('inline mode (with ask callback)', () => {
35
+ it('allows tool execution when approved', async () => {
36
+ const model = new MockMessageModel()
37
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-1', input: {} })
38
+ .addTurn({ type: 'textBlock', text: 'Done' });
39
+ let toolExecuted = false;
40
+ const tool = createMockTool('myTool', () => {
41
+ toolExecuted = true;
42
+ return 'executed';
43
+ });
44
+ const agent = new Agent({
45
+ model,
46
+ tools: [tool],
47
+ interventions: [new HumanInTheLoop({ ask: async () => 'yes' })],
48
+ printer: false,
49
+ });
50
+ const result = await agent.invoke('Run tool');
51
+ expect(result.stopReason).toBe('endTurn');
52
+ expect(toolExecuted).toBe(true);
53
+ });
54
+ it('denies tool execution when rejected', async () => {
55
+ const model = new MockMessageModel()
56
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-1', input: {} })
57
+ .addTurn({ type: 'textBlock', text: 'Understood' });
58
+ let toolExecuted = false;
59
+ const tool = createMockTool('myTool', () => {
60
+ toolExecuted = true;
61
+ return 'executed';
62
+ });
63
+ const agent = new Agent({
64
+ model,
65
+ tools: [tool],
66
+ interventions: [new HumanInTheLoop({ ask: async () => 'no' })],
67
+ printer: false,
68
+ });
69
+ const result = await agent.invoke('Run tool');
70
+ expect(result.stopReason).toBe('endTurn');
71
+ expect(toolExecuted).toBe(false);
72
+ });
73
+ });
74
+ describe('allowedTools config', () => {
75
+ it('does not prompt for tools in allowedTools', async () => {
76
+ const model = new MockMessageModel()
77
+ .addTurn({ type: 'toolUseBlock', name: 'readFile', toolUseId: 'tool-1', input: {} })
78
+ .addTurn({ type: 'textBlock', text: 'Done' });
79
+ let toolExecuted = false;
80
+ const tool = createMockTool('readFile', () => {
81
+ toolExecuted = true;
82
+ return 'content';
83
+ });
84
+ const agent = new Agent({
85
+ model,
86
+ tools: [tool],
87
+ interventions: [new HumanInTheLoop({ allowedTools: ['readFile'], ask: async () => 'no' })],
88
+ printer: false,
89
+ });
90
+ const result = await agent.invoke('Read it');
91
+ expect(result.stopReason).toBe('endTurn');
92
+ expect(toolExecuted).toBe(true);
93
+ });
94
+ it('prompts for tools not in allowedTools', async () => {
95
+ const model = new MockMessageModel()
96
+ .addTurn({ type: 'toolUseBlock', name: 'deleteFile', toolUseId: 'tool-1', input: {} })
97
+ .addTurn({ type: 'textBlock', text: 'Done' });
98
+ let toolExecuted = false;
99
+ const tool = createMockTool('deleteFile', () => {
100
+ toolExecuted = true;
101
+ return 'deleted';
102
+ });
103
+ const agent = new Agent({
104
+ model,
105
+ tools: [tool],
106
+ interventions: [new HumanInTheLoop({ allowedTools: ['readFile'], ask: async () => 'no' })],
107
+ printer: false,
108
+ });
109
+ await agent.invoke('Delete it');
110
+ expect(toolExecuted).toBe(false);
111
+ });
112
+ it('allows all tools except negated ones with "!" prefix', async () => {
113
+ const model = new MockMessageModel()
114
+ .addTurn([
115
+ { type: 'toolUseBlock', name: 'readFile', toolUseId: 'tool-1', input: {} },
116
+ { type: 'toolUseBlock', name: 'deleteFile', toolUseId: 'tool-2', input: {} },
117
+ ])
118
+ .addTurn({ type: 'textBlock', text: 'Done' });
119
+ const execLog = [];
120
+ const readTool = createMockTool('readFile', () => {
121
+ execLog.push('read');
122
+ return 'content';
123
+ });
124
+ const deleteTool = createMockTool('deleteFile', () => {
125
+ execLog.push('delete');
126
+ return 'deleted';
127
+ });
128
+ const agent = new Agent({
129
+ model,
130
+ tools: [readTool, deleteTool],
131
+ interventions: [new HumanInTheLoop({ allowedTools: ['*', '!deleteFile'], ask: async () => 'no' })],
132
+ printer: false,
133
+ });
134
+ await agent.invoke('Do both');
135
+ expect(execLog).toContain('read');
136
+ expect(execLog).not.toContain('delete');
137
+ });
138
+ it('allows all tools with wildcard "*"', async () => {
139
+ const model = new MockMessageModel()
140
+ .addTurn({ type: 'toolUseBlock', name: 'dangerousTool', toolUseId: 'tool-1', input: {} })
141
+ .addTurn({ type: 'textBlock', text: 'Done' });
142
+ let toolExecuted = false;
143
+ const tool = createMockTool('dangerousTool', () => {
144
+ toolExecuted = true;
145
+ return 'ran';
146
+ });
147
+ const agent = new Agent({
148
+ model,
149
+ tools: [tool],
150
+ interventions: [new HumanInTheLoop({ allowedTools: ['*'], ask: async () => 'no' })],
151
+ printer: false,
152
+ });
153
+ const result = await agent.invoke('Do it');
154
+ expect(result.stopReason).toBe('endTurn');
155
+ expect(toolExecuted).toBe(true);
156
+ });
157
+ });
158
+ describe('ask callback', () => {
159
+ it('passes tool name and input in the prompt', async () => {
160
+ const prompts = [];
161
+ const model = new MockMessageModel()
162
+ .addTurn({ type: 'toolUseBlock', name: 'sendEmail', toolUseId: 'tool-1', input: { to: 'bob@example.com' } })
163
+ .addTurn({ type: 'textBlock', text: 'Done' });
164
+ const tool = createMockTool('sendEmail', () => 'sent');
165
+ const agent = new Agent({
166
+ model,
167
+ tools: [tool],
168
+ interventions: [
169
+ new HumanInTheLoop({
170
+ ask: async (prompt) => {
171
+ prompts.push(prompt);
172
+ return 'yes';
173
+ },
174
+ }),
175
+ ],
176
+ printer: false,
177
+ });
178
+ await agent.invoke('Send email');
179
+ expect(prompts[0]).toContain('sendEmail');
180
+ expect(prompts[0]).toContain('bob@example.com');
181
+ });
182
+ it('supports custom evaluate function', async () => {
183
+ const model = new MockMessageModel()
184
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-1', input: {} })
185
+ .addTurn({ type: 'textBlock', text: 'Done' });
186
+ let toolExecuted = false;
187
+ const tool = createMockTool('myTool', () => {
188
+ toolExecuted = true;
189
+ return 'executed';
190
+ });
191
+ const agent = new Agent({
192
+ model,
193
+ tools: [tool],
194
+ interventions: [
195
+ new HumanInTheLoop({
196
+ ask: async () => 'magic-word',
197
+ evaluate: (response) => response === 'magic-word',
198
+ }),
199
+ ],
200
+ printer: false,
201
+ });
202
+ const result = await agent.invoke('Go');
203
+ expect(result.stopReason).toBe('endTurn');
204
+ expect(toolExecuted).toBe(true);
205
+ });
206
+ });
207
+ describe('trust mode (enableTrust: true)', () => {
208
+ it('trusts a tool for the session when response is "t"', async () => {
209
+ let askCount = 0;
210
+ const model = new MockMessageModel()
211
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-1', input: {} })
212
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-2', input: {} })
213
+ .addTurn({ type: 'textBlock', text: 'Done' });
214
+ const tool = createMockTool('myTool', () => 'executed');
215
+ const agent = new Agent({
216
+ model,
217
+ tools: [tool],
218
+ interventions: [
219
+ new HumanInTheLoop({
220
+ enableTrust: true,
221
+ ask: async () => {
222
+ askCount++;
223
+ return 't';
224
+ },
225
+ }),
226
+ ],
227
+ printer: false,
228
+ });
229
+ await agent.invoke('Run tool twice');
230
+ expect(askCount).toBe(1);
231
+ });
232
+ it('does not trust when enableTrust is false even with "t" response', async () => {
233
+ let askCount = 0;
234
+ const model = new MockMessageModel()
235
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-1', input: {} })
236
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-2', input: {} })
237
+ .addTurn({ type: 'textBlock', text: 'Done' });
238
+ const tool = createMockTool('myTool', () => 'executed');
239
+ const agent = new Agent({
240
+ model,
241
+ tools: [tool],
242
+ interventions: [
243
+ new HumanInTheLoop({
244
+ enableTrust: false,
245
+ ask: async () => {
246
+ askCount++;
247
+ return 't';
248
+ },
249
+ }),
250
+ ],
251
+ printer: false,
252
+ });
253
+ await agent.invoke('Run tool twice');
254
+ // 't' is not recognized as approval when trust is disabled, so tool is denied both times
255
+ // but ask is still called both times (no trust memory)
256
+ expect(askCount).toBe(2);
257
+ });
258
+ it('"t" response also approves the current tool call', async () => {
259
+ const model = new MockMessageModel()
260
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-1', input: {} })
261
+ .addTurn({ type: 'textBlock', text: 'Done' });
262
+ let toolExecuted = false;
263
+ const tool = createMockTool('myTool', () => {
264
+ toolExecuted = true;
265
+ return 'executed';
266
+ });
267
+ const agent = new Agent({
268
+ model,
269
+ tools: [tool],
270
+ interventions: [new HumanInTheLoop({ enableTrust: true, ask: async () => 't' })],
271
+ printer: false,
272
+ });
273
+ const result = await agent.invoke('Run tool');
274
+ expect(result.stopReason).toBe('endTurn');
275
+ expect(toolExecuted).toBe(true);
276
+ });
277
+ it.each(['trust', 'T', 'TRUST'])('trusts when response is "%s"', async (trustResponse) => {
278
+ let askCount = 0;
279
+ const model = new MockMessageModel()
280
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-1', input: {} })
281
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-2', input: {} })
282
+ .addTurn({ type: 'textBlock', text: 'Done' });
283
+ const tool = createMockTool('myTool', () => 'executed');
284
+ const agent = new Agent({
285
+ model,
286
+ tools: [tool],
287
+ interventions: [
288
+ new HumanInTheLoop({
289
+ enableTrust: true,
290
+ ask: async () => {
291
+ askCount++;
292
+ return trustResponse;
293
+ },
294
+ }),
295
+ ],
296
+ printer: false,
297
+ });
298
+ await agent.invoke('Run tool twice');
299
+ expect(askCount).toBe(1);
300
+ });
301
+ it('supports custom evaluateTrust function', async () => {
302
+ let askCount = 0;
303
+ const model = new MockMessageModel()
304
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-1', input: {} })
305
+ .addTurn({ type: 'toolUseBlock', name: 'myTool', toolUseId: 'tool-2', input: {} })
306
+ .addTurn({ type: 'textBlock', text: 'Done' });
307
+ const tool = createMockTool('myTool', () => 'executed');
308
+ const agent = new Agent({
309
+ model,
310
+ tools: [tool],
311
+ interventions: [
312
+ new HumanInTheLoop({
313
+ enableTrust: true,
314
+ evaluateTrust: (r) => r === 'approve-and-remember',
315
+ ask: async () => {
316
+ askCount++;
317
+ return 'approve-and-remember';
318
+ },
319
+ }),
320
+ ],
321
+ printer: false,
322
+ });
323
+ await agent.invoke('Run tool twice');
324
+ expect(askCount).toBe(1);
325
+ });
326
+ it('negated tools cannot be trusted even with "t" response', async () => {
327
+ let askCount = 0;
328
+ let toolExecuted = false;
329
+ const model = new MockMessageModel()
330
+ .addTurn({ type: 'toolUseBlock', name: 'dangerTool', toolUseId: 'tool-1', input: {} })
331
+ .addTurn({ type: 'toolUseBlock', name: 'dangerTool', toolUseId: 'tool-2', input: {} })
332
+ .addTurn({ type: 'textBlock', text: 'Done' });
333
+ const tool = createMockTool('dangerTool', () => {
334
+ toolExecuted = true;
335
+ return 'ran';
336
+ });
337
+ const agent = new Agent({
338
+ model,
339
+ tools: [tool],
340
+ interventions: [
341
+ new HumanInTheLoop({
342
+ allowedTools: ['*', '!dangerTool'],
343
+ enableTrust: true,
344
+ ask: async () => {
345
+ askCount++;
346
+ return 't';
347
+ },
348
+ }),
349
+ ],
350
+ printer: false,
351
+ });
352
+ await agent.invoke('Run danger twice');
353
+ expect(askCount).toBe(2);
354
+ expect(toolExecuted).toBe(false);
355
+ });
356
+ });
357
+ });
358
+ //# sourceMappingURL=hitl.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hitl.test.js","sourceRoot":"","sources":["../../../../../src/vended-interventions/hitl/__tests__/hitl.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import { InterventionHandler } from '../../interventions/handler.js';
2
+ import type { InterventionAction } from '../../interventions/actions.js';
3
+ import type { BeforeToolCallEvent } from '../../hooks/events.js';
4
+ import type { JSONValue } from '../../types/json.js';
5
+ /**
6
+ * Configuration for the {@link HumanInTheLoop} intervention handler.
7
+ */
8
+ export interface HumanInTheLoopConfig {
9
+ /**
10
+ * Tools that can execute WITHOUT human approval. All other tools require approval.
11
+ *
12
+ * - Use `'*'` to allow all tools.
13
+ * - Prefix with `!` to exclude specific tools from `'*'` (they still require approval).
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Only readFile and listDir run freely; everything else needs approval
18
+ * { allowedTools: ['readFile', 'listDir'] }
19
+ *
20
+ * // All tools run freely (HITL disabled)
21
+ * { allowedTools: ['*'] }
22
+ *
23
+ * // All tools run freely EXCEPT deleteFile and sendEmail
24
+ * { allowedTools: ['*', '!deleteFile', '!sendEmail'] }
25
+ * ```
26
+ */
27
+ allowedTools?: string[];
28
+ /**
29
+ * When true, trust responses approve the tool AND remember it
30
+ * in `agent.appState` for the rest of the session (won't ask again).
31
+ * Works in both interrupt/resume and inline `ask` modes.
32
+ *
33
+ * Negated tools (`!tool`) cannot be trusted.
34
+ *
35
+ * Defaults to `false`.
36
+ */
37
+ enableTrust?: boolean;
38
+ /**
39
+ * Custom trust response validator. Defaults to accepting `'t'`/`'trust'` (case-insensitive).
40
+ * When this returns true, the tool is approved AND trusted for the session.
41
+ *
42
+ * Only evaluated when `enableTrust` is true.
43
+ */
44
+ evaluateTrust?: (response: JSONValue) => boolean;
45
+ /**
46
+ * Custom approval response validator. Defaults to accepting `true`, `'y'`/`'yes'` (case-insensitive).
47
+ */
48
+ evaluate?: (response: JSONValue) => boolean;
49
+ /**
50
+ * Controls how the human's response is collected.
51
+ *
52
+ * - **Default** (omitted): uses interrupt/resume — agent pauses, caller resumes with response.
53
+ * - **`'stdio'`**: prompts via CLI readline (Node.js only). Agent blocks inline until human responds.
54
+ * - **Custom function**: your own async prompt logic (Slack, web UI, etc.). Agent blocks inline.
55
+ */
56
+ ask?: ((prompt: string) => Promise<JSONValue>) | 'stdio';
57
+ }
58
+ /**
59
+ * Human-in-the-loop intervention handler that pauses agent execution
60
+ * before tool calls to request human approval.
61
+ *
62
+ * By default, ALL tools require approval and the agent pauses via interrupt/resume.
63
+ * Use `allowedTools` to whitelist tools that run freely, and `ask` to provide
64
+ * inline prompting (CLI, custom UI).
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * import { Agent } from '@strands-agents/sdk'
69
+ * import { HumanInTheLoop } from '@strands-agents/sdk/vended-interventions/hitl'
70
+ *
71
+ * // All tools require approval, agent pauses via interrupt (default)
72
+ * const agent = new Agent({
73
+ * interventions: [new HumanInTheLoop()],
74
+ * })
75
+ *
76
+ * // readFile runs freely, everything else pauses for approval
77
+ * const agent = new Agent({
78
+ * interventions: [new HumanInTheLoop({ allowedTools: ['readFile'] })],
79
+ * })
80
+ *
81
+ * // CLI mode — prompts in terminal inline
82
+ * const agent = new Agent({
83
+ * interventions: [new HumanInTheLoop({ ask: 'stdio' })],
84
+ * })
85
+ *
86
+ * // Custom UI — provide your own prompt function
87
+ * const agent = new Agent({
88
+ * interventions: [new HumanInTheLoop({
89
+ * ask: async (prompt) => await slackDM(userId, prompt),
90
+ * })],
91
+ * })
92
+ * ```
93
+ */
94
+ export declare class HumanInTheLoop extends InterventionHandler {
95
+ readonly name = "strands:human-in-the-loop";
96
+ private readonly _allowedTools;
97
+ private readonly _enableTrust;
98
+ private readonly _evaluateTrust;
99
+ private readonly _evaluate;
100
+ private readonly _ask;
101
+ constructor(config?: HumanInTheLoopConfig);
102
+ beforeToolCall(event: BeforeToolCallEvent): Promise<InterventionAction>;
103
+ /**
104
+ * Precedence (first match wins):
105
+ * 1. Negated (`!tool`) → always requires approval (cannot be trusted)
106
+ * 2. Trusted at runtime via 't' response (stored in agent.appState) → runs freely
107
+ * 3. Wildcard (`*`) → runs freely
108
+ * 4. Explicitly listed → runs freely
109
+ * 5. Default → requires approval
110
+ */
111
+ private _requiresApproval;
112
+ private _trustTool;
113
+ private _isTrustResponse;
114
+ }
115
+ //# sourceMappingURL=hitl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hitl.d.ts","sourceRoot":"","sources":["../../../../src/vended-interventions/hitl/hitl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AAEpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AA6BpD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IAEvB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,OAAO,CAAA;IAEhD;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,OAAO,CAAA;IAE3C;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC,GAAG,OAAO,CAAA;CACzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,cAAe,SAAQ,mBAAmB;IACrD,QAAQ,CAAC,IAAI,+BAA8B;IAE3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAa;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAkC;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgD;IAC1E,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsD;gBAE/D,MAAM,CAAC,EAAE,oBAAoB;IAS1B,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAmCtF;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,gBAAgB;CAIzB"}
@@ -0,0 +1,138 @@
1
+ import { InterventionHandler } from '../../interventions/handler.js';
2
+ import { confirm, proceed, defaultEvaluate } from '../../interventions/actions.js';
3
+ const TRUST_RESPONSES = new Set(['t', 'trust']);
4
+ const TRUSTED_TOOLS_KEY = 'hitl:trustedTools';
5
+ /**
6
+ * CLI prompt that reads from stdin.
7
+ * Serializes prompts so concurrent tool calls don't collide on stdin.
8
+ */
9
+ function createStdioAsk(includeTrust) {
10
+ const options = includeTrust ? '(y/n/t)' : '(y/n)';
11
+ let queue = Promise.resolve();
12
+ return (prompt) => {
13
+ const task = queue.then(async () => {
14
+ const { createInterface } = await import('node:readline');
15
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
16
+ return new Promise((resolve) => {
17
+ rl.question(`${prompt} ${options}: `, (answer) => {
18
+ rl.close();
19
+ resolve(answer.trim());
20
+ });
21
+ });
22
+ });
23
+ queue = task.catch(() => { });
24
+ return task;
25
+ };
26
+ }
27
+ /**
28
+ * Human-in-the-loop intervention handler that pauses agent execution
29
+ * before tool calls to request human approval.
30
+ *
31
+ * By default, ALL tools require approval and the agent pauses via interrupt/resume.
32
+ * Use `allowedTools` to whitelist tools that run freely, and `ask` to provide
33
+ * inline prompting (CLI, custom UI).
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * import { Agent } from '@strands-agents/sdk'
38
+ * import { HumanInTheLoop } from '@strands-agents/sdk/vended-interventions/hitl'
39
+ *
40
+ * // All tools require approval, agent pauses via interrupt (default)
41
+ * const agent = new Agent({
42
+ * interventions: [new HumanInTheLoop()],
43
+ * })
44
+ *
45
+ * // readFile runs freely, everything else pauses for approval
46
+ * const agent = new Agent({
47
+ * interventions: [new HumanInTheLoop({ allowedTools: ['readFile'] })],
48
+ * })
49
+ *
50
+ * // CLI mode — prompts in terminal inline
51
+ * const agent = new Agent({
52
+ * interventions: [new HumanInTheLoop({ ask: 'stdio' })],
53
+ * })
54
+ *
55
+ * // Custom UI — provide your own prompt function
56
+ * const agent = new Agent({
57
+ * interventions: [new HumanInTheLoop({
58
+ * ask: async (prompt) => await slackDM(userId, prompt),
59
+ * })],
60
+ * })
61
+ * ```
62
+ */
63
+ export class HumanInTheLoop extends InterventionHandler {
64
+ name = 'strands:human-in-the-loop';
65
+ _allowedTools;
66
+ _enableTrust;
67
+ _evaluateTrust;
68
+ _evaluate;
69
+ _ask;
70
+ constructor(config) {
71
+ super();
72
+ this._allowedTools = new Set(config?.allowedTools ?? []);
73
+ this._enableTrust = config?.enableTrust ?? false;
74
+ this._evaluateTrust = config?.evaluateTrust ?? ((r) => this._isTrustResponse(r));
75
+ this._evaluate = config?.evaluate;
76
+ this._ask = config?.ask === 'stdio' ? createStdioAsk(this._enableTrust) : config?.ask;
77
+ }
78
+ async beforeToolCall(event) {
79
+ const toolName = event.toolUse.name;
80
+ if (!this._requiresApproval(event)) {
81
+ return proceed();
82
+ }
83
+ const prompt = `Tool "${toolName}" requires human approval. Input: ${JSON.stringify(event.toolUse.input)}`;
84
+ const isNegated = this._allowedTools.has(`!${toolName}`);
85
+ const evaluate = (response) => {
86
+ if (!isNegated && this._enableTrust && this._evaluateTrust(response)) {
87
+ this._trustTool(event, toolName);
88
+ return true;
89
+ }
90
+ return this._evaluate ? this._evaluate(response) : defaultEvaluate(response);
91
+ };
92
+ if (!this._ask) {
93
+ return confirm(prompt, { evaluate });
94
+ }
95
+ const response = await this._ask(prompt);
96
+ if (!isNegated && this._enableTrust && this._evaluateTrust(response)) {
97
+ this._trustTool(event, toolName);
98
+ return proceed();
99
+ }
100
+ return confirm(prompt, {
101
+ response,
102
+ evaluate: this._evaluate ?? defaultEvaluate,
103
+ });
104
+ }
105
+ /**
106
+ * Precedence (first match wins):
107
+ * 1. Negated (`!tool`) → always requires approval (cannot be trusted)
108
+ * 2. Trusted at runtime via 't' response (stored in agent.appState) → runs freely
109
+ * 3. Wildcard (`*`) → runs freely
110
+ * 4. Explicitly listed → runs freely
111
+ * 5. Default → requires approval
112
+ */
113
+ _requiresApproval(event) {
114
+ const toolName = event.toolUse.name;
115
+ if (this._allowedTools.has(`!${toolName}`))
116
+ return true;
117
+ const trusted = event.agent.appState.get(TRUSTED_TOOLS_KEY) ?? [];
118
+ if (trusted.includes(toolName))
119
+ return false;
120
+ if (this._allowedTools.has('*'))
121
+ return false;
122
+ if (this._allowedTools.has(toolName))
123
+ return false;
124
+ return true;
125
+ }
126
+ _trustTool(event, toolName) {
127
+ const trusted = event.agent.appState.get(TRUSTED_TOOLS_KEY) ?? [];
128
+ if (!trusted.includes(toolName)) {
129
+ event.agent.appState.set(TRUSTED_TOOLS_KEY, [...trusted, toolName]);
130
+ }
131
+ }
132
+ _isTrustResponse(response) {
133
+ if (typeof response === 'string')
134
+ return TRUST_RESPONSES.has(response.toLowerCase().trim());
135
+ return false;
136
+ }
137
+ }
138
+ //# sourceMappingURL=hitl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hitl.js","sourceRoot":"","sources":["../../../../src/vended-interventions/hitl/hitl.ts"],"names":[],"mappings":"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"}