Collaboration between agents: Using Amazon Nova 2 Lite and Amazon Nova Act in multi-agent systems

Machine Learning


My first attempt at building a travel planning agent was exactly like most early prototypes: one large model, a few tools, and a long system prompt. It was working fine until real world complexities showed up. Flights were served from a clean API, hotels were behind a changing web UI, and models kept mixing up instructions, forgetting context, and hallucinating. It became clear then that a single agent was not the solution, it was the bottleneck.

Finding the fix required splitting the work rather than fixing the prompt. This post explains how collaboration between agents in Amazon Bedrock actually works. Turn your fragile single-agent setup into a predictable multi-agent system using Amazon Nova 2 Lite for planning and Amazon Nova Act for browser operations.

Solution overview

The system is built as a group of small agents working together, as shown in the following diagram. One agent plans the work and discusses it with the user. Other agents handle specific tasks, such as flight searches or hotel searches. Communicate through simple messages so each agent stays focused and understands tasks easily.

The pattern was clear when looking at where the single-agent design broke down. Agents struggle not because the tasks are difficult, but because they are fundamentally different. Flight searches are structured and predictable. Hotel searches are messy, visual, and full of dynamic elements. Balancing both in one model is like asking the same engineer to write a backend API and manually click through your website in real time. And the more I tried to patch it using prompts, tools, and fallback logic, the worse the situation became. When a single agent becomes overloaded with too many responsibilities, it slows down, loses context, makes inconsistent choices, and ultimately collapses under its own weight. The problem is in the design, and trying to address it through prompts doesn’t work. The fix was to divide the work among three agents, allowing each agent to focus on one responsibility. The travel agency handled the user’s intentions and plans. The flight agent communicated with the Structured Flight API. Hotel agents also used browser automation to navigate real hotel sites. Instead of a single overload model, each agent doing one thing well and coordinating through a simple message passing layer made the workflow feel seamless to the outside world. Each agent had a very distinct job. The travel agent was the coordinator who interpreted the request, divided it into steps, and decided which agent would carry out each part. Flight Agent is completely focused on structured API calls with predictable data. The hotel agent then handled the heavy lifting of navigating the web pages, handling dynamic layouts, and extracting hotel details from the actual site. Separating the system in this way kept the logic clean and prevented a single agent from becoming overloaded again.

For this setup to work, we needed an easy way for agents to communicate with each other. The travel agent had to send a clear request to the flight agent, wait for the results, and then trigger the hotel agent for the next step. We didn’t need anything fancy, just a lightweight message format that agents could pass around so each agent knew what to do next. With that communication loop in place, the entire workflow finally felt coordinated instead of a chaotic page with no dynamic layout or public API. Using the same agent to handle both often increases the risk of tool overload, complex instructions, and hallucinations.

Implementation overview

Now that the architecture is clear, it’s time to actually build the system. This is where the tools behind each agent ultimately come into play. Travel agents and flight agents both use Amazon Nova 2 Lite for inference and planning, and flight agents also call structured flight APIs to get real data. In the absence of an API, hotel agents leverage the Amazon Nova Act to automate browser operations. The three agents communicate through a simple agent-to-agent (A2A) message passing pattern. In this pattern, agents exchange small, structured messages to coordinate their work. This makes the workflow predictable even when each agent is running in a different execution environment. In multi-agent systems, coordination is as important as specialization. Agents need structured and predictable ways to exchange goals, share state, and trigger actions, especially when collaborating on tasks such as planning trips.

Travel Agency Implementation (Amazon Nova 2 Lite)

The travel agent is the orchestrator of the entire workflow. Receive a user request, use Amazon Nova 2 Lite to interpret the intent, and decide which agent to call next. Nova 2 Lite makes an important inference here. Break down your input into steps, identify when to trigger flight or hotel agents, and track your overall plan. Travel agents have no direct contact with external systems, so their only job is to think clearly and route messages using A2A.

