Skip to content

Conversation

@He-Pin
Copy link
Contributor

@He-Pin He-Pin commented Nov 26, 2025

SEP-1904: Task filter

Status: Draft
Type: Standards Track
Created: 2025-11-20
Author(s): He-Pin hepin.p@alibaba-inc.com (@He-Pin)

Sponsor: TBD
PR: #1904

Abstract

This SEP proposes a task filtering mechanism to enhance the query of tasks in large-scale distributed systems.
By implementing a filtering layer, the system can quickly identify and prioritize tasks based on predefined criteria,
reducing latency and improving overall performance.

Motivation

The current tasks/list API retrieves all tasks without any filtering capabilities, which can lead to inefficiencies in
large-scale distributed systems.
As in Streamable HTTP transport, a User or Agent system MAY reuse the same session for multiple task submissions.
When querying tasks, the system may return a large number of tasks that not interested(eg. already completed), leading
to increased latency and resource consumption.

To address this issue, we propose introducing a task filtering mechanism that allows users to specify criteria for
filtering tasks during the query process.
This will enable the system to return only relevant tasks, improving efficiency and user experience.

Specification

Capabilities

Servers and Clients that support task filtering MUST advertise this capability during the initial handshake or
capabilities negotiation phase. This can be done by including a filter flag in the capabilities exchange message.

Server capabilities

Capability Description
tasks.list.filter Server supports filter in the tasks/list operation
{
  "capabilities": {
    "tasks": {
      "list": {
        "filter": {
          "methods": ["tools/call"],
          "taskIds": true,
          "status": true,
          "createdAt": {
            "before": true,
            "after": true
          },
          "lastUpdatedAt": {
            "before": true,
            "after": true
          },
          "order": {
            "by": ["createdAt", "lastUpdatedAt"],
            "direction": ["asc", "desc"]
          }
        }
      }
    }
  }
}

Client capabilities

Capability Description
tasks.list.filter Client supports filter in the tasks/list operation
{
  "capabilities": {
    "tasks": {
      "list": {
        "filter": {
          "methods": ["sampling/createMessage", "elicitation/create"],
          "taskIds": true,
          "status": true,
          "createdAt": {
            "after": true,
            "before": true
          },
          "lastUpdatedAt": {
            "after": true,
            "before": true
          },
          "order": {
            "by": ["createdAt", "lastUpdatedAt"],
            "direction": ["asc", "desc"]
          }
        }
      }
    }
  }
}

Capability Negotiation

During the initialization phase, both parties exchange their tasks capabilities to establish which operations support
task-based execution.
Requestors SHOULD only query tasks with filtering if the receivers have advertised support for the tasks.list.filter
capability.

If a specified filter criterion is not supported by the receiver, the receiver MAY just ignore that criterion and
process the request using the supported criteria.
The requester MUST be prepared to handle responses that do not fully adhere to the requested filtering criteria, eg
returning a broader set of tasks than expected.
eg, if a client requests filtering by status but the server does not support it, the server may return all tasks
without filtering by status,
and the client should be able to handle this scenario gracefully, eg. by performing client-side filtering if necessary.

Filter Parameters

When making a tasks/list request, clients MAY include filter parameters to specify the criteria for filtering
tasks.
The following filter parameters are supported:

  • methods (array of strings, optional): Filter tasks by the types of the underlying request (e.g. tools/call,
    sampling/createMessage).
  • taskIds (array of strings, optional): Filter tasks by a list of specific task IDs.
  • status (array of strings, optional): Filter tasks by a list of specified current status (e.g., working,
    completed, failed, cancelled, input_required).
  • createdAfter (string, optional): An ISO 8601 timestamp to filter tasks created after the specified time.
  • createdBefore (string, optional): An ISO 8601 timestamp to filter tasks created before the specified time.
  • lastUpdatedAfter (string, optional): An ISO 8601 timestamp to filter tasks updated after the specified time.
  • lastUpdatedBefore (string, optional): An ISO 8601 timestamp to filter tasks updated before the specified time.
  • orderBy (string, optional): Specifies the field by which to order the returned tasks. Possible values are
    createdAt and lastUpdatedAt. Default is lastUpdatedAt.
  • order (string, optional): Specifies the order of the returned tasks. Possible values are asc for ascending and
    desc for descending. Default is desc.

When the filter is omitted, all tasks belongs to that session are returned.

Backward Compatibility

