Skip to content

Commit 1d95681

Browse files
hitl middleware: use args not arguments (langchain-ai#9210)
2 parents 9e6eb91 + a9e75bc commit 1d95681

File tree

4 files changed

+30
-29
lines changed

4 files changed

+30
-29
lines changed

examples/src/createAgent/middleware/hitl.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
import { createAgent, HumanMessage, tool } from "langchain";
2-
import { humanInTheLoopMiddleware } from "langchain";
1+
import {
2+
createAgent,
3+
HumanMessage,
4+
tool,
5+
humanInTheLoopMiddleware,
6+
} from "langchain";
37
import { Command, MemorySaver } from "@langchain/langgraph";
48
import { z } from "zod";
59

@@ -113,7 +117,7 @@ if (state.next && state.next.length > 0) {
113117
console.log("Tool:", hitlRequest.actionRequests[0].name);
114118
console.log(
115119
"Args:",
116-
JSON.stringify(hitlRequest.actionRequests[0].arguments, null, 2)
120+
JSON.stringify(hitlRequest.actionRequests[0].args, null, 2)
117121
);
118122
console.log("Description:", hitlRequest.actionRequests[0].description);
119123

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

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ const InterruptOnConfigSchema = z.object({
9797
/**
9898
* JSON schema for the arguments associated with the action, if edits are allowed.
9999
*/
100-
argumentsSchema: z.record(z.any()).optional(),
100+
argsSchema: z.record(z.any()).optional(),
101101
});
102102
export type InterruptOnConfig = z.input<typeof InterruptOnConfigSchema>;
103103

@@ -112,7 +112,7 @@ export interface Action {
112112
/**
113113
* Key-value pairs of arguments needed for the action (e.g., {"a": 1, "b": 2}).
114114
*/
115-
arguments: Record<string, any>;
115+
args: Record<string, any>;
116116
}
117117

118118
/**
@@ -126,7 +126,7 @@ export interface ActionRequest {
126126
/**
127127
* Key-value pairs of arguments needed for the action (e.g., {"a": 1, "b": 2}).
128128
*/
129-
arguments: Record<string, any>;
129+
args: Record<string, any>;
130130
/**
131131
* The description of the action to be reviewed.
132132
*/
@@ -148,7 +148,7 @@ export interface ReviewConfig {
148148
/**
149149
* JSON schema for the arguments associated with the action, if edits are allowed.
150150
*/
151-
argumentsSchema?: Record<string, any>;
151+
argsSchema?: Record<string, any>;
152152
}
153153

154154
/**
@@ -158,7 +158,7 @@ export interface ReviewConfig {
158158
* ```ts
159159
* const hitlRequest: HITLRequest = {
160160
* actionRequests: [
161-
* { name: "send_email", arguments: { to: "user@example.com", subject: "Hello" } }
161+
* { name: "send_email", args: { to: "user@example.com", subject: "Hello" } }
162162
* ],
163163
* reviewConfigs: [
164164
* {
@@ -282,7 +282,7 @@ export type HumanInTheLoopMiddlewareConfig = InferInteropZodInput<
282282
* } else if (action.name === "write_file") {
283283
* return {
284284
* type: "edit",
285-
* editedAction: { name: "write_file", arguments: { filename: "safe.txt", content: "Safe content" } }
285+
* editedAction: { name: "write_file", args: { filename: "safe.txt", content: "Safe content" } }
286286
* };
287287
* }
288288
* return { type: "reject", message: "Action not allowed" };
@@ -311,7 +311,7 @@ export type HumanInTheLoopMiddlewareConfig = InferInteropZodInput<
311311
* @param options.interruptOn - Per-tool configuration mapping tool names to their settings
312312
* @param options.interruptOn[toolName].allowedDecisions - Array of decision types allowed for this tool (e.g., ["approve", "edit", "reject"])
313313
* @param options.interruptOn[toolName].description - Custom approval message for the tool. Can be either a static string or a callable that dynamically generates the description based on agent state, runtime, and tool call information
314-
* @param options.interruptOn[toolName].argumentsSchema - JSON schema for the arguments associated with the action, if edits are allowed
314+
* @param options.interruptOn[toolName].argsSchema - JSON schema for the arguments associated with the action, if edits are allowed
315315
* @param options.descriptionPrefix - Default prefix for approval messages (default: "Tool execution requires approval"). Only used for tools that do not define a custom `description` in their InterruptOnConfig.
316316
*
317317
* @returns A middleware instance that can be passed to `createAgent`
@@ -385,7 +385,7 @@ export type HumanInTheLoopMiddlewareConfig = InferInteropZodInput<
385385
* const resume: HITLResponse = {
386386
* decisions: [{
387387
* type: "edit",
388-
* editedAction: { name: "write_file", arguments: { filename: "safe.txt", content: "Modified" } }
388+
* editedAction: { name: "write_file", args: { filename: "safe.txt", content: "Modified" } }
389389
* }]
390390
* };
391391
*
@@ -495,7 +495,7 @@ export function humanInTheLoopMiddleware(
495495
*/
496496
const actionRequest: ActionRequest = {
497497
name: toolName,
498-
arguments: toolArgs,
498+
args: toolArgs,
499499
description,
500500
};
501501

@@ -507,8 +507,8 @@ export function humanInTheLoopMiddleware(
507507
allowedDecisions: config.allowedDecisions,
508508
};
509509

510-
if (config.argumentsSchema) {
511-
reviewConfig.argumentsSchema = config.argumentsSchema;
510+
if (config.argsSchema) {
511+
reviewConfig.argsSchema = config.argsSchema;
512512
}
513513

514514
return { actionRequest, reviewConfig };
@@ -535,20 +535,17 @@ export function humanInTheLoopMiddleware(
535535
`Invalid edited action for tool "${toolCall.name}": name must be a string`
536536
);
537537
}
538-
if (
539-
!editedAction.arguments ||
540-
typeof editedAction.arguments !== "object"
541-
) {
538+
if (!editedAction.args || typeof editedAction.args !== "object") {
542539
throw new Error(
543-
`Invalid edited action for tool "${toolCall.name}": arguments must be an object`
540+
`Invalid edited action for tool "${toolCall.name}": args must be an object`
544541
);
545542
}
546543

547544
return {
548545
revisedToolCall: {
549546
type: "tool_call",
550547
name: editedAction.name,
551-
args: editedAction.arguments,
548+
args: editedAction.args,
552549
id: toolCall.id,
553550
},
554551
toolMessage: null,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ describe("humanInTheLoopMiddleware", () => {
182182
type: "edit",
183183
editedAction: {
184184
name: "draft_email",
185-
arguments: {
186-
...hitlRequest.actionRequests[0].arguments,
185+
args: {
186+
...hitlRequest.actionRequests[0].args,
187187
message: editedMessage,
188188
to: ["john.doe@example.com"],
189189
subject: "Hello",

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ describe("humanInTheLoopMiddleware", () => {
195195
{
196196
"actionRequests": [
197197
{
198-
"arguments": {
198+
"args": {
199199
"content": "Hello World",
200200
"filename": "greeting.txt",
201201
},
@@ -290,7 +290,7 @@ describe("humanInTheLoopMiddleware", () => {
290290
type: "edit",
291291
editedAction: {
292292
name: "write_file",
293-
arguments: { filename: "safe.txt", content: "Safe content" },
293+
args: { filename: "safe.txt", content: "Safe content" },
294294
},
295295
},
296296
],
@@ -521,7 +521,7 @@ describe("humanInTheLoopMiddleware", () => {
521521
type: "edit",
522522
editedAction: {
523523
name: "write_file",
524-
arguments: { filename: "safe.txt", content: "Safe content" },
524+
args: { filename: "safe.txt", content: "Safe content" },
525525
},
526526
};
527527
}
@@ -831,7 +831,7 @@ describe("humanInTheLoopMiddleware", () => {
831831
// eslint-disable-next-line @typescript-eslint/no-explicit-any
832832
const invalidEditedAction: any = {
833833
name: 123, // Invalid: should be string
834-
arguments: { filename: "test.txt", content: "test" },
834+
args: { filename: "test.txt", content: "test" },
835835
};
836836

837837
await expect(() =>
@@ -896,11 +896,11 @@ describe("humanInTheLoopMiddleware", () => {
896896
config
897897
);
898898

899-
// Resume with invalid edited action (arguments is not an object)
899+
// Resume with invalid edited action (args is not an object)
900900
// eslint-disable-next-line @typescript-eslint/no-explicit-any
901901
const invalidEditedAction: any = {
902902
name: "write_file",
903-
arguments: "not an object", // Invalid: should be object
903+
args: "not an object", // Invalid: should be object
904904
};
905905

906906
await expect(() =>
@@ -918,7 +918,7 @@ describe("humanInTheLoopMiddleware", () => {
918918
config
919919
)
920920
).rejects.toThrow(
921-
'Invalid edited action for tool "write_file": arguments must be an object'
921+
'Invalid edited action for tool "write_file": args must be an object'
922922
);
923923
});
924924

0 commit comments

Comments
 (0)