browser-use

Agent SDK — Development skill for Claude Code

Development community

An agent is just a for-loop.

How to install Agent SDK

This entry records only its repository, not the path inside it, so there is no exact command to give. Open browser-use/agent-sdk and copy the folder into ~/.claude/skills/, or the file into ~/.claude/agents/.

What Agent SDK does

_An agent is just a for-loop._

Alternatives in Development

README

bu-agent-sdk

_An agent is just a for-loop._

![Agent Loop](./static/agent-loop.png)

The simplest possible agent framework. No abstractions. No magic. Just a for-loop of tool calls. The framework powering [BU.app](https://bu.app).

Install

uv sync

or

uv add bu-agent-sdk

Quick Start

import asyncio
from bu_agent_sdk import Agent, tool, TaskComplete
from bu_agent_sdk.llm import ChatAnthropic

@tool("Add two numbers")
async def add(a: int, b: int) -> int:
    return a + b

@tool("Signal task completion")
async def done(message: str) -> str:
    raise TaskComplete(message)

agent = Agent(
    llm=ChatAnthropic(model="claude-sonnet-4-20250514"),
    tools=[add, done],
)

async def main():
    result = await agent.query("What is 2 + 3?")
    print(result)

asyncio.run(main())

Philosophy

**The Bitter Lesson:** All the value is in the RL'd model, not your 10,000 lines of abstractions.

Agent frameworks fail not because models are weak, but because their action spaces are incomplete. Give the LLM as much freedom as possible, then vibe-restrict based on evals.

Features

Done Tool Pattern

The naive "stop when no tool calls" approach fails. Agents finish prematurely. Force explicit completion:

@tool("Signal completion")
async def done(message: str) -> str:
    raise TaskComplete(message)

agent = Agent(
    llm=llm,
    tools=[..., done],
    require_done_tool=True,  # Autonomous mode
)

Ephemeral Messages

Large tool outputs (browser state, screenshots) blow up context. Keep only the last N:

@tool("Get browser state", ephemeral=3)  # Keep last 3 only
async def get_state() -> str:
    return massive_dom_and_screenshot

Simple LLM Primitives

~300 lines per provider. Same interface. Full control:

from bu_agent_sdk.llm import ChatAnthropic, ChatOpenAI, ChatGoogle

# All implement BaseChatModel
agent = Agent(llm=ChatAnthropic(model="claude-sonnet-4-20250514"), tools=to