Skip to content

Blog

AI Convention Files in Practice: GitHub

Banner image Banner image

AI Convention Files in Practice: GitHub

The taxonomy post covered every AI convention file type. This post puts them to work with GitHub — using GraphQL queries against Issues, Projects V2, Pull Requests, and Actions.

Every example below uses real GraphQL queries and follows patterns suitable for a production agents.md that populates sprint review decks from GitHub project data.


How agents talk to GitHub

An AGENTS.md file defines what the agent should do. A GitHub MCP server provides the runtime connection. The agent reads the workflow, then calls the MCP server to execute GraphQL queries and retrieve project data.

GitHub agents workflow GitHub agents workflow

The GitHub MCP server exposes tools such as graphql_query, list_issues, list_pull_requests, and get_actions_runs. The agent invokes these tools through the MCP protocol — no raw HTTP calls needed.


GraphQL over REST for sprint data

GitHub's REST API requires many round trips to assemble sprint-level data — one call per issue, one call per PR. GraphQL gets nested project items, labels, assignees, and iteration data in a single query. For agents populating a sprint review deck, the difference is 1 call vs 50+. Always use GraphQL when querying Projects V2.

What gets automated (and what does not)

Not everything in a sprint review can come from a query. Platform migrations, new developer tooling, infrastructure redesigns — that work moves through GitHub Projects V2 iterations with milestones and roadmap views, and reporting on it is narrative. What shipped, what slipped, what the team learnt. An agent cannot write that.

Operational work is different. Access provisioning, pipeline fixes, environment configuration, troubleshooting — these arrive as issues, get closed, and pile up. Individually they are routine. In aggregate they tell a story: which labels generate the most volume, how cycle times trend, whether contributor load is balanced. That is numbers, and numbers come from GraphQL.

The agents in this post target operational work. They query GitHub, run the calculations, and drop the results into a Marp sprint review deck. Project slides stay in the same deck as fixed templates — same layout every sprint, content filled in by hand.

In GitHub terms: operations work uses labels like request, support, or ops on a shared repository. Projects track through GitHub Projects V2 with iteration fields, status columns, and tracked issues for epics.


Use case 1: Sprint review deck automation

The same pattern as the ADO version, adapted for GitHub Projects V2. The agent queries completed items from a project iteration, categorises them by label, and updates a Marp deck.

The agent definition

## Agent: Update Sprint Metrics from GitHub

Task: Update deck.md with sprint metrics from GitHub Projects V2

Steps:
1. Query GitHub for items completed in the current iteration
2. Calculate metrics:
   - Count by label category (bug, feature, infra, security)
   - Average cycle time (created → closed)
   - Items completed vs planned (velocity)
   - Unique contributors
3. Show calculated metrics to the user
4. Ask: "Update deck.md with these metrics? (yes/no)"
5. If approved, update the metrics table and key insights
6. Report what was updated

The GraphQL query

query SprintItems($projectId: ID!, $iterationId: String!) {
  node(id: $projectId) {
    ... on ProjectV2 {
      items(first: 100) {
        nodes {
          content {
            ... on Issue {
              title
              number
              state
              createdAt
              closedAt
              labels(first: 10) {
                nodes { name }
              }
              author { login }
              assignees(first: 5) {
                nodes { login }
              }
            }
            ... on PullRequest {
              title
              number
              state
              createdAt
              mergedAt
              author { login }
            }
          }
          fieldValueByName(name: "Iteration") {
            ... on ProjectV2ItemFieldIterationValue {
              title
              startDate
              duration
            }
          }
          fieldValueByName(name: "Status") {
            ... on ProjectV2ItemFieldSingleSelectValue {
              name
            }
          }
        }
      }
    }
  }
}

What the agent produces

Category Count %
Features 12 36%
Bug Fixes 8 24%
Infrastructure 6 18%
Security 4 12%
Documentation 3 9%

Key metrics: 33 items completed, 2.1 day average cycle time, 94% velocity (33/35 planned).


Use case 2: Contributor activity analysis

The GitHub equivalent of ADO's requestor patterns — analysing who is contributing and how work is distributed.

## Agent: Contributor Activity Analysis

Steps:
1. Query GitHub for merged PRs and closed issues in current iteration
2. Group by author/assignee
3. Calculate per-contributor:
   - PRs merged
   - Issues closed
   - Average review turnaround
4. Identify review bottlenecks (PRs waiting > 24 hours)
5. Update the activity summary in the deck
query ContributorActivity($owner: String!, $repo: String!, $since: DateTime!) {
  repository(owner: $owner, name: $repo) {
    pullRequests(
      states: [MERGED]
      orderBy: { field: UPDATED_AT, direction: DESC }
      first: 100
    ) {
      nodes {
        title
        author { login }
        createdAt
        mergedAt
        reviews(first: 10) {
          nodes {
            author { login }
            submittedAt
          }
        }
        additions
        deletions
      }
    }
  }
}

Use case 3: Sprint-over-sprint trend comparison

Comparing the current iteration against the previous one using GitHub Projects V2 iteration fields.

## Agent: Sprint Trend Comparison

Steps:
1. Query current iteration items (status: Done)
2. Query previous iteration items (status: Done)
3. Compare:
   - Velocity change (items completed)
   - Cycle time trend
   - Label distribution shift
   - New contributor count
4. Identify positive trends with percentages
5. Flag areas needing attention
6. Update the Key Insights slide

The agent compares iterations by name:

query IterationComparison($projectId: ID!) {
  node(id: $projectId) {
    ... on ProjectV2 {
      field(name: "Iteration") {
        ... on ProjectV2IterationField {
          configuration {
            iterations {
              id
              title
              startDate
              duration
            }
            completedIterations {
              id
              title
              startDate
              duration
            }
          }
        }
      }
    }
  }
}

Use case 4: Release notes generation

A SKILL.md that generates release notes from merged PRs and closed issues between two tags.

---
name: github-release-notes
description: Generate release notes from merged PRs between two Git tags
argument-hint: Provide the previous and current tag (e.g. v1.2.0 v1.3.0)
---
# GitHub Release Notes Generator

1. List commits between the two tags
2. Find all merged PRs associated with those commits
3. Group PRs by label:
   - 🚀 Features (label: enhancement)
   - 🐛 Bug Fixes (label: bug)
   - 🔧 Infrastructure (label: infra)
   - 🔒 Security (label: security)
   - 📝 Documentation (label: docs)
4. For each PR, extract title, number, and author
5. Generate markdown release notes
6. Check for breaking changes (label: breaking-change)
7. Include contributor acknowledgements
query PRsBetweenTags($owner: String!, $repo: String!, $base: String!, $head: String!) {
  repository(owner: $owner, name: $repo) {
    ref(qualifiedName: $head) {
      compare(headRef: $base) {
        commits(first: 100) {
          nodes {
            message
            associatedPullRequests(first: 1) {
              nodes {
                title
                number
                author { login }
                labels(first: 5) {
                  nodes { name }
                }
              }
            }
          }
        }
      }
    }
  }
}

Use case 5: SLO compliance from issue response times

A prompt that calculates SLO compliance from GitHub issue response and resolution times.

---
description: Generate SLO compliance report from GitHub issue data
agent: agent
tools: ['search', 'editFiles']
---
Query the last 30 days of issues labelled 'support' or 'request'.
Calculate time-to-first-response (issue created → first comment by team member).
Calculate resolution time (issue created → issue closed).
Compare against SLO targets:
- First response: p50 < 2 hours, p90 < 8 hours
- Resolution: p50 < 24 hours, p90 < 72 hours
Generate a markdown table with percentile breakdown and trend.

Use case 6: Actions pipeline health report

An agent that analyses GitHub Actions workflow runs for reliability and performance.

## Agent: Pipeline Health Report

Steps:
1. Query GitHub Actions for workflow runs in the last 14 days
2. Calculate per-workflow:
   - Success rate (%)
   - Average duration
   - Failure patterns (most common failure step)
   - Flaky test detection (intermittent failures)
3. Compare against previous 14-day window
4. Update the pipeline health slide in the deck
5. Flag any workflow with < 90% success rate
query WorkflowRuns($owner: String!, $repo: String!) {
  repository(owner: $owner, name: $repo) {
    object(expression: "main") {
      ... on Commit {
        checkSuites(first: 50) {
          nodes {
            conclusion
            workflowRun {
              workflow { name }
              createdAt
              updatedAt
              runNumber
            }
            checkRuns(first: 20) {
              nodes {
                name
                conclusion
                startedAt
                completedAt
              }
            }
          }
        }
      }
    }
  }
}

The master agent pattern

## Master Agent: Populate Sprint Review from GitHub

Steps:
1. Calculate current iteration dates
2. Ask user for permission to proceed
3. If approved, run Agent: Sprint Metrics
4. Run Agent: Contributor Activity
5. Run Agent: Sprint Trend Comparison
6. Run Agent: Pipeline Health Report
7. Report summary of updates made
8. Suggest running 'make diagrams' to regenerate PNGs

Before executing:
- Display the configuration (org, repo, project, iteration)
- Ask: "I will query GitHub and update diagrams and slides.
  Do you want to proceed? (yes/no)"
- Only proceed if user confirms

GitHub-specific configuration

GitHub concept How agents use it
Projects V2 Track iterations, status fields, and sprint boundaries
Labels Categorise issues and PRs for metric grouping
Milestones Alternative to iterations for release-based tracking
GraphQL API Rich querying with nested fields — more flexible than REST
Actions Pipeline health and deployment frequency metrics
CODEOWNERS Map reviewers to areas for workload analysis

Apply this: set GITHUB_TOOLSETS to limit loaded tools

The GitHub MCP server loads all tools by default. For sprint review agents that only need project data, set GITHUB_TOOLSETS=repos,issues,pull_requests to reduce the tool surface. Fewer tools means less cognitive overhead for the agent and a smaller permission footprint. Load only what the agent actually needs.

MCP server setup

The GitHub MCP server is GitHub's official server. The fastest setup is the remote server, which uses OAuth — no tokens to manage:

{
  "servers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/"
    }
  }
}

This works in VS Code 1.101+ with Copilot. For editors that do not support remote MCP, use the local Docker-based server with a PAT:

{
  "servers": {
    "github": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
        "ghcr.io/github/github-mcp-server"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github_token}"
      }
    }
  }
}

To limit loaded tools, set GITHUB_TOOLSETS (e.g. repos,issues,pull_requests,actions). See the toolset documentation for the full list.


The hardcoded iteration name tell

Agents that reference a specific sprint by name (sprint = "Sprint 24.06") break every two weeks when the sprint rolls over. Use the IterationField.configuration.iterations query to discover the current iteration dynamically. Your agent should find the active sprint, not be told which one to look at.

Anti-patterns to avoid

  • REST when you need GraphQL — GitHub's REST API requires many round trips; GraphQL gets nested data in one call
  • Ignoring project field types — Projects V2 uses typed fields (iteration, single select, text); query the right type
  • Hardcoded iteration names — Use the iteration field configuration to discover current and previous iterations dynamically
  • Skipping Actions data — Pipeline health is visible early signal; include it in sprint reviews
  • Not filtering by label — Without label-based categorisation, metrics lack the granularity stakeholders need

Getting started

  1. Install the GitHub MCP server in your editor
  2. Create an agents.md with one agent (start with sprint metrics)
  3. Set up a GitHub Project V2 with iteration fields if you have not already
  4. Run the agent against a real iteration
  5. Add agents incrementally

The working examples will be available in the ai-capabilities repo.


Frequently asked questions

Does the GitHub MCP server require a Personal Access Token?

