Skip to main content

Release 0.4.0 — AG-UI Protocol Unification

Released: 2026-04-23 Chart: oci://ghcr.io/cnoe-io/charts/ai-platform-engineering:0.4.0 Previous release: 0.3.x

Highlights

0.4.0 is a major release that fundamentally restructures the platform around the AG-UI protocol, unifying streaming across the web UI, Slack bot, and dynamic agents under a single event model. All traffic now routes through the Next.js gateway, dynamic agents no longer own OIDC auth, and a shared conversation API replaces scattered per-client storage. Helm values for all three components have been restructured — see the Upgrade Guide below for the full before/after mapping.

What's New

AG-UI Protocol

  • Unified streaming — AG-UI event model replaces legacy A2A streaming across dynamic agents, Slack bot, and UI; stream events are now persisted server-side
  • Stream encoder abstractionAGUIStreamEncoder and CustomStreamEncoder implementations via a StreamEncoder ABC
  • Slack bot AG-UI rewrite — typing indicators with live thoughts, todo-aware streaming, subagent suppression (#1259)

Next.js Gateway Architecture

  • All traffic routes through the Next.js gateway — flat /api/v1/chat/ routes with X-User-Context auth; dynamic agents no longer validate tokens or accept direct browser requests
  • Config ownership moved from dynamic-agents to UI (agent CRUD, MCP servers, models endpoint in local MongoDB)
  • Bearer token auth added for service accounts (Slack bot) (#1259)

Shared Conversation API

  • Server-owned ID generation with idempotency_key for cross-client dedup
  • client_type enum (webui | slack) on all conversations; all 10 Slack handlers migrated
  • Delta thread context — follow-ups embed only new messages since last_processed_ts, eliminating quadratic checkpoint growth
  • PATCH /api/chat/conversations/[id]/metadata with MongoDB dot-notation $set (#1259)

Dynamic Agents Runtime

  • ClientContext and Jinja2 system prompt rendering
  • wait and agent_info tools, configurable middlewares
  • NAMESPACE_CONTEXT emitted only on change; UserContext made opaque; RBAC removed from chat routes
  • Metrics endpoint exposed (#1259)

UI Enhancements

  • Streaming markdown: rAF throttle, block animations, cursor improvements
  • Jinja2 syntax highlighting in system prompt editor
  • Turns collection — decoupled stream_events from messages
  • Admin: platform statistics with Slack integration, unified filters, user detail panels, conversations pagination
  • LLM model config page: add/remove models through UI
  • New theme: System (follow OS theme) (#1259)

Bug Fixes

  • slack: add escalation_policy field to VictorOps escalation config; fix humble followup prompt when agent has no record of prior reply (#1277)
  • admin: fix feedback dedup by (permalink, user_email) instead of permalink-only; fix Slack feedback upsert key to (message_id, user_id); fix top-user linkage (#1273)

Breaking Changes

⚠️ This release contains significant breaking Helm value changes. See the Upgrade Guide below for the complete before/after mapping.

  • env: block removed from all components — use config: flat map
  • caipe-ui.seedConfig.* renamed to caipe-ui.appConfig.*
  • slack-bot values completely restructured to flat config: map
  • slack-bot.slack.tokenSecretRef replaced by existingSecret
  • Dynamic-agents OIDC/CORS config keys removed (auth handled by gateway)

Known Issues

  • Admin Statistics page under-reports Slack conversation counts until InteractionTracker equivalent is re-implemented in the new AG-UI Slack bot.

Upgrade

helm upgrade ai-platform-engineering \
oci://ghcr.io/cnoe-io/charts/ai-platform-engineering \
--version 0.4.0 \
-f your-values.yaml

Upgrade Guide: 0.3.x → 0.4.0

This guide covers all breaking changes, Helm value restructuring, and environment variable changes when upgrading from 0.3.x to 0.4.0.


Breaking Changes Summary

AreaChangeSeverity
Helm (all)env: block removed — use config: flat map insteadHigh
Helm (caipe-ui)seedConfig.* renamed to appConfig.*High
Helm (caipe-ui)SEED_CONFIG_PATH env var replaced by APP_CONFIG_PATHHigh
Helm (slack-bot)All named value keys (appName, botMode, caipeApiUrl, silenceEnv, slackWorkspaceUrl, mongodb.*, auth.*, prompts.*) removed — use config: flat mapBreaking
Helm (slack-bot)slack.tokenSecretRef replaced by existingSecretBreaking
Helm (slack-bot)CAIPE_BOT_CONFIG env var replaced by SLACK_INTEGRATION_BOT_CONFIGBreaking
Helm (slack-bot)Bot config file renamed: /etc/caipe/caipe-bot-config.yaml -> /etc/caipe/bot-config.yamlBreaking
Helm (slack-bot)botConfig restructured: qanda/ai_alerts/ai_enabled replaced by flat agents listBreaking
Helm (dynamic-agents)env: block removed, AUTH_ENABLED removedHigh
Env (dynamic-agents)AUTH_ENABLED replaced by DEBUG=true for dev bypassMedium

Component-by-Component Migration

1. CAIPE UI (caipe-ui)

env: merged into config:

The separate env: block is removed. All environment variables now go in a single flat config: map.

Before (0.3.x):

caipe-ui:
env:
A2A_BASE_URL: "http://ai-platform-engineering-supervisor-agent:8000"
SKILLS_DIR: "/app/data/skills"
config:
SSO_ENABLED: "true"
ENABLE_SUBAGENT_CARDS: "true"
# ... other config

After (0.4.0):

caipe-ui:
config:
A2A_BASE_URL: "http://ai-platform-engineering-supervisor-agent:8000"
SKILLS_DIR: "/app/data/skills"
SSO_ENABLED: "true"
ENABLE_SUBAGENT_CARDS: "true"
# ... other config

Action: Move all keys from env: into config:. Delete the env: block.

seedConfig renamed to appConfig

Before (0.3.x):

caipe-ui:
seedConfig:
enabled: true
models:
- model_id: gpt-4o
name: GPT-4o
provider: openai
mcp_servers: []
agents: []

After (0.4.0):

caipe-ui:
appConfig:
models:
- model_id: gpt-4o
name: GPT-4o
provider: openai
mcp_servers: []
agents: []

Action:

  1. Rename seedConfig: to appConfig:.
  2. Remove enabled: true/false — the ConfigMap is auto-created when any of models, mcp_servers, or agents is non-empty.
  3. The env var SEED_CONFIG_PATH is automatically replaced by APP_CONFIG_PATH by the chart; no manual change needed.

2. Dynamic Agents (dynamic-agents)

env: block removed

Before (0.3.x):

dynamic-agents:
env:
SOME_CUSTOM_VAR: "value"
config:
MONGODB_DATABASE: "caipe"
AUTH_ENABLED: "false"

After (0.4.0):

dynamic-agents:
config:
MONGODB_DATABASE: "caipe"
SOME_CUSTOM_VAR: "value"

Action: Move all keys from env: into config:. Delete the env: block.

AUTH_ENABLED removed

The AUTH_ENABLED config key is removed. It was being used as a development shortcut to bypass authentication.

Replacement: Use DEBUG: "true" in config: to enable the dev admin user bypass. In production, omit it (auth is always enabled when the UI passes a valid token).

OIDC and CORS config removed

In 0.4.0, all authentication is handled by the UI gateway (Next.js server). Dynamic-agents no longer validates tokens or accepts direct browser requests, so the following keys should be removed from dynamic-agents.config::

  • OIDC_ISSUER
  • OIDC_CLIENT_ID
  • OIDC_REQUIRED_ADMIN_GROUP
  • CORS_ORIGINS

These are now only needed on the caipe-ui side.


3. Slack Bot (slack-bot) -- Most Breaking Changes

The slack-bot Helm values have been completely restructured from named keys to a flat config: map with an existingSecret: reference. This is the most significant migration.

Full before/after mapping

Before (0.3.x):

slack-bot:
appName: "CAIPE"
botMode: "socket"
caipeApiUrl: "http://ai-platform-engineering-caipe-ui:3000"
silenceEnv: "false"
slackWorkspaceUrl: "https://mycompany.slack.com"

env:
CUSTOM_VAR: "value"

slack:
tokenSecretRef: "slack-bot-secrets"

mongodb:
uri: "mongodb://admin:changeme@mongodb:27017"
database: "caipe"

auth:
enabled: true
tokenUrl: "https://idp.example.com/oauth2/v1/token"
clientId: "my-client-id"
scope: "api://caipe"
audience: ""

prompts:
responseStyle: "Be concise"
qanda: ""
overthinkQanda: ""
mention: ""
humbleFollowup: ""
aiAlerts: ""

botConfig:
C012345678:
name: "#my-channel"
ai_enabled: true
default:
project_key: MYPROJ
issue_type: Bug

After (0.4.0):

slack-bot:
config:
APP_NAME: "CAIPE"
SLACK_BOT_MODE: "socket"
CAIPE_API_URL: "http://ai-platform-engineering-caipe-ui:3000"
SLACK_INTEGRATION_SILENCE_ENV: "false"
SLACK_WORKSPACE_URL: "https://mycompany.slack.com"
MONGODB_URI: "mongodb://admin:changeme@mongodb:27017"
MONGODB_DATABASE: "caipe"
SLACK_INTEGRATION_ENABLE_AUTH: "true"
SLACK_INTEGRATION_DEFAULT_AGENT_ID: "my-agent"
OAUTH2_TOKEN_URL: "https://idp.example.com/oauth2/v1/token"
OAUTH2_CLIENT_ID: "my-client-id"
OAUTH2_SCOPE: "api://caipe"
# OAUTH2_AUDIENCE: "" # omit if empty
SLACK_INTEGRATION_PROMPT_RESPONSE_STYLE: "Be concise"

existingSecret: "slack-bot-secrets"

botConfig:
C012345678:
name: "#my-channel"
agents:
- agent_id: "my-agent"
users: { enabled: true, listen: "mention" }
bots: { enabled: false }

Field-by-field mapping reference

Old key (0.3.x)New key (0.4.0) in config:Notes
appNameAPP_NAME
botModeSLACK_BOT_MODE
caipeApiUrlCAIPE_API_URL
silenceEnvSLACK_INTEGRATION_SILENCE_ENV
slackWorkspaceUrlSLACK_WORKSPACE_URL
env.*Move into config:
slack.tokenSecretRefexistingSecretTop-level key, same secret name
mongodb.uriMONGODB_URISensitive -- consider moving to secret
mongodb.databaseMONGODB_DATABASE
auth.enabledSLACK_INTEGRATION_ENABLE_AUTH"true" / omit
auth.tokenUrlOAUTH2_TOKEN_URL
auth.clientIdOAUTH2_CLIENT_ID
auth.scopeOAUTH2_SCOPEOmit if empty
auth.audienceOAUTH2_AUDIENCEOmit if empty
prompts.responseStyleSLACK_INTEGRATION_PROMPT_RESPONSE_STYLEOmit if empty
prompts.qandaSLACK_INTEGRATION_PROMPT_QANDAOmit if empty
prompts.overthinkQandaSLACK_INTEGRATION_PROMPT_OVERTHINK_QANDAOmit if empty
prompts.mentionSLACK_INTEGRATION_PROMPT_MENTIONOmit if empty
prompts.humbleFollowupSLACK_INTEGRATION_PROMPT_HUMBLE_FOLLOWUPOmit if empty
prompts.aiAlertsSLACK_INTEGRATION_PROMPT_AI_ALERTSOmit if empty

Secret reference change

Before: slack.tokenSecretRef: "slack-bot-secrets" After: existingSecret: "slack-bot-secrets"

The Secret itself does not change -- it still contains SLACK_BOT_TOKEN, SLACK_APP_TOKEN, SLACK_SIGNING_SECRET, and optionally OAUTH2_CLIENT_SECRET. Only the Helm key that references it has moved.

Bot config file rename

0.3.x0.4.0
Env varCAIPE_BOT_CONFIGSLACK_INTEGRATION_BOT_CONFIG (auto-set by chart)
Mount path/etc/caipe/caipe-bot-config.yaml/etc/caipe/bot-config.yaml
ConfigMap name*-config (shared with env)*-bot-config (dedicated)

The chart sets SLACK_INTEGRATION_BOT_CONFIG automatically when botConfig is non-empty. No manual action needed -- just ensure botConfig: is populated.

Fallback behavior: If neither SLACK_INTEGRATION_BOT_CONFIG nor the well-known path /etc/caipe/bot-config.yaml exists, the bot starts with no channel configuration and logs a warning. It will not crash.

botConfig restructured to flat agents list

The old ai_enabled/qanda/ai_alerts/default keys are replaced by a flat agents list. The bot rejects old-format keys with a clear error.

Before:

botConfig:
C012345678:
name: "#my-channel"
ai_enabled: true
qanda:
enabled: true
overthink: false
include_bots:
enabled: true
bot_list: ["AlertBot"]
ai_alerts:
enabled: false

After:

botConfig:
C012345678:
name: "#my-channel"
agents:
- agent_id: "my-agent"
users:
enabled: true
listen: "mention" # "mention" | "message" | "all"
overthink:
enabled: false
bots:
enabled: true
listen: "message" # "mention" | "message" | "all"
bot_list: ["AlertBot"]

Unified Config Pattern (All Components)

All three components now follow the same Helm config pattern:

component:
# 1. Flat env vars → ConfigMap → envFrom
config:
KEY: "value"

# 2. Pre-existing K8s Secret → envFrom secretRef
existingSecret: "my-secret"

# 3. ExternalSecrets operator integration
externalSecrets:
enabled: false
# ...

# 4. Structured data → YAML file → volume mount (component-specific)
appConfig: {} # caipe-ui only
botConfig: {} # slack-bot only

Key principle: config: is always a flat key-value map where each key becomes an environment variable. No nesting, no config.env: sub-keys.


Removed / Deprecated Values

ComponentRemoved ValueReplacement
caipe-uienv:config:
caipe-uiseedConfig.enabledAuto-detected (non-empty = enabled)
caipe-uiseedConfig.*appConfig.*
dynamic-agentsenv:config:
dynamic-agentsconfig.AUTH_ENABLEDconfig.DEBUG: "true" for dev
dynamic-agentsconfig.OIDC_ISSUERRemoved (auth handled by UI gateway)
dynamic-agentsconfig.OIDC_CLIENT_IDRemoved (auth handled by UI gateway)
dynamic-agentsconfig.OIDC_REQUIRED_ADMIN_GROUPRemoved (auth handled by UI gateway)
dynamic-agentsconfig.CORS_ORIGINSRemoved (no direct browser access)
slack-botenv:config:
slack-botappNameconfig.APP_NAME
slack-botbotModeconfig.SLACK_BOT_MODE
slack-botcaipeApiUrlconfig.CAIPE_API_URL
slack-botsilenceEnvconfig.SLACK_INTEGRATION_SILENCE_ENV
slack-botslackWorkspaceUrlconfig.SLACK_WORKSPACE_URL
slack-botslack.tokenSecretRefexistingSecret
slack-botmongodb.uriconfig.MONGODB_URI
slack-botmongodb.databaseconfig.MONGODB_DATABASE
slack-botauth.*config.SLACK_INTEGRATION_ENABLE_AUTH, config.OAUTH2_*
slack-botprompts.*config.SLACK_INTEGRATION_PROMPT_*

Image Tag Overrides

When deploying RC builds (pre-release), the chart's default appVersion may not match the desired image tag. You must explicitly override image tags for each component:

caipe-ui:
image:
repository: "ghcr.io/cnoe-io/caipe-ui"
tag: "0.4.0-rc.16"
pullPolicy: "Always"

dynamic-agents:
image:
tag: "0.4.0-rc.16"

For stable releases, the chart's appVersion is set automatically and no override is needed — you can remove the image.tag overrides after upgrading to the final 0.4.0 release.


Known Gaps (to be addressed before GA)

Slack interaction tracking for admin statistics

The InteractionTracker class (which recorded Slack thread metadata, user upserts, and lightweight message docs to MongoDB for the admin stats dashboard) has been removed as part of the slack bot rewrite. The admin statistics page will not show Slack-sourced data until equivalent tracking is re-implemented in the new AG-UI-based slack bot.

Impact: Admin → Statistics page will under-report conversation counts, active users, and message volumes for Slack interactions.


Pre-Upgrade Checklist

  • Back up current values: helm get values ai-platform-engineering -o yaml > values-backup.yaml
  • Migrate caipe-ui values: merge env: into config:, rename seedConfig to appConfig
  • Migrate dynamic-agents values: merge env: into config:, remove AUTH_ENABLED, remove OIDC/CORS keys
  • Migrate slack-bot values: restructure all named keys into config: flat map (see mapping table above)
  • Verify secret name: existingSecret points to the correct K8s Secret containing Slack tokens
  • Migrate botConfig: replace qanda/ai_alerts/ai_enabled with flat agents list
  • Helm diff: helm diff upgrade ai-platform-engineering ./charts/ai-platform-engineering -f new-values.yaml
  • Deploy and verify: check pod logs for config loading messages

Rollback

If you need to roll back to 0.3.x:

helm rollback ai-platform-engineering <previous-revision>

Restore your backed-up values file. The 0.3.x chart templates expect the old value structure (env:, seedConfig:, slack.tokenSecretRef:, etc.), so the old values file will work as-is with the old chart version.

The slack bot will look for CAIPE_BOT_CONFIG again (the 0.3.x env var). No data migration is needed since these are configuration-only changes.