[Feat]: NoSQL (MongoDB) TaskStore / PushNotificationConfigStore backend — production-verified reference implementation available
Maintainers usually reply within 1 day
@ishymko is already working on this.
Since Aug 28, 2026.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
Research direction
The issue proposes adding a MongoDB-backed TaskStore and PushNotificationConfigStore to the a2a-python SDK. Start by examining the existing DatabaseTaskStore in the a2a-sdk[sql] extra to understand the interface and semantics. Review the Task proto definition and serialization. The implementation must handle owner partitioning, pagination with cursor filters, and TTL indexes for retention. Override get_info_for_dispatch in the push config store with memoization. Tests should verify cross-replica persistence and pagination behavior.
Written by the indexing model from the issue text.
Description
Summary
The SDK currently ships two TaskStore backends: InMemoryTaskStore and the SQLAlchemy-based DatabaseTaskStore (a2a-sdk[sql]). There is no supported path for document/NoSQL databases, even though task records are a natural fit for them. We built and deployed a MongoDB-backed TaskStore + PushNotificationConfigStore for a production A2A server (FastAPI, multi-replica) and would like to propose upstreaming a generic version — either as an optional extra (e.g. a2a-sdk[mongodb]) or as a documented reference implementation.
Why a document store fits this data
- Tasks are ephemeral, retention-bound records. They are written per request, re-read for a bounded window (
GetTask/ListTasks), and then expire. MongoDB TTL indexes handle retention natively (one index on anupdated_atfield); with SQL backends every deployment has to build its own cleanup job (cron /EVENTscheduler / partition rotation). - Many A2A server deployments already run a document store for conversation state, and adding a relational database + Alembic migrations solely for task persistence is a heavy dependency for what is a single-collection workload.
Implementation notes (lessons that may save others time)
We verified these against SDK 1.1.2 semantics; happy to carry them into a PR:
- Store the
Taskas serialized proto bytes, not ProtoJSON.Task.metadatais a protoStructwith arbitrary client-supplied keys — keys containing.or$become invalid MongoDB document keys afterMessageToDict. Storingtask.SerializeToString()as opaque bytes (plus a handful of extracted top-level fields for querying: owner,context_id,status.state,status.timestamp) is exact, round-trip safe, and resilient to unknown fields across SDK upgrades. - Owner partitioning parity. All reads/writes are scoped by
owner_resolver(context)(defaultresolve_user_scope), matchingInMemoryTaskStore— including refusing cross-owner access onget/delete. - Pagination matching in-memory semantics. Sort
(status.timestamp desc — nulls last, id desc); the page token (encode_page_token) is the id of the first item of the requested page (inclusive anchor), so the store re-resolves the anchor document to build a(timestamp, id)cursor filter; unknown tokens raiseInvalidParamsError. MongoDB's BSON ordering (Date > Nullunder descending sort) reproduces the in-memory null-handling exactly. get_info_for_dispatchmust be overridden on customPushNotificationConfigStoreimplementations (the base fallback silently drops notifications for authenticated owners — the docstring warns about this, but it is easy to miss). Since streaming turns call it once per emitted event, we front it with a short (5s) in-process memo keyed bytask_id, invalidated onset_info/delete_info.
The whole thing is ~200 lines for both stores. Deployed behind a FastAPI JSONRPC server; verified: task survives process restart and is served by a different replica, ListTasks cursor pagination over 100+ tasks, push configs dispatching across replicas.
Questions for maintainers
- Is there interest in an official NoSQL backend, and if so, would you prefer an optional extra (
a2a-sdk[mongodb], pymongo async client) or a documented recipe in the docs/examples? - If an extra: should it mirror
DatabaseTaskStore's constructor conventions (create_table→ensure_indexes,owner_resolverinjection), and should retention (TTL) be part of the contract or left to operators? - Would you want the same treatment for
PushNotificationConfigStorein the same PR?
If maintainers are open to it, we're happy to submit the PR with tests (the store semantics above are covered by a small in-memory fake collection in our suite; we can port those tests).
- Dominant language
- Python
- Stars
- 2.2k
- Forks
- 499
- Avg merge
- 3d 10h
- Merged PRs (30d)
- 26
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from a2aproject/a2a-python
-
Create push notification config returns no id on database-backed storesPossibly taken @ConnorMoss02 claimed this 3 days ago. Opencomponent: server
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
a2aproject/a2a-python#1237 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
message/send JSON-RPC result is wrapped in the SendMessageResponse oneof instead of returning the Task/Message directlyMay be free again @rohityan claimed this 43 days ago, and no pull request is open. Opencomponent: server
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
a2aproject/a2a-python#1192 · 3 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
maintainers-only
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
a2aproject/a2a-python#805 · 1 comment ·
Maintainers usually reply within 1 day
-
[Feat]: Change Httpx to Httpx2Possibly taken @rohityan claimed this today. Open
a2aproject/a2a-python#1288 · 2 assignees ·
Maintainers usually reply within 1 day
-
[Bug]: Streaming follow-up on an existing task does not begin with a Task; enqueuing the current task drops the follow-up message from historyPossibly taken @rohityan claimed this 1 day ago. Open
a2aproject/a2a-python#1285 · 2 assignees ·
Maintainers usually reply within 1 day
All issues in a2aproject/a2a-python
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
mozilla/bedrock#17413 · 1 reaction ·
Maintainers usually reply within 2 days
-
instance instance add
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
searxng/searx-instances#943 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
bug tools
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
lance-format/lance#9655 ·
Maintainers usually reply within 2 days