Skip to content

Python: [Bug]: AgentState retains per-session locks after sessions are deleted #9171

Closed

Description

Description

What happened?

AgentState.get_or_create_session() keeps a per-session asyncio.Lock in _session_locks for every distinct session ID passed to it.

The lock is created with:

session_lock = self._session_locks.setdefault(session_id, asyncio.Lock())

_session_locks is a regular dictionary, and completed locks are not removed. As a result, the lock registry can continue growing as new session IDs are processed, even after the corresponding sessions have been deleted from the SessionStore.

For example, after creating and deleting 1,000 unique sessions, the session store is empty but _session_locks still contains 1,000 entries.

What did you expect to happen?

Per-session synchronization state should not be retained indefinitely once there are no active users of the lock.

The existing concurrency behavior should remain unchanged: concurrent callers for the same session ID should continue to share the same lock so that the underlying session is created only once.

Steps to reproduce the issue

Create an AgentState.

Call get_or_create_session() with many unique session IDs.

Delete each corresponding session from the session store.

Inspect _session_locks.

Observe that the lock entries remain even though the sessions have been deleted.

A regression test using 1,000 unique session IDs consistently reproduces the issue.

Code Sample

async def test_get_or_create_session_does_not_retain_locks_for_completed_sessions(self) -> None:
    agent = _FakeAgent()
    state = AgentState(agent)

    for i in range(1000):
        session_id = f"session-{i}"
        await state.get_or_create_session(session_id)
        await state.session_store.delete(session_id)

    assert len(state.session_store._sessions) == 0
    assert len(state._session_locks) == 0

Error Messages / Stack Traces

assert len(state._session_locks) == 0
AssertionError: assert 1000 == 0

1 failed, 23 deselected

Package Versions

agent-framework-hosting: repository main (source checkout) agent-framework-core: repository main (source checkout)

Python Version

Python 3.14.8

Additional Context

The issue was reproduced against the current repository source.

A candidate fix using weakly referenced per-session lock values was also tested locally. This allows unused locks to be released while preserving strong references to locks that are actively being used or awaited.

Validation after the candidate change:

  • New regression test passes.
  • Existing test_get_or_create_session_creates_once_for_concurrent_callers test passes, preserving same-session concurrency behavior.
  • Full packages/hosting/tests/hosting/test_state.py suite: 24 passed.
  • ruff check passes.
  • ruff format --check passes.
  • git diff --check reports no errors.

The candidate change does not alter the SessionStore lifecycle or public API.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 7, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Oct 7, 2026
  3. github-actions commented on Oct 7, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    The bug reproduces in python/packages/hosting/agent_framework_hosting/_state.py::AgentState.get_or_create_session at line 173 when many distinct session IDs are created and later deleted. Minimal repro: create an AgentState, call get_or_create_session() and session_store.delete() for 1,000 unique IDs, then observe an empty store but 1,000 entries in _session_locks.

    • Failing test: python/packages/hosting/tests/hosting/test_state.py
    • Files examined: python/AGENTS.md, python/packages/hosting/agent_framework_hosting/_state.py, python/packages/hosting/tests/hosting/test_state.py, python/packages/hosting/pyproject.toml
    • Tests run: packages/hosting/tests/hosting/test_state.py, TestAgentState::test_get_or_create_session_creates_once_for_concurrent_callers
    • Current version: 1.0.0a261002
  4. added
    hostingUsage: [Issues, PRs], Target: all hosting related solutions
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

hostingUsage: [Issues, PRs], Target: all hosting related solutionspythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions