class_docstr: A CompositeAgent is a group of agents in the same hierarchy level.
  In a CompositeAgent, each agent may take the role of either a controller or an observer.
  Each agent that is defined as observer, gets observations from the environment.
  Each agent that is defined as controller, can potentially also control the environment, in addition to observing it.
  There are several ways to decide on the action from different controller agents:
  1. Ensemble -
      - Take the majority vote (discrete controls)
      - Take the mean action (continuous controls)
      - Round robin between the agents (discrete/continuous)
  2. Skills -
      - At each step a single agent decides (Chosen by the uppoer hierarchy controlling agent)
  
  A CompositeAgent can be controlled using one of the following methods (ActionSpaces):
  1. Goals (in terms of measurements, observation, embedding or a change in those values)
  2. Agent Selection (skills) / Discrete action space.
  3. Attention (a subset of the real environment observation / action space)
class_docstr_tok: ["A","CompositeAgent","is","a","group","of","agents","in","the","same","hierarchy","level",".","In","a","CompositeAgent",",","each","agent","may","take","the","role","of","either","a","controller","or","an","observer",".","Each","agent","that","is","defined","as","observer",",","gets","observations","from","the","environment",".","Each","agent","that","is","defined","as","controller",",","can","potentially","also","control","the","environment",",","in","addition","to","observing","it",".","There","are","several","ways","to","decide","on","the","action","from","different","controller","agents",":","1",".","Ensemble","-","-","Take","the","majority","vote","(","discrete","controls",")","-","Take","the","mean","action","(","continuous","controls",")","-","Round","robin","between","the","agents","(","discrete\/continuous",")","2",".","Skills","-","-","At","each","step","a","single","agent","decides","(","Chosen","by","the","uppoer","hierarchy","controlling","agent",")","A","CompositeAgent","can","be","controlled","using","one","of","the","following","methods","(","ActionSpaces",")",":","1",".","Goals","(","in","terms","of","measurements",",","observation",",","embedding","or","a","change","in","those","values",")","2",".","Agent","Selection","(","skills",")","\/","Discrete","action","space",".","3",".","Attention","(","a","subset","of","the","real","environment","observation","\/","action","space",")"]
docstr: Given a response from the environment as a env_response, filter it and pass it to the agents.
  This method has two main jobs:
  1. Wrap the previous transition, ending with the new observation coming from EnvResponse.
  2. Save the next_state as the current_state to take action upon for the next call to act().
  
  :param env_response:
  :param action_info: additional info about the chosen action
  :return:
docstr_tok: ["Given","a","response","from","the","environment","as","a","env_response",",","filter","it","and","pass","it","to","the","agents",".","This","method","has","two","main","jobs",":","1",".","Wrap","the","previous","transition",",","ending","with","the","new","observation","coming","from","EnvResponse",".","2",".","Save","the","next_state","as","the","current_state","to","take","action","upon","for","the","next","call","to","act","(",")",".",":","param","env_response",":",":","param","action_info",":","additional","info","about","the","chosen","action",":","return",":"]
code: def observe(self, env_response: EnvResponse) -> bool:
      """
      Given a response from the environment as a env_response, filter it and pass it to the agents.
      This method has two main jobs:
      1. Wrap the previous transition, ending with the new observation coming from EnvResponse.
      2. Save the next_state as the current_state to take action upon for the next call to act().
  
      :param env_response:
      :param action_info: additional info about the chosen action
      :return:
      """
  
      # accumulate the unfiltered rewards for visualization
      self.total_reward_in_current_episode += env_response.reward
  
      episode_ended = env_response.game_over
  
      # pass the env_response to all the sub-agents
      # TODO: what if one agent decides to end the episode but the others don't? who decides?
      for agent_name, agent in self.agents.items():
          goal_reached = agent.observe(env_response)
          episode_ended = episode_ended or goal_reached
  
      # TODO: unlike for a single agent, here we also treat a game over by the environment.
      # probably better to only return the agents' goal_reached decisions.
      return episode_ended
  
imports: import copy
  import itertools
  from enum import Enum
  from typing import Union, List, Dict
  import numpy
  from rl_coach.agents.agent_interface import AgentInterface
  from rl_coach.base_parameters import AgentParameters, VisualizationParameters
  from rl_coach.core_types import ActionInfo, EnvResponse, ActionType, RunPhase
  from rl_coach.filters.observation.observation_crop_filter import ObservationCropFilter
  from rl_coach.saver import SaverCollection
  from rl_coach.spaces import ActionSpace
  from rl_coach.spaces import AgentSelection, AttentionActionSpace, SpacesDefinition
  from rl_coach.utils import short_dynamic_import
label_desc: Use image node_id 14 for calling the CompositeAgent obj's underlying member method code with example usage: obj.observe(env_response) and returns: episode_ended