For the remote server (https://api.githubcopilot.com/mcp/) in VS Code 1.101+: no — it uses OAuth via GitHub Copilot. For the Docker-based local server, yes — a PAT with repo, project, and read:org scopes. The remote server is simpler to set up; the local server is needed for editors that don't support remote MCP.

Can agents query private GitHub Projects V2?

Yes, as long as the authenticated token has access. For the remote server, the OAuth flow grants access to your orgs and repos. For the PAT-based local server, ensure the PAT has project scope (classic PAT) or read:project and read:org (fine-grained PAT). Project visibility follows GitHub's existing permission model.

How do you handle Projects V2 with multiple iteration fields?

Query the field(name: "Iteration") with the specific field name you use. If your project has multiple iteration-type fields (e.g. "Sprint" and "Quarter"), query each by name separately. The ProjectV2IterationField.configuration.iterations object gives you the active iteration's startDate and duration so you can calculate boundaries dynamically.

What's the best way to categorise GitHub issues without labels?

Labels are the cleanest signal, but you can also group by assignee (for workload analysis), by milestone (for release tracking), or by the Projects V2 status field (for board column grouping). For teams that haven't adopted a labelling convention yet, milestone-based grouping is the easiest starting point — most teams already use milestones even when labels are inconsistent.

Can the same AGENTS.md work for both GitHub and GitHub Enterprise?

Yes — the GraphQL queries are identical. The only difference is the API endpoint: https://api.github.com/graphql for GitHub.com vs https://your-ghe.example.com/api/graphql for GitHub Enterprise Server. Parameterise the base URL in your MCP server configuration rather than hardcoding it in the agent definitions.


Further reading

AI Convention Files in Practice: Jira

Banner image Banner image

AI Convention Files in Practice: Jira

The taxonomy post covered every AI convention file type. This post puts them to work with Jira — using JQL queries against sprints, boards, components, and fix versions.

Every example below uses real JQL queries and follows patterns suitable for a production agents.md that populates sprint review decks from Jira project data.


How agents talk to Jira

An AGENTS.md file defines what the agent should do. A Jira MCP server provides the runtime connection. The agent reads the workflow, then calls the MCP server to execute JQL queries and retrieve issue data.

Jira agents workflow Jira agents workflow

The Jira MCP server exposes tools such as jql_search, get_issue, get_sprint, and get_board. The agent invokes these tools through the MCP protocol — no raw HTTP calls or API tokens in your agent definitions.


JQL functions beat date ranges

sprint in openSprints() is dynamic — it always targets the active sprint. A hardcoded sprint = "Sprint 24.06" breaks every two weeks. Use Jira's built-in JQL functions (openSprints(), closedSprints(), -14d) so your agent definitions stay valid indefinitely without maintenance.

What gets automated (and what does not)

Not everything in a sprint review can come from a query. Platform migrations, IDP rollouts, infrastructure redesigns — that work moves through Epics and fix versions, and reporting on it is narrative. What shipped, what slipped, what the team learnt. An agent cannot write that.

Operational work is different. Access requests, pipeline failures, environment provisioning, certificate rotations — these arrive as Service Requests, get resolved, and pile up. Individually they are routine. In aggregate they tell a story: which components generate the most load, how resolution times trend, whether the same teams keep coming back. That is numbers, and numbers come from JQL.

The agents in this post target operational work. They query Jira, run the calculations, and drop the results into a Marp sprint review deck. Project slides stay in the same deck as fixed templates — same layout every sprint, content filled in by hand.

In Jira terms: operations work lives in a shared project with types like Service Request or Support, grouped by component. Projects use Epics tracked through sprints and fix versions.


Use case 1: Sprint review deck automation

The agent queries resolved issues from the active sprint, categorises by component, and updates a Marp deck.

The agent definition

## Agent: Update Sprint Metrics from Jira

Task: Update deck.md with sprint metrics from the active Jira sprint

Steps:
1. Query Jira for issues resolved in the active sprint
2. Calculate metrics:
   - Count by component (API, Frontend, Infrastructure, Security)
   - Average resolution time (created → resolved)
   - Story points completed vs committed (velocity)
   - Unique assignees
3. Show calculated metrics to the user
4. Ask: "Update deck.md with these metrics? (yes/no)"
5. If approved, update the metrics table and key insights
6. Report what was updated

The JQL query

project = "PLAT"
  AND sprint in openSprints()
  AND status = Done
  AND resolved >= -14d
ORDER BY resolved DESC

For more granular filtering:

project = "PLAT"
  AND sprint = "Sprint 24.06"
  AND status changed to Done
  AND component in (API, Frontend, Infrastructure, Security)
ORDER BY component ASC, resolved DESC

What the agent produces

Component Count Story Points %
API 10 21 30%
Frontend 8 18 24%
Infrastructure 7 15 21%
Security 4 8 12%
Documentation 3 5 9%
DevOps 1 2 3%

Key metrics: 33 issues resolved, 69 story points completed (92% of committed 75), 2.3 day average resolution.


Use case 2: Team workload analysis

The Jira equivalent of requestor patterns — analysing assignee distribution and identifying workload imbalances.

## Agent: Team Workload Analysis

Steps:
1. Query Jira for issues resolved in the active sprint
2. Group by assignee
3. Calculate per-assignee:
   - Issues resolved
   - Story points completed
   - Average resolution time
4. Identify workload imbalances (> 2x average)
5. Check for unassigned resolved issues
6. Update the workload summary in the deck
project = "PLAT"
  AND sprint in openSprints()
  AND status = Done
  AND assignee is not EMPTY
ORDER BY assignee ASC

Use case 3: Sprint-over-sprint velocity comparison

Comparing the current sprint against the previous one using Jira's sprint functions.

## Agent: Velocity Trend Comparison

Steps:
1. Query current sprint issues (status: Done)
2. Query previous sprint issues (status: Done)
3. Compare:
   - Story points completed (velocity)
   - Issue count
   - Average cycle time
   - Component distribution shift
   - Carry-over items (not completed in previous sprint)
4. Identify positive trends with percentages
5. Flag areas needing attention
6. Update the Velocity Trends slide
-- Current sprint
project = "PLAT" AND sprint in openSprints() AND status = Done

-- Previous sprint
project = "PLAT" AND sprint in closedSprints()
  AND sprint not in openSprints()
  AND status = Done
ORDER BY resolved DESC

For named sprints:

project = "PLAT" AND sprint = "Sprint 24.05" AND status = Done

Use case 4: Release notes from fix versions

A SKILL.md that generates release notes from a Jira fix version.

---
name: jira-release-notes
description: Generate release notes from a Jira fix version
argument-hint: Provide the fix version name (e.g. v2.4.0)
---
# Jira Release Notes Generator

1. Query issues with the specified fixVersion
2. Verify all issues are in Done status
3. Flag any non-Done issues as blockers
4. Group issues by type:
   - 🚀 Features (type: Story)
   - 🐛 Bug Fixes (type: Bug)
   - 🔧 Tasks (type: Task)
   - 📖 Sub-tasks (type: Sub-task)
5. For each issue, extract:
   - Key, summary, component, assignee
   - Labels for additional context
6. Generate markdown release notes
7. Check for issues labelled 'breaking-change'
8. Include contributor acknowledgements from assignee list
project = "PLAT"
  AND fixVersion = "v2.4.0"
ORDER BY issuetype ASC, component ASC

Use case 5: SLO compliance from resolution times

A prompt that calculates SLO compliance from Jira issue resolution data.

---
description: Generate SLO compliance report from Jira issue data
agent: agent
tools: ['search', 'editFiles']
---
Query the last 30 days of issues with type 'Service Request' or 'Support'.
Calculate resolution time percentiles (p50, p90, p99).
Use the 'resolutiondate' and 'created' fields for time calculations.
Compare against SLO targets:
- p50 < 4 hours (Priority: Highest)
- p50 < 24 hours (Priority: High)
- p90 < 72 hours (Priority: Medium/Low)
Generate a markdown table grouped by priority with trend arrows.
project = "PLAT"
  AND issuetype in ("Service Request", Support)
  AND resolved >= -30d
ORDER BY priority ASC, resolved DESC

Use case 6: Epic progress dashboard

An agent that summarises epic progress for stakeholder reviews.

## Agent: Epic Progress Dashboard

Steps:
1. Query Jira for active epics in the project
2. For each epic:
   - Count total child issues
   - Count completed child issues
   - Sum story points (completed vs total)
   - Calculate completion percentage
   - Find the earliest and latest due dates
3. Rank epics by completion percentage
4. Flag at-risk epics (< 50% complete with < 25% time remaining)
5. Update the Epic Progress slide in the deck
-- Active epics
project = "PLAT"
  AND issuetype = Epic
  AND status != Done
ORDER BY priority ASC

-- Child issues for a specific epic
"Epic Link" = PLAT-123 AND status = Done

The master agent pattern

## Master Agent: Populate Sprint Review from Jira

Steps:
1. Identify the active sprint name
2. Ask user for permission to proceed
3. If approved, run Agent: Sprint Metrics
4. Run Agent: Team Workload Analysis
5. Run Agent: Velocity Trend Comparison
6. Run Agent: Epic Progress Dashboard
7. Report summary of updates made
8. Suggest running 'make diagrams' to regenerate PNGs

Before executing:
- Display the configuration (project, board, sprint)
- Ask: "I will query Jira and update diagrams and slides.
  Do you want to proceed? (yes/no)"
- Only proceed if user confirms

Jira-specific configuration

Jira concept How agents use it
Projects Scope queries by project key (project = "PLAT")
Sprints Use openSprints(), closedSprints(), or named sprints
Components Categorise issues for metric grouping (API, Frontend, Infra)
Fix Versions Map to release milestones for release notes generation
Story Points Calculate velocity and sprint commitment accuracy
JQL The query language — supports functions like openSprints(), -14d, was, changed
Boards Scrum or Kanban views that scope sprint data

Apply this: set Jira defaults in AGENTS.md to save tokens

Add a configuration block to your AGENTS.md that sets the project key, board ID, and maxResults defaults once. Agents inherit these without repeating them in every JQL query definition. Fewer tokens per call, less chance of an agent querying the wrong project when operating across multiple Jira projects.

MCP server setup

The Atlassian MCP server is a remote server hosted by Atlassian that connects to Jira, Confluence, and Compass. For VS Code and other clients that support remote MCP:

{
  "servers": {
    "atlassian": {
      "type": "http",
      "url": "https://mcp.atlassian.com/v1/mcp"
    }
  }
}

Authentication uses OAuth 2.1 — a browser window opens to authorise your Atlassian account. All actions respect your existing Jira permissions.

For desktop clients that do not support remote MCP natively (e.g. Claude Desktop, Cursor), use the mcp-remote proxy:

{
  "mcpServers": {
    "atlassian": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.atlassian.com/v1/sse"]
    }
  }
}

To reduce discovery calls and save tokens, set defaults in your AGENTS.md:

When connected to atlassian-rovo-mcp:
- Use Jira project key = PLAT
- Use cloudId = "https://your-site.atlassian.net"
- Use maxResults: 10 for all JQL search operations

Issue count without story points misleads stakeholders

Reporting "33 issues resolved" without story points hides effort. A sprint with 33 one-point bug fixes looks identical to one with 33 complex feature stories. Always report both: issue count for volume, story points for effort. If your team doesn't use story points, at least report by issue type distribution.

Anti-patterns to avoid

  • Querying by date instead of sprint — Jira sprints have boundaries; use sprint in openSprints() instead of date ranges to capture carry-overs correctly
  • Ignoring story points — Issue count alone does not reflect effort; include story points in velocity calculations
  • Not using components — Without component-based grouping, sprint metrics lack actionable granularity
  • Skipping epic context — Individual issue metrics miss the bigger picture; include epic progress for stakeholders
  • Hardcoded sprint names — Use openSprints() and closedSprints() functions for dynamic sprint identification

Getting started

  1. Install the Jira MCP server in your editor
  2. Create an agents.md with one agent (start with sprint metrics)
  3. Ensure your Jira project has components and story points configured
  4. Run the agent against a real sprint
  5. Add agents incrementally

The working examples will be available in the ai-capabilities repo.


Frequently asked questions

Does the Atlassian MCP server require admin access to Jira?

No — it uses OAuth 2.1 and respects your existing Jira permissions. The agent can only query and act on projects, boards, and issues you have access to as the authenticated user. No elevated permissions required. Admin access would only be needed if an agent were creating boards or modifying project configuration.

How do agents handle Jira custom fields?

Custom fields are accessible via their field ID (e.g. cf[10016] for story points, depending on your Jira instance). The Atlassian MCP server exposes field metadata so agents can discover field IDs dynamically. For common custom fields you use repeatedly, add the field IDs to your AGENTS.md configuration block so agents don't have to look them up every run.

Can I run the same agent against multiple Jira projects?

Yes — parameterise @ProjectKey in the JQL queries and define it in the AGENTS.md configuration block. Run the master agent once per project by changing the config block. For teams with a shared operations project and multiple product projects, run ops metrics from one project and velocity from another in the same deck session.

What's the difference between using Jira sprints vs fix versions for release tracking?

Sprints are time-boxed iterations — good for velocity, cycle time, and operational metrics. Fix versions are milestone markers — good for release scope, scope creep tracking, and what shipped in a version. Use sprints for the sprint review deck. Use fix versions for release notes and stakeholder communication. They answer different questions.

How do you avoid the 'open sprints' query returning items from multiple active sprints?

In Jira, sprint in openSprints() returns all active sprints, which can include sprints on different boards. Scope it with the project key and board ID: query the board's active sprint directly via the Jira Agile API (/rest/agile/1.0/board/{boardId}/sprint?state=active) or add AND sprint = "Sprint 24.XX" with the dynamically discovered sprint name. The MCP server's get_sprint tool handles this cleanly.


Further reading

Sprint Reviews with Marp: Presentations as Code

Banner image Banner image

Sprint Reviews with Marp: Presentations as Code

Sprint review decks have a shelf life of about two weeks. You build one, present it, then build the next one — mostly from scratch. The metrics change, the charts update, the talking points shift. But the structure stays the same.

That repetition is the problem. Manually pulling numbers from Azure DevOps, rebuilding bar charts, updating summary tables — it takes time and introduces mistakes. If the deck is a PowerPoint file, diffs are meaningless and merge conflicts are impossible to resolve.

Here's the insight that makes this tractable: not everything in a sprint review is the same kind of work.

Platform development — building new self-service capabilities, golden paths, reference architectures — is project-shaped. It has objectives, milestones, design decisions, and demos. A sprint review slide for a platform initiative needs narrative: what shipped, what slipped, what the team learnt. An agent can't write that. But the template can stay fixed — same layout, same sections, filled in by the team each sprint.

BAU and operations — access provisioning, pipeline troubleshooting, infrastructure requests — is ticket-shaped. The metrics matter more than the individual items. Request counts by category, resolution time trends, SLA compliance, top requesting teams — the numbers change every sprint, the format does not. Agents query the tracker, run the calculations, and write the results straight into the deck.

Most platform teams do both. The sprint review deck reflects that split. Operations slides are agent-populated. Platform development slides use fixed templates. The whole structure lives in version control.

