Skip to content

Add : bdi_recommender model#388

Open
champ-byte wants to merge 7 commits intomesa:mainfrom
champ-byte:bdi_recommender
Open

Add : bdi_recommender model#388
champ-byte wants to merge 7 commits intomesa:mainfrom
champ-byte:bdi_recommender

Conversation

@champ-byte
Copy link
Contributor

@champ-byte champ-byte commented Mar 15, 2026

This is a mesa implementation of BDI Recommender Agent from NetLogo Modeling Commons.

It is a good minimal example of Belief Desire Intention(BDI) architecture

This model simulates an agent ("Bob") who autonomously reasons about his health by maintaining Beliefs (knowledge about his health), Desires (motivations), Goals (achievable desires), and Intentions (action plans). It demonstrates how new information (advice from a Doctor) can dynamically change Bob's beliefs and alter his behavior.

Visualization:
image
image

Review Checklist

Does it belong?

  • No significant overlap with existing examples
  • Well-scoped simplest model that demonstrates the idea
  • Showcases Mesa features not already well-covered
  • Showcases interesting ABM mechanics (LLM reasoning vs rule-based dynamics)

Is it correct?

  • Uses current Mesa APIs (OrthogonalMooreGrid, DataCollector)
  • Runs and visualizes out of the box (does not require api key)
  • Deterministic with fixed rng seed LLM outputs are non-deterministic by nature
  • Moved to examples directory

Is it clean?

  • No dead code or unused imports
  • Clear naming, logic readable
  • README explains what it does, what it demonstrates, how to run it
  • PR follows template, commits reasonably clean

@champ-byte champ-byte changed the title bdi_recommender Add : bdi_recommender model Mar 15, 2026
@EwoutH
Copy link
Member

EwoutH commented Mar 15, 2026

Thanks for the PR, nice to see some BDI.

Could you:

  • Add a screenshot or gif of the visualisation to the PR description
  • Request a peer-review (and maybe do one or two yourself)

Copy link
Contributor

@ShreyasN707 ShreyasN707 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tested it in my local system and it works good with all the different model parameters i tired .

"beliefs": lambda a: dict(a.beliefs) if hasattr(a, "beliefs") else {},
"trust": lambda a: a.trust if hasattr(a, "trust") else 0,
"goals": lambda a: (
dict(a.goals) if hasattr(a, "goals") and callable(a.goals) else {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the DataCollector incorrectly checks if goals is callable.
Since goals is a @computed_property, it already returns a value, so callable() is always false.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi , thanks for looking into this , I will update it

renderer.draw_agents()

page = SolaraViz(
model,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing a model instance here might limit reactivity—using the model class could help updates work better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is not an issue because , SolaraViz accepts model: Model | solara.Reactive[Model]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes SolaraViz accepts both. My concern was more about reactivity in practice (e.g. model resets/param updates), but if it's working correctly with the current setup then it should be fine.

@abhinavk0220
Copy link

abhinavk0220 commented Mar 19, 2026

Peer Review — BDI Recommender Agent

Reviewed agents.py, model.py, app.py, and Readme.md in full.


Overall

A genuinely interesting example BDI architecture is underrepresented in Mesa examples and the NetLogo port is a good choice. The use of mesa_signals (Observable, computed_property) to make beliefs reactive is the right architectural decision and showcases a Mesa feature that barely any other example uses. A few correctness issues need addressing before merge.


Critical: Non-seeded RNG in agents.py

self.compliant = random.random() < self.model.compliance_rate uses Python's stdlib random module directly. This breaks reproducibility running with rng=42 will produce different compliance assignments on each run. Replace with self.model.random.random() (or pass self.random once super().__init__() is called). Same issue appears in the infection check if random.random() > 0.40.


Trust Logic in evaluate_proposal

if sender and sender.trust > 0.5:

This checks the doctor's trust level, not Bob's trust in the doctor. The BDI model says Bob's receptiveness should be governed by his own trust variable (already stored on self.trust). The current code means the proposal is accepted based on whether the doctor trusts himself, which is always true since the doctor's trust initialises above 0.5. This should likely be self.trust > 0.5.


goals computed property recomputes on every access

elect_goals() iterates through all desires and beliefs on every access. In step(), self.goals is called in both step() and update_beliefs() so it runs at least twice per step. This is fine for a small model but worth noting; caching the result until beliefs change would be cleaner given you already have Observable beliefs.


Hardcoded location coordinates in model.py

self.gym = GymAgent(self, self.grid[21, 26])
self.nutrition_centre = NutritionCentreAgent(self, self.grid[24, 22])
self.clinic = ClinicAgent(self, self.grid[16, 19])

These are hardcoded for a 40×40 grid. If a user changes width or height via the sliders, the agents land outside valid coordinates or at unintended relative positions. Consider deriving positions proportionally from grid dimensions.


rng in model_params uses InputText

The rng parameter is exposed as a free-text input. The model does handle the string-to-int conversion with contextlib.suppress(ValueError), but if a user types a non-integer string it silently falls back to rng=None (random seed). This should be a SliderInt or at least have a note in the label.


README abbreviations unexplained

Belief/desire keys like Not-eh, bs, pa, wr, eh, w come from the NetLogo model but are never decoded in the README. Adding a one-line legend (e.g., pa = physical activity, bs = blood sugar) would make the model interpretable without reading the original NetLogo source.


Summary

The core BDI logic is correct and the mesa_signals integration is a genuine strength. The two issues worth fixing before merge are: (1) replace random.random() with self.model.random.random() for reproducibility, and (2) fix the trust check in evaluate_proposal to use Bob's own trust rather than the sender's. The hardcoded coordinates are a minor usability issue. Great concept overall.

@Harshini2411
Copy link

Cool example, BDI is a nice addition to the repo!

Abhinavk0220 already caught the big ones, just want to +1 the two that really need fixing before merge:

  • random.random() should be self.model.random.random() since running with the same seed won't give reproducible results, which breaks a core expectation for Mesa examples.
  • Trust check in evaluate_proposal uses the sender's trust instead of Bob's. The doctor's trust always initialises above 0.5 so the condition is effectively always true and Bob's own self.trust never influences anything.
  • Also the callable(a.goals) fix in the DataCollector that ShreyasN707 flagged, looks like you said you'd update it but I don't see a new commit for that yet?

Otherwise the mesa_signals / computed_property usage is a genuine highlight here, good stuff!

@champ-byte
Copy link
Contributor Author

I have updated the trust . The current implementation does give reproducible results , so no change should be needed, and there is no code like self.compliant = random.random() < self.model.compliance_rate in the file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants