2 · Deploy
Deploying in Brutor is not “get the container running” — that part is yours. Deploying is giving the thing you built its production identity: an AI System entity with exactly the resources it needs, credentials that are scoped to it, a declared owner and intended use, and a lifecycle stage someone accountable signed off on. Everything in Govern, Observe and Assure hangs off what you create here.
All calls in this stage go to the Control Plane Admin API (:5050) with an admin token — or click the same things in the Admin UI. Wrap them in an idempotent setup script so dev, staging and prod are provisioned from code, not memory.
Create the AI System
Section titled “Create the AI System”curl -X POST http://localhost:5050/v1/admin/resource-groups \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "support-copilot", "display_name": "Support Copilot", "description": "Answers customer questions, looks up orders, prepares refunds", "group_type": "ai_system", "system_kind": "agent", "parent_group_id": "<customer-success-team-group-id>", "inherit_resources": true }'{ "id": "group-01ABC...", "name": "support-copilot", "group_type": "ai_system", "system_kind": "agent", "inherit_resources": true}Three fields deserve thought:
system_kind—agentis the default; pick honestly (the six kinds), because it selects which lifecycle signals apply. Silence detection pages you usefully for anintegrationand uselessly for anassistant.parent_group_id— place the system under the team that owns it. The parent’s budgets, limits and policies apply to your system automatically (restrictively — a parent can only ever tighten), and the team’s cost roll-ups will include it.inherit_resources—truemeans your system also sees models and tools bound at the parent. Setfalsefor a strictly least-privilege system that should see only its own bindings.
Bind exactly what it needs
Section titled “Bind exactly what it needs”Bind each resource the agent actually uses — this is the permission set, and later it becomes the contract:
G=group-01ABC... # the AI System's id
# Models (bind a routing group? bind the virtual model AND every member)curl -X POST http://localhost:5050/v1/admin/resource-groups/$G/llm-models \ -H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \ -d '{"llm_model_id": "<model-id>"}'
# MCP servers (the CRM the agent reads orders from)curl -X POST http://localhost:5050/v1/admin/resource-groups/$G/server-configs \ -H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \ -d '{"server_config_id": "<crm-server-config-id>"}'
# A2A peers (the billing agent it delegates to) — PUT replaces the full setcurl -X PUT http://localhost:5050/v1/admin/resource-groups/$G/agent-cards \ -H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \ -d '{"agent_card_ids": ["<billing-agent-card-id>"]}'Skills and knowledge bases bind the same way (Admin UI → the group’s Agent Skills / Knowledge Base tabs). Binding POSTs return 409 on repeat — provisioning scripts treat that as “already there”.
Verify the effective result — what the system actually resolves to, inheritance included:
curl http://localhost:5050/v1/admin/resource-groups/$G/effective-llm-models \ -H "Authorization: Bearer $ADMIN_TOKEN"Mint its credentials
Section titled “Mint its credentials”Two options, and mature deployments use both:
An API key bound to the system — the simplest production credential. The key is the governance scope: any process holding it executes inside support-copilot, its resources, limits and audit trail.
curl -X POST http://localhost:5050/v1/admin/resource-groups/$G/api-keys \ -H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \ -d '{"name": "support-copilot-prod"}'The plaintext is returned once — put it straight into your secret manager.
An agent identity — when you want the agent to be a first-class principal with per-action grants rather than a bearer of a group key. Identity is anchored on your IdP (Okta, Entra Agent ID, SPIFFE); the gateway maps the workload token to the agent and applies default-deny grants:
curl -X POST http://localhost:5050/v1/admin/agent-identities \ -H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \ -d '{"name": "support-copilot", "owner_label": "Customer Success", "idp_server_id": "<idp-id>", "idp_subject": "spiffe://acme/ns/agents/support-copilot"}'Then add the identity to the AI System’s memberships so the group’s stack applies to it. You’ll write its grants (allow / deny / approval-required per action) in Govern; start in dry_run mode. Full model: Agent identity & policies.
Declare what it is for
Section titled “Declare what it is for”The fields that make the system governable by people — owner, intended use, autonomy, risk tier — live on the AI System and are required evidence at the gate below. Set them in the Admin UI under AI Estate → AI Systems → Support Copilot, or via PATCH /v1/admin/resource-groups/{id}:
- Owner — the accountable human, not a team alias someone will rotate out of.
- Intended use / intended clients — what it’s for and what should be calling it. Conformance later compares these declarations against observed traffic — an undeclared caller on a high-risk system is the finding a risk owner reads first.
- Autonomy level —
autonomous,approval_required,restrictedorsuspended. Resolves min-wins with the hierarchy; you can tighten it automatically on drift later. - EU AI Act risk tier —
highadds a named-human-approver floor to every lifecycle transition.
Pass the gate
Section titled “Pass the gate”An AI System moves proposed → approved → active → deprecated → retired, and each forward transition demands evidence. First, mint the contract — the hash-pinned snapshot of everything you just configured, generated from live config (never hand-written):
curl -X POST http://localhost:5050/v1/admin/ai-systems/$G/contracts \ -H "Authorization: Bearer $ADMIN_TOKEN"Then ask the gate what it needs — every reachable stage with each requirement marked satisfied or missing:
curl http://localhost:5050/v1/admin/ai-systems/$G/lifecycle \ -H "Authorization: Bearer $ADMIN_TOKEN"| Transition | Requires |
|---|---|
proposed → approved |
A contract minted for the current config; an owner; intended use |
approved → active |
An approver recorded on the contract; a liveness decision |
active → deprecated |
A successor named, or “no successor” stated explicitly |
deprecated → retired |
No runs for the quiet period (30 days) |
Have the approver approve the contract (POST /v1/admin/contracts/{id}/approve or the Admin UI’s Contract panel), make the liveness decision — for support-copilot, on_demand is right; a nightly pipeline would pick scheduled — and transition:
curl -X POST http://localhost:5050/v1/admin/ai-systems/$G/lifecycle \ -H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \ -d '{"to_stage": "approved"}' # then: {"to_stage": "active"}Point production at it, and script it
Section titled “Point production at it, and script it”Deploy your agent process wherever it runs, with two things in its environment: the gateway URL and the production credential. If you built Develop faithfully, nothing else changes — same code, new key, and the run ledger starts on day one.
Finally: everything on this page should live in a re-runnable script per environment. The setup-script guide shows the idempotency pattern (create-or-409, capture plaintext keys once, verify effective views at the end).

