agentsclimarketplace

Sap event mesh

Skill efeumutaslan/SAP-SKILLS/skills/sap-event-mesh

23 SAP development skills for Claude Code — ABAP, RAP, CAP, Fiori, BTP, HANA, S/4HANA, Integration Suite and more. Agent Skills Specification compatible.

Install
npx -y skills add efeumutaslan/SAP-SKILLS --skill sap-event-mesh

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

SAP Event Mesh and Advanced Event Mesh skill for event-driven architecture on BTP. Use when publishing/consuming S/4HANA business events, configuring queues/topics, working with CloudEvents, or building event-driven microservices with CAP. If the user mentions Event Mesh, SAP business events, CloudEvents, message queue on BTP, or event-driven SAP integration, use this skill.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

10.5 KB, as published. Nobody here has run it

SAP Event Mesh & Event-Driven Architecture

Related Skills

  • sap-kyma-runtime — Event-driven Functions on Kyma consuming Event Mesh
  • sap-s4hana-extensibility — S/4HANA business events as event sources
  • sap-build-process-automation — Trigger workflows from events

Quick Start

Choose your event broker:

BrokerUse CaseProtocolScale
SAP Event MeshBTP-native events, simple pub/subAMQP 1.0, REST, MQTTStandard workloads
Advanced Event MeshEnterprise event mesh, multi-cloudAMQP, MQTT, REST, SMF, JMS, WebSocketHigh throughput, global

Minimal CAP event producer:

// srv/order-service.js
const cds = require('@sap/cds');

module.exports = class OrderService extends cds.ApplicationService {
  async init() {
    this.after('CREATE', 'Orders', async (order) => {
      const msg = await cds.connect.to('messaging');
      await msg.emit('sap/sales/order/created/v1', {
        orderId: order.ID,
        customer: order.customer_ID,
        total: order.total
      });
    });
    await super.init();
  }
};

Core Concepts

CloudEvents Specification

SAP Event Mesh uses CloudEvents 1.0 standard:

{
  "specversion": "1.0",
  "type": "sap.s4.beh.salesorder.v1.SalesOrder.Created.v1",
  "source": "/default/sap.s4.beh/S4HANA_CLD",
  "id": "a1b2c3d4-5678-90ab-cdef",
  "time": "2026-03-24T10:00:00Z",
  "datacontenttype": "application/json",
  "data": {
    "SalesOrder": "1000001",
    "SalesOrganization": "1010",
    "SoldToParty": "CUST001"
  }
}

Topic Naming Convention

{namespace}/{business-object}/{event-type}/{version}

Examples:
sap.s4.beh/salesorder/created/v1
sap.s4.beh/businesspartner/changed/v1
custom/myapp/order/fulfilled/v1

Hierarchy rules:

  • Use / as level separator
  • Wildcards: + (single level), * (multi-level) — for subscriptions only
  • Subscription example: sap/s4/beh/+/created/v1 matches all "created" events

Event Mesh Architecture

S/4HANA ──► Enterprise Messaging ──► Event Mesh ──► Consumers
                                       │
BTP Apps ──► CAP Messaging ────────────┘      ┌── BTP App (webhook)
                                               ├── Kyma Function
External ──► REST/AMQP ───────────────────────├── Integration Flow
                                               └── Queue → Worker

Queue vs. Topic

AspectTopicQueue
DeliveryPub/sub (1-to-many)Point-to-point (1-to-1)
PersistenceNot persistentMessages persisted until consumed
PatternEvents, notificationsTask processing, reliable delivery
SubscriptionTopic filter with wildcardsDirect queue binding

Common Patterns

Pattern 1: Event Mesh Service Instance (BTP)

// mta.yaml resource
{
  "name": "event-mesh",
  "type": "org.cloudfoundry.managed-service",
  "parameters": {
    "service": "enterprise-messaging",
    "service-plan": "default",
    "path": "./event-mesh.json"
  }
}
// event-mesh.json
{
  "emname": "my-app-events",
  "namespace": "custom/myapp",
  "version": "1.0.0",
  "options": {
    "management": true,
    "messagingrest": true,
    "messaging": true
  },
  "rules": {
    "topicRules": {
      "publishFilter": ["${namespace}/order/*"],
      "subscribeFilter": ["${namespace}/order/*", "sap/s4/beh/+/created/v1"]
    },
    "queueRules": {
      "publishFilter": ["${namespace}/*"],
      "subscribeFilter": ["${namespace}/*"]
    }
  }
}

Pattern 2: CAP Event Consumer

// srv/event-handler.js
const cds = require('@sap/cds');

module.exports = async (srv) => {
  const msg = await cds.connect.to('messaging');

  // Subscribe to S/4HANA business partner events
  msg.on('sap/s4/beh/businesspartner/changed/v1', async (event) => {
    const { BusinessPartner } = event.data;
    console.log(`BP changed: ${BusinessPartner}`);

    // Sync to local replica
    const { BusinessPartners } = srv.entities;
    const bpData = await fetchBPFromS4(BusinessPartner);
    await cds.run(UPSERT.into(BusinessPartners).entries(bpData));
  });

  // Subscribe with wildcard
  msg.on('custom/myapp/order/+/v1', async (event) => {
    console.log(`Order event: ${event.headers.type}`, event.data);
  });
};
// package.json — messaging config
{
  "cds": {
    "requires": {
      "messaging": {
        "kind": "enterprise-messaging",
        "format": "cloudevents",
        "publishPrefix": "custom/myapp/",
        "subscribePrefix": "custom/myapp/"
      }
    }
  }
}

Pattern 3: REST API — Publish Event

import requests
import json

def publish_event(token_url, client_id, client_secret, em_url, topic, data):
    """Publish event via Event Mesh REST API."""
    # Get OAuth token
    token_resp = requests.post(
        f"{token_url}/oauth/token?grant_type=client_credentials",
        auth=(client_id, client_secret)
    )
    token = token_resp.json()["access_token"]

    # Publish
    encoded_topic = topic.replace("/", "%2F")
    resp = requests.post(
        f"{em_url}/messagingrest/v1/topics/{encoded_topic}/messages",
        headers={
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/cloudevents+json",
            "x-qos": "1"  # 0=at-most-once, 1=at-least-once
        },
        json={
            "specversion": "1.0",
            "type": topic,
            "source": "/custom/myapp",
            "id": str(__import__('uuid').uuid4()),
            "data": data
        }
    )
    resp.raise_for_status()
    return resp.status_code

Pattern 4: Queue Subscription with Webhook

def create_queue_subscription(token, em_url, queue_name, topic_filter):
    """Create queue and bind topic subscription."""
    headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}

    # Create queue
    requests.put(
        f"{em_url}/messagingrest/v1/queues/{queue_name}",
        headers=headers,
        json={"messageTimeToLive": 86400, "maxQueueSizeInBytes": 10485760}
    )

    # Subscribe queue to topic
    encoded_topic = topic_filter.replace("/", "%2F")
    requests.put(
        f"{em_url}/messagingrest/v1/queues/{queue_name}/subscriptions/{encoded_topic}",
        headers=headers
    )

Pattern 5: S/4HANA Business Event Configuration

Enable events in S/4HANA Cloud:

  1. App: "Enterprise Event Enablement" → Maintain channel binding
  2. Create channel: type = "SAP Event Mesh", connection = destination to Event Mesh
  3. Select event topics: sap.s4.beh.salesorder.v1.SalesOrder.Created.v1
  4. Activate channel

S/4HANA On-Premise (via Integration Suite):

S/4HANA → AIF/IDoc → SAP Integration Suite → Event Mesh

Pattern 6: Dead Letter Queue Pattern

// Handle failed messages with retry
const msg = await cds.connect.to('messaging');

msg.on('custom/myapp/order/created/v1', async (event) => {
  try {
    await processOrder(event.data);
  } catch (err) {
    const retryCount = (event.headers['x-retry-count'] || 0) + 1;
    if (retryCount <= 3) {
      await msg.emit('custom/myapp/order/created/retry/v1', {
        ...event.data,
        _retryCount: retryCount,
        _originalError: err.message
      });
    } else {
      await msg.emit('custom/myapp/dlq/order/v1', {
        ...event.data,
        _error: err.message,
        _failedAt: new Date().toISOString()
      });
    }
  }
});

Error Catalog

ErrorMessageRoot CauseFix
403Publish not allowedTopic not in publishFilterUpdate event-mesh.json rules
403Subscribe not allowedTopic not in subscribeFilterUpdate subscribe filter rules
404Queue not foundQueue deleted or not createdCreate queue before consuming
409Queue already existsDuplicate creation attemptUse PUT (idempotent) instead of POST
413Message too largeExceeds max message size (1 MB default)Reduce payload; use reference pattern (send URL)
429Rate limit exceededToo many requests per secondImplement backoff; upgrade service plan
500Broker unavailableEvent Mesh service issueCheck BTP system status; retry with backoff
Connection refusedAMQP connection failedWrong endpoint or credentialsVerify service key messaging array endpoints
No messagesConsumer gets nothingTopic filter mismatchCheck wildcard syntax; verify namespace prefix
Duplicate eventsSame event processed twiceAt-least-once QoSImplement idempotent consumer (check event ID)

Performance Tips

  1. Use QoS 0 for non-critical events — At-most-once is faster; use QoS 1 only for business-critical events
  2. Batch publishing — Group multiple events per HTTP request where API supports it
  3. Partition queues — Use multiple queues for parallel consumption of high-volume topics
  4. Message TTL — Set appropriate messageTimeToLive to prevent queue overflow
  5. Payload size — Keep events small (<10 KB); reference large data via URL/ID
  6. AMQP over REST — Use AMQP protocol for high-throughput; REST for low-volume/webhook
  7. Consumer acknowledgment — Acknowledge messages promptly; long processing delays redelivery
  8. Namespace isolation — Separate namespaces per application; avoid cross-app topic pollution

Gotchas

  • Topic encoding: Forward slashes in topic names must be URL-encoded (%2F) in REST API paths
  • Namespace prefix: All topics must match namespace defined in service instance; mismatches silently fail
  • Event ordering: Event Mesh does NOT guarantee message ordering — design consumers to be order-independent
  • Duplicate delivery: At-least-once means duplicates are possible — always implement idempotent processing
  • Service plan limits: default plan has message size and throughput limits; check plan quotas
  • S/4HANA events: Business events must be explicitly enabled per tenant; they're not on by default

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.