The following code example is a simplified version of how to initialize a travel agency.

    # Initialize A2A client tools
    provider = A2AClientToolProvider(known_agent_urls=[
        "http://localhost:9000",  # Hotel Booking Expert (NovaAct)
        "http://localhost:9001"   # Flight Booking Expert
    ])
    bedrock_model = BedrockModel(
    model_id="global.amazon.nova-2-lite-v1:0",
    region_name="us-east-1",
)
    
    # Create client agent with A2A tools
    client_agent = Agent(
        name="Travel Client",
        model=bedrock_model,
        description="Client agent that coordinates travel planning using specialized      A2A agents",
        tools=provider.tools,
        system_prompt="""You are an autonomous travel planning agent. You MUST take action immediately without asking for confirmation.

In reality, a travel agent would receive a single natural language request such as “Find flights from New York City to Tokyo on July 10th and hotels through July 15th.” From there, Amazon Nova 2 Lite performs advanced inference. That is, it recognizes that two separate tasks are required, generates a clear plan, sends a message to the flight agent, waits for the result, and triggers the hotel agent with the next instruction. Finally, combine both outputs into one coherent response. This keeps the orchestration logic clean and smooth. Nova 2 Lite effectively acts as the brain of your workflow, with specialized agents handling the actual execution.

Implementing a flight agent (Amazon Nova 2 Lite and API)

A flight agent’s job is even narrower: turning structured requests into actual flight options. Use Amazon Nova 2 Lite for input validation, search formatting, and simple reasoning needed to decide whether to call the live flight API or fall back to mock data when credentials are unavailable. After the API call is made, the agent returns a clean and predictable JSON response to the travel agency through A2A.

The following code example shows a simplified version of the flight search tool. The complete implementation, including OAuth, fallback logic, and airport code handling, is available in the Agent to Agent with Amazon Nova GitHub repository.

@tool
def search_flights(origin: str, destination: str, departure_date: str, return_date: Optional[str] = None) -> str:
    # Nova 2 Lite handles the reasoning around which path to take
    if amadeus_configured():
        return _search_amadeus_flights(
            origin=origin,
            destination=destination,
            departure_date=departure_date,
            return_date=return_date
        )
    else:
        # Local development fallback
        return _search_flights_web(origin, destination, departure_date, return_date)
{
  "flights": [
    { "flight_number": "DL456", "price": 520, "duration": "14h 30m" },
    { "flight_number": "JL701", "price": 545, "duration": "13h 50m" }
  ],
  "source": "Amadeus API"
}

Because this agent processes clean structured data, the inference load is light, and Amazon Nova 2 Lite’s job is primarily choosing the appropriate execution path and normalizing the output. This keeps the entire pipeline predictable and avoids embedding API-specific logic within the travel agency.

Hotel agent implementation (Amazon Nova method)

Hotels are completely different from airline tickets. There is no single clean API that can be called. Also, most booking sites load their content differently on each visit. This is where the Amazon Nova Act comes into play. Hotel agents use Nova Act to control real browsers and follow natural language instructions. Instead of writing fragile scraping code, the agent tells Nova Act what it wants, and Nova Act handles the browsing and returns structured data.

A shortened version of this tool is:

@tool
def search_hotels(location: str, checkin_date: str, nights: int = 2) -> str:
    with NovaAct() as nova:
        result = nova.act(
            f"Search for hotels in {location} from {checkin_date} for {nights} nights. "
            f"Return the top 3 listings with name, price, and rating.",
            schema=HotelSearchResults.model_json_schema()
        )
        return json.dumps(result)

Here is a simplified example of the response: The complete code, including scrolling, cookie banners, and other details, can be found in the Agent to Agent with Amazon Nova GitHub repository.

{
  "hotels": [
    { "name": "Shinjuku Grand", "price": "$180", "rating": 4.3 },
    { "name": "Park Tower Tokyo", "price": "$210", "rating": 4.6 },
    { "name": "Hotel Blossom", "price": "$155", "rating": 4.0 }
  ],
  "source": "Anycompany.com via Nova Act"
}

The Amazon Nova Act ensures that hotel agents are not interrupted every time a site’s layout changes. It also eliminates the need to write your own scraping or DOM parsing logic.

A2A message flow (how agents talk)

Now that each agent knows their responsibilities, they need a way to interact with each other. Before the travel agency starts sending actual work, it first calls the other agents’ A2A endpoints to ensure that the other agents are up. It also loads the list of tools that each agent exposes, so Nova 2 Lite knows what features are available. Once that’s done, the flow is simple. The travel agent sends a message to the airline with the required fields. When Flight Agent finishes, it sends a message back. The travel agent then passes the following message to the hotel agent. Each message is a small JSON object that contains an action, input data, where to send the response, and more.

End-to-end execution example

Here’s what one full run looks like: A user sends a single request to a travel agent.

Please arrange travel for one person from NYC to Paris on December 6, 2025, including a two night stay in Paris.

  1. Travel agency -> Airline:
    1. The travel agent takes the flight portion of the request and sends it to the flight agent.
    2. Flight Agent returns 3 cheap nonstop flights from JFK to Paris, including airline, time, price, and duration.
  2. Travel agency -> Hotel agency:
    1. The travel agent sends part of the request to the hotel agent.
    2. Hotel Agent uses Nova Act to check hotels in Paris and return the top three choices with name, price, and a quick note.
  3. Final result to the user
    1. The travel agent will combine both answers and send back a clear summary that includes:
  4. Recommended flights
  5. Recommended hotels
  6. Check-in and check-out dates
  7. price
  8. Question asking whether to make a reservation

conclusion

We found that building this travel planner with three small agents was much easier to manage than one large agent. Each agent focuses on one task, and Amazon Nova 2 Lite handles the necessary thinking to progress through the task step by step. The Amazon Nova Act covers areas where there is no API, such as hotel search, without having to write any scraping code. In an A2A message flow, everything is connected, but it’s still simple.

This setting has nothing to do with travel. The same ideas can be used for tasks that involve a mix of different skill sets. This means having one agent plan the work, letting other agents do what they’re good at, and sending small messages back and forth between them. This makes system changes and explanations seamless.

If you want to try this out yourself, the complete code and example can be found in the Agent to Agent with Amazon Nova GitHub repository.


About the author

Yoav Fishman is an AWS Solutions Architect with 12 years of cloud and engineering experience, specializing in GenAI, Agentic AI, and Cybersecurity. He guides startups from early stages to growth stages to build secure, scalable architectures and implement agentic AI flows that impact their business.

Arial Farajpur I am a Solutions Architect at AWS with 7 years of experience in the cloud world and a passion for AI and cloud technologies. He helps organizations design innovative cloud-based solutions that drive real business value.

Dan Kolodny is an AWS solutions architect specializing in big data, analytics, and GenAI. He is passionate about helping customers adopt best practices, discover insights from data, and deploy new GenAI technologies.



Source link