Skip to content

React agent

A single agent that uses one tool. The agent's LLMEngine runs a ReAct loop natively: read the task, decide whether to call a tool, observe the result, decide again, return the final answer.

This is the LazyBridge equivalent of LangGraph's create_react_agent — no graph DSL, no @tool decorator. Tools are plain functions; the schema comes from type hints + docstring.

Source

"""LangGraph `create_react_agent` weather example, ported to LazyBridge.

Original (LangGraph):

    from langgraph.prebuilt import create_react_agent

    def check_weather(location: str) -> str:
        '''Return the weather forecast for the specified location.'''
        return f"It's always sunny in {location}"

    graph = create_react_agent(
        "anthropic:claude-3-7-sonnet-latest",
        tools=[check_weather],
        prompt="You are a helpful assistant",
    )
    inputs = {"messages": [{"role": "user", "content": "what is the weather in sf"}]}
    for chunk in graph.stream(inputs, stream_mode="updates"):
        print(chunk)

LazyBridge equivalent: a plain ``Agent`` is already a ReAct loop. Tools are
passed by reference — schemas are derived from type hints + docstring, no
``@tool`` decorator. ``verbose=True`` prints turn-by-turn updates to stdout,
which is the equivalent of LangGraph's ``graph.stream(stream_mode="updates")``.
"""

from lazybridge import Agent, LLMEngine


def check_weather(location: str) -> str:
    """Return the weather forecast for ``location``."""
    return f"It's always sunny in {location}"


def main() -> None:
    agent = Agent(
        engine=LLMEngine("gpt-5.4-mini", system="You are a helpful assistant"),
        tools=[check_weather],
        verbose=True,
    )
    result = agent("what is the weather in sf")
    print("\nFinal answer:", result.text())


if __name__ == "__main__":
    main()

Walkthrough

  • LLMEngine("claude-opus-4-7", system=...) is the engine. The system prompt sets the persona; everything else (tool dispatch, observation, retry on bad tool call) happens inside the engine's loop.
  • tools=[check_weather] — the function is passed by reference; LazyBridge auto-wraps it as a Tool and infers the JSON schema from the type hints and docstring. No @tool decorator.
  • verbose=True prints turn-by-turn updates to stdout — the equivalent of LangGraph's graph.stream(stream_mode="updates").
  • agent("what is the weather in sf") runs the loop synchronously and returns an Envelope. .text() extracts the final answer.

Variations

  • Add more tools by extending tools=[...] — the engine emits parallel tool calls automatically when the model asks for several in one turn.
  • Swap the model for a different provider (gpt-4o, gemini-3-flash-preview) with no other changes; LazyBridge infers the provider from the model string.
  • For typed structured output, pass output=PydanticModel — the payload becomes a model instance and the framework re-prompts on validation errors.

See also

  • Agent — the constructor surface this recipe uses.
  • Tool — how plain functions become tools, and when to construct Tool(...) explicitly.
  • Researcher → reporter — the next rung: two agents in sequence.