Lab 4: Onboard a custom agent
In this lab you move the Throughput Checker of Lab 3 from your computer into the cluster, next to the agents of Lab 1. At the end, the Supervisor uses it to answer your questions in MX-UI.
You, in MX-UI
│
┌──────▼──────┐
│ Supervisor │
└─┬────┬────┬─┘
┌─────────┘ │ └──────────┐
┌────▼────┐ ┌─────▼────┐ ┌──────▼─────────────┐
│ KPI │ │ Topology │ │ Throughput Checker │ ← new
└────▲────┘ └──────────┘ └──────┬─────────────┘
└──────────── asks ────────────┘
By the end of this lab you will be able to:
- build the container image of your blueprint and push it to a registry;
- create the CompositionModel of your blueprint;
- add your agent to an existing AIFabric;
- update the fabric.
Before you start, you need:
- the fabric
observability-labof Lab 1 and its fileobservability-lab.yaml; - the blueprint
tutorial/of Lab 3, working; - Docker, and a container registry you can push to (or the ready-made image, see Part 1).
Where to run the commands:
batanddockercommands: in thetutorial/folder, where you developed in Labs 2 and 3.brcandkubectlcommands: on the cluster master node, as in Lab 1.
If these are two different machines, this lab tells you when to copy a file
from one to the other with scp. If you work on the master node, skip the
scp steps.
Part 1: Build and push the image
The cluster runs agents from container images. Your blueprint becomes one image that holds all its agents, like the Observability blueprint.
⚠️ Your own images need the
extendabilitycapability.The cluster only runs images from
hub.bubbleran.com, unless your BubbleRAN license has the extendability capability. Without it, the cluster refuses to start your agent.If you don't have this capability, or no registry, you can still follow this lab with the ready-made image of the Throughput Checker on
hub.bubbleran.com: skip to Part 2. BubbleRAN can also provide a registry for your images: ask your BubbleRAN contact.
Step 1: Choose where to push
An image name has three parts: <registry>/<repository>:<version>. Tell
bat your registry and repository once:
bat set image --docker-registry <your-registry> --repo <your-team>/tutorial
For example, --docker-registry registry.example.com --repo my-team/tutorial.
You should see:
Updated: /home/you/tutorial/Makefile
Keys updated: DOCKER_REGISTRY, REPO
Then log in to your registry, once:
docker login <your-registry>
Step 2: Build the image
bat build --version 1.0.0
It takes a few minutes. At the end you should see:
Docker image built successfully: registry.example.com/my-team/tutorial:1.0.0
bat buildfirst writesuv.lock, the exact list of package versions. Keep this file: the next builds use the same versions.- Your
.envfile is not put in the image. In the cluster, the API key comes from the Secret you created before Lab 1.
Step 3: Push the image
bat push --version 1.0.0
You should see, at the end:
Docker image pushed successfully: registry.example.com/my-team/tutorial:1.0.0
Part 2: Create the CompositionModel
In Lab 1 you installed the CompositionModels of BubbleRAN's blueprints: their catalogs of agents. Now you create the catalog of your blueprint.
💡 Using the ready-made image? BubbleRAN ships the Throughput Checker with its CompositionModel, also called
tutorial. Install it on the master node, then skip to Part 3:brc install model tutorial
bat writes the CompositionModel for you:
bat manifests composition-model --namespace trirematics --vendor lab --version 1.0.0
You should see:
Wrote /home/you/tutorial/composition-model.yaml
added: throughput-checker
image: registry.example.com/my-team/tutorial:1.0.0 (push it: `bat push`, same options)
bat wrote the file composition-model.yaml:
composition-model.yaml
apiVersion: orama.trirematics.io/v1
kind: CompositionModel
metadata:
name: tutorial
namespace: trirematics
spec:
provider: bubbleran
version: v0.1.0
deploymentModes:
throughput-checker:
kind: agent
name: throughput-checker
vendor: lab
imageTag: registry.example.com/my-team/tutorial:1.0.0
args:
- throughput_checker
env:
- name: AGENT_CARD_PATH
value: throughput_checker/agent.json
rules: []
# Instead, e.g. to read the cluster's networks and terminals:
# rules:
# - apiGroups: [athena.trirematics.io]
# resources: [networks, terminals]
# verbs: [get, watch]
What each part means:
| Part | Meaning |
|---|---|
metadata.name | The name of the catalog: tutorial. It is the first half of <model>/<mode>. |
metadata.namespace | Where it lives: trirematics, the same namespace as your fabric. |
spec | Who provides the catalog, and its version. For information only. |
deploymentModes | The list of modes: one per agent of your blueprint. It sits at the top level, not under spec. |
throughput-checker | The name of the mode: the second half of <model>/<mode>. So your agent is tutorial/throughput-checker. |
kind, name, vendor | It is an agent; its name (always the same as the mode); who made it (--vendor, ideally three lowercase letters). |
imageTag | The image to run. |
args | Which agent of the image to start. It is the same name you used with make throughput_checker. |
env | Environment variables. AGENT_CARD_PATH tells the agent where its card is in the image. |
rules | The Kubernetes permissions the agent needs. Your agent only talks to the KPI agent, so it needs none. The comment shows an example. |
What the cluster adds by itself:
- every agent listens on port
9900; - the cluster gives the agent a new
config.yamlinstead of yours: the KPI agent's address inside the cluster instead oflocalhost:9310, and the LLM of the fabric; - the API key comes from the fabric's Secret.
Install the CompositionModel in the cluster. If you work on your own computer, first copy the file to the master node:
scp composition-model.yaml <user>@<master-node>:
Then, on the master node:
kubectl apply -f composition-model.yaml
You should see:
compositionmodel.orama.trirematics.io/tutorial created
Part 3: Add the agent to the AIFabric
On the master node, open the file observability-lab.yaml of Lab 1, and add
your agent at the end of the agents list:
- name: throughput-checker
type: internal
internal:
model: tutorial/throughput-checker
llm: openai
role: worker
dependencies:
- kpi
annotations:
env.orama.t9s.io/TARGET_DL_MBPS: "50"
What each part means:
| Part | Meaning |
|---|---|
name | The name of your agent in the fabric. |
type: internal | The cluster runs this agent for you, from a CompositionModel. |
internal.model | Your mode, tutorial/throughput-checker: the CompositionModel tutorial of Part 2, and its mode throughput-checker. |
internal.llm | The LLM of the fabric, the same one your agent used on your computer. |
internal.role | worker: the Supervisor calls every worker, so it can now use your agent. |
internal.dependencies | The agents yours may call: kpi, as in the remote-agents of your config.yaml. The cluster also starts your agent only once kpi is ready. |
internal.annotations | env.orama.t9s.io/<NAME> sets the environment variable <NAME> in the agent. Here it sets the target, as your .env file did on your computer. Always write the value in quotes. |
Your file now looks like this:
observability-lab.yaml (click to open)
apiVersion: orama.trirematics.io/v1
kind: AIFabric
metadata:
name: observability-lab
namespace: trirematics
spec:
telemetry:
endpoint: http://phoenix-svc.monitoring.svc.cluster.local:6006
projectName: observability-lab
llms:
- name: openai
provider: openai
model: gpt-6-luna
reasoningEffort: low
apiKeySecretRef:
name: openai-api-key
key: OPENAI_API_KEY
mcp:
- name: victoria-metrics
type: external
external:
baseUrl: http://vmm-victoria-metrics-mcp.monitoring.svc.cluster.local:8080/mcp
agents:
- name: supervisor
type: internal
internal:
model: supervisor/base
llm: openai
role: supervisor
- name: kpi
type: internal
internal:
model: observability/kpi
llm: openai
role: worker
mcpServers:
- victoria-metrics
- name: topology
type: internal
internal:
model: observability/topology
llm: openai
role: worker
- name: throughput-checker
type: internal
internal:
model: tutorial/throughput-checker
llm: openai
role: worker
dependencies:
- kpi
annotations:
env.orama.t9s.io/TARGET_DL_MBPS: "50"
💡 A private registry? If the cluster needs a password to pull your image, create a pull Secret once, on the master node:
kubectl -n trirematics create secret docker-registry my-registry \
--docker-server=<your-registry> \
--docker-username=<user> --docker-password=<password>Then add it to
observability-lab.yaml, underspec:imagePullSecrets:
- name: my-registry
Part 4: Reinstall the fabric
To change a fabric, remove it and install it again. On the master node:
brc remove aifabric observability-lab.yaml
brc install aifabric observability-lab.yaml
You should see:
aifabric.orama.trirematics.io "observability-lab" deleted
aifabric.orama.trirematics.io/observability-lab created
Why remove it first? The Supervisor learns which agents exist only when it starts. Reinstalling restarts all the agents, so the Supervisor finds your new agent.
In MX-UI, open the Fabrics page: observability-lab now has four
agents. Wait until they are all ready. The cluster starts
your agent after KPI, and the Supervisor last.
Part 5: Try it
In MX-UI, go to the Chats page, select observability-lab and choose the
Supervisor. Ask:
Does network o-ran meet its throughput target?
The Supervisor reads the agent cards, sees that the Throughput Checker answers this kind of question, and asks it. Your agent then asks the KPI agent, exactly as it did on your computer. You should get an answer like:
o-ran: BELOW TARGET — 12.4 Mbps measured, target 50.0 Mbps.
Your numbers depend on your network and its traffic.
Now choose the Throughput Checker itself in the chat, and ask the same question: you talk to your agent directly.
Now change the target. On the master node, in observability-lab.yaml, set
the annotation to "1":
annotations:
env.orama.t9s.io/TARGET_DL_MBPS: "1"
Reinstall the fabric (the two brc commands of Part 4) and ask again. While
there is traffic, the answer becomes MEETS TARGET.
💡 Optional: see what the agents did. The fabric sends the traces of all its agents, yours included, to the Phoenix of your cluster, in the project
observability-lab. The trace of your last question shows the work of the Supervisor, of the Throughput Checker and of the KPI agent. To open it, see Phoenix: agents in your cluster.
Part 6: Grow your blueprint
A blueprint can hold many agents. To add one:
bat add agent my_second_agent --clients Helper
bat creates the folder my_second_agent/, and gives it the next free port
on your computer (9901). Write its logic as in Lab 2 and run it with
make my_second_agent. Then follow this lab again: bat build and
bat push put both agents in the same image,
bat manifests composition-model adds a second mode,
tutorial/my-second-agent, and you add a second entry to the agents of
your fabric, as in Part 3.
If something goes wrong
| What you see | What to do |
|---|---|
bat push says no Docker registry set | Run bat set image (Part 1, Step 1). |
bat push says denied or unauthorized | Log in with docker login <your-registry>, then push again. |
In MX-UI, the fabric is not ready and the message says an image outside hub.bubbleran.com needs the "extendability" license capability | Your license does not allow your own images. Use the ready-made image (Part 2), or contact BubbleRAN. |
| The Throughput Checker never becomes ready, and the message talks about pulling the image | Check that you pushed the image (Part 1, Step 3) and that imageTag is right. If your registry is private, add a pull Secret (end of Part 3). |
| The Supervisor answers without asking the Throughput Checker | Check that the agent has role: worker, and reinstall the fabric (Part 4). |
The Throughput Checker answers UNKNOWN | The KPI agent gave no throughput number. Ask the KPI agent directly in MX-UI to see its answer, and check the network name. |
| Still stuck? | Contact BubbleRAN customer support through your usual support channel. |
Clean up
Lab 5 still uses the fabric: clean up after it. When you are done with the labs, remove the fabric and your CompositionModel. On the master node:
brc remove aifabric observability-lab.yaml
kubectl delete -f composition-model.yaml
If you used the ready-made image, remove its CompositionModel with
brc remove model tutorial instead of the kubectl delete command.
If you deployed the network of Lab 1 only for these labs, remove it too:
brc remove network open-ran.yaml
What you learned
bat buildandbat pushturn your blueprint into one container image.bat manifests composition-modelwrites your blueprint's catalog: one mode per agent, which an AIFabric picks as<model>/<mode>.- A few lines of YAML add an agent to an existing fabric: its mode, its LLM, its role and the agents it calls. Annotations set environment variables.
- To change a fabric, remove it and install it again with
brc. - Your code does not change between your computer and the cluster: only
config.yamldoes, and the cluster writes it for you.
In Lab 5 you measure how well your agent answers, with a test
set that bat runs and scores for you.