New Client + Old Server: New clients that support task filtering can still interact with old servers that do not
support
the feature. In this case, the filtering parameters will be ignored by the old server, and the client will receive
the full list of tasks as per the existing behavior.

Old Client + New Server: Old clients that do not support task filtering can still interact with new servers that
support the feature. In this case, the server will return the full list of tasks without applying any filters,
maintaining
compatibility with the old client.

@He-Pin He-Pin requested a review from a team as a code owner November 26, 2025 04:08
@He-Pin
Copy link
Contributor Author

He-Pin commented Nov 26, 2025

@LucaButBoring Would you like to help with this? Thanks, feel free to add you to the authors, too.

@He-Pin He-Pin changed the title SEP-0000 : Add filtering support for tasks/list SEP-1904 : Add filtering support for tasks/list Nov 26, 2025
@LucaButBoring
Copy link
Contributor

LucaButBoring commented Nov 26, 2025

I might be willing to sponsor this, depending on the specifics, but I likely won't be able to directly contribute that much right now due to having several other large SEPs to directly author (including subtasks).

I do have a few questions on this, first (in part because these are questions I'd be asked as a sponsor):

  1. Is there a specific use case you can provide some technical details about, to demonstrate how the current no-filtering API is or will be encountering bottlenecks or integration challenges?
    • One reason I ask this is because in some distributed databases, a filtered/sorted query may actually be much less efficient than an unfiltered one, unless you've already pre-built your database schemas for all access patterns (Cassandra, Scylla). I'm curious what kind of distributed database you're using that would handle that well.
  2. Is this a problem that is best solved by the protocol itself, or by an alternative API exposed by your own server for internal use? In particular, "the system can quickly identify and prioritize tasks based on predefined criteria" sounds like you have a custom architecture already that would benefit from this, so it might make more sense to expose an internal API outside the scope of the protocol, which would access the same database with filtering APIs.
  3. Supporting taskIds sounds more like a batch-get operation, so is there a reason we'd want to have that in tasks/list? Are there other APIs you're aware of that do this which we could look at to see how that's handled in practice, or should we propose an addition to tasks/get to support batching?

Regarding a separate comment from @dsp-ant that #1300 already proposes tool filtering and hasn't been accepted (suggesting this might face similar pushback), I think we should discuss that as well. I'll refer to @cliffhall's comment here describing the feedback from the Core Maintainers on each aspect of that proposal. In particular, this part:

  • Harder to reason about and form for some LLMs.
  • We want to be inclusive of smaller models that could run locally not just super smart (and expensive) foundation models.
  • Making it simple to get to a useful subset of tools is more important than having a complicated filtering language that might yield a marginally better (debatable) subset (for some models) than the statement implied by two lists: “give me tools from any of these groups that have all of these tags.”

Based on this and @dsp-ant's comment right after that, I think the arguments against filtering are actually more specifically arguments against this kind of filtering being done by models.

@He-Pin With that context established, I'd also like to ask you what the intended usage of task filtering is on the consuming side. If this is primarily intended to be invoked with filtering by models, we'll need to address the same questions as #1300. If this is primarily intended to be filtered by some control plane service or the host application itself (which makes more sense to me), then this is completely different from #1300, and those concerns likely don't apply.

@LucaButBoring
Copy link
Contributor

Discussing in parallel with @cliffhall and @scottslewis - the Primitives WG is planning to introduce a unified proposal for filtering across the protocol after the new Groups proposal (addressing feedback) lands, so this may fall under the Primitives WG's purview. It'd be great to have a consistent means of filtering across the entire protocol.

@He-Pin
Copy link
Contributor Author

He-Pin commented Nov 27, 2025

  1. We currently use the Lindorm database and various secondary indexes to achieve fast retrieval. I believe enterprise-level implementations are inherently database-dependent. A simple CQRS implementation without secondary indexes will inevitably be inefficient with a large number of tasks, especially when subsequent subtasks may be associated.

  2. Why support querying by taskIds: Consider a front-end chat application. Users might want to know why a previous call hasn't returned a result. They can retry by clicking the chat block on the interface. When we dispatch subtasks, a list will be available. Currently, we have our own configured Agent and a web-based implementation in AiStudio, but local applications like Cherry Studio can also be used.

  3. My main goal is to enable fast usage on the control plane and Agent side. For example, after an Agent system restarts, it might need to quickly retrieve all unfinished events since the last restart. Otherwise, if we reuse the same sessionId, we will retrieve a large number of tasks that are no longer of interest, thus increasing the time our Agent takes to drive tasks.

@LucaButBoring thanks for your input.

@He-Pin
Copy link
Contributor Author

He-Pin commented Nov 27, 2025

It'd be great to have a consistent means of filtering across the entire protocol.

Thank you for letting me know, I agree 100%.

@dsp-ant
Copy link
Member

dsp-ant commented Nov 28, 2025

Thank you for the proposal. My main feedback on any time of filter proposal is that you have to demonstrate that this is necessary to put into the protocol.

My current stance is that filtering can be done in nearly all instances on the client. Even for large tool lists, they can transfer easily to the client in <100kb with gzip enabled. I just generate 1000 tool descriptions and received the following results:

  | Format                        | Size    |
  |-------------------------------|---------|
  | Uncompressed (pretty-printed) | 851 KB  |
  | Uncompressed (compact)        | 562 KB  |
  | Gzip compressed (pretty)      | 21.7 KB |
  | Gzip compressed (compact)     | 20.9 KB |

This means the client can do everything by themselves, giving it full control how it wants to filter, e.g. by using a search tool, by using RAG or any other method.

For this proposal to get traction, I think you need to show a set of clear use-cases that this enables that otherwise can't be done and are becoming widespread patterns.

@dsp-ant dsp-ant added proposal SEP proposal without a sponsor. SEP labels Nov 28, 2025
@He-Pin
Copy link
Contributor Author

He-Pin commented Nov 28, 2025

You're absolutely right, but the main problem is that bandwidth costs money for large companies. By reducing the number of queries, we can also reduce the database's TPS (transactions per second).

Meanwhile, considering edge-side agents, a user can say to their phone: "Please check the tasks I submitted yesterday but haven't completed yet," or "Please check the tasks with status updates in the last 3 hours." By implementing server-side filtering, we can quickly return results to the user.

A demo implementation shows how to perform result filtering on the server side, thereby avoiding bandwidth costs and improving real-time response.

@scottslewis
Copy link

It'd be great to have a consistent means of filtering across the entire protocol.

Thank you for letting me know, I agree 100%.

I've been a participant in the specification for the OSGi framework. Early on, there was a need to do filtering for osgi service lookup aka runtime service discovery. The required filtering was over a dictionary of name/value properties associated with the service. Dynamic OSGi service lookup and filtering is in heavy use today.

The approach taken then (and in use today) was to use a rfc-standardized filtering syntax RFC-1960.

I bring this up as an example of a filtering use case similar to MCP primitive lookup/discovery/filtering being discussed here.

@bdoyle0182
Copy link

bdoyle0182 commented Dec 1, 2025

@He-Pin you can get involved in the Groups working group channel in the discord. We can discuss filtering but current active priority is delivering the group abstraction that is much more agreed upon as a necessity before we start trying to deliver any dedicated solutions related to filtering.

Whatever is agreed upon from the working group we'll want to make a universal SEP for all primitives, not just tasks like we're doing for the group abstraction

@He-Pin
Copy link
Contributor Author

He-Pin commented Dec 2, 2025

Thanks, Discord is blocked at Alibaba, and I have to reach it with my phone.I am currently working on the Java-side implementation.
@bdoyle0182 Could you give me a Discord channel pointer? thanks

@LucaButBoring
Copy link
Contributor

@He-Pin Discord is here, linked in the governance documentation here. Check the #primitive-grouping-wg channel.


Also linking Agents WG notes on this from two days ago for discoverability for others: #1927

This proposal (#1904) was introduced with a note that it may fit better under the Primitive Grouping WG, as they're already planning to build filtering uniformly across the protocol on top of Groups.

Concerns were raised that this may be nontrivial for servers to support, considering both the range of filter operators and how filtering interacts with pagination, whereas it is very easy for clients to do this filtering themselves. This mirrors the same reasons tool filtering gets pushback.

Several members of the discussion wanted to see concrete evidence that the lack of filtering is a significant pain point for servers before supporting the proposal, as Tasks are still new and the full range of potential scaling challenges remains hypothetical.

@He-Pin
Copy link
Contributor Author

He-Pin commented Dec 9, 2025

image @LucaButBoring FYI,here we may want to filter

@LucaButBoring
Copy link
Contributor

Can you elaborate on this? I'm not sure what this is, exactly (and this appears to be a mockup).

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

Labels

proposal SEP proposal without a sponsor. SEP

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants