Zero-boilerplate multi-provider LLM agent framework
Project description
LazyBridge
Status: alpha (0.7.x). API is intentionally fluid pre-1.0 — see CHANGELOG for breaking changes between minor releases . Pin a minor (
lazybridge>=0.7,<0.8) in production until 1.0.
Zero-boilerplate, multi-provider Python framework for LLM agents. One
Agent class, swappable engines (LLM / Plan / Human / Supervisor), and one
tool contract — plain Python functions, other Agents, MCP servers, and full
pipelines all compose through tools=[...]. Parallelism is automatic when the
engine emits N tool calls in a turn; deterministic when you declare it.
from lazybridge import Agent, LLMEngine
agent = Agent(
engine=LLMEngine("claude-opus-4-7"),
)
result = agent("hello")
print(result.text())
That's the whole surface when you start. It grows only when your problem grows.
- Documentation: https://lazybridge.com
- Recipes: https://lazybridge.com/recipes/
- For LLM assistants (Claude Skill,
llms.txt): https://lazybridge.com/for-llms/
The mental model
Every Agent is the composition Engine + Tools + State:
- Engine — what decides next.
LLMEngineis the common case; swap forPlan(deterministic DAG),HumanEngine(approval gate), orSupervisorEngine(REPL). - Tools — anything the agent can invoke. Functions, other
Agents,Plan-backed pipelines, MCP servers, and provider-native tools live in the sametools=[...]list. - State —
Memory(in-prompt history),Store(durable blackboard),Session(event bus + observability).
The same Agent(engine=..., tools=..., ...) shape supports a one-shot helper,
a hierarchical multi-agent system, and a checkpointed production pipeline —
only the engine= argument changes. See
Concepts → Mental model.
Pick your tier
LazyBridge grows with you — every tier is additive.
| Tier | For | Key imports |
|---|---|---|
| Basic | one-shot or tool-calling agents | Agent · LLMEngine · Tool · NativeTool · Envelope |
| Mid | real apps with memory, tracing, guardrails, composition | Memory · Store · Session · Guard* · verify= · MCP · HumanEngine · EvalSuite |
| Full | production pipelines: typed hand-offs, routing, resume, OTel | Plan · Step · sentinels · SupervisorEngine · checkpoint · exporters |
| Advanced | extending the framework | BaseProvider · Plan.to_dict · custom engines · OpenTelemetry · Visualizer |
See Decisions → Pick your tier for a flowchart.
Install
PyPI version note. Until LazyBridge 0.7.9 is published to PyPI, the 0.4.x release on PyPI exposes the older
LazyAgent/LazyTool/LazySessionAPI and does not match this README. Install from source while we ship 0.7.9 — or pinlazybridge>=0.7.9once it lands:pip install "git+https://github.com/selvaz/LazyBridge.git#egg=lazybridge[anthropic]"
pip install "lazybridge[anthropic]" # post-0.7.9 once on PyPI
# or [openai], [google], [deepseek], [litellm], [mcp], [otel], [encryption], [all]
Confirm you're on the modern API:
import lazybridge
assert lazybridge.__version__.startswith("0.7."), (
f"LazyBridge {lazybridge.__version__} is too old — this README "
f"requires >=0.7.9. See https://github.com/selvaz/LazyBridge."
)
Set an API key for your provider of choice (ANTHROPIC_API_KEY,
OPENAI_API_KEY, GOOGLE_API_KEY, DEEPSEEK_API_KEY).
Worked examples
1 · Function becomes a tool, auto-schema
from lazybridge import Agent, LLMEngine, Tool
def get_weather(city: str) -> str:
"""Return current temperature and conditions for ``city``."""
return f"{city}: 22°C, sunny"
agent = Agent(
engine=LLMEngine("claude-opus-4-7"),
tools=[Tool.wrap(get_weather, name="get_weather")],
)
result = agent("what's the weather in Rome and Paris?")
print(result.text())
No decorators, no JSON schemas. Type hints + docstring become the tool's
LLM-facing schema automatically. The explicit Tool.wrap(fn, name=...)
factory pins the LLM-visible name so refactors don't break tool-maps
or plan references; the bare-callable form tools=[get_weather] works
too (backward-compatible auto-wrap). See
Guides → Basic → Tool.
2 · Native tools (no code at all)
from lazybridge import Agent, LLMEngine, NativeTool
agent = Agent(
engine=LLMEngine("claude-opus-4-7"),
native_tools=[NativeTool.WEB_SEARCH],
)
agent("AI news this week")
WEB_SEARCH · CODE_EXECUTION · FILE_SEARCH · COMPUTER_USE ·
GOOGLE_SEARCH · GOOGLE_MAPS (each supported by a subset of providers).
CODE_EXECUTION and COMPUTER_USE require
allow_dangerous_native_tools=True — they execute code or click your screen.
3 · Tool-is-tool — agents wrap agents
from lazybridge import Agent, LLMEngine
researcher = Agent(
engine=LLMEngine("claude-opus-4-7"),
tools=[search],
name="research",
)
editor = Agent(
engine=LLMEngine("claude-opus-4-7"),
tools=[researcher],
name="editor",
)
result = editor("summarise AI trends April 2026")
print(result.text())
Parallelism is emergent: when editor decides to call two tools in the same
turn, they run concurrently via asyncio.gather. No flag, no config, no
"parallel mode".
4 · MCP servers as tool catalogues
from lazybridge import Agent, LLMEngine
from lazybridge.ext.mcp import MCP
fs = MCP.stdio(
"fs",
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "/tmp/project"],
allow=["fs.read_*", "fs.list_*"], # required since 0.7.9 (deny-by-default)
cache_tools_ttl=60.0,
)
agent = Agent(
engine=LLMEngine("claude-opus-4-7"),
tools=[fs],
)
agent("Read README.md and summarise the install steps")
The MCP server expands into one LazyBridge Tool per remote tool — no
separate engine, no graph wrappers. See
Guides → Mid → MCP.
5 · Declared typed pipeline with crash resume
from lazybridge import Agent, LLMEngine, Plan, Step, Store, from_prev, from_step
store = Store(db="pipeline.sqlite")
researcher = Agent(engine=LLMEngine("claude-opus-4-7"), name="search")
ranker = Agent(engine=LLMEngine("claude-opus-4-7"), name="rank")
writer = Agent(engine=LLMEngine("gpt-5.4-mini"), name="write")
pipeline = Agent(
engine=Plan(
Step("search", writes="hits"),
Step("rank",
task="Rank these search hits by relevance; return the top 5.",
context=from_prev),
Step("write",
task="Write a 200-word brief from the ranked items.",
context=from_step("rank")),
store=store,
checkpoint_key="research",
resume=True,
),
tools=[researcher, ranker, writer],
)
pipeline("AI trends April 2026")
If a step fails mid-plan, the next run with resume=True retries from the
failing step only. Concurrent runs on the same checkpoint_key are serialised
via compare_and_swap — first writer wins, second raises
ConcurrentPlanRunError. Pass on_concurrent="fork" for fan-out workflows.
See Guides → Full → Checkpoint & resume.
6 · Human-in-the-loop with a full REPL
from lazybridge import Agent, LLMEngine
from lazybridge.ext.hil import supervisor_agent
sup = supervisor_agent(
tools=[search],
agents=[researcher], # human can `retry research: <feedback>`
)
result = sup("publish a policy brief")
print(result.text())
REPL commands: continue, retry <agent>: <feedback>, store <key>,
<tool>(<args>). For approval-only flows use the lighter human_agent(...)
or HumanEngine — see
Decisions → HumanEngine vs SupervisorEngine.
What makes LazyBridge different
- Tool-is-Tool. Functions, Agents, Agents-of-Agents,
Plan-backed pipelines, and tool providers (MCP servers, external HTTP gateways) all plug intotools=[...]with the same contract. - Compile-time plan validation.
PlanCompileErrorat construction catches broken DAGs — duplicate names, forward references, brokenfrom_step/from_parallelsentinels — before any LLM call. - CAS-protected crash resume.
Plancheckpoints toStoreviacompare_and_swap. Two concurrent runs on the samecheckpoint_keydeterministically converge instead of silently overwriting. - Parallelism as capability. When the engine emits N tool calls in one
turn, they run concurrently via
asyncio.gather. No flag, notool_choice="parallel"knob. - Transitive cost roll-up.
Envelope.metadata.nested_*aggregates token / cost telemetry across an Agent-of-Agents tree — the outer envelope reports total pipeline spend without double-counting. - OTel GenAI conventions out of the box.
OTelExportershipsgen_ai.*attributes and proper parent-child spans; existing GenAI dashboards render LazyBridge traces unchanged. - First-class LLM-assistant artifact. A signature-first Claude Skill
ships with the library at
lazybridge/skill/, loadable by any LLM coding assistant. See For LLM assistants.
Documentation
The full docs live at https://lazybridge.com. Highlights:
- Concepts — the mental model, "everything is a tool", progressive complexity, and canonical-vs-sugar.
- Guides — one focused page per public concept, all following the same Signature → Synopsis → When to use / NOT → Example → Pitfalls → See also template.
- Recipes — runnable
examples from
examples/, embedded verbatim. - Decisions — "which
one do I use?" trees for tier, return type, state layer, composition,
parallelism, HumanEngine vs SupervisorEngine,
verify=placement, checkpointing. - Errors — cause → diagnosis → fix table for every framework exception.
- For LLM assistants —
Claude Skill install,
/llms.txtindex,/llms-full.txtcorpus.
Contributing
Issues and PRs welcome at https://github.com/selvaz/LazyBridge. Run the
test suite with pip install -e ".[test,all]" then pytest. See
SECURITY.md for the disclosure policy.
Licence
Apache 2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lazybridge-0.7.9.tar.gz.
File metadata
- Download URL: lazybridge-0.7.9.tar.gz
- Upload date:
- Size: 3.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7ab52db773cf68f31e1b92d3dfe1962c5f960a9c74a21fcdf726297d5685728
|
|
| MD5 |
f4fa8deb3bb04fc21e2664a1853d61cf
|
|
| BLAKE2b-256 |
b6b3cac5923fed3be25b89c2d77813f7f673d2e20b6c719cc171634e221f2d7c
|
Provenance
The following attestation bundles were made for lazybridge-0.7.9.tar.gz:
Publisher:
release.yml on selvaz/LazyBridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lazybridge-0.7.9.tar.gz -
Subject digest:
f7ab52db773cf68f31e1b92d3dfe1962c5f960a9c74a21fcdf726297d5685728 - Sigstore transparency entry: 1575028505
- Sigstore integration time:
-
Permalink:
selvaz/LazyBridge@28694cad15cb17bd614baf0e33b700ee55392332 -
Branch / Tag:
refs/tags/v0.7.9 - Owner: https://github.com/selvaz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@28694cad15cb17bd614baf0e33b700ee55392332 -
Trigger Event:
push
-
Statement type:
File details
Details for the file lazybridge-0.7.9-py3-none-any.whl.
File metadata
- Download URL: lazybridge-0.7.9-py3-none-any.whl
- Upload date:
- Size: 1.7 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e81275b37ee59d8af4ae94c60f3620d294ad4ece507259eefb0047a3b8d1fd7
|
|
| MD5 |
600ae279ca32e44bf6b02a7c75d9a527
|
|
| BLAKE2b-256 |
4157913f20f109ed54d8f58b8f303e991ed196d5912a819bc890c2d8e4e64170
|
Provenance
The following attestation bundles were made for lazybridge-0.7.9-py3-none-any.whl:
Publisher:
release.yml on selvaz/LazyBridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lazybridge-0.7.9-py3-none-any.whl -
Subject digest:
0e81275b37ee59d8af4ae94c60f3620d294ad4ece507259eefb0047a3b8d1fd7 - Sigstore transparency entry: 1575028547
- Sigstore integration time:
-
Permalink:
selvaz/LazyBridge@28694cad15cb17bd614baf0e33b700ee55392332 -
Branch / Tag:
refs/tags/v0.7.9 - Owner: https://github.com/selvaz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@28694cad15cb17bd614baf0e33b700ee55392332 -
Trigger Event:
push
-
Statement type: