docs: function Session(channel, config, cb) {
    events.EventEmitter.call(this)
  
    this._agents  = new SMap()
    this._ragents = new SMap()
  
    var agentInfo = {
      id:    "server",
      name:  "server",
      title: "server"
    }
  
    this._ragentServer = agents.createRAgent(this, agentInfo)
  
    this._ragentServer.addListener("agentCreated",   onRAgentCreated)
    this._ragentServer.addListener("agentDestroyed", onRAgentDestroyed)
  
    channel.on("message", onMessage)
    channel.on("close",   onClose)
    channel.on("error",   onError)
  
    DEBUG("connect")
  
    channel.connect(onConnect)
  
    var session = this
  
    //-----------------------------------
    function onConnect(err) {
      if (err) {
        DEBUG("connect error", err)
        return cb(err)
      }
  
      DEBUG("connected")
  
      channel.sendMessage({
        type: "request",
        name: "connect",
        to:   "server",
        id:   "0",
        body: {
          key: config.key
        }
      })
    }
  
    //-----------------------------------
    function onMessage(message) {
  
      if (!session._channel) {
        DEBUG("channel connection message received")
        if (message.type != "response") return
        if (message.name != "connect") return
        if (message.from != "server") return
        if (message.id   != "0") return
  
        DEBUG("channel connection message accepted")
  
        session._channel = channel
        cb(null, session)
        return
      }
  
      var agent
  
      if (message.to == "server") {
        if (message.type == "request")     agent = session._ragentServer
      }
  
      else if (message.from == "server") {
        if (message.type == "response")    agent = session._ragentServer
        if (message.type == "event")       agent = session._ragentServer
      }
  
      else if (message.type == "request")  agent = session._agents.get(message.to)
      else if (message.type == "response") agent = session._ragents.get(message.from)
      else if (message.type == "event")    agent = session._ragents.get(message.from)
  
      if (!agent) return
  
      if      (message.type == "request")  agent._onRequest(message)
      else if (message.type == "response") agent._onResponse(message)
      else if (message.type == "event")    agent._onEvent(message)
    }
  
    //-----------------------------------
    function onClose() {
      DEBUG("closing")
  
      session._agents.forEach(function (agent) {
        agent.destroy()
      })
  
      session._agents  = null
      session._channel = null
      session.emit("close")
  
      // only 'works' if the cb has not already been called
      cb(new Error("closed"))
    }
  
    //-----------------------------------
    function onError(err) {
      DEBUG("error", err)
      session.emit("error", err)
    }
  
    //-----------------------------------
    function onRAgentCreated(agentInfo) {
      DEBUG("ragentCreated", utils.JS(agentInfo))
      var ragent = agents.createRAgent(session, agentInfo)
  
      session._ragents.set(agentInfo.id, ragent)
      session.emit("ragentCreated", ragent)
    }
  
    //-----------------------------------
    function onRAgentDestroyed(agentInfo) {
      DEBUG("ragentDestroyed", utils.JS(agentInfo))
      var ragent = session._ragents.get(agentInfo.id)
      if (!ragent) return
  
      session._ragents.delete(agentInfo.id)
      session.emit("ragentDestroyed", ragent)
    }
  
  }