āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š browser-use/tools/add ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
Create custom tools by decorating functions with @tools.action():
from browser_use import Tools, Agent
tools = Tools()
@tools.action(description='Ask human for help with a question')
def ask_human(question: str) -> ActionResult:
answer = input(f'{question} > ')
return f'The human responded with: {answer}'
Then pass your tools to the Agent:
agent = Agent(task='...', llm=llm, tools=tools)
['*.example.com']). Defaults to all domains.The Agent automatically fills your function parameters based on their names, type hints, and defaults.
Your function has access to these objects:
You can use browser_session to directly interact with page elements using CSS selectors:
from browser_use import Tools, Agent, ActionResult, BrowserSession
tools = Tools()
@tools.action(description='Click the submit button using CSS selector')
async def click_submit_button(browser_session: BrowserSession):
# Get the current page
page = await browser_session.must_get_current_page()
# Get element(s) by CSS selector
elements = await page.get_elements_by_css_selector('button[type="submit"]')
if not elements:
return ActionResult(extracted_content='No submit button found')
# Click the first matching element
await elements[0].click()
return ActionResult(extracted_content='Submit button clicked!')
For more methods, see browser_use/actor/element.py
You can use Pydantic for structured tool parameters:
from pydantic import BaseModel, Field
class Cars(BaseModel):
name: str = Field(description='The name of the car, e.g. "Toyota Camry"')
price: int = Field(description='The price of the car as int in USD, e.g. 25000')
@tools.action(description='Save cars to file')
def save_cars(cars: list[Cars]) -> str:
with open('cars.json', 'w') as f:
json.dump(cars, f)
return f'Saved {len(cars)} cars to file'
task = "find cars and save them to file"
Limit tools to specific domains:
@tools.action(
description='Fill out banking forms',
allowed_domains=['https://mybank.com']
)
def fill_bank_form(account_number: str) -> str:
# Only works on mybank.com
return f'Filled form for account {account_number}'
For a comprehensive example of custom tools with Playwright integration, see the Playwright Integration Example. This shows how to create custom actions that use Playwright's precise browser automation alongside Browser-Use.
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā