Azure Event Hubs Connector
The C3 Agentic AI Platform connector for Azure Event Hubs connects C3 Agentic AI Platform applications to your Azure Event Hubs service.
To consume Event Hubs data and persist it in a C3 Agentic AI Platform data store, use the CloudMessageSourceSystem framework. The framework consumes and ingests messages without code from messaging systems such as Azure Event Hubs, AWS Kinesis, and Apache Kafka.
Prerequisites
Before you use the Azure Event Hubs connector, make sure you have access to an active Event Hubs namespace with one or more hubs. See the Azure Event Hubs documentation for more information.
The steps on this page need the C3.AppAdmin or C3.ClusterAdmin role.
Register Azure Event Hubs credentials with the C3 Agentic AI Platform
Define the Event Hub cloud message broker name:
var ehResourceName = "EVENT_HUB_NAME/EVENT_HUB_NAMESPACE/RESOURCE_GROUP";Generate the configuration key from an AzureEventHub instance that you construct with the broker name. Then set the broker name as the configuration value:
var configKey = AzureEventHub.make({resourceName: ehResourceName}).configKey();
AzureEventHub.setConfigAndSecretValue(configKey, "resourceName", ehResourceName);
AzureEventHub.setConfigAndSecretValue(configKey, "external", true);Set credentials with a service principal
In this task, you configure authentication for your Azure resources with a service principal. Your application then authenticates without user credentials, which is more secure.
Understand service principal authentication
A service principal is an identity that applications, hosted services, and automated tools use to access Azure resources. A service principal authenticates with a client ID and a client secret.
Gather required information
Before you start, make sure you have the following details:
- Active Directory ID: your Microsoft Entra ID tenant ID
- Access Key: the application (client) ID of your registered application
- Secret Key: the client secret (application password) generated for your application
- Account ID: your Azure subscription ID
- Region: the Azure region where your resources are located
Create the credentials object
Use the gathered information to create a credentials object in your code, following this template:
var credentials = {
"type" : "AzureCredentials",
"activeDirectoryId" : "< ACTIVE_DIRECTORY_ID >",
"accessKey" : "< APPLICATION_ID >",
"secretKey" : "< SECRET_ID >",
"accountId" : "< SUBSCRIPTION_ID >",
"region" : "< CLOUD_REGION >"
}Set credentials for your resource
To authenticate your application with Azure resources, call a method such as AzureEventHub.setCredentialsForResourceName and pass in the resource name and the credentials object.
Test your configuration
After you set up the credentials, run your application to confirm that it authenticates and works with Azure resources. Watch for errors and adjust your configuration as needed.
Note on Azure Event Hub client creation
When you provide the following three fields, the platform always tries to create the Azure Event Hub client with the service principal:
activeDirectoryIdsecretKeyaccessKey
If you populate these fields and also intend to use a shared key, the platform may still create the client with the service principal. That client may have different roles from the ones assigned to the shared key.
Assign roles for Azure Event Hub access
After you set up service principal credentials in Azure, assign the roles that let them work with Azure Event Hub:
Open the Azure portal: sign in to the Azure portal and go to your subscription.
Open access control: select the subscription and go to the Access control (IAM) section.
Add a role assignment:
a. Select + Add and choose Add role assignment.
b. Select the Azure Event Hub Owner role to grant full access.
Assign the role to the service principal: search for and select the service principal that needs access.
Verify the assignment: confirm that the service principal appears in the Role assignments section.
With this role, users can send and receive messages through Azure Event Hub.
Test sending and receiving messages in the static console
After you configure service principal authentication for Azure resources, test sending and receiving messages in the static console:
Define Azure Event Hub resource
Set this variable to the name of your Azure Event Hub resource. If you do not have an Azure Event Hub resource, create one first. Make sure the name matches your setup.
eventHubResourceName = "<your_event_hub_resource_name>"Create a service principal credential
Create a service principal credential that authenticates and authorizes access to Azure resources.
cred=AzureCredentials.make({
activeDirectoryId: "<your_active_directory_id>",
secretKey: "<your_client_secret>",
description: "<description>",
accountId: "<your_subscription_id>",
accessKey: "<your_application_client_id>",
region: "<your_region>",
})Set the credential
To enable authenticated access to Azure resources, assign the service principal credential to the CloudMessageSourceSystem. Call the setCredentials() method on the CloudMessageSourceSystem instance with the credential you created.
// create an instance of CloudMessageSourceSystem with the name "EventHub" using the make function
cmss=CloudMessageSourceSystem.make({
"name": "EventHub"
})
//set the credentials
cmss.setCredentials(cred)Create a cloud message
Create a cloud message to send to the Azure Event Hub with the CloudStreamMessage.make() method:
msg = CloudStreamMessage.make({
id: "123",
})The message is now ready to send to the Azure Event Hub.
Send the message
Send the message to the Azure Event Hub with the DataIntegrator.sendObjs() method. The platform delivers the message according to the parameters you pass.
DataIntegrator.sendObjs({'type': 'AzureEventHub', 'resourceName': '<your_event_hub_resource_name>'}, [msg], {'batchSize': 100, 'contentType': "application/json"})Receive and verify the message
Receive the messages sent to the Azure Event Hub to confirm that the whole process, from sending to receiving, works.
msgs=DataIntegrator.receiveMessages({'type': 'AzureEventHub', 'resourceName': '<your_event_hub_resource_name>'}, {'type': 'CloudStreamReceiveMessagesSpec', 'partition': "1", 'timeoutMillis': 1108, 'batchSize': 100})Set credentials with an access key
In this task, you configure authentication for Azure Event Hubs with the access key method. This method uses the general Azure credentials setup, which covers several authentication methods.
Understand access key authentication
With the access key method, your application authenticates with Azure resources through a key that grants access to the associated services.
Gather necessary information
Before you continue, make sure you have the following details:
Active Directory ID: your Microsoft Entra ID tenant ID
Access Key: the key used for authentication, either a primary or a secondary key
Secret Key: if applicable, a client secret for additional security
Account ID: your Azure subscription ID
Region: the Azure region where your resources are located
a. Shared access policy name and key: if you use a shared access signature (SAS), also gather these details.
Create the credentials object
Use the collected information to create a credentials object in your code, following this template:
var credentials = {
"type": "AzureCredentials",
"activeDirectoryId": "< ACTIVE_DIRECTORY_ID >", // Tenant ID
"accessKey": "< ACCESS_KEY >", // Access key
"secretKey": "< SECRET_ID >", // Optional client secret
"accountId": "< SUBSCRIPTION_ID >", // Subscription ID
"region": "< CLOUD_REGION >", // Azure region
"sharedAccessPolicyName": "< SAS_POLICY_NAME >", // Required for SAS
"sharedAccessPolicyKey": "< SAS_KEY >" // Required for SAS
}Set credentials for your resource
To authenticate your application with Azure Event Hubs, call AzureEventHub.setCredentialsForResourceName and pass in the resource name and the credentials object:
AzureEventHub.setCredentialsForResourceName(ehResourceName, credentials, ConfigOverride.APP);This call applies the credentials that secure the connection to the Event Hub. Your application can then authenticate with the Event Hub and process its events.
Test your configuration
After you set up the credentials, run your application to confirm that it authenticates and works with Azure Event Hubs. Watch for errors and adjust your configuration as needed.
Configure an Azure Event Hub consumer
To subscribe the C3 Agentic AI Platform to an Azure Event Hub, complete these three steps:
- Configure the Types to model the messages consumed from the Event Hub.
- Configure
CloudMessageSourceSystemandCloudMessageSourceCollectionseed data. - Enable the
CloudMessageSourceCollectionto receive messages.
You can also configure a CloudInboundMessage Type to model an Event Hub consumer explicitly. CloudInboundMessage is a parametric Type, so you specify a Type that represents the messages consumed from the Event Hub.
The following example subscribes the C3 Agentic AI Platform to the eh1 Event Hub in Azure Event Hubs.
This example contains messages published to the eh1 hub with the following format:
{
"Country": "USA",
"City": "New York",
"Date": "2023-05-11",
"Temperature": 20,
"Humidity": 60,
"Wind Speed": 10,
"Wind Direction": "NW",
"Precipitation": 0,
"Cloud Cover": 20,
"Visibility": 10,
"Pressure": 1013,
"Dew Point": 10,
"UV Index": 5,
"Sunrise": "05:30",
"Sunset": "20:15",
"Moonrise": "22:00",
"Moonset": "08:00",
"Moon Phase": "Waning Gibbous",
"Conditions": "Partly Cloudy",
"Icon": "partly-cloudy-day"
}Configure the Types to model the messages consumed from the Event Hub
Define the Types that model the JSON format of the messages you consume from the Event Hub. This example uses one Type, SourceWeatherDataMeasurement, which models the JSON message above.
/**
* This type represents the raw data that will represent `WeatherDataMeasurement` information.
*/
type SourceWeatherDataMeasurement mixes Source {
Country: string
City: string
Date: datetime
Temperature: int
Humidity: int
@ser(name="Wind Speed")
WindSpeed: int
@ser(name="Wind Direction")
WindDirection: string
Precipitation: int
@ser(name="Cloud Cover")
CloudCover: int
Visibility: int
Pressure: int
@ser(name="Dew Point")
DewPoint: int
@ser(name="UV Index")
UvIndex: int
Sunrise: string
Moonrise: string
Moonset: string
@ser(name="Moon Phase")
MoonPhase: string
Conditions: string
Icon: string
}You may need additional Types, transforms, and Application Types to capture the full models of the messages you consume.
Configure the CloudMessageSourceSystem and CloudMessageSourceCollection Types to register the Event Hub
A CloudMessageSourceSystem organizes related CloudMessageSourceCollection instances.
You create a CloudMessageSourceSystem by specifying its name. For example, add the following EventHub.json file to the \metadata\CloudMessageSourceSystem directory of your package:
{
"name": "EventHub"
}A CloudMessageSourceCollection represents a source collection that references a CloudMessageBroker and its related queue, topic, or stream.
The CloudMessageSourceCollection references a CloudMessageSourceSystem and holds the information needed to process data received from the Event Hub and to connect to the Event Hub.
For example, to model a CloudMessageSourceCollection called WeatherDataMeasurementSource, add the following WeatherDataMeasurementEventHub.json file to the \metadata\CloudMessageSourceCollection directory of your package:
{
"name": "WeatherDataMeasurementSource",
"sourceSystem": {
"type" : "CloudMessageSourceSystem",
"name" : "EventHub"
},
"source": "SourceWeatherDataMeasurement",
"external": true,
"cloudMessageBrokerName": "eh1/c3-eventhub-testing/azv8qa-rsgp-c3-01",
"cloudMessageBrokerType": "AzureEventHub",
"batchSize": 10,
"timeoutMillis": 5000
}In the console, you can configure the CloudMessageSourceCollection further with the SourceCollection.Config mixin. The following code sets the content type, the preferences for archiving records, and the SourceCollectionProcessMode.
var config = CloudMessageSourceCollection.forName("WeatherDataMeasurementSource").config();
config.setConfigValue("contentTypeOverride", "application/json", ConfigOverride.APP);
config.setConfigValue("doNotChunk", true, ConfigOverride.APP);
config.setConfigValue("doNotArchiveStatus", false, ConfigOverride.APP);
config.setConfigValue("doNotArchiveSources", true, ConfigOverride.APP);
config.setConfigValue("doNotArchiveFailedSources", false, ConfigOverride.APP);
config.setConfigValue("processMode", "ON_ARRIVAL", ConfigOverride.APP);Enable the CloudMessageSourceCollection to receive messages
Run the following commands to subscribe the platform to the Event Hub and process messages in real time as they arrive in the broker:
src.register()
src.startOnArrivalMode()To verify that the platform receives messages, create an AzureEventHub instance from your resource name and call the receiveMessages() method. Include the partition of the Event Hub that you want to read messages from. For more information, see the Partition section of the Features and terminology in Azure Event Hubs topic in the Azure Event Hubs documentation.
broker = AzureEventHub.fromResourceName(ehResourceName);
messages = broker.receiveMessages({partition: 0})The platform stores messages as a JavaScript ArrayBuffer. Run the following command to read the messages as objects:
Sources.fromCloudMessages(messages, src).readSources().collect();This command works only when sources are not archived. With archiving on, the platform consumes messages on receipt, so you cannot read them.

