Skip to content

Quickstart

Five minutes from pip install to a running agent that calls a tool.

1. Install

pip install "lazybridge[anthropic]"

LazyBridge has no required provider — pick the SDK matching the model you want to call. Available extras: anthropic, openai, google, deepseek, litellm (for 100+ providers via LiteLLM). You can install several at once.

Set the matching API key:

export ANTHROPIC_API_KEY=sk-ant-...

2. Your first agent

from lazybridge import Agent

# Tier alias — picks "whatever provider X considers cheap-tier right
# now".  Survives model-SKU renames without docs drift.  Works with
# any of: anthropic / openai / google / deepseek.
agent = Agent.from_provider("anthropic", tier="cheap")
result = agent("Explain LazyBridge in one sentence.")
print(result.text())

Prefer tier aliases in first-contact code. When you need to pin a specific model (for reproducibility, multimodal features, or provider-specific behaviour), use the explicit form:

from lazybridge import Agent, LLMEngine

# Pin a specific SKU when you need it.  Cheap-tier models across
# providers (Jan 2026): claude-haiku-4-5, gpt-5.4-mini, gpt-4o-mini,
# gemini-3-flash-preview, deepseek-v4-flash.
agent = Agent(engine=LLMEngine("claude-haiku-4-5"))
result = agent("Explain LazyBridge in one sentence.")
print(result.text())

Both are complete, runnable programs — no asyncio.run, no event loop, no @tool decorators. The canonical shape is Agent(engine=...) with each argument on its own line: it's what every example in examples/ uses, and it's what you'll extend the moment you need to configure the engine (system=, max_turns=, thinking=, …).

A shorter form exists — Agent("claude-opus-4-7") is a positional shortcut for Agent(engine=LLMEngine("claude-opus-4-7")). It saves a line at the cost of hiding which engine drives the agent at the call site. Stick to the canonical form while you're learning; reach for the shortcut only after you can write the canonical version from memory.

(The bare-provider-name form Agent("anthropic") was removed in 0.7.9.x because it left the model id ambiguous at request time — use Agent.from_provider("anthropic", tier="…") for tier-alias selection.)

Calling agent(task) returns an Envelope — LazyBridge's typed result wrapper that carries the payload, token / cost metadata, error info, and any nested sub-agent rollup. Call .text() to get a string.

If you'd rather drive things asynchronously, every agent also exposes await agent.run(task) and an async for chunk in agent.stream(task) streaming form. The sync call shown above is the canonical entry point.

Inside FastAPI / aiohttp / async workers, use await agent.run(...)

agent(task) detects an already-running event loop and dispatches the coroutine onto a worker thread, blocking the caller until the thread finishes. That keeps notebook ergonomics working but stalls async-request handlers and burns one thread per call. Use await agent.run(task) directly when you're already inside a loop.

3. Add a tool

A tool is just a normal Python function. LazyBridge inspects the signature, type hints, and docstring to build the schema the LLM sees — no second JSON definition required.

from lazybridge import Agent, LLMEngine, Tool

def get_weather(city: str) -> str:
    """Return the current weather for ``city``."""
    # Replace with a real API call. This stub keeps the example offline.
    return f"It's 18°C and sunny in {city}."

agent = Agent(
    engine=LLMEngine("claude-opus-4-7"),
    tools=[Tool.wrap(get_weather, name="get_weather")],
)
result = agent("What's the weather like in Paris right now?")
print(result.text())

The bare-function form (tools=[get_weather]) is supported as a convenience. Production code should prefer the explicit Tool.wrap(fn, name=...) form: it pins the LLM-visible tool name, which keeps the agent's tool-map (the name → Tool lookup the LLM uses to dispatch a call) and plan-step references stable as the function name evolves.

The agent will decide on its own to call get_weather("Paris"), observe the result, and produce the final answer. You did not define a JSON schema, you did not write any orchestration code, and you did not lock yourself to a specific provider.

To watch the loop turn-by-turn, pass verbose=True — it's the equivalent of LangGraph's graph.stream(stream_mode="updates").

You've now seen the whole core surface: an agent, a model, and a function exposed as a tool. From here: