How to Build your own Helmholtz Cloud Agent
Here, we guide you through the first steps of writing and connecting your Helmholtz Cloud Agent (HCA) to the central Helmholtz Cloud resource management. A Helmholtz Cloud Agent is a small Python tool that runs close to a service and communicates with the Helmholtz Cloud. It receives resource requests and sends back information about the allocated resource. The communication with Helmholtz Cloud is handled automatically by a provided library so that you can focus on integrating your service.
Developing your first Helmholtz Cloud Agent¶
We provide a template repository that you can use as a starting point for your development. It contains a devcontainer setup with a local RabbitMQ message broker and a Helmholtz Cloud Agent development container. It also includes a sample Dockerfile that can be used to deploy your Helmholtz Cloud Agent.
Fork the template repository to start developing your own agent. If you are using Visual Studio Code with devcontainers you can simply check out the repository and open it. It will ask you to “Reopen in Container” which will launch the development environment. If you are not using VSCode you can just manually start the environment with the provided Docker Compose file in the dev folder.
Communicating with RabbitMQ¶
The template comes with a sample Helmholtz Cloud Agent implementation that we will discuss later. For now, we will just start the Helmholtz Cloud Agent and test if everything is set up correctly. To start the Helmholtz Cloud Agent run this in a shell in the hca_dev
container:
1 |
|
This will start the Helmholtz Cloud Agent and connect to RabbitMQ. RabbitMQ comes with a management console that you can access at http://localhost:15672. You can find the credentials (HCA_USERNAME
and HCA_PASSWORD
) to log in to the environment list in the docker-compose.yml
file. Once you are logged in, you can access information about the RabbitMQ broker. For Helmholtz Cloud Agent development we are only interested in the “Queues and Streams” tab. In the table you will find two queues that are already set up: to_hca
and to_portal
. to_hca
is used to send messages from Helmholtz Cloud to the Helmholtz Cloud Agent and to_portal
to send messages in the other direction. You can send and receive messages directly from this management console which can be useful for debugging. Additionally, the plugin-template repository comes with a script that mocks the interaction of Helmholtz Cloud with the Helmholtz Cloud Agent.
To test the setup, we can start by sending a simple PingV1
message. Helmholtz Cloud may send this message at any time to check whether the Helmholtz Cloud Agent is still running. Your Helmholtz Cloud Agent will then automatically send a PingV1
response back to Helmholtz Cloud. While keeping the Helmholtz Cloud Agent running, open another shell and run:
1 |
|
You should see an output with the message “still alive”. If yes, your development environment is set up correctly, and we can now proceed with resource requests.
Send your first Resource Request¶
In the same way that we sent the PingV1
message we can also send resource requests to the Helmholtz Cloud Agent. The message type is ResourceAllocateV1
and the actual content depends on your resource type and your policy definition in Plony as described in integration guide. However, the main structure is always the same three fields:
- type: A string representing the title of the resource type JSON schema.
- target_entity: A dictionary containing either the group URN or the user ID, depending on the selected policy.
- specification: A dictionary containing the resource specification as defined in the JSON Schema properties of the resource type.
Using the Script¶
The sample Helmholtz Cloud Agent in the template accepts two different resource types (ChatTeamSpecV1
and ComputeResourceSpecV1
). For testing, it randomly returns a ResourceCreatedV1
or ErrorV1
message without actually doing anything. Here, we will start by sending a ChatTeamSpecV1
to our Helmholtz Cloud Agent using the mock_portal.py
scripts:
1 |
|
The mock_portal.py
expects a JSON file with a payload that it will send to the Helmholtz Cloud Agent. Two sample payloads are already provided in the payloads
folder. You can adapt and add payloads as you need for developing your Helmholtz Cloud Agent.
When you run the command you should either see an output with a ResourceCreatedV1
or ErrorV1
message.
Using the RabbitMQ Console¶
If you do not want to use the script you can also send messages directly to the Helmholtz Cloud Agent using the RabbitMQ console. On the RabbitMQ console go to the “Queues and Streams” tab, open the to_hca
queue and go to the “Publish message” section. First, we need to fill in some headers and properties. In the production environment these are handled transparently by Helmholtz Cloud and the Helmholtz Cloud Agent, but here we need to set them manually:
In the headers you need to set the service_id
. This is the ID given to your service in Helmholtz Cloud. In production, you need to set the HCA_SERVICE_ID
environment variable correctly, but here it is set to a mock value that you can find in the docker-compose.yml
file.
The type
property needs to be set to ResourceAllocateV1
for requesting resources.
The correlation_id
is used so that Helmholtz Cloud can match the response from the Helmholtz Cloud Agent to a resource request. This can be set to any value for testing purposes.
The payload is a JSON dictionary that matches the schema defined in the resource type. It is the same as in the PAYLOAD
variable in the mock_portal.py
script. For this test we take a ChatTeamSpecV1
schema. The type is defined in the json_schema
’s title
attribute of the ResourceType
. This can be customized by you when you define your own ResourceType
later on. You are not limited to the example names. The target_entity
is set to a user_id_target
and the specification consists of a team_name
and invite_only
:
1 2 3 4 5 6 7 8 9 10 11 |
|
- If this was a group resource, this would contain the group’s URN.
- This is a personal resource. If this was a group resource, this would be
null
. - This structure is specified by you in the
ResourceType
.

When you send the request you should immediately see some log output from the Helmholtz Cloud Agent. The example script randomly replies with either a successful or failure message, which you can again receive from the to_portal
message in the RabbitMQ console.

Writing a Message Handler¶
So far, we have successfully sent and received messages from the sample Helmholtz Cloud Agent, but we have not seen how message handling is implemented. The Helmholtz Cloud Agent library provides an application that handles the actual communication with RabbitMQ. You can register handler functions that will be called whenever a message of a certain type is received. This is then the entry point for your development, from where you can then make the necessary calls to provision the resource at your service.
A very simple Helmholtz Cloud Agent would look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
We start by importing the HCAApplication
that comes with the Helmholtz Cloud Agent library along with the Pydantic structs for the ResourceAllocateV1
and ResourceCreatedV1
messages. Then, we create the actual app and register a function that will handle the messages we receive with the app.handle
decorator. A different handler needs to be defined for each message type, and we need to specify it with the message_type
parameter. The function itself will always get the correlation ID and the payload. The type will always be the same as the message type.
That’s it. Now you can take the payload and write the code that does the actual resource provisioning.
When the resource is created, you need to send a ResourceCreatedV1
message back to Helmholtz Cloud. The only thing you need to provide is an ID. This ID will be stored by Helmholtz Cloud and when the resource should be deprovisioned, Helmholtz Cloud will send you a deprovisioning request with this ID. Therefor, the ID should uniquely identify the resource at your service.
If for some reason the resource cannot be provisioned, you can send a message back to Helmholtz Cloud that is displayed to the user. To do this, you can define exception classes that can be raised in the message handler. The Helmholtz Cloud Agent application will handle these and send the appropriate message to Helmholtz Cloud.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Deploying your Helmholtz Cloud Agent¶
When you are ready to deploy your Helmholtz Cloud Agent, the template repository provides a sample Dockerfile that you can use to package your code. It installs a Python environment with all the dependencies from pyproject.toml
, takes everything from the src
folder and puts it in the /opt/hca
folder in the container. Then, you just have to adjust the ENTRYPOINT
to invoke your application.
To start the Helmholtz Cloud Agent, you need to set some environment variables:
- HCA_USERNAME: The RabbitMQ username. You will get this from Helmholtz Cloud developers.
- HCA_PASSWORD: The RabbitMQ password. You will get this from Helmholtz Cloud developers.
- HCA_SERVICE: The ID of your service in the Helmholtz Cloud. You will get this from Helmholtz Cloud developers.
- HCA_RABBITMQ_USE_SSL: Set to
True
for production. - HCA_RABBITMQ_HOSTNAME: Set to
hifis-rabbitmq.desy.de
for production. - HCA_RABBITMQ_PORT: Set to
5671
for production.