SPADE: Smart Python Agent Development Environment

repository·master·Indexed 43 days ago

https://github.com/javipalanca/spade

A Python-based multi-agent systems platform leveraging XMPP for real-time communication between agents and humans. It features asynchronous message handling via the Message class, FIPA-ACL compliance through FIPAMessageBuilder and FIPAMessageParser, and support for XEP-0363 HTTP file exchange. The framework provides various behaviour types, including PeriodicBehaviour, TimeoutBehaviour, and FSMBehaviour for complex state-machine logic.

Tokens
22.5K
Snippets
75
Records
98
Agent score
51%

What's inside SPADE

  1. Overview of SPADE (Smart Python Agent Development Environment)

    master
    SPADE is a multi-agent systems platform written in Python. It is designed to allow developers to create agents that can communicate with both other agents and humans using the XMPP (Extensible Messaging and Presence Protocol) standard. The platform is built on asyncio and uses a behavior-based agent model.
  2. Implement agent logic using Behaviours

    master

    The core logic of a SPADE agent is implemented via Behaviours. You add a behaviour to an agent using the add_behaviour() method inside the agent's setup() coroutine.

    Common Behaviour Types

    • spade.behaviour.CyclicBehaviour: A loop-like behaviour that repeats without a specific period.

    Behaviour Lifecycle Methods

    • on_start(): An async coroutine executed just before the first iteration. Use it for initialization.
    • run(): An async coroutine that contains the core logic. It is called on every iteration of the behaviour loop. Because it is async, you can use await (e.g., await asyncio.sleep(1)) without blocking the event loop.
    • on_end(): An async coroutine executed when a behaviour is finished or killed.
    import asyncio
    import spade
    from spade.agent import Agent
    from spade.behaviour import CyclicBehaviour
    
    class DummyAgent(Agent):
        class MyBehav(CyclicBehaviour):
            async def on_start(self):
                print("Starting behaviour . . .")
                self.counter = 0
    
            async def run(self):
                print("Counter: {}".format(self.counter))
                self.counter += 1
                await asyncio.sleep(1)
    
            async def on_end(self):
                print("Behaviour ended")
    
        async def setup(self):
            b = self.MyBehav()
            self.add_behaviour(b)
    
    async def main():
        dummy = DummyAgent("dummy@localhost", "your_password")
        await dummy.start()
        # Use wait_until_finished to keep the agent running
        from spade import wait_until_finished
        await wait_until_finished(dummy)
    
    if __name__ == "__main__":
        spade.run(main())
  3. Understand SPADE behaviour types

    master

    Behaviours are the tasks an agent executes using repeating patterns. SPADE provides several predefined behaviour types to implement different logic structures:

    • Cyclic and Periodic: Best for performing repetitive tasks.
    • One-Shot and Time-Out: Best for performing occasional or single-occurrence tasks.
    • Finite State Machine: Used for building complex, state-dependent behaviours.
  4. Combine Templates using boolean operators

    master

    You can create complex message filtering logic by combining simple Template instances using bitwise operators:

    • &: Boolean AND (both templates must match).
    • |: Boolean OR (either template must match).
    • ^: Boolean XOR (exactly one template must match).
    • ~: Boolean NOT (the complement of the template).
    t1 = Template()
    t1.sender = "sender1@host"
    t2 = Template()
    t2.metadata = {"performative": "query"}
    
    # Matches messages that satisfy BOTH t1 and t2
    combined_template = t1 & t2
    
    # Matches messages that do NOT satisfy t3
    t3 = Template()
    t3.sender = "invalid@host"
    not_t3 = ~t3
  5. How message dispatching and templates work

    master

    Message dispatching is automated by the SPADE agent library. When a message arrives, the Message Dispatcher determines which behaviour should receive it by matching the incoming message against a message template attached to each behaviour.

    This allows a single agent to run multiple behaviours simultaneously, where each behaviour 'subscribes' to specific types of messages by defining its own template.

  6. How the SPADE Agent Model works

    master

    The SPADE Agent Model is built on three core components that work together to enable autonomous agent communication and execution:

    1. Connection Mechanism: Agents use a Jabber ID (JID) and a password to register and authenticate with an XMPP server. Once registered, the agent maintains a persistent communication stream.
    2. Message Dispatcher: An internal component that acts as a mailman. It automatically handles incoming messages by placing them in the correct behaviour 'mailbox' based on message templates, and handles outgoing messages by placing them into the communication stream.
    3. Behaviours: Tasks that an agent executes. An agent can run multiple behaviours simultaneously. Behaviours use message templates to filter which incoming messages they should process.

    To identify an agent on the platform, you must use a JID in the format username@serverdomain (e.g., myagent@localhost).

  7. Implement complex logic with Finite State Machine (FSM) Behaviour

    master

    The FSMBehaviour allows you to build complex agent logic using a Finite State Machine. It manages transitions between different State objects.

    Key Concepts

    • States: Subclasses of State (which is itself a OneShotBehaviour). You must override the run() coroutine. A state becomes a 'final state' if it does not call set_next_state().
    • Registration: Use add_state(name, state, initial=False) to register states. An FSM can have only one initial state; if multiple are registered with initial=True, the last one registered wins.
    • Transitions: Use add_transition(source, dest) to define valid paths between state names. If a state attempts to transition to a non-registered transition, a NotValidTransition exception is raised and the FSM stops.
    • State Transitions: Inside a state's run() method, call self.set_next_state("STATE_NAME") using the exact string name used during registration. If the name is unknown, a NotValidState exception is raised.
    • Message Queue: All states within a single FSMBehaviour share the same unique template and message queue.
    from spade.behaviour import FSMBehaviour, State
    
    STATE_A = "STATE_A"
    STATE_B = "STATE_B"
    
    class StateA(State):
        async def run(self):
            print("In State A")
            self.set_next_state(STATE_B)
    
    class StateB(State):
        async def run(self):
            print("In State B (Final)")
            # Not calling set_next_state makes this the final state
    
    class MyFSM(FSMBehaviour):
        pass
    
    # In Agent setup:
    fsm = MyFSM()
    fsm.add_state(name=STATE_A, state=StateA(), initial=True)
    fsm.add_state(name=STATE_B, state=StateB())
    fsm.add_transition(source=STATE_A, dest=STATE_B)
    self.add_behaviour(fsm)
  8. Define variable Paths

    master

    Paths can include dynamic segments using aiohttp syntax. For example, a path /a/{agentjid}/c will match /a/user@server/c. You can retrieve these variables from the request.match_info dictionary inside your controller.

    async def my_controller(request):
        jid = request.match_info['agentjid']
        return {"jid": jid}
  9. Key features of the SPADE platform

    master

    SPADE provides several core capabilities for multi-agent development:

    • XMPP-based Communication: Uses XMPP for messaging and presence notifications, allowing real-time state tracking of agents.
    • Asyncio-based: Built on Python's asyncio for efficient asynchronous operations.
    • Behavior-based Model: Agents are defined and controlled through specific behaviors.
    • FIPA Metadata Support: Uses XMPP Data Forms (XEP-0004) to support FIPA metadata.
    • Large File Sharing: Supports file transfers via HTTP (XEP-0363).
    • Flexible Server Support: Includes a custom XMPP server (PyJabber) but allows connection to any XMPP server.
    • Web Interface: Provides a web-based interface for interaction.

    Requirements:

    • Python >= 3.10
  10. How Templates work for message dispatching

    master

    In SPADE, a Template is used to dispatch received messages to specific behaviours. When you add a behaviour to an agent, you can provide a Template instance. The agent will only deliver messages to that behaviour if the message's attributes exactly match all the attributes defined in the template.

    Supported template attributes:

    • to: The JID string of the receiver.
    • sender: The JID string of the sender.
    • body: The message body.
    • thread: The thread ID of the conversation.
    • metadata: A (key, value) dictionary of strings (e.g., for FIPA attributes like ontology, performative, or language).
    template = Template()
    template.sender = "sender1@host"
    template.metadata = {"performative": "query"}
    
    # The behaviour will only receive messages matching these criteria
    self.add_behaviour(my_behaviour, template)