Skip to content
Get started
Guides
Automation

How to Use Interactive Mode

Interactive Mode allows the automation agent to pause and request information from the caller when it encounters forms requiring user data like email addresses, credentials, or preferences. Instead of failing or hallucinating, the agent asks for what it needs.

When an automation agent encounters a form that requires personal data, it has a gap: it doesn’t know your email address, your password, or your preferences. Without that context, the agent either fails the task or fills in garbage data.

Consider this task: “Sign up for the Mozilla newsletter.”

The agent can navigate to the signup page, locate the form, and identify the required fields. But it can’t submit the form without your email address. Interactive Mode solves this by letting the agent pause and ask.

When you enable interactive mode, the automation agent gains the ability to request information mid-task. Here’s the flow:

  1. You send an automate request with interactive: true
  2. The agent executes the task normally, navigating pages and interacting with elements
  3. When the agent encounters a form requiring user data, it pauses and emits an interactive:form_data:request event containing the form fields it needs filled
  4. Your application receives this event, collects the data (from a user prompt, a database, another agent, etc.), and submits it back via the input endpoint
  5. The agent fills in the form fields and resumes the task
  6. If form validation fails, the agent emits an interactive:form_data:error event with the specific errors, and you can re-submit corrected values

The agent fills form fields directly without exposing user-provided values to the LLM, keeping sensitive data like passwords and personal information private.

Before using interactive mode, you’ll need:

  1. A valid Tabstack API key: Sign up at https://tabstack.ai to get your key.
  2. An SSE-capable client: Your HTTP client must handle text/event-stream responses.
  3. A way to handle input requests: Your application needs logic to respond when the agent requests form data.
Terminal window
export TABSTACK_API_KEY="your-api-key-here"

Add interactive: true to your automate request:

Terminal window
curl -X POST https://api.tabstack.ai/v1/automate \
-H "Authorization: Bearer $TABSTACK_API_KEY" \
-H "Content-Type: application/json" \
-N \
-d '{
"task": "Sign up for the Mozilla newsletter",
"url": "https://www.mozilla.org",
"interactive": true
}'

When interactive is not set or set to false, the agent will automatically decline any form data requests and attempt to continue without user input.

When the agent needs user input, it emits an interactive:form_data:request event in the SSE stream. The event data contains:

FieldTypeDescription
requestIdstringUnique identifier for this request. Use this when submitting your response.
pageUrlstringURL of the page containing the form.
pageTitlestringTitle of the page.
formDescriptionstringHuman-readable description of the form’s purpose.
fieldsarrayThe form fields the agent needs filled.

Each field in the fields array contains:

FieldTypeDescription
refstringElement reference ID (e.g., "E42"). Include this in your response to map values to fields.
labelstringThe field’s visible label (e.g., "Email Address").
fieldTypestringOne of: text, email, phone, date, number, select, checkbox, radio, textarea, password, other.
requiredbooleanWhether the field must be filled.
optionsstring[]Available options for select and radio fields.
currentValuestringCurrent value if the field is already partially filled.
descriptionstringAdditional context or hints about the field.
event: interactive:form_data:request
data: {
"requestId": "a1b2c3d4",
"pageUrl": "https://www.mozilla.org/en-US/newsletter/",
"pageTitle": "Mozilla Newsletter",
"formDescription": "Newsletter signup form requiring email and format preference",
"fields": [
{
"ref": "E12",
"label": "Your email address",
"fieldType": "email",
"required": true
},
{
"ref": "E15",
"label": "Format",
"fieldType": "select",
"required": false,
"options": ["HTML", "Text"]
}
]
}

Once you have the values for the requested fields, submit them to the input endpoint:

POST /v1/automate/{requestId}/input
Terminal window
curl -X POST "https://api.tabstack.ai/v1/automate/a1b2c3d4/input" \
-H "Authorization: Bearer $TABSTACK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fields": [
{ "ref": "E12", "value": "[email protected]" },
{ "ref": "E15", "value": "HTML" }
]
}'

