Skip to content

Developing a negotiator

The corresponding code for the tutorials can be found in the ANL2025 Drive or at the ANL2025 Github repository.

The agents for the ANL competition are simple extensions of NegMAS negotiators. As such, they can be developed using any approach used to develop negotiators in NegMAS.

To develop a negotiator, you need to inherit from the ANL2025Negotiator class and implement the propose() and respond().

If you want to start developing your negotiator right away, you can download a template agent from here and tweak the code yourself. If you want more instructions, keep reading.

A random negotiator

Here is an example of a random negotiator that implements the propose() and respond() methods. The negotiator accepts the bid with a certain probability (1-p-reject), and ends the negotiaiton with a very small probability (p_end). The agent proposes a random offer at each round, sampled from all the possible outcomes.

from random import random
from negmas import Outcome, ResponseType, SAOState
from anl2025 import ANL2025Negotiator


class MyRandom2025(ANL2025Negotiator):
    p_end = 0.0003
    p_reject = 0.999

    def propose(
        self, negotiator_id: str, state: SAOState, dest: str | None = None
    ) -> Outcome | None:
        nmi = self.get_nmi_from_id(negotiator_id)
        sampled_bid = list(nmi.outcome_space.sample(1))[0]
        return sampled_bid

    def respond(
        self, negotiator_id: str, state: SAOState, source: str | None = None
    ) -> ResponseType:
        if random() < self.p_end:
            return ResponseType.END_NEGOTIATION

        if (
            random() < self.p_reject
            or float(self.ufun(state.current_offer)) < self.ufun.reserved_value  # type: ignore
        ):
            return ResponseType.REJECT_OFFER
        return ResponseType.ACCEPT_OFFER

    def get_nmi_from_id(self, negotiators_id):
        # the nmi is the negotiator mechanism interface, available for each subnegotiation. Here you can find any information about the ongoing or ended negotiation, like the agreement or the previous bids.
        return self.negotiators[negotiators_id].negotiator.nmi

If MyRandom2025 negotiator has the role of center agent, it has a list of side-negotiators: that are the subnegotiators that negotiate bilaterally with one opponent. There is one side-negotiator for each edge agent. You can find that list in self.negotiators, callable by their id. Each such side-negotiator is an object that logs all the information about its one-to-one negotiation. One of these functions is called nmi, short for negotiator mechanism interface, where you can find information such as the outcome space, the previous bids and possibly the agreement.

To test the agent, we use the functions as introduced in the tutorial Run a negotiation. We use a tournament to compare the results between the agents.

from anl2025 import (
    make_multideal_scenario,
    run_session,
    anl2025_tournament,
    Boulware2025,
    Linear2025,
)

scenario = make_multideal_scenario(nedges=3)
competitors = [MyRandom2025, Boulware2025, Linear2025]
# results = run_session(center_type = MyRandom2025, edge_types = competitors, scenario = scenario)
# print(f"Center Utility: {results.center_utility}\nEdge Utilities: {results.edge_utilities}")
results = anl2025_tournament(
    [scenario], n_jobs=-1, competitors=(MyRandom2025, Boulware2025, Linear2025)
)
print(results.final_scores)
print(results.weighted_average)
Output()


Output()


{'Linear2025': 7.12151076118834, 'Boulware2025': 9.952164758275384, '__main__.MyRandom2025': 1.9656240952661561}
{
    'Linear2025': 1.1266639550715007,
    'Boulware2025': 1.2774773478264272,
    '__main__.MyRandom2025': 0.23830922778693428
}

As we can see from the results, does MyRandom not perform very well: it has a lower score than the builtin agents.

The template agent

To give an example about the intuitions you can follow in designing your agent to get a better result, we provide you a template agent. This can form the basis of your own agent. Instead of bidding just anything, this agent tries to aim for the best bid: the target bid. The question is, what is the best target bid? Check out the template agent to see how it is implemented. You can download the template agent here.

As a suggestion, you can make the following folder structure on your own computer:

ANL 2025submission/
├── Code_for_tutorials2025/
│   ├── Tutorial_running_a_negotiation.py
│   └── ...
├── my_agent/
│   ├── helpers
│   ├── report
│   └── myagent.py
├── Official_test_scenarios/
│   ├── dinners
│   └── ...
└── venv/
    └── lib/
        ├── ...

To test the agent, you can either choose to run a session like above, or run myagent.py directly from your favorite IDE.

This example agent has many flaws. Can you spot them? Hint: is there just one best bid? And is the absolute best bid the only option to aim for?

Now, start tweaking the code and rebuild it, to make the best agent of the competition!

Other Examples

The ANL package comes with some more example negotiators. These are not designed to be stong but to showcase how to use some of the features provided by the platform.

Note about running tournaments

  • When running a tournament using anl2025_tournament inside a Jupyter Notebook, you must pass njobs=-1 to force serial execution of negotiations. This is required because the multiprocessing library used by NegMAS does not play nicely with Jupyter Notebooks. If you run the tournament using the same method from a .py python script file, you can omit this argument to run a tournament using all available cores.


Download Notebook