Repository: PrefectHQ/prefect

Issue:
Support multiple match patterns for `agent start`
### First check

- [X] I added a descriptive title to this issue.
- [X] I used the GitHub search to find a similar request and didn't find it.
- [X] I searched the Prefect documentation for this feature.

### Prefect Version

2.x

### Describe the current behavior

The `-m` flag only supports a single pattern.

### Describe the proposed behavior

Multiple `-m` flags should support several match patterns:

```
$ prefect agent start -m "dev-" -m "stag-"
.....
Listening to `dev-` and `stag-`
```

### Example Use

Refer to the previous section

### Additional context

_No response_


Discussion:
This makes sense to me. @anticorrelator what do you think?

Resolving patch:
diff --git a/src/prefect/agent.py b/src/prefect/agent.py
--- a/src/prefect/agent.py
+++ b/src/prefect/agent.py
@@ -25,7 +25,7 @@ class OrionAgent:
     def __init__(
         self,
         work_queues: List[str] = None,
-        work_queue_prefix: str = None,
+        work_queue_prefix: Union[str, List[str]] = None,
         prefetch_seconds: int = None,
         default_infrastructure: Infrastructure = None,
         default_infrastructure_document_id: UUID = None,
@@ -44,6 +44,8 @@ def __init__(
         self.task_group: Optional[anyio.abc.TaskGroup] = None
         self.client: Optional[OrionClient] = None
 
+        if isinstance(work_queue_prefix, str):
+            work_queue_prefix = [work_queue_prefix]
         self.work_queue_prefix = work_queue_prefix
 
         self._work_queue_cache_expiration: pendulum.DateTime = None
diff --git a/src/prefect/cli/agent.py b/src/prefect/cli/agent.py
--- a/src/prefect/cli/agent.py
+++ b/src/prefect/cli/agent.py
@@ -45,7 +45,7 @@ async def start(
         "--work-queue",
         help="One or more work queue names for the agent to pull from.",
     ),
-    work_queue_prefix: str = typer.Option(
+    work_queue_prefix: List[str] = typer.Option(
         None,
         "-m",
         "--match",
diff --git a/src/prefect/client/orion.py b/src/prefect/client/orion.py
--- a/src/prefect/client/orion.py
+++ b/src/prefect/client/orion.py
@@ -794,13 +794,13 @@ async def read_work_queues(
 
     async def match_work_queues(
         self,
-        prefix: str,
+        prefixes: List[str],
     ) -> List[schemas.core.WorkQueue]:
         """
         Query Orion for work queues with names with a specific prefix.
 
         Args:
-            prefix: a string used to match work queue name prefixes
+            prefixes: a list of strings used to match work queue name prefixes
 
         Returns:
             a list of [WorkQueue model][prefect.orion.schemas.core.WorkQueue] representations
@@ -816,9 +816,10 @@ async def match_work_queues(
             )
             if not new_queues:
                 break
-            filtered_queues = list(
-                filter(lambda q: q.name.startswith(prefix), new_queues)
-            )
+            filtered_queues = []
+            for q in new_queues:
+                if any((q.name.startswith(p) for p in prefixes)):
+                    filtered_queues.append(q)
             work_queues += filtered_queues
             current_page += 1
 


Test patch:
diff --git a/tests/test_agent.py b/tests/test_agent.py
--- a/tests/test_agent.py
+++ b/tests/test_agent.py
@@ -106,7 +106,7 @@ async def test_agent_matches_work_queues_dynamically(
 ):
     name = "wq-1"
     assert await models.work_queues.read_work_queue_by_name(session=session, name=name)
-    async with OrionAgent(work_queue_prefix="wq-") as agent:
+    async with OrionAgent(work_queue_prefix=["wq-"]) as agent:
         assert name not in agent.work_queues
         await agent.get_and_submit_flow_runs()
         assert name in agent.work_queues
@@ -124,7 +124,7 @@ async def test_agent_matches_multiple_work_queues_dynamically(
     await orion_client.create_work_queue(name=prod1)
     await orion_client.create_work_queue(name=prod2)
 
-    async with OrionAgent(work_queue_prefix="prod-") as agent:
+    async with OrionAgent(work_queue_prefix=["prod-"]) as agent:
         assert not agent.work_queues
         await agent.get_and_submit_flow_runs()
         assert prod1 in agent.work_queues
@@ -143,12 +143,27 @@ async def test_agent_matches_multiple_work_queues_dynamically(
         ), "work queue matcher should not match partial names"
 
 
+async def test_agent_matches_multiple_work_queue_prefixes(
+    session, orion_client, prefect_caplog
+):
+    prod = "prod-deployment"
+    dev = "dev-data-producer"
+    await orion_client.create_work_queue(name=prod)
+    await orion_client.create_work_queue(name=dev)
+
+    async with OrionAgent(work_queue_prefix=["prod-", "dev-"]) as agent:
+        assert not agent.work_queues
+        await agent.get_and_submit_flow_runs()
+        assert prod in agent.work_queues
+        assert dev in agent.work_queues
+
+
 async def test_matching_work_queues_handes_work_queue_deletion(
     session, work_queue, orion_client, prefect_caplog
 ):
     name = "wq-1"
     assert await models.work_queues.read_work_queue_by_name(session=session, name=name)
-    async with OrionAgent(work_queue_prefix="wq-") as agent:
+    async with OrionAgent(work_queue_prefix=["wq-"]) as agent:
         await agent.get_and_submit_flow_runs()
         assert name in agent.work_queues
 
@@ -184,7 +199,7 @@ async def test_agent_does_not_create_work_queues_if_matching_with_prefix(
         session=session, name=name
     )
     async with OrionAgent(work_queues=[name]) as agent:
-        agent.work_queue_prefix = "goodbye-"
+        agent.work_queue_prefix = ["goodbye-"]
         await agent.get_and_submit_flow_runs()
     assert not await models.work_queues.read_work_queue_by_name(
         session=session, name=name