chore: import upstream snapshot with attribution
Test Browser Use CLI Install / uv pip install (ubuntu-latest) (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use from local wheel (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use[cli] from PyPI (push) Failing after 1s
package / pip-install-on-macos-latest-py-3.11 (push) Has been skipped
package / pip-install-on-macos-latest-py-3.13 (push) Has been skipped
package / pip-install-on-ubuntu-latest-py-3.11 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.13 (push) Has been skipped
cloud_evals / trigger_cloud_eval_image_build (push) Failing after 1s
docker / build_publish_image (push) Failing after 1s
Test Browser Use CLI Install / browser-use skill sync (push) Failing after 1s
lint / code-style (push) Failing after 0s
lint / type-checker (push) Failing after 1s
package / pip-build (push) Failing after 1s
lint / syntax-errors (push) Failing after 3s
package / pip-install-on-ubuntu-latest-py-3.13 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.11 (push) Has been skipped
test / ${{ matrix.test_filename }} (push) Has been skipped
test / evaluate-tasks (push) Has been skipped
test / setup-chromium (push) Failing after 2s
test / find_tests (push) Failing after 2s
Test Browser Use CLI Install / uv pip install (windows-latest) (push) Has been cancelled
Test Browser Use CLI Install / uv pip install (macos-latest) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:02:32 +08:00
commit 4cd2d4af2b
475 changed files with 121829 additions and 0 deletions
+100
View File
@@ -0,0 +1,100 @@
"""
AWS Bedrock Examples
This file demonstrates how to use AWS Bedrock models with browser-use.
We provide two classes:
1. ChatAnthropicBedrock - Convenience class for Anthropic Claude models
2. ChatAWSBedrock - General AWS Bedrock client supporting all providers
Requirements:
- AWS credentials configured via environment variables
- boto3 installed: pip install boto3
- Access to AWS Bedrock models in your region
"""
import asyncio
from browser_use import Agent
from browser_use.llm import ChatAnthropicBedrock, ChatAWSBedrock
async def example_anthropic_bedrock():
"""Example using ChatAnthropicBedrock - convenience class for Claude models."""
print('🔹 ChatAnthropicBedrock Example')
# Initialize with Anthropic Claude via AWS Bedrock
llm = ChatAnthropicBedrock(
model='us.anthropic.claude-sonnet-4-20250514-v1:0',
aws_region='us-east-1',
temperature=0.7,
)
print(f'Model: {llm.name}')
print(f'Provider: {llm.provider}')
# Create agent
agent = Agent(
task="Navigate to google.com and search for 'AWS Bedrock pricing'",
llm=llm,
)
print("Task: Navigate to google.com and search for 'AWS Bedrock pricing'")
# Run the agent
result = await agent.run(max_steps=2)
print(f'Result: {result}')
async def example_aws_bedrock():
"""Example using ChatAWSBedrock - general client for any Bedrock model."""
print('\n🔹 ChatAWSBedrock Example')
# Initialize with any AWS Bedrock model (using Meta Llama as example)
llm = ChatAWSBedrock(
model='us.meta.llama4-maverick-17b-instruct-v1:0',
aws_region='us-east-1',
temperature=0.5,
)
print(f'Model: {llm.name}')
print(f'Provider: {llm.provider}')
# Create agent
agent = Agent(
task='Go to github.com and find the most popular Python repository',
llm=llm,
)
print('Task: Go to github.com and find the most popular Python repository')
# Run the agent
result = await agent.run(max_steps=2)
print(f'Result: {result}')
async def main():
"""Run AWS Bedrock examples."""
print('🚀 AWS Bedrock Examples')
print('=' * 40)
print('Make sure you have AWS credentials configured:')
print('export AWS_ACCESS_KEY_ID=your_key')
print('export AWS_SECRET_ACCESS_KEY=your_secret')
print('export AWS_DEFAULT_REGION=us-east-1')
print('=' * 40)
try:
# Run both examples
await example_aws_bedrock()
await example_anthropic_bedrock()
except Exception as e:
print(f'❌ Error: {e}')
print('Make sure you have:')
print('- Valid AWS credentials configured')
print('- Access to AWS Bedrock in your region')
print('- boto3 installed: pip install boto3')
if __name__ == '__main__':
asyncio.run(main())
+51
View File
@@ -0,0 +1,51 @@
"""
Simple try of the agent with Azure OpenAI.
@dev You need to add AZURE_OPENAI_KEY and AZURE_OPENAI_ENDPOINT to your environment variables.
For GPT-5.1 Codex models (gpt-5.1-codex-mini, etc.), use:
llm = ChatAzureOpenAI(
model='gpt-5.1-codex-mini',
api_version='2025-03-01-preview', # Required for Responses API
# use_responses_api='auto', # Default: auto-detects based on model
)
The Responses API is automatically used for models that require it.
"""
import asyncio
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from dotenv import load_dotenv
load_dotenv()
from browser_use import Agent
from browser_use.llm import ChatAzureOpenAI
# Make sure your deployment exists, double check the region and model name
api_key = os.getenv('AZURE_OPENAI_KEY')
azure_endpoint = os.getenv('AZURE_OPENAI_ENDPOINT')
llm = ChatAzureOpenAI(
model='gpt-5.1-codex-mini', api_key=api_key, azure_endpoint=azure_endpoint, api_version='2025-03-01-preview'
)
TASK = """
Go to google.com/travel/flights and find the cheapest flight from New York to Paris on next Sunday
"""
agent = Agent(
task=TASK,
llm=llm,
)
async def main():
await agent.run(max_steps=25)
asyncio.run(main())
+36
View File
@@ -0,0 +1,36 @@
"""
Example of the fastest + smartest LLM for browser automation.
Setup:
1. Get your API key from https://cloud.browser-use.com/new-api-key
2. Set environment variable: export BROWSER_USE_API_KEY="your-key"
"""
import asyncio
import os
from dotenv import load_dotenv
from browser_use import Agent, ChatBrowserUse
load_dotenv()
if not os.getenv('BROWSER_USE_API_KEY'):
raise ValueError('BROWSER_USE_API_KEY is not set')
async def main():
# `bu-2-0` is the optimized default. ChatBrowserUse can also route to
# provider-prefixed models (e.g. 'anthropic/claude-sonnet-4-6', 'openai/gpt-5.5',
# 'google/gemini-3-pro') through the same gateway - see browser_use_provider_models.py.
agent = Agent(
task='Find the number of stars of the browser-use repo',
llm=ChatBrowserUse(model='bu-2-0'),
)
# Run the agent
await agent.run()
if __name__ == '__main__':
asyncio.run(main())
@@ -0,0 +1,46 @@
"""
Point ChatBrowserUse at provider-prefixed models via the Browser Use gateway.
`ChatBrowserUse` isn't limited to the `bu-*` models - it also accepts
provider-prefixed ids:
- 'anthropic/claude-sonnet-4-6'
- 'openai/gpt-5.5'
- 'google/gemini-3-pro'
A single `BROWSER_USE_API_KEY` reaches Claude, GPT, and Gemini without
juggling separate OpenAI / Anthropic / Google keys. For the best speed and
cost, the default `bu-*` models are still recommended.
Setup:
1. Get your API key from https://cloud.browser-use.com/new-api-key
2. Set environment variable: export BROWSER_USE_API_KEY="your-key"
"""
import asyncio
import os
from dotenv import load_dotenv
from browser_use import Agent, ChatBrowserUse
load_dotenv()
if not os.getenv('BROWSER_USE_API_KEY'):
raise ValueError('BROWSER_USE_API_KEY is not set')
# Swap this for any provider-prefixed id the gateway supports, e.g.
# 'openai/gpt-5.5' or 'google/gemini-3-pro'
MODEL = 'anthropic/claude-sonnet-4-6'
async def main():
agent = Agent(
task='Find the number of stars of the browser-use repo',
llm=ChatBrowserUse(model=MODEL),
)
await agent.run()
if __name__ == '__main__':
asyncio.run(main())
+30
View File
@@ -0,0 +1,30 @@
"""
Setup:
1. Get your API key from https://cloud.browser-use.com/new-api-key
2. Set environment variable: export BROWSER_USE_API_KEY="your-key"
"""
from dotenv import load_dotenv
from browser_use import Agent, ChatBrowserUse
load_dotenv()
try:
from lmnr import Laminar
Laminar.initialize()
except ImportError:
pass
# Point to local llm-use server for testing
llm = ChatBrowserUse(
model='browser-use/bu-30b-a3b-preview', # BU Open Source Model!!
)
agent = Agent(
task='Find the number of stars of browser-use and stagehand. Tell me which one has more stars :)',
llm=llm,
flash_mode=True,
)
agent.run_sync()
+79
View File
@@ -0,0 +1,79 @@
"""
Example of using Cerebras with browser-use.
To use this example:
1. Set your CEREBRAS_API_KEY environment variable
2. Run this script
Cerebras integration is working great for:
- Direct text generation
- Simple tasks without complex structured output
- Fast inference for web automation
Available Cerebras models (9 total):
Small/Fast models (8B-32B):
- cerebras_llama3_1_8b (8B parameters, fast)
- cerebras_llama_4_scout_17b_16e_instruct (17B, instruction-tuned)
- cerebras_llama_4_maverick_17b_128e_instruct (17B, extended context)
- cerebras_qwen_3_32b (32B parameters)
Large/Capable models (70B-480B):
- cerebras_llama3_3_70b (70B parameters, latest version)
- cerebras_gpt_oss_120b (120B parameters, OpenAI's model)
- cerebras_qwen_3_235b_a22b_instruct_2507 (235B, instruction-tuned)
- cerebras_qwen_3_235b_a22b_thinking_2507 (235B, complex reasoning)
- cerebras_qwen_3_coder_480b (480B, code generation)
Note: Cerebras has some limitations with complex structured output due to JSON schema compatibility.
"""
import asyncio
import os
from browser_use import Agent
async def main():
# Set your API key (recommended to use environment variable)
api_key = os.getenv('CEREBRAS_API_KEY')
if not api_key:
raise ValueError('Please set CEREBRAS_API_KEY environment variable')
# Option 1: Use the pre-configured model instance (recommended)
from browser_use import llm
# Choose your model:
# Small/Fast models:
# model = llm.cerebras_llama3_1_8b # 8B, fast
# model = llm.cerebras_llama_4_scout_17b_16e_instruct # 17B, instruction-tuned
# model = llm.cerebras_llama_4_maverick_17b_128e_instruct # 17B, extended context
# model = llm.cerebras_qwen_3_32b # 32B
# Large/Capable models:
# model = llm.cerebras_llama3_3_70b # 70B, latest
# model = llm.cerebras_gpt_oss_120b # 120B, OpenAI's model
# model = llm.cerebras_qwen_3_235b_a22b_instruct_2507 # 235B, instruction-tuned
model = llm.cerebras_qwen_3_235b_a22b_thinking_2507 # 235B, complex reasoning
# model = llm.cerebras_qwen_3_coder_480b # 480B, code generation
# Option 2: Create the model instance directly
# model = ChatCerebras(
# model="qwen-3-coder-480b", # or any other model ID
# api_key=os.getenv("CEREBRAS_API_KEY"),
# temperature=0.2,
# max_tokens=4096,
# )
# Create and run the agent with a simple task
task = 'Explain the concept of quantum entanglement in simple terms.'
agent = Agent(task=task, llm=model)
print(f'Running task with Cerebras {model.name} (ID: {model.model}): {task}')
history = await agent.run(max_steps=3)
result = history.final_result()
print(f'Result: {result}')
if __name__ == '__main__':
asyncio.run(main())
+31
View File
@@ -0,0 +1,31 @@
"""
Simple script that runs the task of opening amazon and searching.
@dev Ensure we have a `ANTHROPIC_API_KEY` variable in our `.env` file.
"""
import asyncio
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from dotenv import load_dotenv
load_dotenv()
from browser_use import Agent
from browser_use.llm import ChatAnthropic
llm = ChatAnthropic(model='claude-sonnet-4-0', temperature=0.0)
agent = Agent(
task='Go to amazon.com, search for laptop, sort by best rating, and give me the price of the first result',
llm=llm,
)
async def main():
await agent.run(max_steps=10)
asyncio.run(main())
+36
View File
@@ -0,0 +1,36 @@
import asyncio
import os
from browser_use import Agent
from browser_use.llm import ChatDeepSeek
# Add your custom instructions
extend_system_message = """
Remember the most important rules:
1. When performing a search task, open https://www.google.com/ first for search.
2. Final output.
"""
deepseek_api_key = os.getenv('DEEPSEEK_API_KEY')
if deepseek_api_key is None:
print('Make sure you have DEEPSEEK_API_KEY:')
print('export DEEPSEEK_API_KEY=your_key')
exit(0)
async def main():
llm = ChatDeepSeek(
base_url='https://api.deepseek.com/v1',
model='deepseek-chat',
api_key=deepseek_api_key,
)
agent = Agent(
task='What should we pay attention to in the recent new rules on tariffs in China-US trade?',
llm=llm,
use_vision=False,
extend_system_message=extend_system_message,
)
await agent.run()
asyncio.run(main())
+31
View File
@@ -0,0 +1,31 @@
import asyncio
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from dotenv import load_dotenv
from browser_use import Agent, ChatGoogle
load_dotenv()
api_key = os.getenv('GOOGLE_API_KEY')
if not api_key:
raise ValueError('GOOGLE_API_KEY is not set')
async def run_search():
llm = ChatGoogle(model='gemini-3-pro-preview', api_key=api_key)
agent = Agent(
llm=llm,
task='How many stars does the browser-use repo have?',
flash_mode=True,
)
await agent.run()
if __name__ == '__main__':
asyncio.run(run_search())
+30
View File
@@ -0,0 +1,30 @@
import asyncio
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from dotenv import load_dotenv
from browser_use import Agent, ChatGoogle
load_dotenv()
api_key = os.getenv('GOOGLE_API_KEY')
if not api_key:
raise ValueError('GOOGLE_API_KEY is not set')
async def run_search():
llm = ChatGoogle(model='gemini-3-flash-preview', api_key=api_key)
agent = Agent(
llm=llm,
task='How many stars does the browser-use repo have?',
flash_mode=True,
)
await agent.run()
if __name__ == '__main__':
asyncio.run(run_search())
+28
View File
@@ -0,0 +1,28 @@
"""
Simple try of the agent.
@dev You need to add OPENAI_API_KEY to your environment variables.
"""
import asyncio
from dotenv import load_dotenv
from browser_use import Agent, ChatOpenAI
load_dotenv()
# All the models are type safe from OpenAI in case you need a list of supported models
llm = ChatOpenAI(model='gpt-4.1-mini')
agent = Agent(
task='Go to amazon.com, click on the first link, and give me the title of the page',
llm=llm,
)
async def main():
await agent.run(max_steps=10)
input('Press Enter to continue...')
asyncio.run(main())
+28
View File
@@ -0,0 +1,28 @@
"""
Simple try of the agent.
@dev You need to add OPENAI_API_KEY to your environment variables.
"""
import asyncio
from dotenv import load_dotenv
from browser_use import Agent, ChatOpenAI
load_dotenv()
# All the models are type safe from OpenAI in case you need a list of supported models
llm = ChatOpenAI(model='gpt-5-mini')
agent = Agent(
llm=llm,
task='Find out which one is cooler: the monkey park or a dolphin tour in Tenerife?',
)
async def main():
await agent.run(max_steps=20)
input('Press Enter to continue...')
asyncio.run(main())
+33
View File
@@ -0,0 +1,33 @@
# Langchain Models (legacy)
This directory contains example of how to still use Langchain models with the new Browser Use chat models.
## How to use
```python
from langchain_openai import ChatOpenAI
from browser_use import Agent
from .chat import ChatLangchain
async def main():
"""Basic example using ChatLangchain with OpenAI through LangChain."""
# Create a LangChain model (OpenAI)
langchain_model = ChatOpenAI(
model='gpt-4.1-mini',
temperature=0.1,
)
# Wrap it with ChatLangchain to make it compatible with browser-use
llm = ChatLangchain(chat=langchain_model)
agent = Agent(
task="Go to google.com and search for 'browser automation with Python'",
llm=llm,
)
history = await agent.run()
print(history.history)
```
+195
View File
@@ -0,0 +1,195 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING, TypeVar, overload
from pydantic import BaseModel
from browser_use.llm.base import BaseChatModel
from browser_use.llm.exceptions import ModelProviderError
from browser_use.llm.messages import BaseMessage
from browser_use.llm.views import ChatInvokeCompletion, ChatInvokeUsage
from examples.models.langchain.serializer import LangChainMessageSerializer
if TYPE_CHECKING:
from langchain_core.language_models.chat_models import BaseChatModel as LangChainBaseChatModel # type: ignore
from langchain_core.messages import AIMessage as LangChainAIMessage # type: ignore
T = TypeVar('T', bound=BaseModel)
@dataclass
class ChatLangchain(BaseChatModel):
"""
A wrapper around LangChain BaseChatModel that implements the browser-use BaseChatModel protocol.
This class allows you to use any LangChain-compatible model with browser-use.
"""
# The LangChain model to wrap
chat: 'LangChainBaseChatModel'
@property
def model(self) -> str:
return self.name
@property
def provider(self) -> str:
"""Return the provider name based on the LangChain model class."""
model_class_name = self.chat.__class__.__name__.lower()
if 'openai' in model_class_name:
return 'openai'
elif 'anthropic' in model_class_name or 'claude' in model_class_name:
return 'anthropic'
elif 'google' in model_class_name or 'gemini' in model_class_name:
return 'google'
elif 'groq' in model_class_name:
return 'groq'
elif 'ollama' in model_class_name:
return 'ollama'
elif 'deepseek' in model_class_name:
return 'deepseek'
else:
return 'langchain'
@property
def name(self) -> str:
"""Return the model name."""
# Try to get model name from the LangChain model using getattr to avoid type errors
model_name = getattr(self.chat, 'model_name', None)
if model_name:
return str(model_name)
model_attr = getattr(self.chat, 'model', None)
if model_attr:
return str(model_attr)
return self.chat.__class__.__name__
def _get_usage(self, response: 'LangChainAIMessage') -> ChatInvokeUsage | None:
usage = response.usage_metadata
if usage is None:
return None
prompt_tokens = usage['input_tokens'] or 0
completion_tokens = usage['output_tokens'] or 0
total_tokens = usage['total_tokens'] or 0
input_token_details = usage.get('input_token_details', None)
if input_token_details is not None:
prompt_cached_tokens = input_token_details.get('cache_read', None)
prompt_cache_creation_tokens = input_token_details.get('cache_creation', None)
else:
prompt_cached_tokens = None
prompt_cache_creation_tokens = None
return ChatInvokeUsage(
prompt_tokens=prompt_tokens,
prompt_cached_tokens=prompt_cached_tokens,
prompt_cache_creation_tokens=prompt_cache_creation_tokens,
prompt_image_tokens=None,
completion_tokens=completion_tokens,
total_tokens=total_tokens,
)
@overload
async def ainvoke(self, messages: list[BaseMessage], output_format: None = None) -> ChatInvokeCompletion[str]: ...
@overload
async def ainvoke(self, messages: list[BaseMessage], output_format: type[T]) -> ChatInvokeCompletion[T]: ...
async def ainvoke(
self, messages: list[BaseMessage], output_format: type[T] | None = None
) -> ChatInvokeCompletion[T] | ChatInvokeCompletion[str]:
"""
Invoke the LangChain model with the given messages.
Args:
messages: List of browser-use chat messages
output_format: Optional Pydantic model class for structured output (not supported in basic LangChain integration)
Returns:
Either a string response or an instance of output_format
"""
# Convert browser-use messages to LangChain messages
langchain_messages = LangChainMessageSerializer.serialize_messages(messages)
try:
if output_format is None:
# Return string response
response = await self.chat.ainvoke(langchain_messages) # type: ignore
# Import at runtime for isinstance check
from langchain_core.messages import AIMessage as LangChainAIMessage # type: ignore
if not isinstance(response, LangChainAIMessage):
raise ModelProviderError(
message=f'Response is not an AIMessage: {type(response)}',
model=self.name,
)
# Extract content from LangChain response
content = response.content if hasattr(response, 'content') else str(response)
usage = self._get_usage(response)
return ChatInvokeCompletion(
completion=str(content),
usage=usage,
)
else:
# Use LangChain's structured output capability
try:
structured_chat = self.chat.with_structured_output(output_format)
parsed_object = await structured_chat.ainvoke(langchain_messages)
# For structured output, usage metadata is typically not available
# in the parsed object since it's a Pydantic model, not an AIMessage
usage = None
# Type cast since LangChain's with_structured_output returns the correct type
return ChatInvokeCompletion(
completion=parsed_object, # type: ignore
usage=usage,
)
except AttributeError:
# Fall back to manual parsing if with_structured_output is not available
response = await self.chat.ainvoke(langchain_messages) # type: ignore
if not isinstance(response, 'LangChainAIMessage'):
raise ModelProviderError(
message=f'Response is not an AIMessage: {type(response)}',
model=self.name,
)
content = response.content if hasattr(response, 'content') else str(response)
try:
if isinstance(content, str):
import json
parsed_data = json.loads(content)
if isinstance(parsed_data, dict):
parsed_object = output_format(**parsed_data)
else:
raise ValueError('Parsed JSON is not a dictionary')
else:
raise ValueError('Content is not a string and structured output not supported')
except Exception as e:
raise ModelProviderError(
message=f'Failed to parse response as {output_format.__name__}: {e}',
model=self.name,
) from e
usage = self._get_usage(response)
return ChatInvokeCompletion(
completion=parsed_object,
usage=usage,
)
except Exception as e:
# Convert any LangChain errors to browser-use ModelProviderError
raise ModelProviderError(
message=f'LangChain model error: {str(e)}',
model=self.name,
) from e
+60
View File
@@ -0,0 +1,60 @@
"""
Example of using LangChain models with browser-use.
This example demonstrates how to:
1. Wrap a LangChain model with ChatLangchain
2. Use it with a browser-use Agent
3. Run a simple web automation task
@file purpose: Example usage of LangChain integration with browser-use
"""
import asyncio
from langchain_openai import ChatOpenAI # pyright: ignore
from browser_use import Agent
from examples.models.langchain.chat import ChatLangchain
async def main():
"""Basic example using ChatLangchain with OpenAI through LangChain."""
# Create a LangChain model (OpenAI)
langchain_model = ChatOpenAI(
model='gpt-4.1-mini',
temperature=0.1,
)
# Wrap it with ChatLangchain to make it compatible with browser-use
llm = ChatLangchain(chat=langchain_model)
# Create a simple task
task = "Go to google.com and search for 'browser automation with Python'"
# Create and run the agent
agent = Agent(
task=task,
llm=llm,
)
print(f'🚀 Starting task: {task}')
print(f'🤖 Using model: {llm.name} (provider: {llm.provider})')
# Run the agent
history = await agent.run()
print(f'✅ Task completed! Steps taken: {len(history.history)}')
# Print the final result if available
if history.final_result():
print(f'📋 Final result: {history.final_result()}')
return history
if __name__ == '__main__':
print('🌐 Browser-use LangChain Integration Example')
print('=' * 45)
asyncio.run(main())
+149
View File
@@ -0,0 +1,149 @@
import json
from typing import overload
from langchain_core.messages import ( # pyright: ignore
AIMessage,
HumanMessage,
SystemMessage,
)
from langchain_core.messages import ( # pyright: ignore
ToolCall as LangChainToolCall,
)
from langchain_core.messages.base import BaseMessage as LangChainBaseMessage # pyright: ignore
from browser_use.llm.messages import (
AssistantMessage,
BaseMessage,
ContentPartImageParam,
ContentPartRefusalParam,
ContentPartTextParam,
ToolCall,
UserMessage,
)
from browser_use.llm.messages import (
SystemMessage as BrowserUseSystemMessage,
)
class LangChainMessageSerializer:
"""Serializer for converting between browser-use message types and LangChain message types."""
@staticmethod
def _serialize_user_content(
content: str | list[ContentPartTextParam | ContentPartImageParam],
) -> str | list[str | dict]:
"""Convert user message content for LangChain compatibility."""
if isinstance(content, str):
return content
serialized_parts = []
for part in content:
if part.type == 'text':
serialized_parts.append(
{
'type': 'text',
'text': part.text,
}
)
elif part.type == 'image_url':
# LangChain format for images
serialized_parts.append(
{'type': 'image_url', 'image_url': {'url': part.image_url.url, 'detail': part.image_url.detail}}
)
return serialized_parts
@staticmethod
def _serialize_system_content(
content: str | list[ContentPartTextParam],
) -> str:
"""Convert system message content to text string for LangChain compatibility."""
if isinstance(content, str):
return content
text_parts = []
for part in content:
if part.type == 'text':
text_parts.append(part.text)
return '\n'.join(text_parts)
@staticmethod
def _serialize_assistant_content(
content: str | list[ContentPartTextParam | ContentPartRefusalParam] | None,
) -> str:
"""Convert assistant message content to text string for LangChain compatibility."""
if content is None:
return ''
if isinstance(content, str):
return content
text_parts = []
for part in content:
if part.type == 'text':
text_parts.append(part.text)
# elif part.type == 'refusal':
# # Include refusal content as text
# text_parts.append(f'[Refusal: {part.refusal}]')
return '\n'.join(text_parts)
@staticmethod
def _serialize_tool_call(tool_call: ToolCall) -> LangChainToolCall:
"""Convert browser-use ToolCall to LangChain ToolCall."""
# Parse the arguments string to a dict for LangChain
try:
args_dict = json.loads(tool_call.function.arguments)
except json.JSONDecodeError:
# If parsing fails, wrap in a dict
args_dict = {'arguments': tool_call.function.arguments}
return LangChainToolCall(
name=tool_call.function.name,
args=args_dict,
id=tool_call.id,
)
# region - Serialize overloads
@overload
@staticmethod
def serialize(message: UserMessage) -> HumanMessage: ...
@overload
@staticmethod
def serialize(message: BrowserUseSystemMessage) -> SystemMessage: ...
@overload
@staticmethod
def serialize(message: AssistantMessage) -> AIMessage: ...
@staticmethod
def serialize(message: BaseMessage) -> LangChainBaseMessage:
"""Serialize a browser-use message to a LangChain message."""
if isinstance(message, UserMessage):
content = LangChainMessageSerializer._serialize_user_content(message.content)
return HumanMessage(content=content, name=message.name)
elif isinstance(message, BrowserUseSystemMessage):
content = LangChainMessageSerializer._serialize_system_content(message.content)
return SystemMessage(content=content, name=message.name)
elif isinstance(message, AssistantMessage):
# Handle content
content = LangChainMessageSerializer._serialize_assistant_content(message.content)
# For simplicity, we'll ignore tool calls in LangChain integration
# as requested by the user
return AIMessage(
content=content,
name=message.name,
)
else:
raise ValueError(f'Unknown message type: {type(message)}')
@staticmethod
def serialize_messages(messages: list[BaseMessage]) -> list[LangChainBaseMessage]:
"""Serialize a list of browser-use messages to LangChain messages."""
return [LangChainMessageSerializer.serialize(m) for m in messages]
+6
View File
@@ -0,0 +1,6 @@
from browser_use import Agent, models
# available providers for this import style: openai, azure, google
agent = Agent(task='Find founders of browser-use', llm=models.azure_gpt_4_1_mini)
agent.run_sync()
+39
View File
@@ -0,0 +1,39 @@
import asyncio
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from dotenv import load_dotenv
load_dotenv()
from browser_use import Agent
from browser_use.llm import ChatGroq
groq_api_key = os.environ.get('GROQ_API_KEY')
llm = ChatGroq(
model='meta-llama/llama-4-maverick-17b-128e-instruct',
# temperature=0.1,
)
# llm = ChatGroq(
# model='meta-llama/llama-4-maverick-17b-128e-instruct',
# api_key=os.environ.get('GROQ_API_KEY'),
# temperature=0.0,
# )
task = 'Go to amazon.com, search for laptop, sort by best rating, and give me the price of the first result'
async def main():
agent = Agent(
task=task,
llm=llm,
)
await agent.run()
if __name__ == '__main__':
asyncio.run(main())
+28
View File
@@ -0,0 +1,28 @@
"""
Simple agent run with Mistral.
You need to set MISTRAL_API_KEY in your environment (and optionally MISTRAL_BASE_URL).
"""
import asyncio
from dotenv import load_dotenv
from browser_use import Agent
from browser_use.llm.mistral import ChatMistral
load_dotenv()
llm = ChatMistral(model='mistral-small-2506', temperature=0.6)
agent = Agent(
llm=llm,
task='List two fun weekend activities in Barcelona.',
)
async def main():
await agent.run(max_steps=10)
input('Press Enter to continue...')
asyncio.run(main())
+34
View File
@@ -0,0 +1,34 @@
"""
Simple try of the agent.
@dev You need to add MODELSCOPE_API_KEY to your environment variables.
"""
import asyncio
import os
from dotenv import load_dotenv
from browser_use import Agent, ChatOpenAI
# dotenv
load_dotenv()
api_key = os.getenv('MODELSCOPE_API_KEY', '')
if not api_key:
raise ValueError('MODELSCOPE_API_KEY is not set')
async def run_search():
agent = Agent(
# task=('go to amazon.com, search for laptop'),
task=('go to google, search for modelscope'),
llm=ChatOpenAI(base_url='https://api-inference.modelscope.cn/v1/', model='Qwen/Qwen2.5-VL-72B-Instruct', api_key=api_key),
use_vision=False,
)
await agent.run()
if __name__ == '__main__':
asyncio.run(run_search())
+38
View File
@@ -0,0 +1,38 @@
import asyncio
import os
from dotenv import load_dotenv
from browser_use import Agent, ChatOpenAI
load_dotenv()
# Get API key from environment variable
api_key = os.getenv('MOONSHOT_API_KEY')
if api_key is None:
print('Make sure you have MOONSHOT_API_KEY set in your .env file')
print('Get your API key from https://platform.moonshot.ai/console/api-keys ')
exit(1)
# Configure Moonshot AI model
llm = ChatOpenAI(
model='kimi-k2-thinking',
base_url='https://api.moonshot.ai/v1',
api_key=api_key,
add_schema_to_system_prompt=True,
remove_min_items_from_schema=True, # Moonshot doesn't support minItems in JSON schema
remove_defaults_from_schema=True, # Moonshot doesn't allow default values with anyOf
)
async def main():
agent = Agent(
task='Search for the latest news about AI and summarize the top 3 articles',
llm=llm,
flash_mode=True,
)
await agent.run()
if __name__ == '__main__':
asyncio.run(main())
+45
View File
@@ -0,0 +1,45 @@
"""
Simple try of the agent.
@dev You need to add NOVITA_API_KEY to your environment variables.
"""
import asyncio
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from dotenv import load_dotenv
load_dotenv()
from browser_use import Agent, ChatOpenAI
api_key = os.getenv('NOVITA_API_KEY', '')
if not api_key:
raise ValueError('NOVITA_API_KEY is not set')
async def run_search():
agent = Agent(
task=(
'1. Go to https://www.reddit.com/r/LocalLLaMA '
"2. Search for 'browser use' in the search bar"
'3. Click on first result'
'4. Return the first comment'
),
llm=ChatOpenAI(
base_url='https://api.novita.ai/v3/openai',
model='deepseek/deepseek-v3-0324',
api_key=api_key,
),
use_vision=False,
)
await agent.run()
if __name__ == '__main__':
asyncio.run(run_search())
+253
View File
@@ -0,0 +1,253 @@
"""
Oracle Cloud Infrastructure (OCI) Raw API Example
This example demonstrates how to use OCI's Generative AI service with browser-use
using the raw API integration (ChatOCIRaw) without Langchain dependencies.
@dev You need to:
1. Set up OCI configuration file at ~/.oci/config
2. Have access to OCI Generative AI models in your tenancy
3. Install the OCI Python SDK: uv add oci
Requirements:
- OCI account with Generative AI service access
- Proper OCI configuration and authentication
- Model deployment in your OCI compartment
"""
import asyncio
import os
import sys
from pydantic import BaseModel
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from browser_use import Agent
from browser_use.llm import ChatOCIRaw
class SearchSummary(BaseModel):
query: str
results_found: int
top_result_title: str
summary: str
relevance_score: float
# Configuration examples for different providers
compartment_id = 'ocid1.tenancy.oc1..aaaaaaaayeiis5uk2nuubznrekd6xsm56k3m4i7tyvkxmr2ftojqfkpx2ura'
endpoint = 'https://inference.generativeai.us-chicago-1.oci.oraclecloud.com'
# Example 1: Meta Llama model (uses GenericChatRequest)
meta_model_id = 'ocid1.generativeaimodel.oc1.us-chicago-1.amaaaaaask7dceyarojgfh6msa452vziycwfymle5gxdvpwwxzara53topmq'
meta_llm = ChatOCIRaw(
model_id=meta_model_id,
service_endpoint=endpoint,
compartment_id=compartment_id,
provider='meta', # Meta Llama model
temperature=0.7,
max_tokens=800,
frequency_penalty=0.0,
presence_penalty=0.0,
top_p=0.9,
auth_type='API_KEY',
auth_profile='DEFAULT',
)
cohere_model_id = 'ocid1.generativeaimodel.oc1.us-chicago-1.amaaaaaask7dceyanrlpnq5ybfu5hnzarg7jomak3q6kyhkzjsl4qj24fyoq'
# Example 2: Cohere model (uses CohereChatRequest)
# cohere_model_id = "ocid1.generativeaimodel.oc1.us-chicago-1.amaaaaaask7dceyapnibwg42qjhwaxrlqfpreueirtwghiwvv2whsnwmnlva"
cohere_llm = ChatOCIRaw(
model_id=cohere_model_id,
service_endpoint=endpoint,
compartment_id=compartment_id,
provider='cohere', # Cohere model
temperature=1.0,
max_tokens=600,
frequency_penalty=0.0,
top_p=0.75,
top_k=0, # Cohere-specific parameter
auth_type='API_KEY',
auth_profile='DEFAULT',
)
# Example 3: xAI model (uses GenericChatRequest)
xai_model_id = 'ocid1.generativeaimodel.oc1.us-chicago-1.amaaaaaask7dceya3bsfz4ogiuv3yc7gcnlry7gi3zzx6tnikg6jltqszm2q'
xai_llm = ChatOCIRaw(
model_id=xai_model_id,
service_endpoint=endpoint,
compartment_id=compartment_id,
provider='xai', # xAI model
temperature=1.0,
max_tokens=20000,
top_p=1.0,
top_k=0,
auth_type='API_KEY',
auth_profile='DEFAULT',
)
# Use Meta model by default for this example
llm = xai_llm
async def basic_example():
"""Basic example using ChatOCIRaw with a simple task."""
print('🔹 Basic ChatOCIRaw Example')
print('=' * 40)
print(f'Model: {llm.name}')
print(f'Provider: {llm.provider_name}')
# Create agent with a simple task
agent = Agent(
task="Go to google.com and search for 'Oracle Cloud Infrastructure pricing'",
llm=llm,
)
print("Task: Go to google.com and search for 'Oracle Cloud Infrastructure pricing'")
# Run the agent
try:
result = await agent.run(max_steps=5)
print('✅ Task completed successfully!')
print(f'Final result: {result}')
except Exception as e:
print(f'❌ Error: {e}')
async def structured_output_example():
"""Example demonstrating structured output with Pydantic models."""
print('\n🔹 Structured Output Example')
print('=' * 40)
# Create agent that will return structured data
agent = Agent(
task="""Go to github.com, search for 'browser automation python',
find the most popular repository, and return structured information about it""",
llm=llm,
output_format=SearchSummary, # This will enforce structured output
)
print('Task: Search GitHub for browser automation and return structured data')
try:
result = await agent.run(max_steps=5)
if isinstance(result, SearchSummary):
print('✅ Structured output received!')
print(f'Query: {result.query}')
print(f'Results Found: {result.results_found}')
print(f'Top Result: {result.top_result_title}')
print(f'Summary: {result.summary}')
print(f'Relevance Score: {result.relevance_score}')
else:
print(f'Result: {result}')
except Exception as e:
print(f'❌ Error: {e}')
async def advanced_configuration_example():
"""Example showing advanced configuration options."""
print('\n🔹 Advanced Configuration Example')
print('=' * 40)
print(f'Model: {llm.name}')
print(f'Provider: {llm.provider_name}')
print('Configuration: Cohere model with instance principal auth')
# Create agent with a more complex task
agent = Agent(
task="""Navigate to stackoverflow.com, search for questions about 'python web scraping' and tap search help,
analyze the top 3 questions, and provide a detailed summary of common challenges""",
llm=llm,
)
print('Task: Analyze StackOverflow questions about Python web scraping')
try:
result = await agent.run(max_steps=8)
print('✅ Advanced task completed!')
print(f'Analysis result: {result}')
except Exception as e:
print(f'❌ Error: {e}')
async def provider_compatibility_test():
"""Test different provider formats to verify compatibility."""
print('\n🔹 Provider Compatibility Test')
print('=' * 40)
providers_to_test = [('Meta', meta_llm), ('Cohere', cohere_llm), ('xAI', xai_llm)]
for provider_name, model in providers_to_test:
print(f'\nTesting {provider_name} model...')
print(f'Model ID: {model.model_id}')
print(f'Provider: {model.provider}')
print(f'Uses Cohere format: {model._uses_cohere_format()}')
# Create a simple agent to test the model
agent = Agent(
task='Go to google.com and tell me what you see',
llm=model,
)
try:
result = await agent.run(max_steps=3)
print(f'{provider_name} model works correctly!')
print(f'Result: {str(result)[:100]}...')
except Exception as e:
print(f'{provider_name} model failed: {e}')
async def main():
"""Run all OCI Raw examples."""
print('🚀 Oracle Cloud Infrastructure (OCI) Raw API Examples')
print('=' * 60)
print('\n📋 Prerequisites:')
print('1. OCI account with Generative AI service access')
print('2. OCI configuration file at ~/.oci/config')
print('3. Model deployed in your OCI compartment')
print('4. Proper IAM permissions for Generative AI')
print('5. OCI Python SDK installed: uv add oci')
print('=' * 60)
print('\n⚙️ Configuration Notes:')
print('• Update model_id, service_endpoint, and compartment_id with your values')
print('• Supported providers: "meta", "cohere", "xai"')
print('• Auth types: "API_KEY", "INSTANCE_PRINCIPAL", "RESOURCE_PRINCIPAL"')
print('• Default OCI config profile: "DEFAULT"')
print('=' * 60)
print('\n🔧 Provider-Specific API Formats:')
print('• Meta/xAI models: Use GenericChatRequest with messages array')
print('• Cohere models: Use CohereChatRequest with single message string')
print('• The integration automatically detects and uses the correct format')
print('=' * 60)
try:
# Run all examples
await basic_example()
await structured_output_example()
await advanced_configuration_example()
# await provider_compatibility_test()
print('\n🎉 All examples completed successfully!')
except Exception as e:
print(f'\n❌ Example failed: {e}')
print('\n🔧 Troubleshooting:')
print('• Verify OCI configuration: oci setup config')
print('• Check model OCID and availability')
print('• Ensure compartment access and IAM permissions')
print('• Verify service endpoint URL')
print('• Check OCI Python SDK installation')
print("• Ensure you're using the correct provider name in ChatOCIRaw")
if __name__ == '__main__':
asyncio.run(main())
+10
View File
@@ -0,0 +1,10 @@
# 1. Install Ollama: https://github.com/ollama/ollama
# 2. Run `ollama serve` to start the server
# 3. In a new terminal, install the model you want to use: `ollama pull llama3.1:8b` (this has 4.9GB)
from browser_use import Agent, ChatOllama
llm = ChatOllama(model='llama3.1:8b')
Agent('find the founders of browser-use', llm=llm).run_sync()
+34
View File
@@ -0,0 +1,34 @@
"""
Simple try of the agent.
@dev You need to add OPENAI_API_KEY to your environment variables.
"""
import asyncio
import os
from dotenv import load_dotenv
from browser_use import Agent, ChatOpenAI
load_dotenv()
# All the models are type safe from OpenAI in case you need a list of supported models
llm = ChatOpenAI(
# model='x-ai/grok-4',
model='deepcogito/cogito-v2.1-671b',
base_url='https://openrouter.ai/api/v1',
api_key=os.getenv('OPENROUTER_API_KEY'),
)
agent = Agent(
task='Find the number of stars of the browser-use repo',
llm=llm,
use_vision=False,
)
async def main():
await agent.run(max_steps=10)
asyncio.run(main())
+27
View File
@@ -0,0 +1,27 @@
import os
from dotenv import load_dotenv
from browser_use import Agent, ChatOpenAI
load_dotenv()
import asyncio
# get an api key from https://modelstudio.console.alibabacloud.com/?tab=playground#/api-key
api_key = os.getenv('ALIBABA_CLOUD')
base_url = 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1'
# so far we only had success with qwen-vl-max
# other models, even qwen-max, do not return the right output format. They confuse the action schema.
# E.g. they return actions: [{"navigate": "google.com"}] instead of [{"navigate": {"url": "google.com"}}]
# If you want to use smaller models and you see they mix up the action schema, add concrete examples to your prompt of the right format.
llm = ChatOpenAI(model='qwen-vl-max', api_key=api_key, base_url=base_url)
async def main():
agent = Agent(task='go find the founders of browser-use', llm=llm, use_vision=True, max_actions_per_step=1)
await agent.run()
if '__main__' == __name__:
asyncio.run(main())
+26
View File
@@ -0,0 +1,26 @@
import asyncio
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from dotenv import load_dotenv
from browser_use import Agent
load_dotenv()
async def run_search():
agent = Agent(
# llm=llm,
task='How many stars does the browser-use repo have?',
flash_mode=True,
skills=['502af156-2a75-4b4e-816d-b2dc138b6647'], # skill for fetching the number of stars of any Github repository
)
await agent.run()
if __name__ == '__main__':
asyncio.run(run_search())
+94
View File
@@ -0,0 +1,94 @@
"""
Example using Vercel AI Gateway with browser-use.
Vercel AI Gateway provides an OpenAI-compatible API endpoint that can proxy
requests to various AI providers. This allows you to use Vercel's infrastructure
for rate limiting, caching, and monitoring.
Prerequisites:
1. Set AI_GATEWAY_API_KEY in your environment variables (or rely on VERCEL_OIDC_TOKEN on Vercel)
To see all available models, visit: https://ai-gateway.vercel.sh/v1/models
"""
import asyncio
import os
from dotenv import load_dotenv
from browser_use import Agent, ChatVercel
load_dotenv()
api_key = os.getenv('AI_GATEWAY_API_KEY') or os.getenv('VERCEL_OIDC_TOKEN')
if not api_key:
raise ValueError('AI_GATEWAY_API_KEY or VERCEL_OIDC_TOKEN is not set')
# Basic usage
llm = ChatVercel(
model='openai/gpt-4o',
api_key=api_key,
)
# Example with provider options - control which providers are used and in what order
# This will try Vertex AI first, then fall back to Anthropic if Vertex fails
llm_with_provider_options = ChatVercel(
model='anthropic/claude-sonnet-4.5',
api_key=api_key,
provider_options={
'gateway': {
'order': ['vertex', 'anthropic'], # Try Vertex AI first, then Anthropic
}
},
)
# Example with reasoning and caching enabled, plus model fallbacks
llm_reasoning_and_fallbacks = ChatVercel(
model='anthropic/claude-sonnet-4.5',
api_key=api_key,
reasoning={
'anthropic': {'thinking': {'type': 'enabled', 'budgetTokens': 2000}},
},
model_fallbacks=[
'openai/gpt-5.2',
'google/gemini-2.5-flash',
],
caching='auto',
provider_options={
'gateway': {
# Example BYOK configuration; replace with your real keys if needed
'byok': {
'anthropic': [
{
'apiKey': os.getenv('ANTHROPIC_API_KEY', ''),
}
]
},
}
},
)
agent = Agent(
task='Go to example.com and summarize the main content',
llm=llm,
)
agent_with_provider_options = Agent(
task='Go to example.com and summarize the main content',
llm=llm_with_provider_options,
)
agent_with_reasoning_and_fallbacks = Agent(
task='Go to example.com and summarize the main content with detailed reasoning',
llm=llm_reasoning_and_fallbacks,
)
async def main():
await agent.run(max_steps=10)
await agent_with_provider_options.run(max_steps=10)
await agent_with_reasoning_and_fallbacks.run(max_steps=10)
if __name__ == '__main__':
asyncio.run(main())