aws-samples / aws-samples/sample-ai-possibilities

Opponent possession is incorrectly resolved as own possession when agent IDs are reused across teams

Open
#145 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
40
Forks
36
Avg merge
5h 26m
Merged PRs (30d)
1

Description

# Bug: Opponent possession incorrectly classified as own-team possession

## Summary

During a match, possession logs never show opponent possession.

The logs only contain:

held by MY player X
held by free

and never:

held by OPP player X

even when the opponent player is clearly controlling the ball.

The issue is caused by an ambiguous possession identity. The ball state provides only `possessionAgentId`, while agent IDs are reused across teams. The current resolver cannot uniquely identify the possession holder and would incorrectly classify opponent possession as own-team possession.

------------------------------------------------------------------------

## Observed Behavior

Example ball state:

``` json
{
"position": {
"x": 0.5445947,
"y": 0.13751486,
"z": 0.108918935
},
"velocity": {
"x": 0,
"y": 0,
"z": 0
},
"isFree": false,
"possessionAgentId": "agentId_4"
}
```

The ball state only contains:

possessionAgentId = agentId_4

However, both teams reuse the same agent IDs:

``` json
[
{
"teamCode": "home",
"agentId": "agentId_4"
},
{
"teamCode": "away",
"agentId": "agentId_4"
}
]
```

`agentId_4` is team-scoped and is not globally unique inside a match.

------------------------------------------------------------------------

## Root Cause

The issue has one root cause and two resulting effects.

## 1. Possession identity is incomplete and cannot be resolved uniquely

The ball state provides only:

possessionAgentId = agentId_4

However, `agentId` is only unique within a team.

A valid player identity requires:

teamCode + agentId

For example:

(home, agentId_4) != (away, agentId_4)

Therefore, `possessionAgentId` alone cannot determine whether the possession belongs to the home team or away team.

------------------------------------------------------------------------

## 2. get_possession_info() resolves ambiguous IDs incorrectly

The current resolver implementation in `lib/state.py` uses:

``` python
holder = next(
(p for p in players if _player_idx(p) == possession_id),
None
)
```

The `_player_idx()` helper converts:

home.agentId_4 -> 4
away.agentId_4 -> 4

Both players therefore have the same lookup key.

Because home players appear first in the player list, `next()` returns the home player whenever both teams contain the same agent index.

Example:

Actual possession:
away.agentId_4

Resolver result:
home.agentId_4

Generated summary:
held by MY player 4

The team check happens only after the player has already been selected, so it cannot correct the mismatch.

The resolver effectively treats a team-scoped `agentId` as globally unique.

------------------------------------------------------------------------

## 3. hasBall is incorrectly determined using the same ambiguous identity

The same identity issue affects the `hasBall` field generated for the current agent.

The current implementation uses:

``` python
has_ball = possession_id == my_player_id
```

This comparison ignores team identity.

Example:

My player:
home.agentId_4

Actual possession:
away.agentId_4

Both are converted to:

possession_id = 4
my_player_id = 4

Therefore:

``` python
has_ball = True
```

even though the opponent actually has possession.

This can generate misleading state information:

Ball: held by MY player 4

YOUR PLAYER (... id=4):
hasBall=True

when the actual possession belongs to:

away.agentId_4

### Note on local workaround limitations

Because the ball state does not include the possession holder's team identity, downstream code cannot reliably resolve the possession owner from `possessionAgentId` alone.

A reliable fix requires either:
- adding team information to the possession data, or
- providing a globally unique player identifier.

------------------------------------------------------------------------

## Steps to Reproduce

1. Start a match with both home and away teams.
2. Enable game state / after summarize_state logging.
3. Wait until an away player gains possession.
4. Check the generated possession summary in CloudWatch logs.

------------------------------------------------------------------------

## Expected Result

When an opponent player has possession:

held by OPP player X

The current agent should also receive:

hasBall=False

------------------------------------------------------------------------

## Actual Result

The state can incorrectly report:

held by MY player X

and:

hasBall=True

when the opponent has possession.

------------------------------------------------------------------------

## Expected Behavior

The possession system should correctly distinguish between players with the same agent ID on different teams.

Situation Expected output
------------------------------ ------------------------
Own player has the ball `held by MY player X`
Opponent player has the ball `held by OPP player X`
No player controls the ball `held by free`

The ball possession holder should include team information so that it can be uniquely identified using:
teamCode + agentId

------------------------------------------------------------------------

## Impact

This issue affects the entire multi-agent decision system because possession information is one of the key factors used by agents to make tactical decisions and is included in the shared game state provided to all agents.

Since each agent uses the summarized game state as LLM context for decision-making, incorrect possession information can cause agents to reason from an incorrect understanding of the match situation.

Potential impact:

- All LLM agents may receive incorrect possession context.
- Offensive and defensive roles may make decisions based on an incorrect game state.
- Defending agents may fail to recognize opponent possession and react too late.
- Attacking agents may incorrectly assume possession and generate suboptimal tactical actions.
- Multi-agent coordination may degrade because agents share an inconsistent view of the game state.
- Match analysis, possession statistics, and historical training data may become unreliable.

Contributor guide

Open the contributing guide

Research direction

Start in lib/state.py at get_possession_info(), _player_idx(), and the hasBall comparison, then trace where possessionAgentId is produced and shaped. Confirm how team identity or a globally unique player identifier can reach the resolver; done means own and opponent players with reused IDs produce distinct possession summaries and opponent possession yields hasBall=False.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
ai, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.