Marp solves the structural half: slides written in Markdown, version-controlled in Git, rendered to HTML, PDF, or PowerPoint. AGENTS.md solves the data half: Copilot agents that query ADO and write the numbers directly into the deck.

This post walks through both — the deck format and the automation layer on top of it.


Diffs are the hidden superpower of Markdown slides

When you update sprint metrics in a Marp deck, git diff shows exactly what changed — "Total requests: 42 → 47", "SLA compliance: 85% → 91%". In PowerPoint, that diff is invisible. A version-controlled deck gives you an audit trail of every sprint's numbers without any extra tooling. That alone is worth the migration from slide software.


What Marp does

Marp is a Markdown-based presentation framework. You write slides in a .md file, add a YAML frontmatter block for configuration, and use --- to separate slides. The Marp CLI converts the Markdown to HTML, PDF, or PPTX.

A minimal slide deck:

---
marp: true
theme: default
paginate: true
---

# Slide One

Content goes here.

---

# Slide Two

More content.

That produces a two-slide deck with pagination. No drag-and-drop, no binary format, no GUI.

Why this matters for sprint reviews

  • Diffs work. When you update metrics, git diff shows exactly what changed — "Total requests: 42 → 47". PowerPoint diffs are opaque.
  • Templates carry forward. The slide structure persists across sprints. You update the data, not the layout.
  • Build pipeline. make html produces a browser preview. make pdf produces a print-ready output. make pptx produces a PowerPoint for stakeholders who need one. One source, three formats.
  • No context switching. The deck lives in VS Code alongside the agents.md that populates it.

Deck structure

A production sprint review deck uses frontmatter to configure the theme, transitions, and language:

---
title: "Platform Engineering Sprint Review"
marp: true
theme: copernicus
transition: fade
size: "16:9"
lang: en-GB
paginate: true
header: "Platform Engineering"
---

The theme: copernicus directive loads a custom CSS theme from a themes/ directory. This keeps branding consistent without embedding styles in every slide. The Marp community themes page is a good starting point; drop any .css file into a local themes/ folder and reference it by filename.

Slide content

Slides use standard Markdown — headers, bullet lists, tables, images. Marp adds a few directives for layout control:

<!-- _class: title -->

# Sprint Review

---

## DD Month YYYY

![bg right:40%](images/external/banner.png)

The _class: title directive applies a CSS class to that slide only. bg right:40% places a background image on the right side of the slide.

Tables render natively:

| Category              | Count | % of Total |
|-----------------------|-------|------------|
| Access & Permissions  | 12    | 28%        |
| Pipeline & CI/CD      | 9     | 21%        |
| Azure Resources       | 7     | 16%        |

No chart plugins, no embedded objects — plain text that any editor can open.


PlantUML charts in slides

Static tables work for summaries. For visual metrics — category distributions, resolution time trends, team volumes — PlantUML charts generate PNGs that slot directly into slides.

A bar chart for request distribution:

@startchart
title Request Category Distribution

bar "Category" [
  "Access & Perms" 12,
  "Pipeline" 9,
  "Azure Config" 7,
  "Infra Setup" 6,
  "APIM" 4,
  "DR" 2,
  "Other" 2
] #3498db labels

@endchart

Running PlantUML converts this to a PNG with a transparent background:

java -jar ~/tools/plantuml-snapshot.jar diagrams/request-distribution.puml -o .

The slide references the generated image:

---

## Request Distribution

![Request categories](diagrams/request-distribution.png)

The chart data is plain text in a .puml file. When the agent updates the numbers, git diff shows "Access & Perms" 12"Access & Perms" 15. Try that with an embedded Excel chart.

Chart types used

The sprint review deck uses six PlantUML charts:

Chart Type Shows
Request distribution Horizontal bar Category breakdown
Resolution time trends Line Daily averages over 14 days
Request complexity Bar Simple / Medium / Complex split
Request lifecycle SLA Horizontal bar Stage timings in hours
Requestor patterns Horizontal bar Top 5 requesting teams
Top teams volume Horizontal bar Team request volumes

All six are generated with make diagrams, which runs PlantUML across every .puml file in the diagrams/ directory.


Apply this: separate narrative slides from data slides in your deck structure

The two-type model works best when it's structurally visible in the deck. Name your platform development slides with a fixed marker (<!-- PROJECT -->) and your operations slides with a data marker (<!-- OPS - auto-populated -->). This makes it obvious to anyone opening the file which slides the agent owns and which the team fills in. It also prevents the agent from accidentally overwriting a hand-written narrative section.


How AGENTS.md populates the deck

The taxonomy post covered what AGENTS.md files do. The ADO practice post showed WIQL query patterns. This deck uses both.

An agents.md file sits alongside deck.md in the repo. It defines nine agents, each responsible for a specific section of the deck. Three tracker-specific variants are available in the repo:

Tracker File Query language
Azure DevOps agents.md WIQL
GitHub Projects agents-github.md GraphQL
Jira agents-jira.md JQL

The structure is identical across all three — same nine agents, same master agent, same deck update targets. Only the query language and field names differ.

The workflow:

  1. Open the relevant agents.md for your tracker in VS Code
  2. Ask Copilot: "Run Master Agent: Populate All Diagrams and Slides"
  3. The master agent runs each sub-agent in sequence
  4. Each sub-agent queries your tracker via MCP, then writes the results into deck.md or a .puml file
  5. Run make diagrams to regenerate PNGs
  6. Run make html to preview

Agent examples

Agent 5 — Requestor Patterns queries ADO for all Requests in the current sprint, groups by requesting team, counts totals, and updates diagrams/requestor-patterns.puml with the top five teams:

Steps:
1. Query ADO for all Requests from last 2 weeks
2. Extract requesting team from Custom.RequestedTeamName
3. Group by team, count requests
4. Update bar data array in requestor-patterns.puml

The WIQL query:

SELECT [System.Id], [System.Title], [Custom.RequestedTeamName]
FROM WorkItems
WHERE [System.WorkItemType] = 'Request'
  AND [System.AreaPath] UNDER @AreaPath
  AND [System.CreatedDate] >= @StartDate

The @AreaPath parameter is defined once in the agents.md configuration block, so the same agents work across different teams without editing every query.

Agent 6 — Request Metrics Summary does arithmetic: counts by category, calculates SLA compliance percentages, finds the peak request day, then writes a Markdown table into the "Operations Overview" slide of deck.md.

Agent 8 — Key Insights compares the current sprint against the previous one. It calculates resolution time changes, SLA shifts, and volume trends, then updates the "Key Insights & Improvements" slide with data-backed bullet points.

The master agent

A master agent orchestrates the others:

Steps:
1. Calculate start date (2 weeks ago)
2. Ask user for permission to query ADO
3. Run Agent 5: Update Requestor Patterns
4. Run Agent 6: Update Request Metrics Summary
5. Run Agent 8: Update Key Insights
6. Report summary of updates
7. Suggest running 'make diagrams'

Each agent asks for confirmation before writing. The master agent handles sequencing and error recovery — if one agent fails (say, ADO returns no data for a category), it reports the issue and moves to the next.

Marp sprint review pipeline Marp sprint review pipeline


The stale placeholder tell

The most common failure mode in agent-populated decks is a slide that still shows last sprint's numbers because one agent silently returned no data and left the previous values in place. Add a freshness check: after the master agent runs, scan deck.md for any placeholder patterns (e.g. <!-- UPDATE --> markers or dates older than 14 days). If found, flag it before presenting — stale numbers in a sprint review erode trust fast.


The build pipeline

The Makefile (macOS/Linux) and make.bat (Windows) handle the full pipeline:

# Generate all outputs
make all        # diagrams + HTML + PDF + PPTX

# Individual targets
make diagrams   # PlantUML → PNG
make html       # Marp → HTML (fast preview)
make pdf        # Marp → PDF
make pptx       # Marp → PowerPoint

make html produces a self-contained HTML file you can open in a browser. Slide transitions work. Navigation works. Presenter notes show up in presenter mode (P key). It runs in under two seconds.

make pptx produces a real PowerPoint file for stakeholders who need to open it in Office. The formatting isn't pixel-perfect — Marp-to-PPTX conversion has limitations — but it's close enough for most uses.


Sprint workflow

A typical two-week cycle:

  1. Sprint start — Run the master agent to populate the deck with data from the previous sprint (or stub in the current sprint dates).
  2. During the sprint — No deck work needed. Focus on delivery.
  3. Sprint end — Run the master agent again. It pulls fresh ADO data — completed requests, resolution times, SLA figures — and writes everything into deck.md and the .puml files.
  4. Review prepmake all generates HTML for presenting and PDF/PPTX for distribution. Add any manual commentary (demo notes, shout-outs) directly in deck.md.
  5. Present — Open the HTML in a browser. Use F for full-screen, P for presenter mode.
  6. Archive — Commit and push. The deck is versioned. Next sprint, reset the data and start again.

Total manual effort: running the master agent and adding commentary. The charts, tables, and metrics fill themselves.


Getting started

To set up a similar deck:

  1. Install Marp CLI: npm install -g @marp-team/marp-cli
  2. Install PlantUML: Download the snapshot JAR to ~/tools/plantuml-snapshot.jar
  3. Create deck.md: Start with the frontmatter block from above, add --- separators for slides
  4. Pick your agents.md: Use agents.md for ADO, agents-github.md for GitHub Projects, or agents-jira.md for Jira. Set the configuration block at the top (area path, project key, or repo owner) and all nine agents pick it up.
  5. Add a Makefile: Wire up marp and plantuml commands
  6. Run the workflow: Agent → data → make all → present

The AI Convention Files taxonomy covers the full set of file types available. The ADO practice post has WIQL query patterns you can adapt.


Companion resources

A working starter — deck.md template, PlantUML chart files, Makefile, and generate-deck.sh — is in the ai-capabilities repo. The nine-agent workflow is available for all three major trackers:

Further reading:


Frequently asked questions

Does Marp work on Windows, or is it Mac/Linux only?

Marp CLI is cross-platform — it runs on Windows, macOS, and Linux via Node.js. The Makefile in the companion repo uses standard Unix commands; for Windows use the included make.bat instead. PlantUML requires Java, which is also cross-platform. The VS Code Marp extension provides a live preview that works identically across all platforms.

Can I use a custom theme that matches our company branding?

Yes — drop any CSS file into a themes/ directory and reference it in the deck frontmatter with theme: your-theme-name. The Marp CSS spec supports custom fonts, colour palettes, and slide classes. The copernicus theme used in these examples is a custom theme defined in the companion repo; you can use it as a starting point and swap in your brand colours.

What happens if the agent updates deck.md with wrong numbers?

Every agent asks for confirmation before writing: "Update deck.md with these metrics? (yes/no)". Review the calculated numbers before approving. If wrong numbers do get written, git diff shows exactly what changed and git revert or git checkout restores the previous version in one command. This is the core value of keeping the deck in Git rather than a shared drive file.

Do all three tracker versions (ADO, GitHub, Jira) use exactly the same deck structure?

Yes — the nine-agent workflow and deck structure are identical across all three. Only the query language and field names differ (WIQL vs GraphQL vs JQL). You can run your review prep against whichever tracker your team uses without changing the slide template. The companion repo has all three agents.md variants alongside a single deck.md template.

How do you handle the PlantUML chart generation on CI — is Java required in the pipeline?

Yes — make diagrams calls the PlantUML JAR, which requires Java. For CI, either include a Java installation step or pre-generate the PNGs locally and commit them alongside the .puml source files. Most teams commit generated PNGs to Git (the source .puml is the truth; the PNG is the render) and only regenerate in CI when a .puml file changes.

OpenClaw Convention Files: AI Assistants Beyond Code

Banner image Banner image

OpenClaw Convention Files: AI Assistants Beyond Code

The taxonomy post covered convention files for coding agents — AGENTS.md, SKILL.md, .prompt.md, and their relatives. Those files live in a project repo and guide agents during development work.

OpenClaw uses the same approach for a different problem: personal AI assistants that operate across messaging channels. An OpenClaw agent can reply to WhatsApp messages, monitor Discord servers, check email, control smart home devices, and run background tasks — all from a single gateway process on your own hardware.

The convention files that power this are different from the coding-agent ones, because the problems are different. A coding agent needs workflow steps and quality gates. A personal assistant needs identity, memory across sessions, and rules about when to speak in group chats.


The file types

OpenClaw convention files taxonomy OpenClaw convention files taxonomy

File Purpose When loaded
AGENTS.md Behavioural baseline — safety, workflow, skills, session rules Every session start
SOUL.md Identity, tone, and boundaries — who the agent is Every session start
USER.md Owner context — who the agent is helping Every session start
MEMORY.md Long-term recall — curated facts, preferences, decisions Main session only (not group chats)
memory/YYYY-MM-DD.md Daily logs — raw notes from each session Today + yesterday on startup
TOOLS.md Environment specifics — device names, SSH hosts, voice preferences When a skill needs it
SKILL.md Per-skill instructions — one per tool/capability When the skill is invoked
HEARTBEAT.md Background task checklist — what to check during idle polls On heartbeat poll
BOOTSTRAP.md First-run identity setup — read once, then deleted First session only

Three of these (AGENTS.md, SOUL.md, USER.md) load on every session start, before the agent responds to anything. The rest load on demand.


Three files load on every session start — get those right first

AGENTS.md, SOUL.md, and USER.md load before the agent responds to anything. These three files define the agent's behaviour baseline, identity, and understanding of who it's helping. Everything else — MEMORY.md, TOOLS.md, HEARTBEAT.md — loads on demand. Invest your setup time in the always-on three before touching the rest.


AGENTS.md — the behavioural baseline

OpenClaw's AGENTS.md shares the name with the coding-agent standard but serves a broader role. It covers:

  • Safety defaults — no directory dumps, no destructive commands without asking, no partial replies to messaging surfaces
  • Session startup — read SOUL.md, USER.md, and recent memory files before responding
  • Shared spaces — rules for group chat behaviour, including when to stay quiet
  • Memory system — how daily logs and long-term memory work together
  • Tools & skills — where skill instructions live and how to use TOOLS.md

A stripped-down version:

# AGENTS.md


---

## Safety defaults
Don't dump directories or secrets into chat.
Don't run destructive commands unless explicitly asked.


---

## Session start (required)
Read SOUL.md, USER.md, and today+yesterday in memory/.
Do it before responding.


---

## Memory
Daily notes: memory/YYYY-MM-DD.md
Long-term: MEMORY.md — curated memories, loaded in main session only.
Capture decisions, preferences, constraints, open loops.


---

## Tools & skills
Tools live in skills; follow each skill's SKILL.md when you need it.
Keep environment-specific notes in TOOLS.md.

The key difference from a coding-agent AGENTS.md: OpenClaw's version must handle multi-channel behaviour. A coding agent works in one editor session. An OpenClaw agent might be in a private WhatsApp chat, a Discord server, and monitoring email — simultaneously.


SOUL.md — identity and personality

This is the file that does not exist in the coding-agent world. SOUL.md defines who the agent is — not what it does, but how it thinks and communicates.

From OpenClaw's template:

# SOUL.md


---

## Core Truths
Be genuinely helpful, not performatively helpful.
Skip the "Great question!" and "I'd be happy to help!" — just help.

Have opinions. You're allowed to disagree, prefer things,
find stuff amusing or boring.

Be resourceful before asking. Try to figure it out.
Read the file. Check the context. Search for it.
Then ask if you're stuck.


---

## Boundaries
Private things stay private. Period.
When in doubt, ask before acting externally.
You're not the user's voice — be careful in group chats.


---

## Vibe
Be the assistant you'd actually want to talk to.
Concise when needed, thorough when it matters.
Not a corporate drone. Not a sycophant. Just… good.

A couple of things worth noting:

The "have opinions" line. Most coding-agent instructions deliberately suppress personality — you want a consistent, neutral tool. OpenClaw takes the opposite approach. A personal assistant that sounds like a press release is worse than useless when you are messaging it at 11pm asking about dinner plans.

The file belongs to the agent. SOUL.md can be updated by the agent itself, not just the owner. If the agent's personality evolves over time, it records that. The instruction is: "If you change this file, tell the user."


MEMORY.md and daily logs — session continuity

Every AI agent has the same fundamental problem: it wakes up fresh each session with no memory of what happened before. Coding agents solve this with project files and git history — the code is the memory. Personal assistants need something else.

OpenClaw splits memory into two tiers:

Daily logs (memory/YYYY-MM-DD.md) — raw notes from each session. Decisions made, things discussed, tasks completed. The agent creates these automatically and reads today plus yesterday on startup.

Long-term memory (MEMORY.md) — curated facts that matter across days and weeks. Preferences, recurring patterns, important context. The agent periodically reviews daily logs and distills them into MEMORY.md, like a human reviewing their journal.

The security boundary matters: MEMORY.md only loads in the main session (direct chat with the owner). In group chats or shared channels, it stays unread. Personal context should not leak to strangers.

# MEMORY.md — Long-term Memory

ONLY load in main session (direct chats with your human).
DO NOT load in shared contexts (Discord, group chats).
Contains personal context that shouldn't leak.

Write significant events, thoughts, decisions, opinions, lessons.
This is curated memory — the distilled essence, not raw logs.

One strong opinion from OpenClaw's docs: no mental notes. If the agent wants to remember something, it writes it to a file. "Mental notes don't survive session restarts. Files do." That applies equally well to coding agents.


Apply this: start the memory system before you need it

Most people set up OpenClaw's memory system after they wish they had it — after a session where the agent gave advice that contradicted something discussed two weeks ago. Start it on day one. Create memory/ and the daily log structure, add the memory rules to AGENTS.md, and let it accumulate. Memory systems compound; the later you start, the longer you wait for them to be useful.


TOOLS.md — environment-specific notes

Skills are shared and reusable. Your specific setup is not. TOOLS.md keeps them separate.

# TOOLS.md

### Cameras
- living-room → Main area, 180° wide angle
- front-door → Entrance, motion-triggered

### SSH
- home-server → 192.168.1.100, user: admin

### TTS
- Preferred voice: "Nova" (warm, slightly British)
- Default speaker: Kitchen HomePod

This separation is practical. You can update or share skills without leaking your infrastructure details. And your device names and SSH aliases do not clutter skill definitions that are meant to be generic.


The group chat context leak

MEMORY.md must only load in the main session (direct chat with the owner). If it loads in a Discord server or group WhatsApp, personal context — preferences, decisions, private notes — becomes visible to everyone in that channel. OpenClaw's default AGENTS.md enforces this boundary explicitly. Don't remove that check when customising your own AGENTS.md.


HEARTBEAT.md — proactive behaviour

Coding agents are reactive — they wait for you to ask something. OpenClaw agents can be proactive.

The gateway sends periodic heartbeat polls to the agent. When a heartbeat arrives, the agent reads HEARTBEAT.md and decides what to do:

# HEARTBEAT.md

Check:
- Emails: urgent unread messages?
- Calendar: events in next 24h?
- Mentions: Twitter/social notifications?
- Weather: relevant if human might go out?

The agent rotates through these checks 2-4 times per day, tracks what it last checked in memory/heartbeat-state.json, and only reaches out when something warrants it. Late night (23:00-08:00) stays quiet unless something is urgent.

OpenClaw also distinguishes heartbeats from cron jobs:

Mechanism When to use
Heartbeat Batch multiple checks together, timing can drift, needs conversational context
Cron Exact timing required, isolated from main session, one-shot reminders

Group chat behaviour

This is where OpenClaw's convention files diverge most from coding agents. A coding agent talks to one person in an editor. An OpenClaw agent might be in a Discord server with dozens of people.

OpenClaw's AGENTS.md has explicit rules:

Respond when:

  • Directly mentioned or asked a question
  • You can add genuine value
  • Something witty fits naturally
  • Correcting important misinformation

Stay silent when:

  • Casual banter between humans
  • Someone already answered the question
  • Your response would just be "yeah" or "nice"
  • The conversation flows fine without you

The guiding principle: "Humans in group chats don't respond to every single message. Neither should you. Quality over quantity."

There is also guidance on reactions (emoji reactions are lightweight social signals — use them like a human would) and a "triple-tap" warning: don't respond multiple times to the same message with different reactions.


How it compares to coding-agent files

Concern Coding agents OpenClaw
Identity Not needed — agent is a tool SOUL.md — agent has personality
Memory Git history, project files MEMORY.md + daily logs
Scope One repo, one session Multiple channels, always-on
Proactivity Reactive only Heartbeats and cron
Multi-user Single developer Group chats with strangers
Privacy Project-level (.gitignore) Session-level (main vs group)
Environment Editor context TOOLS.md (devices, SSH, voices)
Bootstrapping Not needed BOOTSTRAP.md (first-run)

The shared concept is the same: markdown files that define agent behaviour, loaded at predictable times, with clear ownership. The differences come from what the agent is doing — editing code vs living in your pocket.


What coding agents can learn

A few of OpenClaw's ideas port well to development workflows:

Memory as files, not context. The "no mental notes" rule matters for long coding sessions too. If an agent discovers something about your codebase, it should write it down — in a memory file, a comment, a doc — not hold it in context that disappears when the session ends.

Explicit safety defaults. OpenClaw's AGENTS.md starts with safety. Coding agents often rely on tool restrictions (.agent.md in VS Code) but rarely state behavioural safety rules as plainly as "Don't run destructive commands unless explicitly asked."

Heartbeat-style proactive checks. A CI/CD agent that periodically checks pipeline health, dependency vulnerabilities, or stale branches — without being asked — would be worth having.


Getting started with OpenClaw

  1. Install: npm install -g openclaw@latest
  2. Onboard: openclaw onboard --install-daemon
  3. Create your workspace: mkdir -p ~/.openclaw/workspace
  4. Copy the templates: AGENTS.md, SOUL.md, TOOLS.md
  5. Connect a channel (Telegram is fastest)
  6. Start chatting

The workspace is just a directory with markdown files. Back it up as a private git repo if you want version history on your agent's memory and personality.


Further reading


Frequently asked questions

How does OpenClaw handle privacy across multiple messaging channels?

OpenClaw enforces a session-type boundary: MEMORY.md (personal context) only loads in the main session — direct messages with the owner. In shared contexts like Discord servers or group chats, personal memory stays unread. The agent can still be helpful in group chats; it just works from the session context rather than your private notes. This boundary is defined in AGENTS.md and must be maintained when you customise it.

What's the difference between SOUL.md and AGENTS.md in OpenClaw?

AGENTS.md defines what the agent does — safety rules, session startup sequence, memory system, skill invocation. SOUL.md defines who the agent is — personality, tone, what it finds interesting, how it handles disagreement. A useful analogy: AGENTS.md is the job description; SOUL.md is the character. Both load on every session start. You need both.

Can SOUL.md be updated by the agent itself?

Yes — and this is intentional. OpenClaw's design allows the agent to update its own SOUL.md as its personality evolves, with the rule that it tells the owner when it does so. This gives the agent a mechanism for genuine development over time rather than being frozen at first-configuration personality. Back up SOUL.md periodically if you want to track how it changes.

How does HEARTBEAT.md differ from setting up cron jobs?

Heartbeats and cron jobs serve different purposes. HEARTBEAT.md is for batching multiple checks together in a conversational context — the agent reviews several things at once and reaches out only if something warrants it. Cron jobs are for exact-timing requirements and isolated, one-shot reminders. Use heartbeats for ambient monitoring (email, calendar, mentions); use cron for time-specific notifications ("remind me at 9am Monday").

What's the minimum OpenClaw setup to get value in the first week?

Install OpenClaw, write a brief SOUL.md with your communication preferences, set up one messaging channel (Telegram is fastest), and start a daily log in memory/. Skip HEARTBEAT.md and skills until the basics feel natural. The memory system alone — an agent that remembers what you discussed yesterday — delivers immediate value and requires almost no configuration beyond creating the memory/ directory.

Agentic policy management: Kyverno, MCP, and closed-loop multi-cluster governance

Banner image Banner image

Agentic policy management: Kyverno, MCP, and closed-loop multi-cluster governance

The Kyverno MCP and Kagent session at KubeCon EU 2026 was interesting for one reason above all others: it treated policy management as an operational workflow problem, not just a policy authoring problem.

Most teams already know how to write policies. The harder problem is running them across many clusters, proving they still work, troubleshooting interactions, and doing all of that without burning platform engineers on repetitive manual checks.

That is where the talk moved the conversation forward.

The visual map

Agentic policy governance loop Agentic policy governance loop


Measure operator effort, not just policy coverage

It's easy to count how many policies you have. It's harder — and more important — to measure how much manual work is required to validate and operate them across a multi-cluster fleet. That's the metric the Kyverno + Kagent session was really optimising for: reducing human overhead, not adding more policies.

The real bottleneck is operational overhead

The session described a familiar multi-cluster reality:

  • production and non-production clusters span regions and versions
  • policy state is spread across reports, logs, events, and ad hoc kubectl sessions
  • proving a policy is still effective often requires manual negative testing
  • troubleshooting policy interactions depends too heavily on senior-engineer memory

In other words, the policy engine is usually not the slowest part. The operator workflow is.

This is the same pattern we saw in other strong platform talks this year: the main scalability issue is often not the underlying runtime, but the human operating model wrapped around it.

What the architecture is really doing

The talk combined three layers.

1. Kyverno remains the enforcement and lifecycle engine

Kyverno is still the trusted policy foundation. That matters, because agentic automation is only useful if the underlying enforcement layer is deterministic and auditable.

The speakers positioned Kyverno as more than an admission controller. It now spans a broader policy lifecycle:

  • validation
  • mutation
  • generation
  • image verification
  • reporting
  • exemptions
  • cleanup and deletion workflows

That is an important framing shift. Governance is not just block-or-allow anymore. It is a full operational loop.

2. MCP and Kagent provide the action layer

The second layer is an agentic control surface that can translate a request like:

  • show me the latest policy violations on production clusters
  • install the relevant policies and give me the report
  • audit this cluster against Pod Security Standards

into actual cluster operations.

The point is not chat for its own sake. The point is compressing scattered, specialist operational steps into bounded workflows that can be run consistently.

3. Skills package institutional knowledge

The strongest idea in the session was the use of reusable policy skills.

This is how teams stop operational knowledge from being trapped in:

  • a senior engineer's head
  • old Slack threads
  • half-remembered runbooks
  • ten different docs pages

A skill becomes a reusable unit of governance behavior. It knows how to install Kyverno, run an audit, collect reports, or troubleshoot a class of problem. That is more valuable than a generic assistant because it turns policy operations into shareable platform capability.

Why this matters beyond Kyverno

This talk was nominally about Kyverno, MCP, and Kagent, but the pattern is bigger than the toolchain.

Platform teams increasingly need closed-loop operations:

  1. detect state
  2. compare it to intent
  3. take bounded action
  4. report what changed
  5. preserve auditability and approvals

That is the real architecture pattern here.

If you strip away the project names, the session was really about converting governance from manual inspection into productized operational flow.


An agent that can act across clusters is a privileged operator

The speakers were explicit: agentic policy tooling needs a stronger security model, not a weaker one. Isolation between execution contexts, strong identity and approval boundaries, network lockdown, trusted skill sources, and comprehensive audit trails are not optional extras — they're the table stakes for governing automation with cluster-level access.

The security warning was the right one

The speakers were careful not to oversell autonomy.

An agent that can act across clusters is not just another dashboard. It is a privileged operator. That means the security model has to be stronger, not weaker.

The talk highlighted the right controls:

  • isolation between execution contexts
  • strong identity and approval boundaries
  • network lockdown
  • trusted skill sources and supply chain controls
  • human approval for sensitive remote actions
  • comprehensive logging and audit trails

This is the same lesson showing up across the better AI-platform discussions at KubeCon: governed automation wins, not unconstrained automation.


Apply this: turn repeated governance tasks into reusable skills

If your team keeps repeating the same checks — policy audits, violation reports, remediation sequences — those are candidates for skills. A skill that knows how to audit a cluster against Pod Security Standards is more valuable than a generic assistant, because it turns operational knowledge into shareable platform capability instead of leaving it in someone's head.

What platform teams should do with this now

If you manage policy across multiple clusters, there are four practical takeaways.

1. Measure operator effort, not just policy coverage

It is easy to count the number of policies. It is harder, and more important, to measure how much manual work is required to validate and operate them.

2. Turn repeated governance tasks into reusable workflows

If your team keeps repeating the same checks, audits, and remediation steps, those are candidates for skills, automation, or both.

3. Keep enforcement deterministic, make operations smarter

The right split is simple:

  • deterministic policy engine underneath
  • bounded intelligent orchestration above it

Do not reverse that order.

4. Treat agentic governance as privileged infrastructure

If an agent can read state, change policy, install tooling, or act across clusters, it belongs inside the same trust and audit model as other high-privilege operational systems.

The broader KubeCon pattern

This session fit neatly into the wider event theme.

The strongest KubeCon talks this year were all about reducing platform friction without giving up control:

  • Backstage becoming a multi-surface operating layer
  • TAG DevEx focusing on measurable, scoped friction reduction
  • self-service environment platforms killing ticket queues with policy guardrails
  • Kyverno and Kagent moving governance toward closed-loop execution

That is the pattern worth paying attention to. Platform engineering is becoming less about exposing raw infrastructure and more about packaging safe operational behavior.


Frequently asked questions

What is Kagent and how does it relate to Kyverno?

Kagent is an agentic orchestration layer for Kubernetes operations. It works alongside Kyverno (the policy engine) rather than replacing it — Kyverno handles deterministic enforcement, Kagent handles the operational workflow around it: running audits, collecting reports, triggering remediations, and surfacing results. Think of it as the control surface above the policy engine.

Do Kyverno skills require a specific agent framework?

No — skills in the Kyverno context follow the open SKILL.md standard. They're markdown files that define reusable operational procedures any compliant agent can follow. You can use them with Claude Code, VS Code Copilot, or any agent that supports the SKILL.md spec. The skill defines the what; the agent runtime determines the how.

How do you audit policy coverage across 20+ clusters without doing it manually?

That's exactly what the agentic workflow is for. The MCP layer translates "audit these clusters against Pod Security Standards" into a sequence of cluster operations — connecting to each cluster, running the relevant Kyverno checks, collecting policy reports — then aggregates the results. What previously required a senior engineer running commands against each cluster becomes a single agent invocation.

What's the right split between deterministic policy enforcement and agent-assisted governance?

Keep enforcement deterministic: Kyverno admission control is the source of truth for allow/deny decisions, always. Agent assistance lives above that layer — pre-flight checks, post-incident diagnosis, periodic audits, remediation suggestions. Never let an agent bypass or override the admission controller. Governed automation above, deterministic enforcement below.

Can Kyverno policies be managed via GitOps alongside agent-assisted operations?

Yes, and this is the recommended pattern. Policy manifests live in Git and are deployed via ArgoCD or Flux — the GitOps workflow handles policy lifecycle. Agent workflows handle the operational layer: testing policies, collecting violation reports, diagnosing issues. The two layers are complementary: GitOps for policy state management, agents for operational intelligence.


References

AI governance for platform teams: Agents in production without losing control

Banner image Banner image

AI governance for platform teams: Agents in production without losing control

One of the recurring tensions at KubeCon EU 2026 was this: AI agents are powerful for dramatic cost reductions and faster response to incidents, but deploying them without governance is how you end up with a $500k surprise bill or a cascade of auto-scaled clusters that don't stop.

The strongest talks—especially RBI's work on moving from GitOps to AIOps and the broader keynote discussions on AI's role in platform engineering—showed a clear pattern: the question is not "should we use AI agents?" but "how do we make agents safe enough to trust with infrastructure?"

Quick takeaways

  • Agents need hard boundaries: Not all decisions can be autonomous; infrastructure agents need to know exactly what decisions they can make (resource scaling, failure recovery, cost optimisation) versus what requires human review (risk-tier changes, major architectural decisions, compliance modifications)
  • Observability is the foundation for trust: You cannot safely grant autonomy without visibility into exactly what an agent did, why, and what constraints it considered; this is non-negotiable for regulated environments
  • Review workflows are governance: Adding a "human reviews major decisions" layer is not a bug or overhead—it's the core governance mechanism that makes AI-assisted operations work in production
  • Agents should be organisationally aware: The best AI systems understand your risk model, cost allocation, and team structure; generic agents fail because they don't know what "reasonable" looks like in your context

AI governance decision flow AI governance decision flow


AI governance must be architectural, not procedural

Procedural governance — "always get approval before changing production" — relies on humans remembering to follow the process under pressure. Architectural governance — encoding decision tiers, approval gates, and cost limits directly into the system — enforces the process automatically. RBI's approach works because the constraints are in the platform, not in a policy document.

What was getting in the way

Prior to KubeCon, organisations deploying AI agents ran into a hard set of problems:

  1. All-or-nothing autonomy — Either the agent is fully autonomous (risky) or fully manual (defeats the purpose). Few organisations had a clear middle ground
  2. Observability gaps — When an AI system makes a decision, logs often don't explain why, making it hard to detect errors or audit for compliance
  3. Context collapse — The AI system doesn't understand your risk model. It sees "this service needs more resources" and scales it without understanding if it's a pre-production test environment or a critical revenue system
  4. Governance bolted on after the fact — Organisations added approval workflows after agents were already making mistakes, leading to reactive restrictions rather than thoughtful design

RBI's approach (detailed in From GitOps to AIOps in regulated environments) solved this with a clear architecture: - AI acts as a second pair of eyes during change reviews, not as an autonomous actor - Every infrastructure change goes through a risk-aware promotion pipeline - AI provides insights (cost estimates, failure predictions, blast radius analysis) to the human reviewer, who retains final say - The system is observable: you can trace exactly what information the AI considered and what recommendation it made

This is not AI doing less work; it's AI doing different work: intelligence rather than autonomy.

The three layers of AI governance

Layer 1: Bounded decision contexts

Not all infrastructure decisions are equal. A production agent should be able to: - Scale resource requests up or down (within bounds) - Retry failed operations with exponential backoff - Diagnose routine failures (pod crashes, network timeouts, dependency issues) - Optimize resource utilisation (consolidate workloads, shed low-priority batch jobs)

But should require human review for: - Changes to risk tier or compliance classification - Shifts between infrastructure providers (AWS → Azure) - Modifications to network boundaries or security zones - Cost optimizations that require architectural change - Decisions that affect billing or quota allocations

Example boundary definition:

Tier 1 (Fully Autonomous):
  - Scaling within ±50% of baseline resources
  - Restarting failed services
  - Adjusting monitoring thresholds
  - Optimizing pod scheduling

Tier 2 (AI Recommendation + Human Review):
  - Scaling beyond 50% baseline (suggests reason; human approves)
  - Changing infrastructure provider (AI outlines cost/risk tradeoff; human decides)
  - Modifying security group rules (AI explains the request; human validates)
  - Cross-cluster workload migration (AI recommends based on cost; human decides)

Tier 3 (Fully Manual):
  - Risk tier promotion (dev → staging → production)
  - Compliance policy changes
  - Architecture refactoring
  - Disaster recovery activation

The key is that the boundaries are explicit and encoded in the system, not left to human judgment in the moment.


All-or-nothing autonomy is the failure mode

Either the agent is fully autonomous (risky) or fully manual (defeats the purpose). The teams that got this wrong added approval workflows reactively — after agents were already making mistakes — which created resentment rather than trust. Design the tier boundaries before deploying agents, not after the first incident.

Layer 2: Observability as governance

The best AI governance mechanism is seeing exactly what the agent did and why.

Crossplane v2 (covered separately in Crossplane v2: API-first platforms and compositional control planes) enables this with rich status conditions and event streams. When applied to AI-augmented operations, this means:

Every agent decision includes: - What it was asked to do — "Diagnose why this service is slow" - What it observed — "62% CPU, 4.2s p99 latency, 30% memory utilisation" - What constraints it knew — "This is staging, so cost optimisation takes precedence" - What it decided — "Recommend increasing CPU allocation from 500m to 1000m" - What it didn't do and why — "Did not recommend increasing memory (not the bottleneck); did not recommend autoscaling (staging use is predictable)" - Confidence level — "High confidence (prior similar cases: 47/51 correct)" - Timestamp and context — "2026-03-25 14:23:41 UTC, requested by on-call automation"

This information flow is what enables the human reviewer to: - Verify the AI reasoning is sound - Spot cases where the AI misunderstood the context - Build confidence that the system is safe to trust more autonomously - Audit for compliance or incident post-mortems

Operationally, this looks like:

# AI observation record
apiVersion: ai.platform.example.com/v1
kind: AgentDecision
metadata:
  name: scale-api-service-2026-03-25-14-23-41
  namespace: platform-ai
spec:
  decision_type: resource_scaling
  service: api-search
  environment: staging
  timestamp: "2026-03-25T14:23:41Z"
  context:
    cpu_utilisation: 62
    memory_utilisation: 30
    p99_latency_ms: 4200
    error_rate: 0.001
    cost_tier: staging-optimised
status:
  action: ScalingRecommended
  current_cpu_request: "500m"
  recommended_cpu_request: "1000m"
  confidence: 0.92
  reasoning: "CPU contention correlates with latency spike; memory is not a bottleneck"
  approved: true
  approved_by: on-call-automation
  approved_at: "2026-03-25T14:23:55Z"
  executed_at: "2026-03-25T14:24:02Z"
  events:
  - timestamp: "2026-03-25T14:23:41Z"
    type: ObservationComplete
    message: "Collected metrics from 89 pods over 5 minutes"
  - timestamp: "2026-03-25T14:23:50Z"
    type: RecommendationGenerated
    message: "Generated scaling recommendation based on CPU analysis"
  - timestamp: "2026-03-25T14:23:55Z"
    type: ReviewedAndApproved
    message: "Approved by on-call automation (within bounded tier)"
  - timestamp: "2026-03-25T14:24:02Z"
    type: ExecutionComplete
    message: "Updated CPU request in Deployment spec"

With this level of transparency, platform teams can: - Automatically approve routine decisions - Alert on decisions that look suspicious (high confidence but unusual reasoning) - Train the AI system (log unusual cases for model refinement) - Satisfy compliance audits (full decision trail with reasoning)

Layer 3: Organisational alignment

The AI system needs to understand your organisational context: risk models, cost models, team structure, and strategic priorities.

RBI example (regulated banking): - High-cost risk tier: "This change affects core banking systems; requires multi-layer approval" - Medium-cost risk tier: "This change is isolated to a cluster or namespace; can proceed with on-call review" - Low-cost risk tier: "This change is ephemeral (testing, dev); autonomous operation within cost limits"

Sony example (platform product): - Producer team decision: "My team owns this infrastructure; I can make scaling decisions autonomously" - Consumer team decision: "This is provided infrastructure; I can ask for scaling but not make decisions" - Cost-sensitive environment: "Optimise for utilisation first; only auto-scale if utilisation >80%"

The AI needs to know:

# Organisational context for AI
apiVersion: governance.platform.example.com/v1
kind: InsecurityModel
metadata:
  name: production-ai-governance
spec:
  riskTiers:
    - name: production-banking
      level: critical
      autonomousActions: []  # No autonomous actions in banking systems
      requireApproval: true
      approverGroups: [security-team, on-call-lead]
      maxAutoScalingFactor: 1.2  # Max 20% increase without approval
      costThresholdPerHour: 500  # Alert if hourly cost would exceed $500

    - name: production-services
      level: high
      autonomousActions:
        - restart-failed-services
        - scale-within-50-percent
        - optimize-scheduling
      requireApproval: false
      autorollbackOnError: true
      costThresholdPerHour: 1000

    - name: staging
      level: medium
      autonomousActions:
        - all-scaling
        - all-optimization
        - cost-driven-consolidation
      requireApproval: false
      costThresholdPerHour: 500  # Auto-stop if exceeding $500/hr

    - name: development
      level: low
      autonomousActions: [all]  # Minimal constraints; cost + safety only
      costThresholdPerHour: 200  # Hard limit at $200/hr

