Docs · Tower
Service classes and tabs
Tower does not keep a list of the kinds of service it supports. A service says what it is with two annotations on its catalog Component, and Tower works out the rest.
| Annotation | Meaning | Example values |
|---|---|---|
hangar.io/service-class |
what the service is. Any slug. | container-app, function, infra-service, ai-workload, ai-service, storage, secret-store, data-lake |
hangar.io/deploy-target |
where it runs. Optional. | k8s-rollout, aws-ecs, aws-lambda, azure-container-apps |
deploy-target mirrors deploy.target in the service’s cicd.yaml. The XRD writes both
from one parameter at onboarding. cicd.yaml stays the source of truth; Tower reads the
annotation because the tab bar needs it before any file is fetched.
Services that predate these annotations keep working. The four application kinds are
inferred as container-app on k8s-rollout, and InfraService as infra-service on
k8s-rollout. LambdaFunction and
AzureFunction are inferred as function on aws-lambda and azure-container-apps
(Azure Functions are hosted on Container Apps), so they work before the catalog ingestor
emits the annotations. An explicit annotation always wins. The older
hangar.io/workload-type: ai and spec.type: ai-agent markers are inferred as
ai-workload.
Which services Tower lists
A Component is listed when it declares a class or is one of the inferred legacy kinds. A Component registered by hand in the catalog declares nothing and stays out. A service that runs on a cluster is listed only while Kubernetes can see it; any other service is listed as soon as the catalog has it.
Which tabs a service gets
Each tab declares the capabilities it needs (requires in TowerPage.tsx). A class
grants capabilities. A deploy target adds or removes some. A tab shows when the service
has all of the ones it requires; a tab with none required always shows.
| Capability | Granted by | Tabs that need it |
|---|---|---|
source |
classes with a GitHub repo | Pull Requests, Notifications (with ci) |
ci |
classes onboarded to Glidepath (a cicd.yaml) |
Pipelines, Environments, Notifications, Glidepath |
build |
container-app, function, ai-service: a source repo Glidepath builds | Pipelines (with ci) |
releases |
container-app, function, ai-service | Releases |
images |
container-app, function, ai-service | Images |
slo |
container-app, infra-service, ai-service | SLOs (also needs k8s-runtime) |
values-config |
container-app, infra-service, ai-service; removed by cloud targets | Configure › Shared values |
k8s-runtime |
the k8s-rollout target |
Deployments, Topology, SLOs |
cloud-runtime |
every cloud target | Deployments (the cloud variant, see cloud-deploys.md) |
autopilot |
ai-workload, ai-service | the agent definition on Overview; Agent (mounted by the Autopilot plugin, see mounted-tabs.md) |
clearance |
container-app, infra-service, function, ai-service; any unknown class with a repo | Clearance (mounted by the Clearance plugin; shown where an agent’s scope names the app or an agent has acted on it) |
An infra-service (an Airframe InfraService such as a broker) has no source repo, build,
image or release records: it gets source, ci, values-config and slo but not build,
releases or images. Its own filter chip on the Services list is “Infra services”.
An ai-workload is an Autopilot agent in an ephemeral shape (task, session, scheduled, event,
team): it runs as AgentRuns and leaves nothing deployed. An ai-service is the long-running
service shape that Glidepath builds from its own repo and deploys like a container app. Both show
the agent’s definition on Overview (see below), and the Agent tab when the Autopilot plugin is installed: the
agent’s live runs, each run’s flight log (every call it made through Clearance) and the questions it is waiting on.
Tabs by service type
| Tab | Container app (Kubernetes) | Container app (cloud) | Function | Infra service | AI workload | AI service |
|---|---|---|---|---|---|---|
| Overview | yes | yes | yes | yes | yes (agent definition, no environments) | yes (with agent definition) |
| Pull Requests | yes | yes | yes | yes (gitops-infra repo) | yes | yes |
| Agent (Autopilot plugin) | yes | yes | ||||
| Pipelines | yes | yes | yes | yes | ||
| Deployments | Rollout variant | cloud variant | cloud variant | Rollout variant (StatefulSet) | Rollout variant | |
| Releases | yes | yes | yes | yes | ||
| Configure › Environments | yes | yes | yes | yes | yes | |
| Topology | yes | yes | yes | |||
| Images | yes | yes | yes | yes | ||
| SLOs | yes | yes | yes | |||
| Clearance (Clearance plugin) | where relevant | where relevant | where relevant | where relevant | where relevant | |
| Notifications | yes | yes | yes | yes | yes | |
| Configure › Shared values | yes | yes (no preview section) | yes | |||
| Configure › Pipeline | yes | yes | yes | yes (deploy, governance, notifications, secrets, advanced) | yes |
“Container app (cloud)” is aws-ecs or azure-container-apps; “Function” is aws-lambda (LambdaFunction) or
azure-container-apps (AzureFunction). The table is asserted by src/TowerPage.tabs.test.ts. The two tabs marked
with a plugin exist only while that plugin is installed; “where relevant” means the Clearance plugin found an agent
whose scope names the app, or agent activity on it (mounted-tabs.md).
Within a tab, an InfraService also gets less: Configure › Shared values has no Preview environments section (nothing
builds its pull requests) and Configure › Pipeline shows only the sections its cicd.yaml uses. The tab-by-tab
analysis is in the Tower service types spec.
An agent’s definition
An AI workload or AI service shows its Autopilot definition on Overview: shape, identity, tier ceiling, models,
network, compute, framework, triggers, the tools it may call through Clearance, the service APIs it may reach and
its limits. Tower reads it through the backend’s /agent-definition route from the Component’s own repo
(github.com/project-slug), at the path in hangar.io/agent-definition or agent.yaml at the root. The route reads
only agent.yaml or a YAML file under agents/, and refuses a file without a name and one of the six kinds.
Runs and cost join it when the Autopilot backend exposes them.
A class Tower has no entry for gets a label made from its slug, no capabilities, and
source if its Component has a github.com/project-slug. It still lists, filters and
opens on Overview.
Adding a kind of service
- No Tower change: the XRD emits the two annotations. The service appears, gets its own filter chip, and shows Overview (and Pull Requests if it has a repo).
- To give it a nicer label or capabilities: add an entry to
SERVICE_CLASSESinsrc/serviceClass.ts. - To give it tabs of its own: add the tab to
TABSwith the capability it needs, and grant that capability from the class. - A new deploy target: add an entry to
DEPLOY_TARGETS. Without one it still works, filed under its provider by prefix (aws-,azure-,gcp-).
Not built yet
Live health for cloud targets. The cloud Deployments tab shows what Glidepath deployed, not whether the service is up; see cloud-deploys.md.