Configure a CloudInboundMessage Type and link to Event Hub
To model an Event Hub consumer and configure downstream processing, create a CloudInboundMessage Type. When a Type mixes in CloudInboundMessage, the platform treats it as an Event Hub consumer.
The platform dispatches each message consumed from the eh1 Event Hub to the SourceWeatherDataMeasurementInboundQueue.process() method.
type SourceWeatherDataMeasurementInboundQueue mixes CloudInboundMessage<SourceWeatherDataMeasurement> {
process: ~ js-server
}Implement the process method in SourceWeatherDataMeasurementInboundQueue.js, which persists data to the WeatherDataMeasurement Type.
function process(messages) {
var array = WeatherDataMeasurement.array();
var meas;
messages.forEach(function (msg) {
meas = WeatherDataMeasurement.make({
country: msg.Country,
city: msg.City,
date: msg.Date,
temperature: msg.Temperature,
humidity: msg.Humidity,
windSpeed: msg.WindSpeed,
windDirection: msg.WindDirection,
precipitation: msg.Precipitation,
cloudCover: msg.CloudCover,
visibility: msg.Visibility,
pressure: msg.Pressure,
dewPoint: msg.DewPoint,
uvIndex: msg.UvIndex,
sunrise: msg.Sunrise,
moonrise: msg.Moonrise,
moonset: msg.Moonset,
moonPhase: msg.MoonPhase,
conditions: msg.Conditions,
icon: msg.Icon
});
array.push(meas);
})
try {
WeatherDataMeasurement.createBatch(array);
} catch (e) {
log.error(e.message);
}
}The example catches errors from createBatch so that one bad batch does not stop the consumer. The error is logged, and the messages in that batch are not loaded. If you remove the try block, an error in process makes the platform read the same messages again, because delivery is at least once. In that case make process idempotent, for example by using upsertBatch with stable IDs.
Next, associate the SourceWeatherDataMeasurementInboundQueue Type with the eh1 Event Hub.
SourceWeatherDataMeasurementInboundQueue.setBrokerName(ehResourceName, "AzureEventHub");
SourceWeatherDataMeasurementInboundQueue.setBatchSize(10);
SourceWeatherDataMeasurementInboundQueue.setTimeoutMillis(5000);
SourceWeatherDataMeasurementInboundQueue.register();Data now populates the WeatherDataMeasurement Type.