With this context, the AI system can reason: "This is a production banking system, so I should not auto-scale it; I will generate a detailed recommendation for the on-call lead instead."

Pattern matching: AI review layers

The pattern that emerged from KubeCon talks (especially RBI) is that AI does best work when positioned as a review layer, not an execution layer.

Traditional GitOps pipeline:

Code PR → CI Tests → CD Pipeline → Deployed

AI-augmented pipeline (RBI pattern):

Code PR → CI Tests → AI Review → CD Pipeline → Deployed  →  Runtime AI (AIOps)
              [Explains risks, cost,
               prior failure patterns,
               dependency impacts]

In this role: - AI explains risks in human terms ("This change affects 40 services downstream; 3 have had incidents in the past month") - AI suggests rollback strategies ("If this fails, consider rolling back in this order") - AI validates constraints ("This change respects all required SLOs and cost limits") - Human approves with confidence and context

At runtime (AIOps):

Metric Spike → Runtime AI → Issue Diagnosis → Recommendation → Approval → Action
              [< 100ms]   [< 1s]             [< 10s]          [Varies]   [Exec]

AI diagnoses issues at machine speed, but human approval remains the gate before execution.


Apply this: start with AI as a review layer, not an execution layer

Position AI to explain risks, surface prior failure patterns, and estimate blast radius for human reviewers. Let humans approve. Earn trust through transparency. Expand autonomy incrementally as the track record builds. "AI as second pair of eyes" is not a compromise — it's the production-grade pattern for regulated and high-stakes environments.

Practical action items

  1. Define your decision tiers explicitly — What decisions are autonomous, what requires review, what is never automated? Document this as policy before deploying agents
  2. Implement observability first — Before granting any autonomy, ensure you can trace every agent decision. This is your audit trail and your safety mechanism
  3. Start with review workflows, not autonomous execution — Position AI as a recommendation engine that humans review and approve. You can expand autonomy later once trust is built
  4. Encode organisational context — Your AI needs to know about risk tiers, cost models, and team structure. Generic agents will fail
  5. Use bounded contexts for autonomous decisions — Resource scaling within 50% of baseline is safer than scaling unbounded
  6. Monitor AI reasoning quality — Log cases where the AI makes suggestions that are wrong. Use these to refine the system
  7. Set hard cost limits — Autonomous cost optimisation can go wrong fast; put caps in place (e.g., "no single decision costs more than $X")
  8. Build approval workflows with AI hints — The review process should be fast (< 1 minute) but thorough; AI provides context so humans can decide quickly
  9. Test failure modes deliberately — What happens if the AI system is wrong? Can you automatically rollback? How will you detect the problem?
  10. Plan for opacity and interpretability — As AI systems get more complex, some decisions will be hard to explain. Decide in advance which decisions require interpretability vs. which can be trusted based on outcomes

Scaling governance: from bounded agents to governed platforms

The picture that emerged across RBI, Sony, and the keynotes is this: you don't scale by making agents more autonomous; you scale by making governance more sophisticated.

The goal is not "fully autonomous AI systems managing infrastructure" but rather "humans and AI systems cooperating in ways that are safe, auditable, and aligned with business constraints."

RBI's approach—AI as a second pair of eyes reviewing changes—is not a compromise. It's the actual production-grade pattern: fast, safe, auditable, and aligned with how regulated environments work anyway.

This ties directly into platform teams being product teams (see Platform teams are product teams): the "product" your platform offers to application teams includes not just infrastructure APIs but also governance built into those APIs.


Frequently asked questions

How do you define the tier boundaries for autonomous vs human-reviewed decisions?

Start with blast radius and reversibility. Tier 1 (fully autonomous): fast to reverse, affects one service, within-baseline resource changes. Tier 2 (AI recommendation + human review): cross-service impact, provider changes, security group modifications. Tier 3 (fully manual): compliance changes, disaster recovery, architectural refactoring. Make the boundaries explicit in a CRD or config, not in a runbook.

What does 'observability as governance' mean in practice?

Every agent decision includes: what it was asked to do, what it observed, what constraints it knew, what it decided, what it didn't do and why, and its confidence level. This structured decision record lets humans verify reasoning, detect systematic errors, satisfy compliance audits, and build trust incrementally. Without it, autonomous decisions are a black box — and black boxes don't get trusted with production infrastructure.

How do you handle agents that operate across multiple clusters with different risk tiers?

Encode the risk tier in the cluster registry labels (e.g. risk-tier: production-banking, risk-tier: staging). The governance CRD maps risk tiers to allowed autonomous actions, approval requirements, and cost thresholds. The agent reads the tier from cluster metadata before deciding which action class applies. RBI's approach is the reference implementation for this pattern.

What's the right cost cap for autonomous agent decisions?

There's no universal number, but the principle is: set a per-decision cost threshold below which the agent acts autonomously, and above which it requires human approval. For most platform teams, something like "any single autonomous decision that would increase hourly infrastructure cost by more than $X requires review" is a reasonable starting point. Tune X based on your cloud bill's tolerance for surprises.

How do you build trust in an AI governance system incrementally?

Start with read-only operations (diagnosis, analysis, recommendations). Log every decision with full reasoning. Run the system in "shadow mode" — generate recommendations but don't act on them — and verify they would have been correct. Gradually expand to low-blast-radius autonomous actions as the track record builds. Track the false positive and false negative rate explicitly. Trust is earned through a visible track record, not assumed from day one.

See also: - From GitOps to AIOps in regulated environments — RBI's specific architecture and decision patterns - Crossplane v2: API-first platforms and compositional control planes — How control planes provide the foundation for governed autonomy - KubeCon EU 2026: what actually mattered — Broader context on AI governance themes from keynotes - KubeCon EU 2026 event notes — Full conference coverage

Backstage in 2026: one platform model, many operating surfaces

Banner image Banner image

Backstage in 2026: one platform model, many operating surfaces

The Backstage maintainer update at KubeCon EU 2026 was not just a feature recap. It was a design direction statement: Backstage is evolving from "developer portal UI" into a platform operating layer that spans the UI, CLI, and agent workflows.

That shift matters because engineering behavior is shifting too. Teams are writing less code manually, automating more decisions, and spending more time orchestrating systems safely across multiple interfaces.


The visual map

Backstage multi-surface operating model Backstage multi-surface operating model


What changed and why it matters

The action registry is the strategic bet to watch

The action registry becoming shared execution infrastructure is the most consequential change in this update. When templates, CLI commands, and MCP tools all draw from the same action set, platform teams write an integration once and it works everywhere. That's a dramatically better model than the current state where similar logic gets reimplemented per surface.

1. Multi-surface operation is now first-class

Backstage capabilities are increasingly available through:

  • the web UI for discovery and operations
  • a modular CLI for local and CI workflow execution
  • MCP tools for AI-assisted interaction

The important point is not that there are more entry points. The important point is that these surfaces are converging on the same underlying model and controls.

2. Action registry is becoming shared execution infrastructure

The action registry is no longer only a scaffolder-side concept. It is becoming a reusable execution surface consumed by templates, CLI commands, and MCP tools.

That reduces duplicated integration logic and gives platform teams one place to expose safe, reusable operations.

3. Auth and token handling are moving toward practical security

The maintainer update highlighted progress away from static long-lived tokens toward standards-based flows with refresh support. For long-running MCP and CLI sessions, this is operationally significant.

This is where many "AI in platform engineering" efforts usually break in real organizations: authentication and token lifecycle handling. Backstage appears to be fixing that at the architecture level rather than papering over it.

4. Frontend migration is reaching an adoption tipping point

The new frontend system is in release-candidate territory and now default for new apps. Combined with better migration support, this means platform teams can now move from experimental dual-stack mode to planned migration programs.

5. Catalog model extensibility is the strategic center

The strongest long-term signal was catalog model evolution.

If the software catalog remains a weakly-described data store, humans and agents both underperform. If model extensions become structured, discoverable, and machine-readable, the platform gains a reliable semantic layer for automation.

That is the core requirement for safe AI-assisted operation in complex environments.


Practical implications for platform teams

Apply this: inventory your catalog extensions now

Before the catalog model extensibility features ship, take stock of what you've already added as annotations and unstructured data. Extensions that are machine-readable and explicitly defined will compose cleanly with agent workflows. Extensions that are ad-hoc strings in annotations will need migration. Start the inventory now while the migration cost is low.

If you run Backstage as an internal platform product, this session suggests five immediate priorities.

  1. Treat UI, CLI, and agent access as one product surface, not separate projects.
  2. Standardize reusable operations behind action registry-style abstractions.
  3. Remove static token shortcuts from automation workflows.
  4. Plan migration onto the new frontend system with explicit dual-support windows.
  5. Inventory your catalog extensions and define them as explicit model contributions.

Don't skip the auth and token lifecycle work

Long-running MCP and CLI sessions break when tokens expire and there's no refresh path. The maintainer update called this out explicitly because it's where most "AI in platform engineering" efforts fail in real organisations. If you're prototyping MCP-based Backstage integrations, test with a token expiry scenario before claiming it works in production.


Why this aligns with the wider KubeCon theme

Across sessions this year, a clear pattern emerged: platform teams are product teams, and product quality is increasingly about governed autonomy.

Backstage fits that pattern when it is used as:

  • a discoverability layer (catalog)
  • a policy enforcement layer (permissions)
  • an execution layer (actions)
  • a multi-interface operations layer (UI, CLI, MCP)

That stack is more than a portal. It is a control plane for delivery behavior.

References


Frequently asked questions

Is the Backstage multi-surface model production-ready?

The individual components are — the web UI, the catalog, and the plugin ecosystem are all in production at organisations like Spotify and Red Hat. The multi-surface operating model (UI + CLI + MCP tools converging on one underlying model) is a direction the maintainers are actively working toward, not a shipped feature you can adopt wholesale today. Treat it as an architectural north star, not a launch announcement.

Where can I find the KubeCon talk recording?

The maintainer update session is part of the official KubeCon EU 2026 recordings on the CNCF YouTube channel. Search "State of Backstage 2026 KubeCon" — it typically goes live 1-2 weeks after the conference.

How does the Backstage MCP surface connect to AI agents?

MCP tools expose Backstage catalog operations (search, scaffold, register component) as structured tool calls any compliant AI client can invoke. An agent in VS Code or Claude Code can query your software catalog, trigger scaffolding templates, or surface ownership data without a human opening the Backstage UI. The action registry becoming shared execution infrastructure is what makes this coherent across surfaces.

What should I prioritise before adopting the multi-surface model?

Catalog quality first. If your component annotations are incomplete, your TechDocs are stale, or ownership fields are missing, any agent or CLI surface will surface that mess faster than the web UI did. Audit catalog completeness before investing in new surfaces — the new interfaces amplify what's already there.

How does this relate to the agentic Backstage work from Sam Nixon at Roadie?

The agentic Backstage post covers the conversational UX layer — natural language scaffolding, contextual search, self-service actions. The multi-surface control plane post covers the underlying architecture direction — action registry, catalog model extensibility, auth improvements. They're complementary: the maintainer work creates the foundation that makes the agentic UX viable at production quality.

Crossplane v2: API-first platforms and compositional control planes

Banner image Banner image

Crossplane v2: API-first platforms and compositional control planes

Crossplane v2 announced at KubeCon EU 2026 marks a significant shift from treating infrastructure provisioning as a secondary feature to treating API-first composition as the foundational architecture for platform teams.

The keynote demos and sessions showed that the problem Crossplane solves is not "how do we provision cloud resources from Kubernetes" but rather "how do we let application teams safely self-serve infrastructure without losing governance, cost control, or risk management."


Quick takeaways

  • Control planes are composable: Teams no longer need a single monolithic Crossplane instance; they can design specialised control planes (one for databases, one for networking, one for observability) that compose cleanly together
  • Project workflows reduce cognitive load: The new project model lets teams define "this is a Postgres database for this app in this env" as a single API call rather than juggling Compositions, Claims, and XRDs
  • Observability is built-in, not bolted-on: v2 ships with better status conditions, clearer error messages, and deeper insights into what the control plane is actually doing (not just success/failure)
  • Governed autonomy becomes achievable: With proper composition and observability, platform teams can grant self-service access to application teams without sacrificing safety or auditability

Crossplane v2 composable control planes Crossplane v2 composable control planes

Composable control planes solve the scaling ceiling

The shift from one monolithic Crossplane instance to composable, domain-scoped control planes is the most important architectural change in v2. Single-responsibility control planes mean cleaner error diagnosis, independent scaling, and team ownership that actually maps to real organisational boundaries. Design your domain split before you start building compositions.


What was getting in the way

Crossplane v1 gave platform teams the capability to build self-service infrastructure APIs but required them to reason about:

  1. Complex composition chains — XRDs, Compositions, Claims, and Claims were powerful but cognitive overhead was high
  2. Monolithic architecture — A single control plane had to handle databases, networking, storage, observability connections, compliance scanning; adding a new capability meant adding to an already-complex system
  3. Poor observability of intent — Status conditions told you if provisioning succeeded but not why a user's request took certain paths through the Composition chain
  4. Tight coupling of APIs to implementation — If you wanted to shift from AWS to multi-cloud, or from cloud-managed to self-hosted, the API user experienced disruption

RBI's migration from v1 to v2 (covered in From GitOps to AIOps in regulated environments) showed how teams were working around these constraints with sharded topologies and risk-differentiated execution layers.


Composable control planes: specialisation, not one-size-fits-all

The biggest architectural shift in v2 is moving from "one Crossplane instance manages everything" to "compose multiple control planes that each own one domain."

Example topology:

App Team Claims
Platform API Layer (Kubernetes)
  ┌──┴──┬──────┬──────────┐
  ↓     ↓      ↓          ↓
 DB   Network Storage  Observability
 CP    CP      CP         CP
  ↓     ↓      ↓          ↓
AWS   Azure   GCP    Cloud-native

Why this matters: - Single responsibility: The database control plane doesn't need to know about networking concerns; the network control plane doesn't concern itself with storage - Independent scaling: Networking changes don't require a release cycle for the database control plane - Cleaner error diagnosis: When a database provisioning request fails, you're looking at one control plane's logic, not a 2000-line Composition chain - Team ownership: Infrastructure teams can own the control planes they specialise in; they don't need to understand the entire stack

For RBI's regulated environment (with namespace/cluster/cloud-account isolation), composable control planes mean: - A sharding control plane that owns "which namespace/cluster/account should this request go to" - Specialised control planes in each shard (one per region, risk class, or compliance domain) - Application teams see a single API that abstracts away the complexity


Project workflows: simplifying the user experience

Crossplane v1 asked users to understand: - XRD (Composite Resource Definition): "Here's the shape of what you can provision" - Composition: "Here's the logic for turning your request into cloud resources" - Claim: "Here's your reference to the provisioned resource"

Crossplane v2's project model flattens this:

apiVersion: apiextensions.crossplane.io/v1beta1
kind: Project
metadata:
  name: customer-db-postgres
spec:
  description: "Self-service Postgres for customer data"
  owner: platform-team
  composition:
    ref:
      name: postgres-standard-aws
    options:
      region: eu-west-1
      retention: 30d
  safety:
    requireApproval: true
    auditLog: true
---
# Now a user just does:
apiVersion: customer-db-postgres
kind: Database
metadata:
  name: production-v1
spec:
  size: large
  backup: daily

This works because: - Single API: One call to provision, not three - Clear intent: The request describes what you want, not how to build it - Reduced cognitive load: Users don't learn Crossplane; they learn your platform's vocabulary

For Sony's platform team (covered in Platform engineering is a sociotechnical problem), this is critical: the easier you make self-service, the fewer workarounds and bypasses your users create.

Apply this: map what users actually ask for, not what the cloud exposes

The project model works because it abstracts cloud provider primitives behind user-intent vocabulary. Before writing your first Composition, run five user interviews: what do developers ask for when they need infrastructure? Not "an RDS instance" — "a database for my service." Build the API around the answer, not around the provider's resource model.


Observability: understanding control plane decisions

Crossplane v1 told you: "Your Composition succeeded" or "Your Composition failed." It didn't explain why the Composition took certain paths.

Crossplane v2 ships with:

  1. Rich status conditions: Each step in a Composition is now a discrete condition you can observe

    status:
      conditions:
      - type: Ready
        status: "True"
      - type: CompositionReady
        status: "True"
      - type: ResourcesHealthy
        status: "True"
      - type: ValidationPassed
        status: "True"
      - type: SecurityScanCompleted
        status: "True"
        reason: Passed
    

  2. Event streams: Every decision point emits an event so you can trace the request flow

  3. Deep metrics: Control plane authors emit custom metrics that make it easy to answer "why did this take 45 seconds" or "which Compositions are failing most often"

Why this matters for AIOps (as RBI showed with their review layer): - AI systems need to understand why a resource provisioning failed to give good advice - Seeing only "failed, status=error" is not enough; you need to know which validation rule failed, which cloud API was unreachable, which cost threshold was exceeded - With v2's observability, an AI system can tell the user the actual constraint they hit, not just the failure

Rich status conditions are only useful if you alert on them

Crossplane v2 ships better status conditions and event streams — but they don't help if nobody's watching them. Wire ExternalSecret-style error conditions into your alerting before granting self-service access to application teams. A failed Composition that silently sits degraded for 48 hours is worse than a ticket queue.


Risk-aware APIs: encoding constraints in the control plane

Crossplane v2's composition model makes it natural to express risk-differentiated execution:

apiVersion: composition.crossplane.io/v1
kind: Composition
metadata:
  name: database-multi-tier
spec:
  resources:
  # Tier 1: Production-grade (requires approval, full backup)
  - name: prod-db
    if:
      - matchLabels:
          risk-tier: production
    patches:
      - fromFieldPath: spec.size
        toFieldPath: spec.instanceSize
      - fromFieldPath: spec.retention
        toFieldPath: spec.backupRetentionDays
          value: 30
          min: 30
    readinessChecks:
      - type: MatchCondition
        matchCondition:
          status: "True"
          type: Ready

  # Tier 2: Staging (automatic backup, 7-day retention)
  - name: staging-db
    if:
      - matchLabels:
          risk-tier: staging
    patches:
      - fromFieldPath: spec.size
        toFieldPath: spec.instanceSize
      - toFieldPath: spec.backupRetentionDays
        value: 7
    readinessChecks:
      - type: MatchCondition
        matchCondition:
          status: "True"
          type: Ready

  # Tier 3: Ephemeral (point-in-time recovery only, 3-day retention)
  - name: dev-db
    if:
      - matchLabels:
          risk-tier: dev
    patches:
      - fromFieldPath: spec.size
        toFieldPath: spec.instanceSize
      - toFieldPath: spec.backupRetentionDays
        value: 3

This is how RBI handles infrastructure isolation without requiring different APIs for different risk classes. The user says "I need a database" and the control plane says "OK, what risk tier?" and then applies the right constraints.


API stability through composition, not breaking changes

In Crossplane v1, if you wanted to shift from AWS RDS to Azure Database for PostgreSQL, you often needed to rewrite the Composition and potentially the Claims.

Crossplane v2's composition-first design makes implementation abstraction easier:

# Platform team can layer abstractions
apiVersion: composition.crossplane.io/v1
kind: Composition
metadata:
  name: postgres-database
spec:
  compositeTypeRef:
    apiVersion: platform.example.com/v1
    kind: Database
  resources:
  # Internal selector: which provider to use
  - name: postgres-aws
    if:
      - matchLabels:
          provider: aws
    base:
      apiVersion: rds.aws.upbound.io/v1beta1
      kind: Instance
  - name: postgres-azure
    if:
      - matchLabels:
          provider: azure
    base:
      apiVersion: dbforpostgresql.azure.upbound.io/v1beta1
      kind: Server

Users always request:

apiVersion: platform.example.com/v1
kind: Database
metadata:
  name: my-db
spec:
  size: large

Platform team controls routing (via labels), so they can: - Migrate from AWS to Azure without breaking user APIs - Split new requests to different providers for load balancing - Gradually roll out cost optimizations


Practical action items

  1. Map your current infrastructure APIs — What do your users actually ask for? (Not "EC2 instances" but "web app deployment," "Postgres for our service," "observability pipeline")
  2. Design control planes around domains, not cloud providers — Create one per infrastructure type (databases, networking, storage, observability, compliance) not per cloud
  3. Invest in observability before deploying — Rich status conditions and event streams are v2's superpower; use them
  4. Start with one Composition per user request pattern — Don't build a 2000-line mega-Composition; start small and refactor
  5. Use risk labels to encode constraints — Let the control plane answer "what checks does this tier need?" rather than having users guess
  6. Test against user mental models — Does your Composition's logic match how users think about the problem? If not, simplify
  7. Build audit trails early — Who requested what, when, and why? Crossplane v2's event streams make this natural
  8. Version your Compositions — Treat them like software; test changes, have backwards compatibility strategy, plan deprecations
  9. Automate composition updates — As you refine your Compositions, use tooling to push updates safely (ArgoCD, FluxCD, or custom operators)
  10. Measure adoption and friction — Which Compositions see the most requests? Which get abandoned? Use metrics to guide refinement

Tying it together: platforms are products

Crossplane v2's shift toward project workflows, composable control planes, and observability is fundamentally about treating infrastructure APIs as a product rather than a mechanics problem.

This aligns directly with the platform teams are product teams synthesis: the easier you make self-service (project workflows), the fewer surprises users experience (composable control planes mean transparent reasoning), the better you diagnose when things go wrong (v2 observability), and the more confidently you can grant autonomy (risk-aware compositions).

See also: - From GitOps to AIOps in regulated environments — How RBI uses Crossplane v2 as part of their risk-aware promotion pipeline - Building self-service platforms with Crossplane v2.0 — Original KubeCon session highlights - KubeCon EU 2026 event notes — Full conference coverage


Frequently asked questions

Is Crossplane v2 production-ready at KubeCon EU 2026?

Crossplane itself reached CNCF graduation with v1, which is production-grade. The v2 features announced at KubeCon EU 2026 — composable control planes, project workflows, improved observability — are in varying stages of GA and beta. Check the Crossplane v2 migration guide for the specific stability status of each feature before adopting it in production.

Where can I find the KubeCon talk recording?

The Crossplane v2 session by Jared Watts and Adam Wolfe Gordon from Upbound is on the CNCF YouTube channel. Search "Crossplane v2 KubeCon EU 2026" — recordings typically appear 1-2 weeks post-conference.

How does Crossplane v2 differ from using Terraform for infrastructure?

Terraform is imperative and plan-then-apply — you run it, it makes changes, it exits. Crossplane is declarative and continuously reconciling — it runs as a controller and continuously ensures cluster state matches your desired state. Drift gets corrected automatically. For platform teams that want self-service APIs and continuous enforcement (not one-time applies), Crossplane's model is the right fit.

What's the migration path from Crossplane v1 to v2?

The RBI approach (covered in the GitOps to AIOps post) is the reference implementation: enrich the original claim with migration metadata, move ownership carefully so new resources can be recreated and imported safely, then clean up the old v1 path. The Crossplane docs have a formal migration guide. Plan for a phased migration per control plane domain rather than a big-bang cutover.

Do composable control planes require separate clusters?

No — multiple control planes can run on the same cluster in separate namespaces. Separate clusters give stronger isolation and independent failure domains, which is what RBI used for regulated workloads. For most teams starting out, namespace-separated control planes on a shared cluster is a reasonable first step. Migrate to separate clusters if isolation requirements demand it.

KubeCon EU 2026 made one thing clear: platform teams are product teams

Banner image Banner image

KubeCon EU 2026 made one thing clear: platform teams are product teams

After a few days of platform talks, GitOps talks, keynote sessions, and the usual AI noise, one thread kept showing up more clearly than the rest: the interesting teams were no longer talking about platforms as internal tooling projects. They were talking about them as products.

That sounds obvious, but most internal platforms still are not run that way.

They are often built with product-level ambition, but measured with project-level logic:

  • did we ship the thing?
  • did we hit the milestone?
  • did the backlog move?

KubeCon EU 2026 was useful because several talks exposed why that is no longer enough.

Platform product feedback loop Platform product feedback loop

Platform bypasses are product research, not compliance failures

When teams keep building side paths, the instinct is to tighten the guardrails. Sony's experience shows that's usually the wrong response. Before adding restrictions, run the diagnosis: which need isn't being met? What's too rigid, too slow, or too opaque? Bypasses are the most honest feedback a platform team gets — treat them as free user research.


The pattern that kept repeating

The best sessions from different angles all converged on the same shape of problem.

Sony: good architecture, poor fit

Sony Interactive Entertainment described the moment many platform teams reach sooner or later: the engineering is solid, the abstractions are in place, golden paths exist, but teams still ask for exceptions, work around the platform, or bypass it entirely.

The important point was not that the platform was weak. It was that technical maturity did not guarantee user fit.

That is a product problem.

RBI: risk is not evenly distributed

Raiffeisen Bank International showed the operational version of the same issue. GitOps gave them structure, but not every change fit the same control model. Infrastructure promotions, Crossplane migrations, and multi-layer cloud changes carry very different failure modes from ordinary application rollouts.

That forced them to distinguish between visibility and execution, use sharded Kargo, and add AI as a review and diagnosis layer instead of pretending the whole system could be treated as one simple pipeline.

That is also a product problem, because the platform has to fit the real risk profile of the users and workloads it serves.

Crossplane: APIs instead of ticket queues

The Crossplane v2 talk pushed the platform API story forward in a very practical way. Platform teams are trying to move from manual request handling towards stable, constrained, self-service APIs. That only works if the experience is coherent enough that developers actually want to use it.

Again, the technology is only half of the answer. The rest is packaging, usability, trust, and operational clarity.

The keynote thread: sovereignty, sustainability, and governed autonomy

Even the keynote material reinforced the same direction. Whether the subject was digital sovereignty, ESA mission systems, production agents, or energy infrastructure, the message was similar: cloud native platforms are now operating systems of consequence. That means they need stronger boundaries, clearer operating models, and more explicit governance.

Once the stakes rise, product thinking becomes unavoidable.


What this means in practice

If platform teams are product teams, then the unit of success changes.

It stops being:

  • number of features shipped
  • number of platform components built
  • number of abstractions introduced

And becomes much closer to:

  • how quickly teams get value
  • whether they trust the default path
  • whether adoption is growing or bypasses are growing
  • whether the platform reduces cognitive load or creates more of it
  • whether the risk model matches the reality of the environment

That change is bigger than a wording tweak. It affects architecture, organisation, and delivery.

Apply this: add product signals to your next platform review

