Add: climate negotiation multi-agent LLM example #453
Conversation
e6d4d4c to
eee2e14
Compare
sadrasabouri
left a comment
There was a problem hiding this comment.
I left some comments that may be helpful. My overall suggestion is to trim this PR down to an atomic contribution on top of deffuant_weisbuch. One possible direction:
LLM-driven dynamic opinion change: define a few agent types with distinct system prompts reflecting different personalities. Give each agent a personal stance on the topic (e.g., "I believe we should use ..."). Opinion updates come from querying an LLM with something like: "Given that agent X's argument is Y, rate how much do you agree with Z ? Answer between 0 and 1." This setup can simulate the echo-chamber effect by tuning
- X: other interacting agents
- Y: X's opinion statement which gets updated as their
opiniongets updated each round - Z: the subject that the whole model is going to be about (e.g., climate)
| ### 1. Install dependencies | ||
|
|
||
| ```bash | ||
| pip install mesa-llm mesa solara python-dotenv rich |
There was a problem hiding this comment.
Can you add a requirements.txt for this?
| ## Robustness Against LLM Hallucinations | ||
|
|
||
| Two common failure modes are guarded in code: | ||
|
|
||
| - **Phantom agent IDs in `form_coalition`** - `partner_ids` are filtered against | ||
| the live agent set before being stored. Invalid IDs are dropped and logged as | ||
| `WARNING` in `climate_negotiation.log`. | ||
| - **Invalid `proposer_id` in `accept_proposal`** - the ID is validated before | ||
| recording an acceptance. If it doesn't match any agent, an error string listing | ||
| valid IDs is returned to the LLM so it can self-correct on its next step. | ||
|
|
||
| Every agent's step prompt also includes an explicit `VALID COUNTRY IDs` block so | ||
| models are less likely to invent IDs in the first place. |
There was a problem hiding this comment.
I think the reader does not necessary benefit from this in readme as it's very low-level implementation details. Feel free to remove it.
|
|
||
| ### 2. Set your API key | ||
|
|
||
| Create a `.env` file in `llm/climate_negotiation/`: |
There was a problem hiding this comment.
nit: add a local .gitignore file avoid committing .env mistakenly.
| **Try different LLMs**: Change `llm_model` in `app.py`. `gpt-4o` produces richer diplomatic | ||
| language; `gemini-2.0-flash` is faster and free. | ||
|
|
||
| **Add more countries**: Add a new dict to the `COUNTRIES` list in `model.py` and assign it | ||
| a system prompt encoding that country's real-world stance. | ||
|
|
||
| **Change the treaty threshold**: Edit `_treaty_reached()` in `model.py` | ||
| (currently requires a 2/3 majority). |
There was a problem hiding this comment.
These are nearly trivial edits. Feel free to remove them.
|
|
||
| from .agents import country_tool_manager | ||
|
|
||
| if TYPE_CHECKING: |
There was a problem hiding this comment.
you don't need this if here. for your code as a application script you can just import the type and start using it.
| Confirmation of coalition formation and the partners notified. | ||
| """ | ||
| if isinstance(partner_ids, str): | ||
| import json |
| proposer_id: Unique ID of the country whose proposal you are rejecting. | ||
| counter_reduction_percent: Your alternative reduction percentage. | ||
| reason: Explanation of why you reject the original and what you offer instead. | ||
| agent: Provided automatically. |
| counter_reduction_percent = float(counter_reduction_percent or 20.0) | ||
| proposer_id = int(proposer_id or 0) |
| id_to_name = { | ||
| a.unique_id: getattr(a, "country_name", f"Agent {a.unique_id}") | ||
| for a in self.model.agents | ||
| } |
There was a problem hiding this comment.
having this dict as a model's parameter makes more sense.
| Mesa-LLM features demonstrated | ||
| - STLTMemory : short-term stores recent proposals; long-term consolidates | ||
| committed positions across rounds. | ||
| - ReActReasoning: agents reason then act within each simulation step. | ||
| - speak_to : inbuilt diplomatic messaging tool between agents. | ||
| - Custom tools : make_proposal, accept_proposal, form_coalition, | ||
| reject_and_counter. | ||
| - vision=-1 : agents observe all other parties (full-room awareness, | ||
| no spatial grid needed). | ||
|
|
Summary
Adds a new LLM example under
llm/climate_negotiation/, a multi-agent simulation of international climate treaty negotiations. Six country agents (USA, EU, China, India, Brazil, Russia), each driven by an LLM, negotiate on a shared emissions-reduction target over multiple rounds until a 2/3 majority treaty is reached.References issue #454
What makes this different from existing examples
The existing mesa-examples cover classic ABM patterns (opinion dynamic, resource competition, spatial movement). This is
llm/directory that uses LLM agents for structured multi-partynegotiation and a qualitatively different use-case where:
speak_to) and domain-specific tools rather than generic actions.The closest existing example is
deffuant_weisbuch(opinion convergence without LLMs). This model demonstrates how LLM reasoning produces qualitatively richer convergence: coalition-building, diplomatic counters, and conditional acceptance behaviours that rule-based agents cannot replicate.Mesa-LLM features demonstrated
STLTMemoryReActReasoningspeak_to(inbuilt tool)@toolfunctionsmake_proposal,accept_proposal,form_coalition,reject_and_countervision=-1DataCollectorTotalProposals,AveragePledge,LargestCoalitionSize,TreatyReachedper roundFeatures
Two LLM hallucination failure modes are explicitly guarded:
form_coalition-partner_idsare filtered against the live agent set; invalid IDs are dropped and logged asWARNING.proposer_idinaccept_proposal- the ID is validated before recording; if wrong, an error listing valid IDs is returned to the LLM for self-correction.Every agent's step prompt also includes an explicit
VALID COUNTRY IDsblock to reduce hallucination at the source.Visualisation (Solara)
Supported LLMs
Works with any LiteLLM-compatible model string. Tested with
openai/gpt-4o(best emergent behaviour),gemini/gemini-2.0-flash(default),openai/gpt-4o-mini,anthropic/claude-haiku-4-5-20251001, andollama/llama3.2.File Structure
llm/climate_negotiation/
├── app.py # Solara visualisation entry point
├── README.md
└── climate_negotiation/
├── init.py # triggers tool registration on import
├── agents.py # CountryAgent + negotiation history helper
├── tools.py # four custom @tool negotiation functions
└── model.py # ClimateNegotiationModel + countries configs
To Try
pip install mesa-llm mesa solara python-dotenv richllm/climate_negotiation/.envpython -m climate_negotiation.model- confirm rounds print and treaty is reached within ~6 rounds withgpt-4osolara run app.py- confirm all four visualisation panels render and update per round