Skip to content

feat(agents): platform-admin enable/disable toggle per agent CLI - #629

Merged
jeromevdl merged 2 commits into
aws-samples:mainfrom
gpmattoo:feat/platform-agent-cli-toggle
Oct 27, 2026
Merged

jeromevdl merged 2 commits into
aws-samples:mainfrom
gpmattoo:feat/platform-agent-cli-toggle

Conversation

@gpmattoo

@gpmattoo gpmattoo commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Implements the approach proposed in #368: a per-CLI enabled/disabled toggle in platform settings, so only enabled CLIs can be selected.

  • Admin UI: new Admin → Agents → Agent CLIs card with a switch per CLI (Kiro, Claude Code, OpenCode, Codex). At least one CLI must stay enabled.
  • Storage: new disabled-clis SSM parameter (JSON array), seeded from a new disabled_clis Terraform variable (default []) with ignore_changes, then Admin UI managed — same pattern as stage-skipping / pr-strategy. A missing parameter means all CLIs are enabled, so existing deployments are unchanged.
  • Enforcement (agent_cli_disabled, 400): in resolveSelectedAgentCredential, the shared path for every new selection — intent start, DRAFT compose, DRAFT discussion assists — and on changing a space's recommended CLI (re-saving the current recommendation stays allowed). An SSM read failure on these paths fails closed.
  • Pinned config preserved: executions that already pinned a CLI never go through selection, so disabling a CLI does not affect running/parked intents.
  • Listings: /projects/{id}/agent-capabilities and /agents/capabilities mark disabled CLIs enabled: false, exclude them from available, and return disabledClis. Compose page and space settings grey them out as "disabled by admin".
  • IAM: read/write for agents lambda; read for intents, projects, discussions.
  • codex_model description clarified: it only pins a default model, it doesn't enable Codex. Default unchanged.
  • Docs: platform-settings.md, projects.md.

Deployment: requires a Terraform apply (new SSM parameter + IAM grants) alongside the Lambda/frontend deploy.

Screenshots

image image

Testing

  • ✅ New lambda/shared/test/agent-cli-availability.test.js (validation, SSM read semantics, selection gate)
  • ✅ lambda/agents/test/settings.test.js (GET default/parse, admin-only PUT, rejects unknown / all-disabled)
  • ✅ Frontend: new AgentClisCard.test.tsx, compose-page "disabled by admin" case, PlatformAdmin.test.tsx; npm --prefix frontend run build
  • ✅ lint, format:check, secretlint, dep:check; esbuild bundles for agents/intents/projects/discussions
  • ⚠️ Not run locally (Docker/Testcontainers unavailable): new cases in intents.test.js (start rejects disabled CLI without mutating DRAFT), projects.test.js (recommended CLI), history-auth.test.js (capabilities marking), and the rest of the container-backed backend suite. Relying on CI.
  • ⚠️ terraform fmt/validate not run locally (Terraform not installed).
  • Pre-existing, unrelated: AppSidebar.test.tsx / intentSectionPreference.test.ts fail locally on Node 26 (localStorage undefined); identical on clean main.

Refs #368

Platform admins can switch individual agent CLIs (kiro, claude, opencode,
codex) off in Admin -> Agents -> Agent CLIs. Disabled CLIs are greyed out
on the compose page and in space settings, and the backend rejects new
selections with agent_cli_disabled at intent start, DRAFT compose, DRAFT
discussion assists, and when changing a space's recommended CLI.
Intents that already pinned a CLI are unaffected.

The disabled set lives in a new disabled-clis SSM parameter (seeded from
the disabled_clis Terraform variable, empty by default, then Admin UI
managed). A missing parameter means every CLI is enabled, so existing
deployments keep their behavior. Clarifies that codex_model only pins a
default model and does not enable Codex.

Refs aws-samples#368
@jeromevdl

Copy link
Copy Markdown
Collaborator

Thanks for your contribution @gpmattoo , could you please add a screenshot of the result, so we can see what it looks like?

@gpmattoo

Copy link
Copy Markdown
Contributor Author

Thanks @jeromevdl! Here's how it looks, with Codex disabled as the example.

Admin → Agents → Agent CLIs (new card): one switch per CLI. The last enabled CLI can't be switched off.

Admin Agent CLIs card

Space Settings → Agent → Recommended CLI: a disabled CLI is greyed out and labelled "disabled by admin". The intent compose page CLI picker shows the same label and disables the card.

Space settings Recommended CLI with Codex disabled

These are the actual components from this branch, rendered locally with mocked API responses rather than captured from a deployed stack.

@jeromevdl jeromevdl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No major issue found.

Optional suggestions

  • Creating a space ignores the toggle. lambda/projects/index.js:1590 still writes data.agentCli || 'kiro' without checking the disabled list. With Kiro disabled, a new space recommends a greyed-out CLI. This is only cosmetic, because selection is still enforced at start. Default to the first enabled CLI.
  • A failed settings load in AgentClisCard can re-enable CLIs. If the load fails, the card shows everything enabled; toggling and saving then overwrites the stored list. DefaultModelsCard behaves the same way, so this follows the existing pattern. Disabling Save after a load error would close the gap.

Thanks for contributing!

…s load

A new space now recommends Kiro, or the first enabled CLI when Kiro is
disabled, and rejects an explicitly requested disabled CLI. A failed
settings read does not block space creation, because the recommendation
is advisory.

The Agent CLIs card now blocks saving and editing when the stored
settings fail to load, so it cannot overwrite the saved list with an
all-enabled default.
@gpmattoo

Copy link
Copy Markdown
Contributor Author

Thanks for the review @jeromevdl. Both suggestions are in 63608a2.

Creating a space now respects the toggle. A new space recommends Kiro, or the first enabled CLI when Kiro is disabled (new defaultAgentCli helper in lambda/shared/agent-cli-availability.js). Creating a space with an explicitly disabled agentCli returns agent_cli_disabled. The create response also reported a hard-coded 'kiro'; it now returns the stored value. The recommendation is advisory, so if the disabled list can't be read, creation still goes ahead and logs a warning. Selection is still enforced at intent start.

A failed settings load no longer lets the card overwrite the saved list. AgentClisCard disables the switches and Save, and shows a "reload before saving" message. I left DefaultModelsCard as is to keep this PR focused; happy to fix it in a follow-up if you'd like.

Added tests: defaultAgentCli and the load-failure case pass locally. The new space-create case in projects.test.js needs Testcontainers, which I couldn't run here, so CI will be its first run. I also updated projects.md to describe the new-space default.

@jeromevdl
jeromevdl merged commit 876da33 into aws-samples:main Oct 27, 2026
5 checks passed
@jeromevdl

Copy link
Copy Markdown
Collaborator

Thanks again for contributing @gpmattoo, merged into main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants