Skip to main content

Overview

The Tessa SDK uses Pydantic models for data validation and type safety. All models are fully typed for better IDE support and runtime validation.
from tessa_sdk import (
    BrowserConfig,
    JobStatus,
    JobResult,
    JobStatusEnum,
    ActionSelectionModel
)

BrowserConfig

Configuration options for browser sessions.
class BrowserConfig(BaseModel):
    width: int = 1920           # Viewport width (320-4096)
    height: int = 1080          # Viewport height (320-4096)
    residential_ip: bool = False  # Use residential IP proxy
    max_duration_minutes: int = 30  # Max duration (1-240)
    idle_timeout_minutes: int = 2   # Idle timeout (1-60)

Fields

width
integer
default:"1920"
Browser viewport width in pixels. Must be between 320 and 4096.
height
integer
default:"1080"
Browser viewport height in pixels. Must be between 320 and 4096.
residential_ip
boolean
default:"False"
Whether to use residential IP proxy for geo-restricted content or sites with anti-bot measures.
max_duration_minutes
integer
default:"30"
Maximum duration for the browser session in minutes. Must be between 1 and 240.
idle_timeout_minutes
integer
default:"2"
Time to wait before timing out an idle session. Must be between 1 and 60.

Examples

from tessa_sdk import BrowserConfig

# Default configuration
config = BrowserConfig()

# Mobile viewport
mobile_config = BrowserConfig(
    width=375,
    height=812
)

# High-security configuration
secure_config = BrowserConfig(
    residential_ip=True,
    max_duration_minutes=60,
    idle_timeout_minutes=5
)

# Desktop 4K viewport
desktop_4k = BrowserConfig(
    width=3840,
    height=2160
)

# Validation example
try:
    invalid_config = BrowserConfig(width=5000)  # Too large
except ValidationError as e:
    print(f"Invalid config: {e}")

ActionSelectionModel

AI models available for browser action selection.
class ActionSelectionModel(str, Enum):
    CLAUDE_SONNET = "claude-sonnet-4-20250514"
    GEMINI_FLASH = "gemini/gemini-2.5-flash"
    GPT_4O = "gpt-4o"

Available Models

ModelValueDescriptionBest For
CLAUDE_SONNET"claude-sonnet-4-20250514"Claude 3.5 Sonnet (Default)General automation, best accuracy
GPT_4O"gpt-4o"OpenAI GPT-4Complex reasoning, creative tasks
GEMINI_FLASH"gemini/gemini-2.5-flash"Google Gemini FlashFast, cost-effective tasks

Usage

from tessa_sdk import BrowserAgent, ActionSelectionModel

# Using enum
agent = BrowserAgent(
    api_key="YOUR_API_KEY",
    model=ActionSelectionModel.CLAUDE_SONNET
)

# Using string value
agent = BrowserAgent(
    api_key="YOUR_API_KEY",
    model="gpt-4o"
)

# Get default model
default = ActionSelectionModel.default()
print(f"Default model: {default.value}")

JobStatusEnum

Possible job status values.
class JobStatusEnum(str, Enum):
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    USER_TAKEN_OVER = "user_taken_over"

Status Values

StatusDescriptionFinal State
RUNNINGJob is currently executingNo
COMPLETEDJob finished successfullyYes
FAILEDJob encountered an errorYes
USER_TAKEN_OVERUser took manual controlYes

Example

from tessa_sdk import JobStatusEnum

def is_job_done(status: JobStatusEnum) -> bool:
    """Check if job is in a final state."""
    return status in [
        JobStatusEnum.COMPLETED,
        JobStatusEnum.FAILED,
        JobStatusEnum.USER_TAKEN_OVER
    ]

# Usage
if status == JobStatusEnum.COMPLETED:
    print("Success!")
elif status == JobStatusEnum.FAILED:
    print("Job failed")

JobStatus

Complete job status information.
class JobStatus(BaseModel):
    job_id: str                          # Unique job identifier
    user_id: str                         # Owner user ID
    directive: Optional[str]             # Original instruction
    status: JobStatusEnum                # Current status
    output: Optional[Dict[str, Any]]    # Result data
    error: Optional[str]                 # Error message if failed
    live_url: Optional[str]              # Live viewing URL
    cdp_url: Optional[str]               # Chrome DevTools URL
    history_url: Optional[str]           # History viewing URL
    credits_used: Optional[int]          # Credits consumed
    credit_balance: Optional[int]        # Remaining credits
    created_at: Optional[datetime]       # Creation timestamp
    updated_at: Optional[datetime]       # Last update timestamp

Fields

job_id
string
required
Unique identifier for the job.
user_id
string
required
ID of the user who owns this job.
directive
string
The original natural language instruction.
status
JobStatusEnum
required
Current job status.
output
dict
The extracted data or results when completed.
error
string
Error message if the job failed.
live_url
string
URL to watch the live browser session.
cdp_url
string
Chrome DevTools Protocol URL for debugging.
history_url
string
URL to view session history and logs.
credits_used
integer
Number of credits consumed by this job.
credit_balance
integer
User’s remaining credit balance.
created_at
datetime
When the job was created.
updated_at
datetime
When the job was last updated.

Example

from tessa_sdk import TessaClient

client = TessaClient("YOUR_API_KEY")
status = client.get_job_status("job_abc123")

# Access fields
print(f"Job ID: {status.job_id}")
print(f"Status: {status.status}")
print(f"Credits used: {status.credits_used}")

if status.status == "completed":
    print(f"Output: {status.output}")
elif status.status == "failed":
    print(f"Error: {status.error}")

# Calculate duration
if status.created_at and status.updated_at:
    duration = (status.updated_at - status.created_at).total_seconds()
    print(f"Duration: {duration:.2f} seconds")

JobResult

Final result of a completed job.
class JobResult(BaseModel):
    job_id: str                          # Job identifier
    status: JobStatusEnum                # Final status
    output: Optional[Dict[str, Any]]    # Result data
    error: Optional[str]                 # Error if failed
    credits_used: int                    # Credits consumed
    duration_seconds: Optional[float]    # Job duration
    
    @property
    def is_successful(self) -> bool:
        """Check if job completed successfully."""
        return self.status == JobStatusEnum.COMPLETED
    
    @property
    def is_failed(self) -> bool:
        """Check if job failed."""
        return self.status == JobStatusEnum.FAILED
    
    def get_output(self, key: Optional[str] = None) -> Any:
        """Get output data, optionally by key."""
        if not self.output:
            return None
        if key:
            return self.output.get(key)
        return self.output

Properties and Methods

is_successful
boolean
Returns True if the job completed successfully.
is_failed
boolean
Returns True if the job failed.
get_output(key)
method
Get output data, optionally by specific key.

Example

from tessa_sdk import BrowserAgent

agent = BrowserAgent("YOUR_API_KEY")
result = agent.run("Extract data from example.com")

# Check success
if result.is_successful:
    print(f"Success! Credits used: {result.credits_used}")
    
    # Access output
    data = result.output
    
    # Get specific field
    title = result.get_output("title")
    
    # Duration if available
    if result.duration_seconds:
        print(f"Took {result.duration_seconds:.2f} seconds")
else:
    print(f"Failed: {result.error}")

Request/Response Models

RunBrowserAgentRequest

Internal request model for starting browser agents.
class RunBrowserAgentRequest(BaseModel):
    directive: str                                  # Required instruction
    initial_url: Optional[str] = None              # Starting URL
    cdp_url: Optional[str] = None                  # Custom browser CDP URL
    live_url: Optional[str] = None                 # Custom live view URL
    action_selection_model: ActionSelectionModel   # AI model
    browser_config: Optional[BrowserConfig] = None # Browser settings

RunBrowserAgentResponse

Response when starting a browser agent.
class RunBrowserAgentResponse(BaseModel):
    job_id: str                    # Job identifier
    status: JobStatusEnum          # Initial status
    live_url: Optional[str]        # Live viewing URL
    cdp_url: Optional[str]         # Chrome DevTools URL
    history_url: str               # History URL
    polling_url: str               # Status polling endpoint

Type Hints and Validation

The SDK provides full type hints for better IDE support:
from typing import Optional, Dict, Any
from tessa_sdk import BrowserAgent, JobResult

def extract_with_retry(
    agent: BrowserAgent,
    url: str,
    max_retries: int = 3
) -> Optional[Dict[str, Any]]:
    """Extract data with retry logic."""
    
    for attempt in range(max_retries):
        result: JobResult = agent.extract(
            url=url,
            data_description="all text content"
        )
        
        if result.is_successful:
            return result.output
    
    return None

# IDE will provide autocomplete and type checking
agent = BrowserAgent("YOUR_API_KEY")
data = extract_with_retry(agent, "https://example.com")

Custom Models

You can extend the SDK models for your use case:
from pydantic import BaseModel, Field
from tessa_sdk import JobResult
from typing import List, Optional

class ProductData(BaseModel):
    """Custom model for product data."""
    name: str
    price: float
    availability: bool
    url: str

class ScrapingResult(BaseModel):
    """Extended result model."""
    job_result: JobResult
    products: List[ProductData]
    scraped_at: datetime
    
    @classmethod
    def from_job_result(cls, result: JobResult):
        """Create from JobResult."""
        products = []
        if result.is_successful and result.output:
            for item in result.output.get("products", []):
                products.append(ProductData(**item))
        
        return cls(
            job_result=result,
            products=products,
            scraped_at=datetime.now()
        )

# Usage
result = agent.run("Extract product data")
scraping_result = ScrapingResult.from_job_result(result)

for product in scraping_result.products:
    print(f"{product.name}: ${product.price}")

Validation Examples

The SDK validates all inputs automatically:
from tessa_sdk import BrowserConfig
from pydantic import ValidationError

# Invalid width (too large)
try:
    config = BrowserConfig(width=5000)
except ValidationError as e:
    print(f"Validation error: {e}")
    # width: ensure this value is less than or equal to 4096

# Invalid duration (too long)
try:
    config = BrowserConfig(max_duration_minutes=500)
except ValidationError as e:
    print(f"Validation error: {e}")
    # max_duration_minutes: ensure this value is less than or equal to 240

# Valid configuration
config = BrowserConfig(
    width=1920,
    height=1080,
    residential_ip=True,
    max_duration_minutes=60
)
print(f"Valid config: {config.model_dump()}")

JSON Serialization

All models support JSON serialization:
import json
from tessa_sdk import BrowserConfig, JobResult

# Serialize to JSON
config = BrowserConfig(width=1920, height=1080)
json_str = config.model_dump_json()
print(json_str)
# {"width": 1920, "height": 1080, "residential_ip": false, ...}

# Deserialize from JSON
json_data = '{"width": 1366, "height": 768}'
config = BrowserConfig.model_validate_json(json_data)
print(config.width)  # 1366

# Save results to file
result = agent.run("Extract data")
with open("result.json", "w") as f:
    json.dump(result.model_dump(), f, indent=2, default=str)

See Also

I