A2A Classifier Routing

Routes A2A requests by body-derived method, family, context ID, task ID, and streaming detection

Category: Setup-dependent integration
Task: Routes A2A requests by body-derived method, family, context ID, task ID, and streaming detection

Prerequisites: The external service, credentials, or certificates referenced by this configuration.

Run it: Use ghcr.io/praxis-proxy/ai:0.4.1 and follow the container quickstart to mount and start the configuration.

This configuration comes from the selected release. The example has not been run here; external services are not bundled.

Download the source file.

# A2A Classifier Routing
#
# Routes A2A requests by body-derived method, family, context ID, task ID, and streaming detection.
# The `a2a` filter parses JSON-RPC bodies and promotes internal routing headers
# (x-praxis-a2a-*) for router matching. These internal headers are stripped
# before upstream by header hygiene.
#
# This example demonstrates static A2A routing based on:
# - Method classification (SendMessage, SendStreamingMessage, GetTask, etc.)
# - Streaming detection for SendStreamingMessage and SubscribeToTask
# - Context ID extraction from params.message.contextId and ListTasks params.contextId
# - Task ID extraction from params.id and params.taskId
# - Method alias support for compatibility (slash-delimited → PascalCase)
#
# For mixed A2A/non-A2A traffic, set on_invalid: continue to let
# non-A2A requests pass through to the default cluster.

listeners:
  - name: a2a
    address: "127.0.0.1:8080"
    filter_chains: [a2a-routing]

filter_chains:
  - name: a2a-routing
    filters:
      - filter: a2a
        max_body_bytes: 65536
        on_invalid: continue
        method_aliases:
          message/send: SendMessage
          message/stream: SendStreamingMessage
          tasks/get: GetTask
          tasks/cancel: CancelTask
        headers:
          method: x-praxis-a2a-method
          family: x-praxis-a2a-family
          context_id: x-praxis-a2a-context-id
          task_id: x-praxis-a2a-task-id
          kind: x-praxis-a2a-kind
          streaming: x-praxis-a2a-streaming
          version: x-praxis-a2a-version

      - filter: router
        routes:
          # First-match routing requires specific context rules before broader method/family rules.
          - path_prefix: "/"
            headers:
              x-praxis-a2a-context-id: "ctx-123"
            cluster: "message-backend"

          # Route SendMessage to agent backend
          - path_prefix: "/"
            headers:
              x-praxis-a2a-method: "SendMessage"
            cluster: "agent-backend"

          # Route streaming methods to streaming backend
          - path_prefix: "/"
            headers:
              x-praxis-a2a-streaming: "true"
            cluster: "streaming-backend"

          # Route GetTask by task ID to task-specific backend
          - path_prefix: "/"
            headers:
              x-praxis-a2a-method: "GetTask"
              x-praxis-a2a-task-id: "task-123"
            cluster: "task-specific-backend"

          # Route GetTask with different task ID pattern
          - path_prefix: "/"
            headers:
              x-praxis-a2a-method: "GetTask"
            cluster: "task-backend"

          # Route all task family methods to task management backend
          - path_prefix: "/"
            headers:
              x-praxis-a2a-family: "task"
            cluster: "task-backend"

          # Route message family methods to message backend
          - path_prefix: "/"
            headers:
              x-praxis-a2a-family: "message"
            cluster: "message-backend"

          # Route push notification methods to notification backend
          - path_prefix: "/"
            headers:
              x-praxis-a2a-family: "push_notification"
            cluster: "notification-backend"

          # Route agent card requests to agent info backend
          - path_prefix: "/"
            headers:
              x-praxis-a2a-family: "agent_card"
            cluster: "agent-info-backend"

          # Default fallback for non-A2A traffic and unknown methods
          - path_prefix: "/"
            cluster: "default-backend"

      - filter: load_balancer
        clusters:
          - name: "agent-backend"
            endpoints:
              - "127.0.0.1:9001"
          - name: "streaming-backend"
            endpoints:
              - "127.0.0.1:9002"
          - name: "task-specific-backend"
            endpoints:
              - "127.0.0.1:9003"
          - name: "task-backend"
            endpoints:
              - "127.0.0.1:9004"
          - name: "message-backend"
            endpoints:
              - "127.0.0.1:9005"
          - name: "notification-backend"
            endpoints:
              - "127.0.0.1:9006"
          - name: "agent-info-backend"
            endpoints:
              - "127.0.0.1:9007"
          - name: "default-backend"
            endpoints:
              - "127.0.0.1:9000"

insecure_options:
  allow_private_endpoints: true # example proxies to local backends