feat(studio-cp,oab-mcp,src-tauri): add deploy_provision_agent (studio#128) - #129
Merged
Conversation
…#128) New Fleet wizard direction (Brett, this thread): drop the compose-library Template/Overlay model, replace with a vendor + chat-platform + ACP flow that composes config.toml directly. Confirmed earlier (#128 investigation) that provision_manifest/provision_k8s don't require a Bundle produced by compose_named — a hand-built Bundle{image_tag, files} works identically. This PR adds the backend capability only (all 3 layers: MCP tool, Tauri bridge, studio-cp core) — purely additive, doesn't touch the existing deploy_provision/compose-library path at all. Console wiring (replacing the Template/Overlay UI with the new wizard) is a separate follow-up PR. - studio-cp: provision_agent / provision_agent_k8s — near-duplicates of provision_from_library[_k8s] from "resolve the bucket" onward (same create-vs-redeploy branch, same pre_seed hook injection, same bundle upload), except the Bundle's config.toml comes from the caller directly instead of studio_compose::compose_named(library, template, overlay). Deliberate duplication over a shared refactor, matching the tradeoff provision_from_library_k8s's own doc comment already made for the same reason (avoid risking the already-landed functions' shape). - oab-mcp: new deploy_provision_agent tool (config_toml + image + name, same provider/context/expected_principal/fleet/cluster args as deploy_provision minus library/template/overlay), dispatches to the new studio-cp functions. Tool-count test updated (17 -> 18). - src-tauri: deploy_provision_agent bridge command, mirroring deploy_provision's shape, registered in generate_handler!. Ref #128.
…rver-side
Brett's catch: this form's output is ultimately a config.toml for the
created agent, and that file can also be produced by an admin agent
calling the same tool directly (not through Studio's UI) — for those to
stay in sync, the actual TOML-rendering logic can't live in the console
(TypeScript), it has to be the single server-side source of truth both
callers go through.
deploy_provision_agent's config_toml:string param is replaced with
structured fields (api_key, chat_platform, chat_bot_token,
chat_channel_secret) — studio-cp's new generate_agent_config() renders the
actual text (the structured-input counterpart of oabctl create's
generate_config, generalized from Discord-only to discord/telegram/line).
Any caller sending the same fields — the wizard or a future admin agent —
gets byte-identical config.toml by construction, not by convention.
provision_agent_secrets() stores the secret-bearing fields in the same
oab/{namespace}/{name} Secrets Manager convention oabctl create already
uses for the Discord token — a separate secret from #127's ACP auth key,
since these feed config.toml's [secrets.refs]/${secrets.x} (openab's own
resolution, aws-sm:// only) while the ACP key is a container-level env var
injected via spec.secrets, a different delivery path entirely.
k8s deploys refuse a non-empty chat_platform rather than silently
deploying something broken: config.toml's secret resolution only
understands aws-sm://, and k8s_driver.rs's build_deployment injects no AWS
credentials into the pod at all (confirmed by reading it) — so a k8s pod
has no way to actually resolve that URI at runtime. ACP-only k8s deploys
are unaffected (already-working, different mechanism).
api_key is captured/stored but not yet wired into config.toml — which env
var a given vendor's CLI expects it under needs vendor-specific research
this round didn't do. Flagged in the tool schema and struct doc comment
rather than fabricating a config key nothing reads.
Ref #128.
brettchien
added a commit
that referenced
this pull request
Aug 29, 2026
…write (studio#128) (#132) Replaces the Template/Overlay compose-library step (empty on every fresh install by design, blocking the whole deploy flow — the original #119 screenshot that started this) with the vendor + chat platform + ACP flow confirmed with Brett across #128's design thread. ## Console (items 1-5 of the runbook, shipped together — all fields live on the same new Step 2 screen) - Vendor <select>: Claude/codex/agy/cursor/kiro. "agy" is only the display label — the option value is "antigravity" (the GHCR image variant / Dockerfile.package build-target name resolve_vendor_image_tags expects). - Image tag: pre-filled from resolve_vendor_image_tags (#131) — Stable if GHCR confirms it exists, else Beta (pre-beta-<vendor>), else left for manual entry. Always editable — no lookup failure blocks the field. - API key (optional): captured, stored as a secret server-side; not yet wired into config.toml (documented gap from #129, unchanged here). - Chat platform (optional, default none — "use ACP directly"): Discord/Telegram/LINE, reveals the right token field(s) per platform. k8s deploys refuse a non-empty selection both client-side (clean validation message) and server-side (#129's existing refusal) — config.toml secret resolution needs AWS credentials a k8s pod doesn't have. - Enable ACP checkbox: default checked, forced off + disabled for vendor=agy (its bridge bypasses openab-gateway's /acp route entirely). - Agent name: pre-filled with a random Greek god name, shuffle button to re-roll, still freely editable. - No separate "Preview bundle" step anymore — fill in the fields, Deploy. ## Backend: acp_enabled made caller-controlled (was hardcoded true in #127) #127 hardcoded `acp_enabled: Some(true)` inside build_default_manifest / build_default_k8s_manifest with no way for a caller to turn it off — fine when nothing exposed a toggle, not fine once the wizard has an actual checkbox (needed for the agy case above). Both functions, and AgentWizardInput, now take `acp_enabled: bool` explicitly: - studio-cp: build_default_manifest/build_default_k8s_manifest gained an `acp_enabled: bool` param — only generates the ACP auth secret when true. provision_from_library[_k8s] (the older compose-library path, unrelated to this wizard) pass `true` at their call sites, preserving #127's original unconditional-on behavior there unchanged. - oab-mcp: deploy_provision_agent's schema gained `acp_enabled: boolean`, defaulting to true when the caller omits it (same default #127 had, now explicit and overridable instead of baked in). - src-tauri: bridge command threads the new param through. Ref #128.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First slice of #128 — backend capability only. Adds a new provisioning path for the New Fleet wizard's vendor/chat-platform/ACP flow, bypassing the compose library (
template ⊕ overlay) entirely. Purely additive: the existingdeploy_provision/compose-library path is completely untouched.Revised after Brett's review: config.toml is now rendered server-side from structured fields, not assembled as text on the console and passed through — this file can also be produced by an admin agent calling the same MCP tool directly (not through Studio's UI), so the actual rendering logic has to be a single source of truth both callers go through, not duplicated client-side.
Change (all 3 layers)
studio-cp:provision_agent/provision_agent_k8stake anAgentWizardInput(api_key, chat_platform, chat_bot_token, chat_channel_secret) instead of rawconfig_tomlbytes. Newgenerate_agent_config()renders the actual TOML text server-side — the structured-input counterpart ofoabctl create'sgenerate_config, generalized from Discord-only to discord/telegram/line. Newprovision_agent_secrets()stores the secret-bearing fields in the sameoab/{namespace}/{name}Secrets Manager conventionoabctl createalready uses for the Discord token (a separate secret from feat(oabctl,studio-cp): enable ACP by default on Studio-deployed agents #127's ACP auth key — different delivery mechanism, config-level[secrets.refs]/aws-sm://vs. container-level env var injection). k8s deploys refuse a non-emptychat_platform: confirmedk8s_driver.rs'sbuild_deploymentinjects no AWS credentials into the pod, so config.toml'saws-sm://secret resolution has nothing to authenticate with at runtime — refusing up front beats deploying something that silently fails inside the container. ACP-only k8s deploys are unaffected. Otherwise unchanged from the original slice: same create-vs-redeploy branch, samepre_seedhook injection, same bundle upload sequence asprovision_from_library[_k8s], deliberately duplicated rather than shared-refactored for the same reasonprovision_from_library_k8s's own doc comment already gives.oab-mcp:deploy_provision_agenttool schema updated to the structured fields;t_provision_agentbuilds anAgentWizardInputfrom args and dispatches. Tool-count test still 18 (only the schema changed, not the tool list).src-tauri: bridge command signature updated to match.Known gap, flagged not hidden:
api_keyis captured and stored as a secret but not yet wired into config.toml — which env var a given vendor's CLI actually expects its API key under needs vendor-specific research this round didn't do. Documented in the struct/tool schema rather than fabricating a config key nothing reads.Verification
aws-sdk-ec2OOM limitation as every other Rust PR this week;src-tauriadditionally can't be checked at all in this sandbox (no macOS system libs).provision_from_library/provision_from_library_k8sfor the studio-cp shape;oabctl create'sgenerate_config/store_secretfor the TOML-rendering and secret-storage patterns) — hand-verified line by line against them.build-test/bundle-macosjobs are the real gate here.Ref #128.
🤖 Generated with Claude Code