The endpoint returns 202 Accepted on success. If the request has expired or already been answered, it returns 410 Gone.

If the form submission fails validation (e.g., an invalid email format), the agent emits an interactive:form_data:error event. This event includes the same field structure as the original request, plus a fieldErrors map showing which fields failed and why.

event: interactive:form_data:error
data: {
"requestId": "e5f6g7h8",
"pageUrl": "https://www.mozilla.org/en-US/newsletter/",
"pageTitle": "Mozilla Newsletter",
"formDescription": "Newsletter signup form requiring email and format preference",
"fields": [
{
"ref": "E12",
"label": "Your email address",
"fieldType": "email",
"required": true,
"description": "Invalid email address"
}
],
"fieldErrors": {
"E12": "Invalid email address"
}
}

Handle this the same way as the initial request: collect corrected values from the user and submit them to the input endpoint using the new requestId.

If you want to skip the form or abort the interactive request, submit with cancelled: true:

Terminal window
curl -X POST "https://api.tabstack.ai/v1/automate/a1b2c3d4/input" \
-H "Authorization: Bearer $TABSTACK_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "cancelled": true }'

When cancelled, the agent will attempt to continue the task without the form data, which may result in task failure depending on the form’s requirements.

This example shows the full flow: starting an interactive automation, listening for form data requests, prompting the user, and submitting the response.

from tabstack import Tabstack
client = Tabstack()
# Start a task with interactive mode enabled
stream = client.agent.automate(
task="Sign up for the Mozilla newsletter",
interactive=True,
)
# Listen for events in the stream
for event in stream:
print(f"[{event.event}]")
# When the agent requests form data
if event.event == "interactive:form_data:request":
request_id = event.data.get("requestId")
fields = event.data.get("fields", [])
print(f"\nThe agent needs the following information:")
field_values = []
for field in fields:
ref = field.get("ref")
label = field.get("label", "Unknown field")
required = field.get("required", False)
field_type = field.get("fieldType", "text")
options = field.get("options")
# Show available options for select/radio fields
if options:
print(f" {label} (options: {', '.join(options)})")
prompt = f" {label}{'*' if required else ''}: "
value = input(prompt)
field_values.append({"ref": ref, "value": value})
# Submit the values back to the agent
client.agent.automate_input(request_id, fields=field_values)
print("Input submitted, agent resuming...\n")
# Handle validation errors
elif event.event == "interactive:form_data:error":
request_id = event.data.get("requestId")
field_errors = event.data.get("fieldErrors", {})
fields = event.data.get("fields", [])
print(f"\nForm validation failed:")
for ref, error in field_errors.items():
print(f" {ref}: {error}")
field_values = []
for field in fields:
ref = field.get("ref")
label = field.get("label", "Unknown field")
error = field_errors.get(ref, "")
prompt = f" {label} ({error}): " if error else f" {label}: "
value = input(prompt)
field_values.append({"ref": ref, "value": value})
client.agent.automate_input(request_id, fields=field_values)
print("Corrected input submitted...\n")
# Print the final result
elif event.event == "complete":
result = event.data
print(f"\nTask complete: {result}")

Interactive mode is useful whenever the agent needs context that only the caller can provide:

  • Account signups: The agent navigates the signup flow while you provide email, username, and password.
  • Form submissions: Contact forms, registration forms, surveys where personal data is required.
  • Checkout flows: Providing shipping addresses, payment preferences, or coupon codes.
  • Multi-agent pipelines: A parent orchestrator agent automatically supplies data from its own context when the automation agent requests it, with no human involvement needed.
  • Form-filling only: This beta release is optimized for form completion. The agent requests data specifically when it encounters form fields requiring user input.
  • 2-minute timeout: Input requests expire after 2 minutes. A 410 Gone response means the task is unrecoverable — restart it.
  • Single request per form: The agent requests all fields for a form in a single event. It does not ask for fields one at a time.
  • Not available via MCP: Interactive Mode requires a persistent SSE stream to exchange events. It is not supported through the Tabstack MCP server. Use the SDK directly.