Configure an Azure Event Hubs producer
Publishing to an Event Hub takes nearly the same steps as consuming from one.
Configure a CloudOutboundMessage Type to model an Event Hub producer explicitly. The published messages have the same structure as the consumed ones, so you reuse the SourceWeatherDataMeasurement Type in the CloudOutboundMessage parametric Type.
Configure a CloudOutboundMessage Type and link to Event Hub
When a Type mixes in CloudOutboundMessage, the platform treats it as an Event Hub producer.
type SourceWeatherDataMeasurementOutboundQueue mixes CloudOutboundMessage<SourceWeatherDataMeasurement>Next, associate the SourceWeatherDataMeasurementOutboundQueue Type with the eh1 Event Hub.
SourceWeatherDataMeasurementOutboundQueue.setBrokerName("eh1/c3-eventhub-testing/azv8qa-rsgp-c3-01", "AzureEventHub");
SourceWeatherDataMeasurementOutboundQueue.setBatchSize(10);Publish messages to the eh1 Event Hub with the SourceWeatherDataMeasurementOutboundQueue.sendBatch() method. The following code generates sample data and publishes it to the Event Hub:
function createMeasurements(city, country, date) {
var cAry = C3.ArrayBuilder.fromJson({type: 'ArrayBuilder<SourceWeatherDataMeasurement>'});
var partition = 1;
var meas;
var t = DateTime.fromString(date);
for (var i=0; i < 10; i++) {
t = t.plusDays(1);
meas = SourceWeatherDataMeasurement.make({
Country: country,
City: city,
Date: t,
Temperature: randomBetween(18, 28),
Humidity: randomBetween(20, 90),
WindSpeed: randomBetween(2, 20),
WindDirection: "SW",
Precipitation: randomBetween(0, 15),
CloudCover: randomBetween(0, 10),
Visibility: randomBetween(25, 50),
Pressure: randomBetween(900, 1200),
DewPoint: randomBetween(0, 40),
UvIndex: randomBetween(0, 10),
Sunrise: "05:25",
Moonrise: "21:00",
Moonset: "09:00",
MoonPhase: "Waning Gibbous",
Conditions: "Sunny",
Icon: "clear-day"
});
cAry.push(meas);
}
SourceWeatherDataMeasurementOutboundQueue.sendBatch(cAry.build(), partition);
}
function randomBetween(min,max) {
return Math.floor(Math.random()*(max-min+1)+min);
}
createMeasurements("Los Angeles", "USA", "2023-06-01");You can then verify that the messages reached the Event Hub.
