Skip to content

preserve explicit meta attributes/methods over inferred members#3472

Merged
tpike3 merged 12 commits intomesa:mainfrom
falloficarus22:meta-agent-explicit-overrides-inferred
Mar 21, 2026
Merged

preserve explicit meta attributes/methods over inferred members#3472
tpike3 merged 12 commits intomesa:mainfrom
falloficarus22:meta-agent-explicit-overrides-inferred

Conversation

@falloficarus22
Copy link
Copy Markdown
Contributor

@falloficarus22 falloficarus22 commented Mar 7, 2026

Note

Use this template for bug fixes only. For enhancements/new features, use the feature template and get maintainer approval in an issue/discussion before opening a PR.

Pre-PR Checklist

  • This PR is a bug fix, not a new feature or enhancement.

Summary

Fixes create_meta_agent so explicitly provided meta_attributes and meta_methods are not overwritten by values inferred from constituting agents. Inferred values now only fill missing keys.

Bug / Issue

When assume_constituting_agent_attributes=True and/or assume_constituting_agent_methods=True, the previous implementation could overwrite caller-provided keys in meta_attributes / meta_methods if constituting agents had matching names.
Expected behavior: explicit caller-provided values should always win.
Actual behavior: inferred values could replace explicit ones without warning.

Related context: meta-agent determinism discussions in #3184, but this PR addresses explicit-vs-inferred priority specifically.

Implementation

  • Updated helper logic inside create_meta_agent in mesa/experimental/meta_agents/meta_agent.py:
    • add_methods(...) now:
      • starts from a copy of explicit meta_methods
      • adds inferred methods only when a name is missing (setdefault)
      • keeps deterministic class traversal based on input agent order (seen_classes)
    • add_attributes(...) now:
      • starts from a copy of explicit meta_attributes
      • adds inferred attributes only when a key is missing (setdefault)
  • Preserved existing Mesa primitive attribute exclusions.
  • Updated helper type hints to accept None for meta_methods / meta_attributes.

Testing

Added regression tests in tests/experimental/test_meta_agents.py:

  • test_explicit_meta_attributes_take_precedence_over_inferred
  • test_explicit_meta_methods_take_precedence_over_inferred

Additional Notes

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 7, 2026

Performance benchmarks:

Model Size Init time [95% CI] Run time [95% CI]
BoltzmannWealth small 🔵 +0.2% [-0.1%, +0.5%] 🔵 -0.0% [-0.2%, +0.1%]
BoltzmannWealth large 🔵 +0.0% [-0.6%, +0.5%] 🔵 +0.2% [-0.5%, +0.8%]
Schelling small 🔵 +1.1% [+0.8%, +1.6%] 🔵 +1.4% [+1.3%, +1.6%]
Schelling large 🔵 +0.5% [-0.1%, +1.2%] 🔵 +1.0% [-0.3%, +2.1%]
WolfSheep small 🔵 -0.7% [-1.0%, -0.5%] 🔵 -0.8% [-0.9%, -0.7%]
WolfSheep large 🔵 -0.3% [-1.1%, +0.6%] 🔵 +1.1% [+0.3%, +2.0%]
SugarscapeG1mt small 🔵 +0.3% [-0.2%, +0.9%] 🔵 +0.3% [+0.2%, +0.5%]
SugarscapeG1mt large 🔵 +0.3% [-0.6%, +1.3%] 🔵 +0.1% [-0.2%, +0.4%]
BoidFlockers small 🔵 -1.3% [-1.6%, -1.1%] 🔵 -1.6% [-1.6%, -1.5%]
BoidFlockers large 🔵 -2.2% [-2.6%, -1.9%] 🔵 -0.9% [-1.1%, -0.8%]

@souro26 souro26 mentioned this pull request Mar 9, 2026
7 tasks
@tpike3 tpike3 self-assigned this Mar 16, 2026
# Initialize meta_methods if not provided
meta_methods = {}
for agent_class in agent_classes:
seen_classes = set()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why are you looping through all the agents here, instead of just looping through a set of the types as was being done previously?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I switched away from iterating a plain set of types because that loses order, which made inherited method selection unstable when multiple constituting agent classes define the same method name. The goal was not to inspect every agent for its own sake, but to preserve first-seen type order while still deduplicating classes.

