How-To: Register Agents with Generators
An agent must be registered with a generator before any stack that generator owns can be targeted at it — registration is the agent’s opt-in consent boundary. For the reasoning behind this application-level tenancy model, see Generator registration and application scopes. This guide is the operational reference for granting, revoking, and inspecting those registrations.
Prerequisites
Section titled “Prerequisites”- Admin PAK for cross-entity registration (registering one entity on behalf of another)
- Access to the Brokkr broker API, or the
brokkrCLI configured with a broker URL and PAK - The UUIDs of the agents and generators you intend to link
Examples below assume an admin PAK in $ADMIN_PAK and a broker reachable at http://localhost:3000. The brokkr CLI resolves its broker URL and PAK from --broker-url/BROKKR_BROKER_URL and --pak/BROKKR_PAK (see the CLI Reference).
Register an Agent at Deploy Time
Section titled “Register an Agent at Deploy Time”The most common path is to have the agent register itself at startup. Supply the generator UUIDs the agent should opt into through any one of the following, in precedence order (highest first):
--generator-ids <UUID,UUID,...>CLI flag onbrokkr-agent startBROKKR__AGENT__GENERATOR_IDSenvironment variable (config keyagent.generator_ids)BROKKR_GENERATOR_IDS— deprecated bare variable, still honored but logs a warning
Values are comma-separated UUIDs; malformed entries are skipped with a warning. An empty value is valid and leaves the agent in system/fleet scope only (it still receives system-generator stacks — see System generator scope).
Via Helm (brokkr-agent chart)
Section titled “Via Helm (brokkr-agent chart)”Set broker.generatorIds as either a YAML list or a comma string; the chart renders it as BROKKR__AGENT__GENERATOR_IDS in the agent ConfigMap:
# values.yamlbroker: generatorIds: - a1b2c3d4-e5f6-7890-abcd-ef1234567890 - b2c3d4e5-f6a7-8901-bcde-f12345678901helm upgrade --install brokkr-agent oci://ghcr.io/colliery-io/charts/brokkr-agent \ -f values.yamlThe default is empty, which leaves the agent in system/fleet scope only.
Via environment variable
Section titled “Via environment variable”BROKKR__AGENT__BROKER_URL=https://broker.example.com \BROKKR__AGENT__PAK=brokkr_BRx9y2Kq_A1B2C3D4E5F6G7H8I9J0K1L2 \BROKKR__AGENT__GENERATOR_IDS=a1b2c3d4-e5f6-7890-abcd-ef1234567890,b2c3d4e5-f6a7-8901-bcde-f12345678901 \ brokkr-agent startVia CLI flag
Section titled “Via CLI flag”brokkr-agent start \ --generator-ids a1b2c3d4-e5f6-7890-abcd-ef1234567890,b2c3d4e5-f6a7-8901-bcde-f12345678901Register or Deregister an Existing Agent (Admin)
Section titled “Register or Deregister an Existing Agent (Admin)”Use this when an agent is already running and you need to grant or revoke a generator scope without restarting it.
Register via the brokkr CLI
Section titled “Register via the brokkr CLI”brokkr register \ --agent a1b2c3d4-e5f6-7890-abcd-ef1234567890 \ --generator b2c3d4e5-f6a7-8901-bcde-f12345678901 \ --pak "$ADMIN_PAK"You can give the agent and the generator by name instead of by id, for example brokkr register --agent prod-1 --generator payments-team --pak "$ADMIN_PAK". The same is true for brokkr deregister and brokkr registrations. If two agents have the same name, the command stops and lists their ids. See brokkr register.
You can run brokkr register again. For a pair that is registered already, the command changes nothing, prints a line that starts with unchanged:, and exits 0. For a new pair, it prints the registration record. Thus a bootstrap script does not need to check first. Agent startup self-registration also treats a repeat as success — see Register an Agent at Deploy Time. The REST API still returns 409 already_registered for a repeat.
Register via the REST API
Section titled “Register via the REST API”POST /generators/{id}/register with an agent_id in the body registers that agent (admin acting cross-entity). Omit agent_id and the calling agent registers itself. A generator PAK cannot call this endpoint — it returns 403 forbidden:
curl -s -X POST "http://localhost:3000/api/v1/generators/${GENERATOR_ID}/register" \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d '{"agent_id": "'"$AGENT_ID"'"}' | jq .Response (201 Created):
{ "id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "generator_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "registered_at": "2026-06-27T10:00:00Z"}Deregister (destructive)
Section titled “Deregister (destructive)”Warning: Deregistration cascades. It removes the agent’s explicit
agent_targetsfor every stack the generator owns and pushes aTargetChangedframe to the agent over its WebSocket, which prunes the corresponding Kubernetes resources on the next reconcile. There is no force flag and admin cannot bypass the consent boundary — deregistering is the supported way to revoke it.
Via the CLI:
brokkr deregister \ --agent a1b2c3d4-e5f6-7890-abcd-ef1234567890 \ --generator b2c3d4e5-f6a7-8901-bcde-f12345678901 \ --pak "$ADMIN_PAK"Via the REST API:
curl -s -X DELETE "http://localhost:3000/api/v1/generators/${GENERATOR_ID}/register" \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d '{"agent_id": "'"$AGENT_ID"'"}'Inspect Registrations
Section titled “Inspect Registrations”List a generator’s scopes for one agent
Section titled “List a generator’s scopes for one agent”brokkr registrations --agent "$AGENT_ID" --pak "$ADMIN_PAK"curl -s "http://localhost:3000/api/v1/agents/${AGENT_ID}/registrations" \ -H "Authorization: Bearer $ADMIN_PAK" | jq .List the agents registered with one generator
Section titled “List the agents registered with one generator”brokkr registrations --generator "$GENERATOR_ID" --pak "$ADMIN_PAK"curl -s "http://localhost:3000/api/v1/generators/${GENERATOR_ID}/registered-agents" \ -H "Authorization: Bearer $ADMIN_PAK" | jq .Both endpoints are authorized for admin, or for the agent/generator acting on itself.
Pre-register at Agent Creation
Section titled “Pre-register at Agent Creation”POST /agents accepts an optional generator_ids array that pre-registers the new agent at creation time, alongside the automatic system-generator registration every agent receives:
curl -s -X POST "http://localhost:3000/api/v1/agents" \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d '{ "name": "prod-1", "cluster_name": "us-east-1", "generator_ids": [ "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "b2c3d4e5-f6a7-8901-bcde-f12345678901" ] }' | jq .An unknown generator UUID rejects the whole request with 400 invalid_generator_id.
The broker CLI creates agents with the same semantics — system registration plus whatever you name — so a bootstrap script does not have to make a second call:
brokkr-broker create agent \ --name prod-1 \ --cluster-name us-east-1 \ --generator-ids a1b2c3d4-e5f6-7890-abcd-ef1234567890,b2c3d4e5-f6a7-8901-bcde-f12345678901Every UUID is validated before anything is written, so a typo fails the command rather than leaving a half-registered agent behind.
System Generator Scope
Section titled “System Generator Scope”The system generator (__system__) is provisioned at broker startup, and every agent is auto-registered with it at creation — through POST /agents and brokkr-broker create agent alike. It carries fleet- and system-wide stacks that should reach all agents, so an agent with an empty generator_ids still serves those stacks. The system generator is excluded from the public GET /generators listing.
The one gap: if you create an agent before the broker has ever started, there is no system generator to register it with. The CLI warns and creates the agent anyway. Start the broker once to provision the system generator, then register the agent with it explicitly.
The system generator is not the admin generator — the admin generator is a separate entity tied to the admin role/PAK, and agents are not auto-registered with it.
Troubleshoot 403 agent_not_registered
Section titled “Troubleshoot 403 agent_not_registered”A POST /agents/{id}/targets (add a target) or DELETE /agents/{id}/targets/{stack_id} (remove a target) that fails with HTTP 403 and error code agent_not_registered means the agent is not registered with the generator that owns the stack. Both mutations are gated, and admin cannot bypass the check — there is no force flag.
To resolve:
- Identify the stack’s owning generator, then confirm the gap:
Terminal window brokkr registrations --agent "$AGENT_ID" --pak "$ADMIN_PAK" - Register the agent with that generator (see Register or Deregister an Existing Agent).
- Retry the target mutation.
What registration controls on the read path: GET /agents/{id}/target-state serves the union of explicit agent_targets, label matches, and annotation matches — and the label and annotation legs are limited to stacks whose owning generator the agent is registered with. So labelling a stack cannot pull it onto an agent that never registered with its generator; registration decides which generators an agent hears from, and labels select among their stacks. Explicit targets are not filtered at read time because registration was checked when they were created, and existing targets remain valid. (Migration 23 back-fills registrations from pre-existing agent_targets, so upgrades do not break current targeting.)
A Note on the Two Isolation Layers
Section titled “A Note on the Two Isolation Layers”Generator registration is application-level isolation within a single broker. It is complementary to, and must not be conflated with, schema-per-tenant (database.schema) isolation, which is a separate deployment-level mechanism. See the application-level section of the Multi-Tenancy Reference.
Related
Section titled “Related”- Security Model — Generator registration and application scopes — why registration exists
- Core Concepts — generators, agents, and targeting
- API Reference — the registration endpoints,
agent_not_registered, andgenerator_ids - CLI Reference —
register/deregister/registrationsandgenerate-pak - Environment Variables Reference —
BROKKR__AGENT__GENERATOR_IDSand the deprecatedBROKKR_GENERATOR_IDS - Error Codes Reference —
agent_not_registered - Generators Reference — generator entity and permission model
- Multi-Tenancy Reference — application-level vs. deployment-level isolation