class_docstr: Manages interactions between agents on a websocket as well as direct interactions
  between agents and an overworld.
class_docstr_tok: ["Manages","interactions","between","agents","on","a","websocket","as","well","as","direct","interactions","between","agents","and","an","overworld","."]
docstr: An iteration of the manager's main loop to launch worlds.
docstr_tok: ["An","iteration","of","the","manager","'s","main","loop","to","launch","worlds","."]
code: def _manager_loop_fn(self):
      """
      An iteration of the manager's main loop to launch worlds.
      """
      with self.agent_pool_change_condition:
          valid_pools = self._get_unique_pool()
          for world_type, agent_pool in valid_pools.items():
              # check if agent has exceeded max time in pool
              world_config = self.task_configs[world_type]
              if world_config.max_time_in_pool is not None:
                  self.check_timeout_in_pool(
                      world_type,
                      agent_pool,
                      world_config.max_time_in_pool,
                      world_config.backup_task,
                  )
  
              needed_agents = self.max_agents_for[world_type]
              if len(agent_pool) >= needed_agents:
                  log_utils.print_and_log(
                      logging.INFO, "starting pool", should_print=True
                  )
                  # enough agents in pool to start new conversation
                  self.conversation_index += 1
                  task_id = "t_{}".format(self.conversation_index)
  
                  # Add the required number of valid agents to the conv
                  agent_states = [w for w in agent_pool[:needed_agents]]
                  agents = []
                  for state in agent_states:
                      agent = self._create_agent(
                          task_id, state.get_id()
                      )
                      agent.onboard_data = state.onboard_data
                      agent.data = state.data
                      state.assign_agent_to_task(agent, task_id)
                      state.set_active_agent(agent)
                      agents.append(agent)
                      # reset wait message state
                      state.stored_data["seen_wait_message"] = False
                  assign_role_function = utils.get_assign_roles_fn(
                      self.world_module, self.taskworld_map[world_type]
                  )
                  if assign_role_function is None:
                      assign_role_function = (
                          utils.default_assign_roles_fn
                      )
                  assign_role_function(agents)
                  # Allow task creator to filter out workers and run
                  # versions of the task that require fewer agents
                  for a in agents:
                      # Remove selected workers from the agent pool
                      self.remove_agent_from_pool(
                          self.get_agent_state(a.id),
                          world_type=world_type,
                          mark_removed=False,
                      )
                  for a in agents:
                      partner_list = agents.copy()
                      partner_list.remove(a)
                      a.message_partners = partner_list
  
                  done_callback = self._get_done_callback_for_agents(
                      task_id, world_type, agents
                  )
  
                  # launch task world.
                  future = self.world_runner.launch_task_world(
                      task_id, self.taskworld_map[world_type], agents
                  )
                  future.add_done_callback(done_callback)
                  self.active_worlds[task_id] = future
  
imports: import json
  import asyncio
  import logging
  from parlai.core.agents import create_agent
  from parlai.chat_service.core.chat_service_manager import ChatServiceManager
  import parlai.chat_service.utils.logging
  import parlai.chat_service.utils.misc
  from parlai.chat_service.services.websocket.sockets import MessageSocketHandler
  from .agents import WebsocketAgent
  import tornado
  from tornado.options import options
label_desc: Use image node_id 6 for calling the WebsocketManager obj's underlying member method code with example usage: obj._manager_loop_fn() without return types