I agree the current form makes that less obvious, so I can simplify it to iterate an order-preserving deduplicated list of types instead, for example via dict.fromkeys(type(agent) for agent in agents). That keeps the determinism fix while making the intent clearer.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This raises some key questions that need to be addressed for the larger meta-agent development. So with GSoC pending I am going to use this PR to explore some meta-agent challenges.

For consideration:
Deterministic order of "inheritance" is not necessarily the problem we want to solve/ the capability we want to provide. My thoughts are below, but curious on other thoughts.

The first question is what is the purpose of a meta-agent inheriting a method from one of its constituting agents?

  • one use is the idea that a meta-agent, would have a different "view" than that of a constituting agent so would have a different outcome than that of the constituting agent. Otherwise, the user could just execute the constituting agents method
  • another would be a potential efficiency where say the meta-agent has numerous constituting of the same type and can get a similar impact by executing once as the meta-agent.

Either way, if two constituting agent types have a method with the same name resulting in a collision, just selecting the first one may create a bug in their simulation if they don't realize they have a naming collision. In this dynamic it may be better to have a warning about the collision than it would be to select for them. There may be some other ways to handle this, but I am not sure effectively making the choice for them is the right answer.

The second question is what is the purpose of meta-agents inheriting attributes from its constituting agents? This raises different concerns, for example, if you take the alliance formation and lets say the constituting agents have an attribute of wealth, adding that attribute is a problem as it will only have one agent's wealth as opposed to the aggregation (as one possible approach to wealth sharing in an alliance) of all constituting agents wealth. Conversely, if one constituting agent has gold and the other has silver than this could be useful.

Based on this thought experiment, I am thinking meta-agent attribute adoption is of a different kind and should be handled differently than methods. Thoughts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There are really two different questions here, and I do not think this PR should answer both by accident.

For this PR, the bug I was aiming to fix is narrower: if the user explicitly passes meta_methods or meta_attributes, Mesa should not overwrite those with inferred values. That seems independent from the larger question of how inferred values should behave when they collide.

My current view is that methods and attributes should be treated differently. For methods, inference can still be useful as a convenience, but if two constituting agent types infer the same method name, I do not think Mesa should silently pick one without surfacing that collision. For attributes, I think the risk is higher: copying one constituent’s state onto the meta-agent can easily imply meaning that is not generally valid, so attribute inference probably needs a more restrictive design than method inference.

So I think this PR can stay narrowly focused on preserving explicit user intent, while broader handling of inferred collisions, especially for attributes, is better handled in the larger meta-agent work.

@falloficarus22 falloficarus22 requested a review from tpike3 March 16, 2026 14:29
@tpike3
Copy link
Copy Markdown
Member

tpike3 commented Mar 18, 2026

See #3538 (comment)

@falloficarus22 let me know what think, in short I think there is a different solution that solves the problem identified here as well as the current brittleness of the meta-agent approach.

@falloficarus22
Copy link
Copy Markdown
Contributor Author

In light of the discussion on #3538, I think the attribute side of this PR should probably follow the “do not overwrite existing meta-agent attributes” direction instead. That seems like a better fix shape for attributes than what I have here. I’m planning to narrow this PR to the method side only, since explicit meta_methods being overwritten by inferred methods still seems like a separate bug not addressed by the attribute overwrite guard.

Copy link
Copy Markdown
Member

@tpike3 tpike3 left a comment

Choose a reason for hiding this comment

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

LGTM -- Thanks @falloficarus22

@tpike3 tpike3 merged commit 71cfd39 into mesa:main Mar 21, 2026
14 checks passed
@falloficarus22 falloficarus22 deleted the meta-agent-explicit-overrides-inferred branch March 23, 2026 04:50
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.

explicit meta_attributes/meta_methods are overwritten by inferred constituent values

3 participants