Tip: How Does the Event Mesh Entrypoint Work in Solace Agent Mesh?

Tip: How Does the Event Mesh Entrypoint Work in Solace Agent Mesh?

Solace Agent Mesh is an event-driven framework for building distributed ecosystems of collaborative AI agents, powered by the Solace Event Mesh for enterprise-grade agent orchestration. Agents do the thinking. But what if the trigger for an agent task is not a human typing a prompt, but a business event flowing through your message broker? That is where the Event Mesh Entrypoint comes in.

The Event Mesh Entrypoint is a plugin that bridges your Solace event mesh (the data plane) with the Agent Mesh ecosystem (the control plane). External systems publish events to Solace topics. The Entrypoint picks them up, transforms them into agent tasks, and publishes agent responses back to the event mesh for consumption by other applications.

In this post, we will walk through how the Event Mesh Entrypoint works, how to install and configure it, the key concepts behind event handlers and output handlers, and practical examples you can use as starting points.


How It Works

The Event Mesh Entrypoint maintains two separate Solace broker connections:

  1. Control Plane (A2A): The standard Agent Mesh broker connection used for agent-to-agent communication via the A2A protocol. This is how the Entrypoint submits tasks to agents and receives responses.

  2. Data Plane: A dedicated Solace client that connects to your existing broker infrastructure. This can be the same broker or a completely different one. This is where your business events flow.

The processing flow is:

  1. An external system publishes an event on a Solace topic on the data plane (e.g., orders/placed/ORD-20250612-001)
  2. The Event Mesh Entrypoint picks up the message, transforms it into an agent prompt, and submits it as an A2A task on the control plane
  3. Agents process the task and return a response
  4. The Entrypoint’s output handler transforms the response and publishes it back to the data plane (e.g., orders/validated)

The Entrypoint itself makes no LLM calls. It is a translation and routing layer between your event mesh and the Agent Mesh.


Installation

Install the Event Mesh Entrypoint plugin:

sam plugin add my-event-mesh --plugin sam-event-mesh-gateway

See the Plugins documentation for all installation options and the sam-event-mesh-gateway documentation.

This creates a configuration file at configs/gateways/my-event-mesh.yaml. Edit the config for your environment (see Configuration section below), then start it:

sam run configs/gateways/my-event-mesh.yaml

Core Concepts

Event Handlers (Input Side)

An event handler defines what to listen for on the data plane and how to process it. Each handler has:

  • Subscriptions: Solace topic filters to subscribe to (with wildcard support: * for one level, > for one or more)
  • Input expression: How to transform the incoming message into an agent prompt
  • Target agent: Which agent to send the task to (static or dynamic)
  • Forward context: Data to extract from the message and carry through to the output handler
  • On success / on error: Which output handlers to route results to

Output Handlers (Response Side)

An output handler defines how to format and publish agent responses back to the data plane. Each handler has:

  • Topic expression: The Solace topic to publish the response to (can include forwarded context for correlation)
  • Payload expression: How to extract and format the agent’s response
  • Output schema: Optional JSON Schema validation before publishing

Expression Engine

Both input and output handlers use an expression engine for transformations. The most common form is template: syntax:

template:Validate this order: Customer: {{text://input.payload:customerName}}, Items: {{text://input.payload:items}}, Total: {{text://input.payload:totalAmount}}

Available input selectors:

Selector Description
input.payload Full decoded message payload
input.payload:field Specific field from the payload
input.topic: The incoming topic string
input.user_properties:key Solace user properties
json://input.payload JSON-serialized full payload
text://input.payload:field Text value of a field
static:value Literal static value
list_item:field Field from each item during artifact processing

Available output selectors:

Selector Description
task_response:text The agent’s text response
task_response:files List of file objects from the agent
task_response:data Data parts from the agent
task_response:structured_output Parsed output from structured invocation
task_response:a2a_task_response.error Error details
user_data.forward_context:key Data forwarded from the event handler

Configuration

Here is a complete working configuration based on an order processing use case. It listens for new orders, asks the OrchestratorAgent to validate them, and publishes the validation result back to the event mesh.

log:
  stdout_log_level: INFO
  log_file_level: DEBUG
  log_file: my-event-mesh.log

shared_config:
  - broker_connection: &broker_connection
      broker_url: ${SOLACE_BROKER_URL, ws://localhost:8008}
      broker_username: ${SOLACE_BROKER_USERNAME, default}
      broker_password: ${SOLACE_BROKER_PASSWORD, default}
      broker_vpn: ${SOLACE_BROKER_VPN, default}

  - services:
      artifact_service: &default_artifact_service
        type: "filesystem"
        base_path: "/tmp/samv2"
        artifact_scope: namespace

apps:
  - name: my-event-mesh-app
    app_module: sam_event_mesh_gateway.app
    broker:
      <<: *broker_connection

    app_config:
      namespace: "${NAMESPACE}"
      gateway_id: "event-mesh-gw-01"
      artifact_service: *default_artifact_service
      default_user_identity: "sam_dev_user"

      # Data Plane Connection (can be the same or different broker)
      event_mesh_broker_config:
        broker_url: ${DATAPLANE_SOLACE_BROKER_URL, ws://localhost:8008}
        broker_vpn: ${DATAPLANE_SOLACE_BROKER_VPN, default}
        broker_username: ${DATAPLANE_SOLACE_BROKER_USERNAME, default}
        broker_password: ${DATAPLANE_SOLACE_BROKER_PASSWORD, default}

      event_handlers:
        - name: "order_placed_handler"
          subscriptions:
            - topic: "orders/placed/>"
              qos: 1
          input_expression: >
            template:Validate the following new order and check for any issues
            (missing fields, suspicious amounts, invalid quantities):
            Order ID: {{text://input.payload:orderId}},
            Customer: {{text://input.payload:customerName}},
            Items: {{json://input.payload:items}},
            Total: {{text://input.payload:totalAmount}}.
            Return a JSON object with fields 'orderId', 'status' (valid or flagged), and 'notes'.
          payload_format: "json"
          payload_encoding: "utf-8"
          target_agent_name: "OrchestratorAgent"
          on_success: "order_validated_handler"
          on_error: "order_error_handler"
          forward_context:
            order_id: "input.payload:orderId"

      output_handlers:
        - name: "order_validated_handler"
          topic_expression: "template:orders/validated/{{text://user_data.forward_context:order_id}}"
          payload_expression: "task_response:text"

        - name: "order_error_handler"
          topic_expression: "template:orders/error/{{text://user_data.forward_context:order_id}}"
          payload_expression: "task_response:a2a_task_response.error"

Context Forwarding

Context forwarding is how you carry data from the incoming event through to the output handler. This is essential for request-reply correlation.

In the event handler, define what to extract:

forward_context:
  correlation_id: "input.user_properties:correlation_id"
  original_topic: "input.topic:"
  order_id: "input.payload:orderId"

In the output handler, reference it:

topic_expression: "template:responses/{{text://user_data.forward_context:correlation_id}}"

This lets you route the agent’s response back to a topic that includes the original correlation ID, so downstream systems can match it to their request.


Acknowledgment Policy

The acknowledgment policy controls when the Entrypoint tells the Solace broker that a message has been processed. This is critical for delivery guarantees.

on_receive (Default)

The message is acknowledged immediately when received. If the agent fails to process it, the message is lost. This is the simplest mode and suitable for non-critical events.

on_completion (Deferred ACK)

The message stays unacknowledged until the A2A task completes AND the response is published back to the data plane. This provides at-least-once delivery.

acknowledgment_policy:
  mode: "on_completion"
  on_failure:
    action: "nack"            # "nack" or "ack"
    nack_outcome: "rejected"  # "rejected" (redeliver) or "failed" (DLQ)
  timeout_seconds: 300

On failure behavior:

  • nack + rejected: the broker redelivers the message
  • nack + failed: the broker sends the message to the Dead Letter Queue (DLQ)
  • ack: the message is acknowledged and discarded even on failure

Timeout: If the agent does not respond within timeout_seconds, the message is settled as a failure.

Rate limiting: Combine deferred ACK with the Solace broker’s max-delivered-unacked-msgs-per-flow setting to control how many messages are processed concurrently. For example, setting it to 5 means the Entrypoint will have at most 5 in-flight tasks at any time.

You can set the policy at the gateway level (applies to all handlers) or override it per handler:

event_handlers:
  - name: "low_priority_handler"
    # Uses gateway default (on_receive)
    subscriptions:
      - topic: "events/low/>"
    ...

  - name: "critical_order_handler"
    acknowledgment_policy:
      mode: "on_completion"
      on_failure:
        nack_outcome: "failed"   # Send to DLQ on failure
      timeout_seconds: 120
    subscriptions:
      - topic: "orders/placed/>"
    ...

User Identity

User identity is resolved in the following priority order:

  1. user_identity_expression on the handler: expression evaluated against the incoming message (e.g., "input.user_properties:user_id" or "input.payload:userId")
  2. default_user_identity on the handler: fallback if the expression yields nothing

Tip: Set default_user_identity: "sam_dev_user" at the gateway level to match the WebUI’s default user. This lets you visualize Event Mesh tasks in the WebUI’s Activities tab.


Dynamic Agent Selection

You can route events to different agents based on message content.

Static routing (same agent for all events on this handler):

target_agent_name: "OrchestratorAgent"

Dynamic routing (agent determined by message content):

target_agent_name_expression: "input.user_properties:target_agent"

The expression is evaluated against each incoming message. If it fails or returns empty, the Entrypoint falls back to target_agent_name.

You can also target workflows instead of individual agents:

target_workflow_name: "OrderProcessingWorkflow"
# or dynamically:
target_workflow_name_expression: "input.payload:workflow_name"

Artifact Processing

For messages that contain files (binary payloads or embedded documents in JSON), the Entrypoint can extract them as artifacts before sending to agents.

Binary Payload (e.g., IoT Camera Image)

- name: "iot_image_handler"
  subscriptions:
    - topic: "iot/camera/*/image"
  payload_format: "binary"
  artifact_processing:
    extract_artifacts_expression: "input.payload"
    artifact_definition:
      filename: "template:image-{{text://input.user_properties:deviceId}}.jpg"
      content: "list_item:"
      mime_type: "static:image/jpeg"
      content_encoding: "static:binary"
  input_expression: "template:Analyze the attached security camera image for anomalies."
  target_agent_name: "ImageAnalysisAgent"

Embedded Documents in JSON (e.g., Insurance Claims)

- name: "insurance_claim_handler"
  subscriptions:
    - topic: "claims/new"
  artifact_processing:
    extract_artifacts_expression: "input.payload:documents"
    artifact_definition:
      filename: "list_item:docName"
      content: "list_item:docContent"
      mime_type: "list_item:docType"
      content_encoding: "list_item:encoding"
  input_expression: "template:Process insurance case {{text://input.payload:caseId}}."
  target_agent_name: "ClaimsProcessingAgent"

Testing with Try Me

You can test the Event Mesh Entrypoint without any external systems. The example configuration listens for JSON events on order topics, but no actual order management system is involved. You are simply publishing a Solace message that simulates what an order system would produce.

Step 1: Subscribe to responses

Open the Solace broker web console (e.g., http://localhost:8080), go to the Try Me tab, and in the Subscriber section, subscribe to:

orders/validated/>

This is where the Entrypoint will publish agent responses.

Step 2: Publish a test event

In the Publisher section of Try Me, set:

  • Topic: orders/placed/ORD-20250612-001
  • Message:
{"orderId": "ORD-20250612-001", "customerName": "Acme Corp", "items": [{"sku": "WIDGET-100", "qty": 50, "price": 12.99}, {"sku": "GADGET-200", "qty": 10, "price": 49.99}], "totalAmount": 1149.40}

Click Publish.

What happens

  1. The Entrypoint picks up the message from the orders/placed/> subscription
  2. The event handler transforms it into a prompt: “Validate the following new order and check for any issues: Order ID: ORD-20250612-001, Customer: Acme Corp, Items: […]…”
  3. The OrchestratorAgent processes the prompt using the LLM and generates a validation result
  4. The Entrypoint publishes the result to orders/validated/ORD-20250612-001 via the output handler
  5. Your Try Me subscriber receives the response

No external systems are involved. The entire flow is Solace messages in, agent processing, Solace messages out.

Tip: You may be able to watch Event Mesh tasks in the WebUI’s Activities tab by ensuring the Entrypoint’s default_user_identity matches the WebUI’s default (sam_dev_user). Alternatively, configure the WebUI admin user with the tasks:read:all scope to see tasks from all Entrypoints. Check with your admin for the exact setup.


Event Mesh vs. REST vs. Webhook

Event Mesh REST Webhook
Transport Solace broker topics HTTP API HTTP endpoints
Trigger Events on Solace topics HTTP request from client HTTP POST from external service
Response Published back to Solace topics Polling-based result retrieval Transforms webhook payloads to A2A messages
Connection Persistent Solace subscriber HTTP server HTTP server
Delivery guarantee At-least-once via deferred ACK HTTP-level HTTP-level
Bidirectional Yes (subscribe + publish on data plane) Yes (submit + poll) No (inbound only)
Input transform Template expressions Per gateway docs Per gateway docs
Use case Event-driven integration for Solace users Programmatic API access Third-party webhooks (GitHub, Stripe)

The Event Mesh Entrypoint is purpose-built for organizations that already run a Solace event mesh. It adds AI agent capabilities to your existing event-driven architecture without introducing HTTP or new protocols. For a full overview of all available Entrypoint types, see the Gateways documentation.


Last Words of Wisdom

  1. Start with a simple handler. One event handler, one output handler, one topic. Get a message flowing end-to-end before adding context forwarding, artifact processing, or deferred ACKs.

  2. Use on_receive for development, on_completion for production. Deferred ACK adds complexity. Get your transformations and routing right first, then switch to on_completion for delivery guarantees.

  3. Forward context for correlation. If you need to route the response to a specific topic (e.g., including an order ID), use forward_context to carry that data through the agent processing.

  4. The data plane can be a different broker. The event_mesh_broker_config does not have to point to the same broker as the A2A control plane. This is useful when your business events are on a separate infrastructure.

  5. Set default_user_identity: "sam_dev_user" to match the WebUI default. This ensures consistent identity across Entrypoints.

  6. Rate limit with deferred ACK. Combine mode: "on_completion" with the Solace broker’s max-delivered-unacked-msgs-per-flow to control concurrency. This prevents the Entrypoint from overwhelming your agents with too many simultaneous tasks.

  7. Test with Try Me. Use the Solace broker’s “Try Me” feature in the web console to publish test events to your subscribed topics without writing any code.


For more information about Solace Agent Mesh, visit the repository:

An event-driven framework designed to build and orchestrate multi-agent AI systems. It enables seamless integration of AI agents with real-world data sources and systems, facilitating complex, multi-step workflows.