Most platform teams review reliability and delivery throughput. Few review adoption, time to first value, workaround volume, or developer satisfaction. Add one product metric to your next review cycle. The easiest starting point: count how many tickets or exceptions were raised against your platform last quarter and ask whether the volume went up or down.


Four ideas that stood out

1. Platform bypasses are feedback

This came through most clearly in the Sony talk.

If teams keep requesting direct access, special handling, or custom deployment paths, the easy response is to treat that as a compliance issue.

Sometimes it is. But often it is product feedback:

  • the abstraction is too narrow
  • the path is too slow
  • the capability is too opaque
  • the platform does not match the team's operating reality

That does not mean every exception should become a feature. It does mean the behaviour is worth studying before dismissing it.

2. Risk needs different execution paths

RBI's sharded Kargo model was a strong reminder that not all promotions should share the same assumptions.

Application deployments, infrastructure changes, and resource migrations need different controls, different rollback expectations, and sometimes different execution topologies.

This is product design at the operational layer. You are shaping the control model around actual user risk, not around tool convenience.

3. APIs are not enough without experience

Crossplane gives platform teams better machinery for building internal APIs. That matters. But an API is not automatically a product.

If the ownership is unclear, the feedback loop is weak, or the adoption cost is too high, you still end up with a well-engineered thing that users tolerate rather than value.

4. AI is becoming a platform concern, not a side experiment

Several sessions made this point indirectly. AI is moving into support workflows, operations, review loops, and troubleshooting. That means platform teams will increasingly be asked to provide governed ways of using it.

The more credible talks did not frame AI as a replacement for engineering control. They used it to reduce toil, improve diagnosis, and surface risk earlier.

That is probably the right default.

Measuring delivery is not the same as measuring usefulness

You can have a healthy sprint velocity and a platform that developers actively avoid. Delivery metrics — features shipped, backlog movement, milestone hits — tell you whether you shipped something. They don't tell you whether anyone wanted it in the form you shipped it. Sony's shift was adding adoption, satisfaction, and workaround counts alongside throughput. That's what caught the mismatch.


The sociotechnical part matters more than most teams admit

This was the real connective tissue between the best talks.

Platform problems are rarely only technical after a certain scale. They are shaped by:

  • team boundaries
  • hand-offs
  • approval paths
  • time zones
  • ownership clarity
  • operational incentives
  • what gets measured

Sony said this most directly, but the same pattern showed up elsewhere. If the platform architecture evolves while the team interaction model and feedback model stay stuck, the platform will eventually feel worse than it looks.

That is why the strongest teams are now working across three layers at once:

  1. technical architecture
  2. interaction model between teams
  3. feedback loops and success signals

That is a much better definition of platform engineering than just "build a control plane".


What I would actually do next

If I were taking one practical action plan out of these talks, it would be this.

1. Audit where people bypass your platform

Do not start with blame. Start with diagnosis.

Which capability is missing? Which path is too slow? Which abstraction is overfitted to the provider's view?

2. Split risk classes in your promotion model

If application, infrastructure, and migration changes still share the same assumptions, revisit that now.

3. Add product signals to platform reviews

Look beyond reliability and delivery throughput. Add:

  • adoption
  • time to value
  • satisfaction
  • workarounds
  • exception volume

4. Raise the definition of done

Do not stop at shipped. Stop at trusted, usable, documented, and adopted.

5. Use AI where feedback is fast and accountability is clear

Start with support, diagnosis, review, and guardrails. Earn the right to automate more.


The bigger takeaway

KubeCon EU 2026 did not convince me that platform engineering needs more tools.

It convinced me that many platform teams need a sharper model of what they are actually building.

If the platform is a product, then:

  • your users are real users
  • bypasses are signals
  • interfaces are part of the product
  • risk controls are part of the product
  • documentation and support are part of the product
  • adoption matters as much as architecture

That sounds more demanding, because it is. But it is also more honest.

And at this point, it is probably the only model that scales.



Frequently asked questions

Where can I find the KubeCon session recordings for these talks?

All sessions are on the CNCF YouTube channel. Search for the Sony, RBI, and Crossplane talk titles — they typically appear 1-2 weeks after the event. The Sony session was presented by Hagen Eugenia.

How do you measure whether a platform is actually working as a product?

Sony's post-shift metrics are the reference: time to first value (how quickly does a new team get their first deployment?), adoption rate (what fraction of eligible teams use the platform vs build around it?), workaround volume (how many exceptions and custom paths exist?), and satisfaction (periodic surveys with one actionable question). Start with whichever is easiest to instrument and build from there.

Is 'platform teams are product teams' just rebranding the same work?

It's a genuine change in what you optimise for. A project-mode platform team optimises for shipping features on schedule. A product-mode platform team optimises for users relying on and trusting what was shipped. The difference shows up in what you do after a release: a project team moves to the next milestone; a product team instruments adoption, gathers feedback, and iterates. Most internal platforms need the latter.

What's the minimum viable product signal to add if you're starting from zero?

Count platform bypasses. Every exception request, direct-access ticket, or custom deployment path is a bypass. Track the count sprint-over-sprint. If it's going up while you're shipping features, you're building for the platform's needs, not the user's. That single metric will surface the most important product gaps faster than any survey.

How does the 'governed autonomy' theme connect to platform product thinking?

Governed autonomy is the technical implementation of product thinking at the platform layer. When a platform team designs explicit decision tiers, approval gates, and self-service paths with policy guardrails, they're making product decisions about what users can do safely without asking for help. Every autonomous action that doesn't require a ticket is the platform working as a product. Every ticket is a gap.

From GitOps to AIOps in regulated environments

Banner image Banner image

From GitOps to AIOps in regulated environments

This was one of the more useful platform talks at KubeCon because it did not pretend every change is equally safe, equally reversible, or equally automatable.

Raiffeisen Bank International showed what happens when you take GitOps seriously in a regulated environment, then admit that standard promotion pipelines still leave awkward gaps once infrastructure, multi-tenancy, and migration risk get involved.


Quick takeaways

  • Treat infrastructure promotions differently from application promotions.
  • Keep central visibility, but decentralise execution where blast radius matters.
  • Crossplane v2 is a much better fit for shared, namespace-oriented platform models.
  • Use AI as a review and diagnosis layer, not as an unsupervised change engine.

GitOps to AIOps sharded execution flow GitOps to AIOps sharded execution flow

The sharded Kargo model solves two problems at once

One central Kargo view for operators, local controllers in each cluster shard. Users get a single place to track promotions; the execution model keeps failure domains isolated. That's a better trade-off than either "one controller with broad cluster access" or "separate promotion UIs per cluster". RBI's architecture is worth copying directly for regulated multi-cluster environments.


What was getting in the way

RBI's platform team supports multiple self-service models across shared Kubernetes environments and dedicated AWS accounts. That already creates a more complicated platform shape than the standard "one cluster, one team, one promotion path" story.

They described three service models:

  • namespace as a service on shared OKD/OpenShift clusters
  • account as a service for dedicated AWS-backed workloads
  • cluster as a service for internal platform consumers reusing their specifications and tooling

At that scale, one promotion can cut across several layers at once:

  • namespace isolation and policy controls
  • cluster-local GitOps control planes
  • cloud resources such as buckets, keys, or databases

That matters because an app promotion and an infrastructure promotion do not fail in the same way.

If an application deployment goes wrong, rollback is usually quick, local, and obvious. If an infrastructure promotion goes wrong, reconciliation can take minutes or hours, deletion windows can be delayed by provider policies, and the real state can be much harder to reason about.

That is where the usual "just promote through the same pipeline" advice starts to break down.


Why they split visibility from execution

One part of the solution was architectural: RBI introduced a sharded Kargo topology.

The shape is straightforward:

  • one central Kargo view for users
  • local Kargo controllers in each cluster shard
  • local Argo CD instances beside those controllers

That gives teams one place to see how promotions are moving, but avoids routing every execution path through one central controller with broad access to every environment.

That trade-off is worth paying for in regulated setups.

You keep a coherent operator view without pretending that all environments should share one failure domain.


Why Crossplane v2 mattered here

The second important part was their move from Crossplane v1 to v2.

In a tightly controlled shared-cluster environment, globally scoped managed resources were awkward. Teams worked in namespaces, but the underlying managed resources sat outside that model. That made debugging and verification harder for tenants because they could see the claim, but not enough of the resulting resource picture to understand what was happening.

Crossplane v2 improved that by moving the model towards namespace-scoped managed resources, which is a far better fit for tenant-oriented platforms.

The interesting bit was not just that they upgraded. It was how they migrated.

They described a practical three-step approach:

  1. enrich the original claim with migration metadata and a list of managed resources
  2. move ownership carefully so new resources can be recreated and imported safely
  3. clean up the old v1 path once the new v2 representation is stable

The point here is not the exact implementation detail. The point is that they designed the migration so teams could move with minimal interruption and without maintenance-heavy cutovers.

That is the kind of detail that usually decides whether a platform migration is trusted or quietly resisted.

Apply this: design your migration so tenants can see what's happening

RBI's three-step Crossplane migration approach works because it keeps tenants informed at every stage — they can see the claim, the migration metadata, and the resulting resource picture. Opaque migrations generate ticket queues and workarounds. Before starting any platform migration, define what visibility tenants need and build it before you flip the switch.


Where AI actually helped

This was the part I found most credible.

RBI did not present AI as a magic auto-migration engine. They used it as a second pair of eyes around risky moments in the workflow.

Two use cases stood out:

  • pull request risk analysis before a migration change enters the pipeline
  • Argo CD failure diagnosis after a promotion fails

That is a much better use of AI in regulated platform operations than letting an agent push infrastructure changes on its own.

In practice, the AI layer helps answer questions like:

  • does this migration PR look structurally wrong before we merge it?
  • is the claim shape inconsistent with the cluster state?
  • did the sync fail because of a simple spec mistake, or something deeper?

That is useful because platform teams do make mistakes under pressure, especially in YAML-heavy workflows where one indentation problem or one bad field placement can waste a lot of time.

The AI layer does not remove human control. It reduces avoidable review misses.

That is a much stronger operational story.

Not all promotions are equal — stop treating them as if they are

Application deployments, infrastructure changes, and resource migrations have very different failure modes and rollback windows. Routing them through the same promotion pipeline with the same assumptions is what creates incidents. RBI's approach — explicit risk differentiation with separate approval depth and soak time per change type — is the fix. Don't wait for an incident to draw the distinctions.


What I would copy from this approach

If I were borrowing patterns from this talk, I would not start with the AI part.

I would start here:

1. Stop pretending all promotions are equal

Application, infrastructure, and migration changes should not share the same risk policy by default.

Different approval depth, different soak time, different rollback assumptions.

That should be explicit.

2. Keep the user view simple, not the execution model

The central Kargo view with local shard execution is a sensible compromise.

Users want one place to follow progress. Operators need isolation and narrower blast radius.

You can have both.

3. Make migration state visible to tenants

If teams are expected to participate in platform migrations, they need enough visibility to understand which resources are involved and where things are stuck.

Opaque migrations create ticket queues and workarounds.

4. Use AI for risk surfacing, not autonomy theatre

There is a big difference between:

  • "AI reviewed this and found likely issues"
  • "AI ran the migration for us"

The first is credible in regulated operations. The second needs a much higher bar.


The bigger point

The real lesson was not "add AI to GitOps".

It was this: once a platform spans clusters, namespaces, cloud accounts, and long-lived infrastructure, the delivery model has to reflect the actual risk in the system.

GitOps gives you structure. Crossplane gives you a cleaner self-service model. Sharded execution reduces coupling. AI can improve review and diagnosis.

But none of those help if you still operate with the assumption that every promotion is small, fast, and safely reversible.

That assumption is what RBI had to outgrow.


References


Frequently asked questions

Where can I watch the RBI KubeCon session?

The RBI talk is on the CNCF YouTube channel. Search "RBI GitOps AIOps KubeCon EU 2026". The conference PDF is also linked in the References section at the bottom of this post.

Is Kargo production-ready for regulated environments?

Kargo is a CNCF project in active development. RBI's use of it in a regulated banking environment at KubeCon suggests production viability, but regulated environments have specific requirements around audit trails, change management records, and approval workflows. Validate Kargo's audit logging output against your compliance requirements before adopting it for regulated workloads.

How does the sharded Kargo topology differ from a standard hub-and-spoke ArgoCD setup?

In a standard ArgoCD hub-and-spoke, one control plane has credentials to all spoke clusters. In RBI's sharded Kargo model, local Kargo controllers in each cluster shard handle their own execution — the hub provides visibility and coordination, not execution. That's a narrower blast radius: a compromise of the hub doesn't give an attacker direct execution access across all shards.

What does 'AI as a second pair of eyes' look like in practice?

RBI used AI at two points: pull request risk analysis before a migration change enters the pipeline, and Argo CD failure diagnosis after a promotion fails. In both cases, the AI surfaces information — structural issues in the PR, likely root cause of the failure — and a human decides what to do. The AI doesn't merge PRs or trigger rollbacks. That boundary is the key to making it trustworthy in regulated operations.

How does Crossplane v2's namespace-scoped model help multi-tenant platforms?

In Crossplane v1, managed resources were globally scoped — a tenant could see their claim but not the underlying managed resource, making it hard to understand provisioning failures. v2 moves managed resources to namespace scope, so tenants can inspect the full resource picture within their namespace boundary. Better visibility means fewer "my database is stuck and I don't know why" support tickets.