Skip to content

Interactive Tools

Interactive tools let your agent pause execution and request explicit user input before proceeding. The LLM calls ask_confirmation or ask_question as tool calls; the runtime emits an InteractionRequested event, the frontend shows a prompt, and on the next run the user’s response is injected back into the conversation.

[dependencies]
agent_sdk = { workspace = true, features = ["llm-engine"] }

Interactive tools are bundled with the LLM engine — no separate feature flag needed.

  1. Register interaction tools — call make_interaction_tools() and add them to your agent’s tool registry.

  2. LLM calls the tool — during a streaming run, the LLM decides to call ask_confirmation or ask_question.

  3. Runtime emits InteractionRequested — the tool returns { "status": "interaction_pending", "interaction_id": "<uuid>" } and emits an AgentTraceEvent::InteractionRequested with the full InteractionRequest.

  4. Frontend shows the prompt — the AG-UI SSE stream translates this into a RunInputRequired event. The run pauses.

  5. User responds — the frontend sends the next run request with an interaction_response data part containing the user’s selection or free text.

  6. LLM reads the response — the response appears in conversation history as a ContentPart::Data with interaction_response, and the LLM continues from where it paused.

use agent_sdk::agent::interaction_tools::make_interaction_tools;
let interaction_tools = make_interaction_tools();
// Returns Vec<ToolSpec> with "ask_confirmation" and "ask_question"
for tool in interaction_tools {
agent.register_tool(tool);
}

A mandatory safety gate for mutating operations. The LLM must call this before any create/update/delete/deploy action.

Parameters:

ParameterTypeRequiredDescription
questionstringyesThe approval question shown to the user
target_toolstringnoName of the tool that will be called if approved (informational)

Fixed options presented to the user:

Option IDLabelMeaning
yesYesApproved — proceed
noNoRejected — stop
no_with_feedbackNo — tell me what to changeRejected with revision notes in free_text

Example LLM tool call:

{
"name": "ask_confirmation",
"arguments": {
"question": "Deploy agent 'weather-bot' to production?",
"target_tool": "deploy_agent"
}
}

An open-ended question with optional structured choices. The user can always type freely regardless of whether options are provided.

Parameters:

ParameterTypeRequiredDescription
questionstringyesThe question to present
optionsarraynoStructured choices (clickable buttons)
options[].idstringyesStable identifier returned in selected_option_id
options[].labelstringyesDisplay text on the button
options[].descriptionstringnoClarifying text below the button

Example LLM tool call:

{
"name": "ask_question",
"arguments": {
"question": "Which data source should I connect to?",
"options": [
{ "id": "postgres", "label": "PostgreSQL" },
{ "id": "bigquery", "label": "BigQuery", "description": "Google Cloud warehouse" }
]
}
}

The InteractionKind enum distinguishes the two flows:

KindToolBehavior
InteractionKind::Confirmationask_confirmationYes/No/No-with-feedback, fixed options
InteractionKind::Questionask_questionCustom options + free text

Emitted by the tool via AgentTraceEvent::InteractionRequested:

FieldTypeDescription
interaction_idStringUnique ID correlating request ↔ response
kindInteractionKindConfirmation or Question
questionStringPrompt text shown to the user
optionsVec<InteractionOption>Clickable choices (may be empty)
allow_free_textboolAlways true — user can type freely
allow_cancelboolAlways true — user can dismiss
default_option_idOption<String>Pre-selected option
timeout_msOption<u64>Auto-expiry (currently unused)
continuation_idOption<String>Multi-step flow correlation
source_nodeOption<String>Coordination graph node ID
metadataOption<Value>Extension data (e.g., { "target_tool": "..." })

Sent by the frontend on the next run:

FieldTypeDescription
interaction_idStringMust match the pending request
selected_option_idOption<String>ID of the option the user clicked
free_textOption<String>Free-text answer
confirmedOption<bool>Explicit yes/no for confirmations
cancelledbooltrue if user dismissed without resolving
metadataOption<Value>Extension data
FieldTypeDescription
idStringStable identifier
labelStringDisplay text
descriptionOption<String>Optional clarifying text

These policies are enforced by the runtime and not exposed to the LLM:

  • allow_free_text: true — options are suggestions; user can always type freely
  • allow_cancel: true — user always has an exit
  • timeout_ms: None — no auto-expiry; timeout is a system-level concern
TypeModuleDescription
make_interaction_tools()agent_sdk::agent::interaction_toolsReturns Vec<ToolSpec> with both interaction tools
InteractionKindagent_sdk::interactionQuestion or Confirmation
InteractionRequestagent_sdk::interactionFull request payload emitted by tools
InteractionResponseagent_sdk::interactionUser’s response payload
InteractionOptionagent_sdk::interactionSelectable option: id, label, description
ToolSpecagent_sdk::agent::toolsTool registration: name, description, schema, executor
ToolExecutoragent_sdk::agent::toolsWithContext(fn) — executor with event emission
ToolContextagent_sdk::agent::tool_contextContext handle for emitting AgentTraceEvent
AgentTraceEvent::InteractionRequestedagent_sdk::agent::traceTrace event carrying the InteractionRequest