opensistemas-hub / osbrain

osBrain - A general-purpose multi-agent system module written in Python
https://osbrain.readthedocs.io/en/stable/
Apache License 2.0
175 stars 43 forks source link

agent communication when agents are not defined in agent initialisation scripts #359

Open brownbytes opened 4 years ago

brownbytes commented 4 years ago

Hi,

I am wondering if there is a way in which an agent can send message to another agent when both the agents are not defined in the name server initialisation script.

my name_server / agent initialisation script: from AgentA import agenta from AgentB import agentb

ns = run_nameserver() aa = run_agent('agenta',base=agenta) ab = run_agent('agents',base=agentb)

Now, assuming that agenta is a Agent class defined in AgentA script and agentb is a Agent class defined in AgentB script, I am trying to figure out if there is a way in which AgentA script can send/receive information to agentb? Most of the examples provided in the documentation have both agents defined in the name_server script, thus are able to connect to an agent using alias, but do we 'connect' if the agents are defined otherwise?

Peque commented 4 years ago

I am assuming you can, and want to, use a single name server. In that case you can create a proxy to an existing name server.

Peque commented 4 years ago

A little example; first run alice.py:

import time

from osbrain import run_nameserver
from osbrain import run_agent
from osbrain import Agent

class Alice(Agent):
    def on_init(self):
        self.count = 0

    def log_message(self, message):
        self.log_info("Received: %s" % message)
        self.count += 1

    def total_count(self):
        return self.count

    def idle(self):
        self.log_info("Waiting for messages...")

if __name__ == "__main__":
    ns = run_nameserver(addr="127.0.0.1:1234")
    alice = run_agent("Alice", base=Alice)
    addr = alice.bind("PULL", alias="main", handler="log_message")

    while alice.total_count() < 3:
        time.sleep(1)

    ns.shutdown()

Then run bob.py:

import time

from osbrain import NSProxy
from osbrain import run_agent

if __name__ == "__main__":
    ns = NSProxy(nsaddr="127.0.0.1:1234")
    bob = run_agent("Bob", nsaddr=ns.addr())
    alice = ns.proxy("Alice")

    # System configuration
    addr = alice.addr("main")
    bob.connect(addr, alias="push")

    # Send messages
    for _ in range(3):
        bob.send("push", "Hello, Alice!")
        time.sleep(1)

I could add that to the documentation if it is useful or helps understand how to deal with already-running name servers.

brownbytes commented 4 years ago

Hi, Thank you very much for your response. I do understand the example and I tested the examples.

Meanwhile, I did some trails and tested creating multiple communication channels to enable bi-directional communication and access other agents defined in other scripts. Not sure if this is the osbrain way of doing things :s

agentns.py

import time
from osbrain import run_agent
from osbrain import run_nameserver
from agent1 import Agent1
from agent2 import Agent2
from agent3 import Agent3

def main():
    ns = run_nameserver() 
    print(" Starting agents ...")
    ag1 = run_agent('ag1',base=Agent1)
    ag2 = run_agent('ag2',base=Agent2)
    ag3 = run_agent('ag3',base=Agent3)
    #client connections
    ag2.connect(ag1.addr('agent11'),handler='custom_log')
    ag3.connect(ag1.addr('agent12'),handler='custom_log')

    ag1.connect(ag2.addr('agent21'),handler='custom_log')
    ag3.connect(ag2.addr('agent22'),handler='custom_log')

    ag1.connect(ag3.addr('agent31'),handler='custom_log')
    ag2.connect(ag3.addr('agent32'),handler='custom_log')

if __name__ == '__main__':
    main()

agent1.py and agent2.py and agent3.py are as below (except channel names are (agent21,agent22), (agent31,agent32) respectively.

from osbrain import Agent
import time
from threading import Thread

class Agent1(Agent):
    def on_init(self):
        #server sides
        addr1=self.bind('PUSH',alias='agent11')
        addr2=self.bind('PUSH',alias='agent12')
        timer_thread = TimerThread(self)
        timer_thread.start()

    def custom_log(self,message):
        self.log_info('Recieved:%s'%message)

class TimerThread(Thread):
    def __init__(self, agent):
        super().__init__()
        self.agent = agent

    def run(self):
        time.sleep(5)
        self.agent.send('agent11','Hello!,%s' 'ag2')
        self.agent.send('agent12','Hello!,%s' 'ag3')