Skip to content

Multi-Agent Download System with Cheerleader

This example demonstrates several advanced features of LLMling-agent:

  • Continuous repetitive tasks
  • Async parallel execution of LLM calls
  • YAML configuration with storage providers
  • Capability usage (agent listing and task delegation)
  • Stateful callback mechanism
  • Multiple storage providers (SQLite + pretty-printed logs)

Configuration

Our download_agents.yml defines four agents and storage configuration:

storage:
  # List of storage providers (can use multiple)
  providers:
    # Primary storage using SQLite
    - type: sql
      url: "sqlite:///history.db"
    # Pretty printed text file output
    - type: text_file
      path: "logs/chat.log"
      format: "chronological"
      template: "chronological"

agents:
  fan:
    name: "Async Agent Fan"
    description: "The #1 supporter of all agents!"
    model:
      type: fallback
      models:
          - openai:gpt-4o-mini
          - openai:gpt-3.5-turbo
    capabilities:
      can_list_agents: true  # Need to know who to cheer for!
    system_prompts:
      - |
        You are the MOST ENTHUSIASTIC async fan who runs in the background!
        Your job is to:
        1. Find all other agents using your tool (don't include yourself!)
        2. Cheer them on with over-the-top supportive messages considering the situation.
        3. Never stop believing in your team! 🎉
    tools:
      - type: import
        name: show_love
        import_path: llmling_agent_examples.download_agents.cheer

  file_getter_1:
    name: "Mr. File Downloader"
    description: "Downloads files from URLs"
    model: openai:gpt-4o-mini
    system_prompts:
      - "You have ONE job: use the download_file tool to download files."
    tools:
      - type: import
        import_path: llmling_agent_tools.download_file

  overseer:
    name: "Download Coordinator"
    description: "Coordinates parallel downloads"
    model: openai:gpt-4o-mini
    capabilities:
      can_delegate_tasks: true
      can_list_agents: true
    system_prompts:
      - |
        You coordinate file downloads using available agents. Your job is to:
        1. Check out the available agents and assign each of them the download task
        2. Report the EXACT download results from the agents including speeds and sizes

Implementation

Here's how we orchestrate our download team:

class CheerProgress:
    """State keeper for our enthusiastic fan."""
    def __init__(self):
        self.situation = "The team is assembling, ready to start the downloads!"

    def create_prompt(self) -> str:
        return (
            f"Current situation: {self.situation}\n"
            "Be an enthusiastic and encouraging fan!"
        )

    def update(self, situation: str):
        self.situation = situation
        print(situation)

async def run():
    async with AgentPool[None]("download_agents.yml") as pool:
        # Get first worker from config
        worker_1 = pool.get_agent("file_getter_1")

        # Clone it for second worker
        worker_2 = await pool.clone_agent(worker_1, new_name="file_getter_2")

        # Create team and get fan
        team = worker_1 & worker_2
        fan = pool.get_agent("fan")
        progress = CheerProgress()

        # Start continuous fan support in background
        await fan.run_in_background(progress.create_prompt)

        # Sequential downloads
        progress.update("Sequential downloads starting - let's see how they do!")
        sequential = await team.run_sequential(TEAM_PROMPT)
        progress.update(f"Downloads completed in {sequential.duration:.2f} secs!")

        # Parallel downloads
        parallel = await team.run_parallel(TEAM_PROMPT)
        progress.update(f"Downloads completed in {parallel.duration:.2f} secs!")

        # Let overseer coordinate
        overseer = pool.get_agent("overseer")
        result = await overseer.run(OVERSEER_PROMPT)
        progress.update(f"\nOverseer's report: {result.data}")

        await fan.stop()  # End of joy

if __name__ == "__main__":
    import asyncio
    asyncio.run(run())

How It Works

  1. We set up a team of downloaders and a cheerleading fan
  2. The fan runs continuously in the background, getting updates via callbacks
  3. We test downloads in different modes:
  4. Sequential (one after another)
  5. Parallel (both at once)
  6. Overseer-coordinated (using agent capabilities)
  7. The fan cheers appropriately for each situation
  8. All interactions are logged to both SQLite and pretty-printed text files

This demonstrates:

  • Background tasks with continuous prompts
  • Agent cloning
  • Team operations (sequential vs parallel)
  • Capability-based delegation
  • Multi-provider storage