> ## Documentation Index
> Fetch the complete documentation index at: https://docs.optexity.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Building automations

> Build your first browser automation in 5 minutes

This guide walks you through creating a simple login automation from scratch. By the end, you'll understand how to define actions, use parameters, and run your first Optexity workflow.

<Info>
  **What you'll learn:** - How to record browser interactions with the Optexity Recorder - How to
  understand and edit automation JSON/Python - How to use parameters for dynamic values - How to
  run your automation via the API
</Info>

## Prerequisites

Before you begin, ensure you have:

1. ✅ Completed the [Installation](/docs/getting-started/installation) guide
2. ✅ Optexity running in your local environment
3. ✅ Your API key from the [dashboard](https://dashboard.optexity.com)

### Install the Recorder Extension

Install the **Optexity Recorder** extension from the [Chrome Web Store](https://chromewebstore.google.com/detail/optexity-recorder/pbaganbicadeoacahamnbgohafchgakp). This extension captures your browser interactions and converts them into automation workflows.

<Steps>
  <Step title="Install the extension">Click "Add to Chrome" on the Chrome Web Store page</Step>

  <Step title="Pin the extension">
    Click the puzzle icon in Chrome and pin Optexity Recorder for easy access
  </Step>

  <Step title="Add your API key">
    Click the extension icon and enter your API key from the dashboard
  </Step>
</Steps>

***

## What We're Building

Let's create an automation that logs into a website. This simple example demonstrates the core concepts you'll use in every Optexity workflow:

| Step | Action | Description                                      |
| ---- | ------ | ------------------------------------------------ |
| 1    | Click  | Navigate to the login page by clicking "Sign in" |
| 2    | Type   | Enter the email address                          |
| 3    | Type   | Enter the password                               |
| 4    | Click  | Submit the login form                            |

***

## Step 1: Record the Automation

The fastest way to create an automation is by recording your actions directly in the browser.

<Steps>
  <Step title="Navigate to the target website">
    Open Chrome and go to the website you want to automate (e.g., `https://example.com`)
  </Step>

  <Step title="Start capturing">
    Click the Optexity Recorder extension icon and hit **Start Capture**
  </Step>

  <Step title="Perform your actions">
    Interact with the website naturally, click buttons, fill in forms, navigate pages. The
    recorder captures every interaction.
  </Step>

  <Step title="Stop and save">
    When finished, click **Complete Capture**. The automation is automatically saved to your
    dashboard as a JSON file.
  </Step>
</Steps>

<Tip>
  **Recording Tips:** - Perform actions slowly and deliberately for better accuracy - Avoid
  unnecessary scrolling or hovering - The recorder captures clicks, text input, and form
  selections
</Tip>

***

## Step 2: Understand the Automation Structure

Once recorded, your automation is saved as JSON on the dashboard. Let's break down the structure using a login example.

### The Complete Automation

Here is a sample automation:

```json theme={null}
{
    "url": "https://example.com",
    "parameters": {
        "input_parameters": {
            "username": ["user@example.com"],
            "password": ["mypassword123"]
        },
        "generated_parameters": {}
    },
    "nodes": [
        {
            "interaction_action": {
                "click_element": {
                    "command": "get_by_role(\"link\", name=\"Sign in\")",
                    "prompt_instructions": "Click the Sign in link in the navigation bar"
                }
            },
            "end_sleep_time": 1.0
        },
        {
            "interaction_action": {
                "input_text": {
                    "command": "get_by_role(\"textbox\", name=\"Email\")",
                    "prompt_instructions": "Enter the email address in the login form",
                    "input_text": "{username[0]}"
                }
            },
            "end_sleep_time": 1.0
        },
        {
            "interaction_action": {
                "input_text": {
                    "command": "get_by_role(\"textbox\", name=\"Password\")",
                    "prompt_instructions": "Enter the password in the login form",
                    "input_text": "{password[0]}"
                }
            },
            "end_sleep_time": 1.0
        },
        {
            "interaction_action": {
                "click_element": {
                    "command": "get_by_role(\"button\", name=\"Sign In\")",
                    "prompt_instructions": "Click the Sign In button to submit the form"
                }
            },
            "end_sleep_time": 1.0
        }
    ]
}
```

Here's what a login automation looks like in Python:

```python theme={null}
from optexity.schema.actions.interaction_action import (
    ClickElementAction,
    InputTextAction,
    InteractionAction,
)
from optexity.schema.automation import ActionNode, Automation, Parameters

login_automation = Automation(
    url="https://example.com",
    parameters=Parameters(
        input_parameters={
            "username": ["user@example.com"],
            "password": ["mypassword123"],
        },
        generated_parameters={},
    ),
    nodes=[
        # Step 1: Click the Sign in link
        ActionNode(
            interaction_action=InteractionAction(
                click_element=ClickElementAction(
                    command="""get_by_role("link", name="Sign in")""",
                    prompt_instructions="Click the Sign in link in the navigation bar",
                )
            )
        ),
        # Step 2: Enter the email
        ActionNode(
            interaction_action=InteractionAction(
                input_text=InputTextAction(
                    command="""get_by_role("textbox", name="Email")""",
                    input_text="{username[0]}",
                    prompt_instructions="Enter the email address in the login form",
                )
            )
        ),
        # Step 3: Enter the password
        ActionNode(
            interaction_action=InteractionAction(
                input_text=InputTextAction(
                    command="""get_by_role("textbox", name="Password")""",
                    input_text="{password[0]}",
                    prompt_instructions="Enter the password in the login form",
                )
            )
        ),
        # Step 4: Click Sign In button
        ActionNode(
            interaction_action=InteractionAction(
                click_element=ClickElementAction(
                    command="""get_by_role("button", name="Sign In")""",
                    prompt_instructions="Click the Sign In button to submit the form",
                )
            )
        ),
    ],
)
```

### Breaking Down Each Component

<AccordionGroup>
  <Accordion title="Automation — The Container" icon="box">
    The `Automation` object is the top-level container that holds your entire workflow:

    ```python theme={null}
    Automation(
        url="https://example.com",      # Where the browser starts
        parameters=Parameters(...),      # Input and generated values
        nodes=[...],                     # Sequence of actions
    )
    ```

    | Property     | Purpose                                            |
    | ------------ | -------------------------------------------------- |
    | `url`        | The starting URL—where the browser navigates first |
    | `parameters` | Container for variables used during execution      |
    | `nodes`      | Ordered list of actions to execute sequentially    |
  </Accordion>

  <Accordion title="Parameters — Your Variables" icon="code">
    Parameters define the data flowing through your automation. They're divided into two types:

    **Input Parameters** — Values you provide before execution:

    ```python theme={null}
    input_parameters={
        "username": ["user@example.com"],  # Access as {username[0]}
        "password": ["secret123"],          # Access as {password[0]}
    }
    ```

    **Generated Parameters** — Values extracted during execution:

    ```python theme={null}
    generated_parameters={
        "order_id": [],      # Populated by extraction actions
        "confirmation": [],  # Available for later steps
    }
    ```

    <Note>
      Values are stored as **lists of strings**. Access them using `{variable_name[index]}` syntax, where index is typically `0` for single values.
    </Note>
  </Accordion>

  <Accordion title="ActionNode — Individual Steps" icon="play">
    Each `ActionNode` represents a single atomic action. An ActionNode contains exactly **one** of
    these action types: | Action Type | Purpose | Example | |-------------|---------|---------| |
    `interaction_action` | Click, type, select, scroll, navigate | Clicking a button | |
    `extraction_action` | Extract data from the page | Scraping product prices | |
    `assertion_action` | Verify conditions | Check if logged in | | `python_script_action` | Run
    custom Python code | Data transformation | | `fetch_2fa_action` | Handle two-factor
    authentication | Get OTP from email | `python ActionNode(
            interaction_action=InteractionAction( click_element=ClickElementAction(
            command="""get_by_role("button", name="Submit")""", prompt_instructions="Click the submit
            button", ) ), before_sleep_time=0.0, # Wait before action end_sleep_time=1.0, # Wait after
            action ) `
  </Accordion>

  <Accordion title="Locators — Finding Elements" icon="crosshairs">
    Optexity uses **Playwright locators** to find elements on the page. The `command` field accepts Playwright's powerful locator syntax:

    ```python theme={null}
    # By role (recommended — most resilient)
    command="""get_by_role("button", name="Submit")"""

    # By text content
    command="""get_by_text("Welcome back")"""

    # By label (great for form fields)
    command="""get_by_label("Email address")"""

    # By test ID
    command="""get_by_test_id("login-button")"""

    # By CSS selector
    command="""locator("#email-input")"""
    ```

    <Tip>
      The `prompt_instructions` field provides a **natural language fallback**. If the locator fails, Optexity's AI uses this description to find the element visually.
    </Tip>
  </Accordion>
</AccordionGroup>

***

## Step 3: Edit and Customize

After recording, you may want to customize your automation. Common edits include:

### Parameterizing Values

Replace hardcoded values with parameters for flexibility:

```python theme={null}
# Before: Hardcoded email
input_text="user@example.com"

# After: Parameterized
input_text="{username[0]}"
```

### Adding Descriptive Instructions

Improve the `prompt_instructions` for better AI fallback:

```python theme={null}
# Basic (less reliable)
prompt_instructions="Click the button"

# Descriptive (more reliable)
prompt_instructions="Click the blue 'Sign In' button at the bottom of the login form"
```

### Adjusting Timing

Control execution speed with timing properties:

```python theme={null}
ActionNode(
    interaction_action=InteractionAction(...),
    before_sleep_time=2.0,  # Wait 2 seconds before action
    end_sleep_time=1.0,     # Wait 1 second after action
)
```

***

## Step 4: Run Your Automation

Once your automation is defined, execute it through the inference API.

### Using cURL

```bash theme={null}
curl -X POST http://localhost:9000/inference \
  -H "Content-Type: application/json" \
  -d '{
    "endpoint_name": "login-flow",
    "input_parameters": {
      "username": ["user@example.com"],
      "password": ["mypassword123"]
    },
    "unique_parameter_names": ["username"]
  }'
```

### Understanding the Request

| Field                    | Description                                                    |
| ------------------------ | -------------------------------------------------------------- |
| `endpoint_name`          | The name of your automation (as saved on the dashboard)        |
| `input_parameters`       | Values to inject into your automation                          |
| `unique_parameter_names` | Parameters that uniquely identify this run (for deduplication) |

### Expected Response

A successful run returns:

```json theme={null}
{
    "status": "success",
    "run_id": "run_abc123",
    "output": {
        "generated_parameters": {},
        "extracted_data": []
    }
}
```

***

## Common Patterns

Here are some patterns you'll use frequently:

### Clicking Elements

```python theme={null}
ActionNode(
    interaction_action=InteractionAction(
        click_element=ClickElementAction(
            command="""get_by_role("button", name="Continue")""",
            prompt_instructions="Click the Continue button",
        )
    )
)
```

### Filling Form Fields

```python theme={null}
ActionNode(
    interaction_action=InteractionAction(
        input_text=InputTextAction(
            command="""get_by_label("Email")""",
            input_text="{email[0]}",
            prompt_instructions="Enter email in the form field",
        )
    )
)
```

### Selecting Dropdowns

```python theme={null}
from optexity.schema.actions.interaction_action import SelectOptionAction

ActionNode(
    interaction_action=InteractionAction(
        select_option=SelectOptionAction(
            command="""get_by_label("Country")""",
            select_values=["United States"],
            prompt_instructions="Select country from dropdown",
        )
    )
)
```

### Handling New Tabs

```python theme={null}
ActionNode(
    interaction_action=InteractionAction(
        click_element=ClickElementAction(
            command="""get_by_role("link", name="View Details")""",
            prompt_instructions="Click link that opens in new tab",
        )
    ),
    expect_new_tab=True,  # Waits for and switches to new tab
)
```

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Element not found">
    **Problem:** The automation fails to find an element. **Solutions:** 1. Improve
    `prompt_instructions` with more visual details 2. Try a different locator strategy (role →
    label → text → CSS) 3. Add `before_sleep_time` to wait for the element to appear 4. Check if
    the element is inside an iframe
  </Accordion>

  <Accordion title="Action executed too fast">
    **Problem:** The page hasn't loaded before the next action runs. **Solution:** Increase
    `end_sleep_time` on the previous action: `python ActionNode(
                interaction_action=InteractionAction(...), end_sleep_time=3.0, # Wait 3 seconds after action
                ) `
  </Accordion>

  <Accordion title="Variable not substituted">
    **Problem:** You see `{username[0]}` instead of the actual value. **Solutions:** 1. Ensure
    the variable is defined in `input_parameters` 2. Check the index is correct (starts at 0) 3.
    Verify the syntax: `{variable_name[index]}`
  </Accordion>
</AccordionGroup>

***

## Next Steps

Now that you've built your first automation, explore these topics to level up:

<CardGroup cols={2}>
  <Card title="Core Concepts" icon="book" href="/docs/building-automations/core-concepts">
    Deep dive into the automation model, nodes, and execution flow
  </Card>

  <Card title="Locators" icon="crosshairs" href="/docs/building-automations/locators">
    Master element location strategies for reliable automations
  </Card>

  <Card title="Interaction Actions" icon="hand-pointer" href="/docs/interaction-actions">
    Explore all available interaction types: clicks, inputs, navigation
  </Card>

  <Card title="Extraction Actions" icon="download" href="/docs/extraction-actions">
    Learn to capture data from web pages into your workflow
  </Card>
</CardGroup>
