This sample demonstrates how to create a custom agent that incorporates human-in-the-loop text input within its tools. Human-in-the-loop (HIL) interrupts pause an agent’s workflow to collect additional input from the user before proceeding with the agent’s actions. HIL is an important design pattern for ensuring user control and oversight in automated workflows, especially when the agent can perform potentially destructive or irreversible actions, such as editing or deleting data.

This application creates a map export SkillAgent that includes tools for exporting a map as a PNG, PDF, or a new web map. Each tool is created using the FunctionTool class.

// Defines a tool for saving the current map as a new web map
const saveAsWebMapTool = new FunctionTool({
name: "saveAsWebMap",
description: "Save the current state as a new web map. The middleware obtains its title; do not ask for it in chat.",
});

To pause a tool’s execution and collect additional input from the user, you must provide a middleware that handles the human-in-the-loop interaction. Use the createHumanInTheLoopToolMiddleware function to define the information required from the user, including a message prompting them for that information.

saveAsWebMapTool.middlewares = [
// Asks the user to provide a title for the exported web map as text input
// This accepts any text input from the user
createHumanInTheLoopToolMiddleware({
id: "export-title",
outputKey: "title", // The key under which the user's input will be stored for the tool's execute function
interrupt: () => ({ kind: "textInput", message: "Provide a title for the exported web map." }),
}),
// Asks the user to approve the export before proceeding
// This is a boolean choice asking the user to approve the export before proceeding
createHumanInTheLoopToolMiddleware({
id: "export-approval",
// the output from the previous middleware (e.g., the title) is accessible
// via the outputKey specified in the previous middleware (e.g., "title")
interrupt: ({ input, toolName }) => ({
kind: "booleanChoice",
message: `Proceed with ${toolName} using the title or filename "${input.title?.trim() || "Untitled Map"}"?`,
}),
}),
];

Each of the defined HIL middlewares pauses the tool’s execution for their defined purpose. The Assistant component renders its built-in HIL input UI and resumes the workflow when the user submits the required responses.

Any input collected from the user through the HIL middlewares is available as parameters to the execute function as a named parameter provided in the outputKey defined by the HIL middleware. The function provided to FunctionTool.execute defines the actual execution logic for the tool and is only called after all required human input has been collected and approved.

For example, the title collected from the user through the HIL middleware is available as a parameter named title in the execute function. The execute function uses this title in the web map save operation.

// The title is available as a parameter to the execute function
// The agent can then do what it needs with the human input before proceeding with the operation
functionTool.execute = async ({ title }, config) => {
const item = await map.saveAs({ title });
return "Web map exported successfully.";
},
2Dai-componentsarcgis-assistantarcgis-assistant-agenthuman-in-the-loopexportscreenshotPDFweb-mapSkillAgent5.2