Skip to content

Commit 8166101

Browse files
fix(langchain/createAgent): rename toolConfigs to interruptOn (#9034)
1 parent baa6c74 commit 8166101

File tree

4 files changed

+24
-24
lines changed

4 files changed

+24
-24
lines changed

examples/src/createAgent/middleware/hitl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const writeFileTool = tool(
5252

5353
// Configure HITL middleware
5454
const hitlMiddleware = humanInTheLoopMiddleware({
55-
toolConfigs: {
55+
interruptOn: {
5656
write_file: {
5757
allowAccept: true,
5858
description: "⚠️ File write operation requires approval",

libs/langchain/src/agents/middlewareAgent/middleware/hitl.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ const contextSchema = z
142142
* - `false` -> auto-approve (no human review)
143143
* - `ToolConfig` -> explicitly specify which reviewer responses are allowed for this tool
144144
*/
145-
toolConfigs: z.record(z.union([z.boolean(), ToolConfigSchema])).default({}),
145+
interruptOn: z.record(z.union([z.boolean(), ToolConfigSchema])).default({}),
146146
/**
147147
* Prefix used when constructing human-facing approval messages.
148148
* Provides context about the tool call being reviewed; does not change the underlying action.
@@ -209,11 +209,11 @@ const contextSchema = z
209209
* - `response`: Provide a manual response instead of executing the tool
210210
*
211211
* @param options - Configuration options for the middleware
212-
* @param options.toolConfigs - Per-tool configuration mapping tool names to their settings
213-
* @param options.toolConfigs[toolName].allowAccept - Whether the human can approve the current action without changes
214-
* @param options.toolConfigs[toolName].allowEdit - Whether the human can reject the current action with feedback
215-
* @param options.toolConfigs[toolName].allowRespond - Whether the human can approve the current action with edited content
216-
* @param options.toolConfigs[toolName].description - Custom approval message for the tool
212+
* @param options.interruptOn - Per-tool configuration mapping tool names to their settings
213+
* @param options.interruptOn[toolName].allowAccept - Whether the human can approve the current action without changes
214+
* @param options.interruptOn[toolName].allowEdit - Whether the human can reject the current action with feedback
215+
* @param options.interruptOn[toolName].allowRespond - Whether the human can approve the current action with edited content
216+
* @param options.interruptOn[toolName].description - Custom approval message for the tool
217217
* @param options.messagePrefix - Default prefix for approval messages (default: "Tool execution requires approval"). Only used for tools that do not define a custom `description` in their ToolConfig.
218218
*
219219
* @returns A middleware instance that can be passed to `createAgent`
@@ -225,7 +225,7 @@ const contextSchema = z
225225
* import { createAgent } from "langchain";
226226
*
227227
* const hitlMiddleware = humanInTheLoopMiddleware({
228-
* toolConfigs: {
228+
* interruptOn: {
229229
* // Interrupt write_file tool and allow edits or accepts
230230
* "write_file": {
231231
* allowEdit: true,
@@ -304,7 +304,7 @@ const contextSchema = z
304304
* Production use case with database operations
305305
* ```typescript
306306
* const hitlMiddleware = humanInTheLoopMiddleware({
307-
* toolConfigs: {
307+
* interruptOn: {
308308
* "execute_sql": {
309309
* allowAccept: true,
310310
* allowEdit: true,
@@ -352,20 +352,20 @@ export function humanInTheLoopMiddleware(
352352
/**
353353
* Don't do anything if the last message isn't an AI message with tool calls.
354354
*/
355-
const lastMessage = messages
355+
const lastMessage = [...messages]
356356
.reverse()
357357
.find((msg) => AIMessage.isInstance(msg)) as AIMessage;
358358
if (!lastMessage || !lastMessage.tool_calls?.length) {
359359
return;
360360
}
361361

362-
if (!config.toolConfigs) {
363-
throw new Error("HumanInTheLoopMiddleware: toolConfigs is required");
362+
if (!config.interruptOn) {
363+
throw new Error("HumanInTheLoopMiddleware: interruptOn is required");
364364
}
365365

366366
// Resolve per-tool configs (boolean true -> all actions allowed; false -> auto-approve)
367367
const resolvedToolConfigs: Record<string, ToolConfig> = {};
368-
for (const [toolName, toolConfig] of Object.entries(config.toolConfigs)) {
368+
for (const [toolName, toolConfig] of Object.entries(config.interruptOn)) {
369369
if (typeof toolConfig === "boolean") {
370370
if (toolConfig === true) {
371371
resolvedToolConfigs[toolName] = {

libs/langchain/src/agents/middlewareAgent/middleware/tests/hitl.int.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ describe("humanInTheLoopMiddleware", () => {
5858
model,
5959
middleware: [
6060
humanInTheLoopMiddleware({
61-
toolConfigs: {
61+
interruptOn: {
6262
calculator: true,
6363
},
6464
}),
@@ -150,7 +150,7 @@ describe("humanInTheLoopMiddleware", () => {
150150
model,
151151
middleware: [
152152
humanInTheLoopMiddleware({
153-
toolConfigs: {
153+
interruptOn: {
154154
draft_email: true,
155155
},
156156
}),
@@ -222,7 +222,7 @@ describe("humanInTheLoopMiddleware", () => {
222222
model,
223223
middleware: [
224224
humanInTheLoopMiddleware({
225-
toolConfigs: {
225+
interruptOn: {
226226
calculator: true,
227227
},
228228
}),
@@ -265,7 +265,7 @@ describe("humanInTheLoopMiddleware", () => {
265265
model,
266266
middleware: [
267267
humanInTheLoopMiddleware({
268-
toolConfigs: {
268+
interruptOn: {
269269
calculator: true,
270270
name_generator: true,
271271
},

libs/langchain/src/agents/middlewareAgent/middleware/tests/hitl.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ describe("humanInTheLoopMiddleware", () => {
6666
it("should auto-approve safe tools and interrupt for tools requiring approval", async () => {
6767
// Configure HITL middleware
6868
const hitlMiddleware = humanInTheLoopMiddleware({
69-
toolConfigs: {
69+
interruptOn: {
7070
write_file: {
7171
allowAccept: true,
7272
description: "⚠️ File write operation requires approval",
@@ -212,7 +212,7 @@ describe("humanInTheLoopMiddleware", () => {
212212

213213
it("should handle edit response type", async () => {
214214
const hitlMiddleware = humanInTheLoopMiddleware({
215-
toolConfigs: {
215+
interruptOn: {
216216
write_file: true,
217217
},
218218
});
@@ -280,7 +280,7 @@ describe("humanInTheLoopMiddleware", () => {
280280

281281
it("should handle manual response type", async () => {
282282
const hitlMiddleware = humanInTheLoopMiddleware({
283-
toolConfigs: {
283+
interruptOn: {
284284
write_file: {
285285
allowRespond: true,
286286
},
@@ -349,7 +349,7 @@ describe("humanInTheLoopMiddleware", () => {
349349

350350
it("should throw if response is not a string", async () => {
351351
const hitlMiddleware = humanInTheLoopMiddleware({
352-
toolConfigs: {
352+
interruptOn: {
353353
write_file: {
354354
allowRespond: true,
355355
},
@@ -413,7 +413,7 @@ describe("humanInTheLoopMiddleware", () => {
413413

414414
it("should allow to interrupt multiple tools at the same time", async () => {
415415
const hitlMiddleware = humanInTheLoopMiddleware({
416-
toolConfigs: {
416+
interruptOn: {
417417
write_file: {
418418
allowEdit: true,
419419
description: "⚠️ File write operation requires approval",
@@ -516,7 +516,7 @@ describe("humanInTheLoopMiddleware", () => {
516516

517517
it("should throw if not all tool calls have a response", async () => {
518518
const hitlMiddleware = humanInTheLoopMiddleware({
519-
toolConfigs: {
519+
interruptOn: {
520520
write_file: {
521521
allowEdit: true,
522522
description: "⚠️ File write operation requires approval",
@@ -583,7 +583,7 @@ describe("humanInTheLoopMiddleware", () => {
583583

584584
it("should not allow me to approve if I don't have allowAccept", async () => {
585585
const hitlMiddleware = humanInTheLoopMiddleware({
586-
toolConfigs: {
586+
interruptOn: {
587587
write_file: {
588588
allowEdit: true,
589589
description: "⚠️ File write operation requires approval",

0 commit comments

Comments
 (0)