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

# Python Agents

> Build code-based agents in Agent Studio using the Narada Python SDK

## What are Python Agents?

Python Agents are code-based automations that run directly in Agent Studio using the Narada Python SDK. Unlike GUI workflow agents, Python Agents give you the full flexibility of Python code for loops, conditions, data processing, API calls, and browser automation.

<CardGroup cols={3}>
  <Card title="Full Python" icon="code">
    Write Python code with access to the Narada SDK, Pydantic, and common libraries
  </Card>

  <Card title="AI-Generated" icon="wand-magic-sparkles">
    Created automatically by [Agent Maker](/documentation/agent-maker) and [Imitation Learning](/documentation/imitation-learning)
  </Card>

  <Card title="SDK-Powered" icon="robot">
    Use `Agent.run()`, browser actions, Google Sheets helpers, and human-in-the-loop prompts
  </Card>
</CardGroup>

## How Python Agents Are Created

There are three ways to create a Python Agent in Agent Studio:

### 1. Agent Maker

Describe your goal in natural language, and [Agent Maker](/documentation/agent-maker) generates a complete Python Agent for you:

```text theme={null}
/agentMaker Create an agent that extracts product prices from amazon.com and saves them to a Google Sheet
```

### 2. Imitation Learning

Record yourself performing a task in the browser, and [Imitation Learning](/documentation/imitation-learning) generates an agent from your recording.

### 3. Manual Creation

Create a Python Agent from scratch in Agent Studio:

<Steps>
  <Step title="Open Agent Studio">
    Navigate to Agent Studio and click **+ Create**.
  </Step>

  <Step title="Select Python Agent">
    Choose the Python Agent option from the creation dialog.
  </Step>

  <Step title="Write your code">
    The editor opens with a starter template. Write your automation using the Narada SDK.
  </Step>
</Steps>

## Writing Python Agent Code

In Agent Studio, `BrowserEnvironment()` targets the current browser window. Create an `Agent` with that environment, then call `agent.run()` or browser action methods on the agent:

```python theme={null}
from narada import Agent, BrowserEnvironment

env = BrowserEnvironment()
agent = Agent(environment=env)

# Navigate to a starting page. Use new_tab=True for the first navigation.
await agent.go_to_url(url="https://example.com", new_tab=True)

response = await agent.run(
    prompt="Extract the main heading from this page",
)

print(response.text)
```

<Warning>
  Use `new_tab=True` for the first `go_to_url()` call in Agent Studio. This keeps the workflow runtime tab separate from the page your automation controls.
</Warning>

### Using Structured Output

Extract typed data using Pydantic models:

```python theme={null}
from narada import Agent, BrowserEnvironment
from pydantic import BaseModel, Field


class ProductInfo(BaseModel):
    name: str = Field(description="Product name")
    price: str = Field(description="Product price with currency")
    rating: str = Field(description="Product rating out of 5")


env = BrowserEnvironment()
agent = Agent(environment=env)

await agent.go_to_url(url="https://example.com/product", new_tab=True)

response = await agent.run(
    prompt="Extract the product information from this page",
    output_schema=ProductInfo,
)

product = response.structured_output
assert product is not None

print(f"{product.name}: {product.price} ({product.rating})")
```

### Using Input Variables

Python Agents can accept input variables when invoked, making them reusable with different data:

```python theme={null}
from narada import Agent, BrowserEnvironment

env = BrowserEnvironment()
agent = Agent(environment=env)

# Access input variables with sensible defaults.
search_term = variables.get("searchTerm", "machine learning")
max_results = variables.get("maxResults", 5)

await agent.go_to_url(
    url=f"https://www.google.com/search?q={search_term}",
    new_tab=True,
)

response = await agent.run(
    prompt=f"Extract the top {max_results} search result titles",
)

print(response.text)
```

<Tip>
  Use `variables.get("key", default)` instead of `variables["key"]` so your agent can run standalone without input variables.
</Tip>

To pass values when invoking a custom Python agent, see [Input Variables](/documentation/input-variables).

### Google Sheets Integration

Read from and write to Google Sheets:

```python theme={null}
from narada import Agent, BrowserEnvironment

env = BrowserEnvironment()
agent = Agent(environment=env)

sheet_data = await agent.read_google_sheet(
    spreadsheet_id="your-spreadsheet-id",
    range="Sheet1!A2:A10",
)
companies = [row[0] for row in sheet_data.values]

results = []
for company in companies:
    await agent.go_to_url(
        url=f"https://www.google.com/search?q={company}+valuation",
    )
    response = await agent.run(
        prompt=f"What is {company}'s latest valuation?",
    )
    results.append([company, response.text])

await agent.write_google_sheet(
    spreadsheet_id="your-spreadsheet-id",
    range="Sheet1!B2",
    values=results,
)

await agent.print_message(message="Done! Results written to Google Sheet.")
```

## Available SDK Methods

Python Agents have access to the same agent-centered SDK methods as standalone scripts:

| Method                                                            | Description                                       |
| ----------------------------------------------------------------- | ------------------------------------------------- |
| [`run()`](/api-reference/agent)                                   | Execute an AI-powered automation task             |
| [`go_to_url()`](/api-reference/go-to-url)                         | Navigate to a URL                                 |
| [`agentic_selector()`](/api-reference/agentic-selector)           | Interact with specific UI elements                |
| [`agentic_mouse_action()`](/api-reference/agentic-mouse-action)   | Replay recorded mouse actions with agent fallback |
| [`get_url()`](/api-reference/get-url)                             | Read the current page URL                         |
| [`get_screenshot()`](/api-reference/get-screenshot)               | Capture a screenshot                              |
| [`get_full_html()`](/api-reference/get-full-html)                 | Get the page's full HTML                          |
| [`get_simplified_html()`](/api-reference/get-simplified-html)     | Get cleaned HTML                                  |
| [`print_message()`](/api-reference/print-message)                 | Show a message in the side panel chat             |
| [`prompt_for_user_input()`](/api-reference/prompt-for-user-input) | Collect structured user input                     |
| [`user_approval()`](/api-reference/user-approval)                 | Ask the user to approve or reject a step          |
| [`read_google_sheet()`](/api-reference/read-google-sheet)         | Read data from Google Sheets                      |
| [`write_google_sheet()`](/api-reference/write-google-sheet)       | Write data to Google Sheets                       |

## Agent Kinds

Choose the agent kind when you construct an `Agent`:

<CardGroup cols={2}>
  <Card title="OPERATOR" icon="robot">
    Browser automation: clicks, navigation, form filling, and data extraction from pages.
  </Card>

  <Card title="CORE_AGENT" icon="eye">
    Read-only reasoning: extracting visible data, answering questions about page content, and conversation-style tasks.
  </Card>
</CardGroup>

```python theme={null}
from narada import Agent, AgentKind, BrowserEnvironment

env = BrowserEnvironment()

# Web automation (default)
operator = Agent(environment=env)
await operator.run(prompt="Click the Submit button")

# Read-only reasoning
core_agent = Agent(environment=env, kind=AgentKind.CORE_AGENT)
await core_agent.run(prompt="What products are listed?")
```

## Running Python Agents

### From Agent Studio

Click the **Run** button in the Agent Studio editor to execute your Python Agent in the current browser.

### From the SDK

Invoke a custom Python Agent from the SDK using the namespaced format:

```python theme={null}
import asyncio

from narada import Agent, BrowserEnvironment


async def main() -> None:
    env = BrowserEnvironment()
    custom_agent = Agent(environment=env, kind="/$USER/my-research-agent")

    try:
        response = await custom_agent.run(
            prompt="Search for machine learning papers",
        )
        print(response.text)
    finally:
        await env.close()


if __name__ == "__main__":
    asyncio.run(main())
```

### From Chat

Type the agent shortcut in the Narada chat:

```text theme={null}
/$USER/my-research-agent Search for machine learning papers
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Use new_tab=True First" icon="plus">
    Open a new tab for the first navigation so the workflow runtime stays separate
  </Card>

  <Card title="Handle Errors" icon="shield">
    Catch `NaradaTimeoutError` for slow pages and call `agent.reset_agent_state()` after timeouts
  </Card>

  <Card title="Use Structured Output" icon="table">
    Define Pydantic models for reliable data extraction instead of parsing text responses
  </Card>

  <Card title="Print Progress" icon="message">
    Use `print_message()` to show progress updates in the side panel during long workflows
  </Card>
</CardGroup>
