Generated banner for Agent Advisor
Generated logo for Agent Advisor

Agent Advisor

AWSOfficialPublished by AWS

  • Skill
  • Workflow
  • Cloud and DevOps
  • Apache-2.0
  • Low risk
  • Has scripts

From the author

Entry point for AI-agent work on AWS: pick a runtime, plan a migration for existing workloads, and build an executable POC — one phased flow. Triggers on: which runtime for my agent, AgentCore vs ECS vs EKS vs Lambda, AgentCore vs Lambda MicroVMs, deploy an AI agent on AWS, agent architecture on AWS, I have an agent idea what do I build, move/migrate my agents to AWS, agent migration plan, add AgentCore services (memory, gateway, identity, policy, observability) to an agent already on AWS, Temporal on AWS (migrate/run Temporal workers on AWS, a service orchestrated by Temporal, Temporal Cloud vs self-hosted). Temporal Workflow code is never rewritten into Step Functions. Requires at least one agentic component — a purely non-agent system (plain services, batch jobs, HTTP endpoints, non-agent Temporal Activities) is out of scope, redirected to gcp-to-aws / heroku-to-aws / llm-to-bedrock. Not for: compute/data migration with no AI agent; pure LLM SDK rewrite (use llm-to-bedrock); per-model pricing.
— the description by AWS

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

Agent Advisor provides a structured, multi-phase workflow to help users determine the optimal AWS runtime for their AI agents. It uses a deterministic scoring engine to evaluate requirements and guides users through a process that includes discovery, architectural design, cost estimation, and the creation of an executable proof-of-concept. The skill supports various AWS compute options, including AgentCore, ECS, EKS, and Lambda, and integrates with migration engines for existing workloads.

What it does

  • Recommends AWS runtimes for AI agents based on technical requirements.
  • Generates migration plans for existing AI workloads moving to AWS.
  • Provides architectural guidance for agentic systems.
  • Assembles executable proof-of-concept scaffolding.
  • Estimates coarse cost magnitudes for proposed agent deployments.
  • Integrates with external migration engines for workload transitions.

When to use it

  • When you need to decide which AWS runtime is best for a new AI agent.
  • When migrating an existing AI agent workload to AWS.
  • When you need to add services like memory, identity, or observability to an existing AWS agent.
  • When you require a structured plan and POC for deploying agents on AWS.

Advantages

  • Provides a deterministic, repeatable recommendation process.
  • Supports a wide range of AWS compute environments.
  • Offers a unified flow from initial idea to executable POC.
  • Adapts to both technical and business-focused user backgrounds.

Usage examples

“I have an agent idea, what do I build?”
The agent initiates the intake process to clarify your requirements and recommend an appropriate AWS architecture.
“Move my agents to AWS.”
The agent triggers the migration workflow to assess your existing workload and plan the transition to an AWS runtime.
“Which runtime for my agent, AgentCore vs ECS vs EKS vs Lambda?”
The agent runs a scoring analysis to compare these runtimes against your specific agentic needs.
“Add AgentCore services to an agent already on AWS.”
The agent enters the add-capabilities branch to guide you through integrating memory, gateway, and observability services.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/aws/agent-advisor/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip agent-advisor.zip -d .agents/skills

Documentation by AWS

AWS Agent Advisor

Helps startups decide how and where to run AI agents on AWS. Deterministic scoring recommends a runtime; the conversation adapts to the user's technical background.

Definitions

  • "Load" = Read the file with the Read tool and follow it. Do not summarize or skip.

  • $RUN_DIR = the run directory under .agent-advisor/ (e.g. .agent-advisor/0630-1430/), created in Intake.

  • $PLUGIN = ${CLAUDE_PLUGIN_ROOT} (the installed plugin root). On Claude Code this token substitutes inline. If ${CLAUDE_PLUGIN_ROOT} does not resolve (some Cursor/Codex builds, or a literal ${CLAUDE_PLUGIN_ROOT} string showing up in a path error), fall back to the skill's own directory: this SKILL.md lives at <plugin>/skills/agent-advisor/SKILL.md, so the engine and its data are all inside this skill — scripts at ./scripts/..., runtime profiles at ./references/runtimes/..., and decision refs at ./references/decision-refs/... relative to it. Prefer ${CLAUDE_PLUGIN_ROOT}/skills/agent-advisor/...; use the relative fallback only when it fails to resolve.

Prerequisites

Phase Structure (frontmatter)

Phase, fragment, and assembler files carry a YAML frontmatter block that declares how each phase is composed — its inputs, triggers, fragments, assembler, artifacts, gates, and ordering. The execution contract is the vendored references/vendored/dsl/INTERPRETER.md: it defines every frontmatter key, the fragment/assembler model, the gate protocol (HANDOFF_OK / GATE_FAIL), and the interpreter loop. Load it first (once, at the start of a run), then execute each phase file's prose body. Elsewhere in this skill, INTERPRETER.md (without a path) refers to this loaded contract.

Execution

This skill is driven by the interpreter loop in INTERPRETER.md (§ The interpreter loop): it reads .phase-status.json, determines the current phase, runs each phase's _preconditions / fragments / _assemble / _postconditions, advances on HANDOFF_OK via _advances_to, and validates state. The backbone (intake → discover → clarify → confirm → design → estimate → generate → migration-plan → poc → complete) and the one sidebar branch (add-capabilities) are derived from the phase files' frontmatter — they are not restated here.

Cold start (entry phase). With no run under .agent-advisor/ carrying a .phase-status.json, begin at references/phases/intake/intake.md — this skill's entry phase (the one carrying _init: true). On a warm start, current_phase in .phase-status.json is authoritative (INTERPRETER.md § The interpreter loop).

Skill bindings (INTERPRETER.md § Skill bindings). This skill declares:

  • Run root: .agent-advisor/ — $RUN_DIR is this skill's name for the run directory (.agent-advisor/[MMDD-HHMM]/). Intake's own prose performs the _init bootstrap.

  • State shape: § State file below (advisor-specific keys such as entry_point, audience, recommendation_reviewed, migration_plan_ctx, migration_plan_unavailable); the shared state schema is not vendored.

  • Run seed (optional): $RUN_DIR/seed.json, else .agent-advisor/seed.json at the run root (schema scripts/schemas/seed.json) supplies machine-readable answers for a non-interactive run — the Clarify dimensions, the two gate answers, the POC mode, the live-probe answer, and a co_recommend tie-break. It is the HIGHEST-precedence source for every value it carries (clarify.md Step 2.5), which is what makes a repeated run's score comparable: the deterministic engine gets byte-identical input. A gate the seed omits is declined; a dimension the seed omits falls through to detection, then prose, then an assumed value that MUST be recorded in $RUN_DIR/UNANSWERED.md. With no seed, the interactive flow is unchanged.

  • Resolved statuses: skipped (routing resolved the phase without running it), plus not_applicable for migration_plan only.

  • Conditional backbone routing: the entry-point routing below. When a routing rule marks a phase not-applicable, set it skipped and advance through its _advances_to in the same state write.

Routing & gates (orchestration)

Sidebar placement and conditional backbone routing are orchestration prose owned by this file (INTERPRETER.md § Skill bindings, § Backbone vs sidebar).

Entry-point routing:

  • build_scratch → skip Discover; Clarify → Confirm → Design → Estimate → Generate → Gate 2 → POC (any winning runtime). No migration plan (nothing existing to migrate).

  • build_deploy → Discover (if code) → Clarify → Confirm → Design → Estimate → Generate → Gate 1 → Migration Plan (if existing non-AWS AI workload detected and user confirms) → Gate 2 → POC (any winning runtime).

  • migrate → Discover (if code) → Clarify → Confirm → Design → Estimate (target-state run cost; migration TCO comparison stays with the Migration Plan engine) → Generate → Gate 1 → Migration Plan (in-skill, reusing the sibling gcp-to-aws skill) → Gate 2 → POC (any winning runtime, when the plan was produced). Declining Gate 1 keeps the classic handoff: pointer to /aws-startup-advisor:llm-to-bedrock with handoff-summary.md.

  • add_capabilities → load references/phases/add-capabilities/add-capabilities.md and follow it (no runtime scoring; writes capabilities-recommendation.md). This is a self-contained branch — it does NOT pass through Clarify / Confirm / Design / Estimate / Generate, so the phase gate below never applies to it.

  • Temporal detection routes into migrate with temporal units pre-seeded (see discover).

Gate semantics (backbone tail):

  • Gate 1 → migration_plan runs only when generate is done AND recommendation_reviewed == true (generate.md Step 5.5) AND entry point ∈ {migrate, build_deploy} AND the run is migration-eligible (generate.md Step 6) AND the user confirmed Gate 1. Otherwise resolve it: not_applicable (build_scratch / no migratable workload) or skipped (declined) — and advance.

  • Gate 2 → poc runs only when phases.poc == "in_progress" (set when the user answers Gate 2 "yes" — asked in generate.md Step 7 or migration-plan.md Step 6) AND recommendation_reviewed == true. Any winning runtime (agentcore / ecs / eks / lambda / lambda_microvms) — the POC shape follows the verdict (poc.md Step 3 dispatch on references/decision-refs/poc-shapes.md). Gate 2 is only offered when migration_plan ∈ {completed, skipped, not_applicable} — or in_progress on build_deploy only (Stage 2 failed/aborted; fallback POC from design.json per migration-plan.md failure handling); for entry point migrate, only when migration_plan == "completed" (the POC implements the plan) OR when the stage resolved not_applicable with migration_plan_unavailable == "engine_absent" — a standalone deployment that does not bundle the migration engine, where Gate 2 is offered by migration-plan.md Step -1 and the POC is design-backed. A migrate-POC with no plan for any OTHER reason (the user declined) has nothing to implement.

  • Persisting Gate 2 as phases.poc = "in_progress" BEFORE poc.md loads makes the confirmation resumable: if the session breaks between the "yes" and the load, the interpreter re-enters poc without re-asking. (A declared deviation from INTERPRETER.md § The interpreter loop step 5's gate-then-in_progress ordering — the user's confirmation is the entry event worth persisting.)

Phase gate: Do NOT load design.md / estimate.md / generate.md unless $RUN_DIR/.phase-status.json exists and BOTH phases.clarify == "completed" AND phases.confirm == "completed". Confirm confirms the deployment model, the service set, and (for a co_recommend tie) the user's chosen_runtime — Design and the diagram depend on its confirm.json output, so it must not be skipped. If the user asks to skip Clarify or Pass 2, refuse briefly and run it.

State file (.phase-status.json)

{
  "run_id": "0630-1430",
  "entry_point": "build_scratch",
  "audience": "technical",
  "current_phase": "clarify",
  "phases": {
    "intake": "completed",
    "discover": "skipped",
    "clarify": "in_progress",
    "confirm": "pending",
    "design": "pending",
    "estimate": "pending",
    "generate": "pending",
    "migration_plan": "pending",
    "poc": "pending"
  }
}

Status values: pending → in_progress → completed, plus skipped. Use read-merge-write: read before each update, change only the advancing keys, keep prior phases.

recommendation_reviewed (top level, boolean) is set to true by generate.md Step 5.5 when the user explicitly confirms they have seen the recommendation. Gate 1, Gate 2, and the migration_plan / poc states all require it — no gate may be asked while it is absent.

migration_plan additionally uses not_applicable (build_scratch, or no migratable workload detected). When Stage 2 runs, migration_plan_ctx is added at the top level: {"repo": "<abs path to target repo>", "migration_dir": "<abs path to .migration/<id>/>"} — Stage 3 reads gcp-to-aws artifacts ONLY via this recorded path, never by re-globbing.

Files

FilePurpose
references/vendored/dsl/INTERPRETER.mdVendored DSL execution contract (interpreter loop + gate protocol)
references/phases/intake/intake.mdEntry point + technical background + open context
references/phases/discover/discover.mdLightweight code detection
references/phases/clarify/clarify.mdClarify orchestrator + answer mapping to scoring keys
references/phases/clarify/clarify-technical.mdTechnical-background question wording
references/phases/clarify/clarify-business.mdBusiness-background question wording
references/phases/confirm/confirm.mdWinner-specific follow-ups
references/phases/design/design.mdAssemble recommendation; Migrate handoff branch
references/phases/estimate/estimate.mdCoarse cost magnitude
references/phases/generate/generate.mdLayered recommendation doc + scaffolding
references/phases/migration-plan/migration-plan.mdStage 2: full migration plan via the sibling gcp-to-aws engine
references/decision-refs/temporal.mdTemporal rules: Tier 1/2 tables, adapter, runbooks, commercials (consumed by discover/clarify/design/generate)
references/decision-refs/poc-shapes.mdPer-runtime POC deploy shapes (ECS/EKS/Lambda/MicroVMs/Temporal)
references/decision-refs/*.mdRuntime service cards, model defaults, freshness
references/decision-refs/workload-classes.mdDeterministic verdicts for non-agent workload units (batch/service/io)
references/runtimes/*.jsonRuntime registry (read by scoring.py)
scripts/scoring.pyDeterministic scoring engine
scripts/test_temporal_decision_refs.pyContent lock for the Temporal decision reference
scripts/test_poc_shapes.pyContent lock for the POC deploy shapes
scripts/test_workload_classes.pyContent lock for workload-classes.md (verdicts table)
scripts/test_unit_grouping.pyUnit grouping + pattern matching (workload-class assignment)
scripts/test_collapse_invariant.pyCollapse-invariant ordering enforcement (A→B implies [B] ⊆ [A] outputs)

Maturity and readiness contract

Intake persists target_maturity (prototype, private_beta, or production) in run state. Clarify carries it and the readable readiness record into answers.json. Current-run verification evidence remains exclusively in the sibling $RUN_DIR/current-run-verifications.json artifact: never copy it into seed.json or answers.json. Design and Generate may consume that artifact only after validating its schema and matching run_id, and may carry forward verified outcomes but not the raw evidence records. Load references/decision-refs/maturity-readiness.md whenever target maturity is selected. A cached volatile fact may inform discovery, but only a record verified in this run can make a verification-required constraint final; otherwise the score remains provisional with deferred verification requirements.

Contextual offers (final step)

Before you finish: your answer is not complete until you have run the Contextual offers (final step) below.

This is a mandatory closing step of every final recommendation — complete it before you consider your answer done. Run this offer check inline yourself; do not depend on loading another skill. The recommendation is decided on merit first; this step never changes, re-ranks, or re-opens it, and the offer is looked up only after the advice is final.

  1. Read ../knowledge-base-for-startups/references/offers.md — the offer index (Offer · Summary · Keywords), one row per offer.

  2. Judge relevance against what the founder actually surfaced this session. Surface an offer only if one holds: a named-product match (you recommended a specific partner product by name and it has a row); a direct intent/component match (an offer's Keywords directly serve a concrete workload, a component in the final recommendation, or a need the founder raised). Keep a high bar — if the match is weak, or you would be inferring an unstated need, append nothing. Never surface an offer that competes with a product or provider the founder already uses or decided to keep (e.g. existing auth provider → no Auth0 unless they are already on Auth0, and then only as a credit on it; existing vector DB such as Pinecone → no Qdrant).

  3. If (and only if) one offer clears the bar, open only its detail file ../knowledge-base-for-startups/references/offers/<slug>.md and append exactly one quiet, dismissible italic line — stating the value and condensing eligibility faithfully from that file (drop no qualifying criterion; never fabricate), with the redeem link built from the canonical source_url plus a source attribution param — append ?source=ide-startupAdvisor-<host> (or &source=... if the url already has a query string), filling <host> from your execution environment (Claude Code → claude; AWS Startup Advisor IDE extension / VS Code → vscode; Cursor → cursor; Kiro → kiro; Codex → codex), or the generic ide-startupAdvisor when you cannot tell. Only append the query param; never change the destination. When an offer clears the bar you MUST append that single offer line as the last step; do not omit it. The offer is never the pick — only a line under the AWS pick — and stage gates in the references apply (e.g. no Datadog line for an early-stage founder; see ../architect-for-startups/references/observability.md). For a single-service pick (auth, payments, vector DB, observability, etc.) where missing budget/team/traffic inputs would not change the pick, assume an early-stage (pre-PMF) startup unless the founder says otherwise and answer in one turn without a stage-only question; this only removes a stage-only question and never skips the Intake/Clarify/Confirm gates before final advice or the POC. Show exactly one, never a list. If none clears the bar, append nothing and do not mention offers, partner alternatives, or why none appeared.

Standard line:

***<Offer>** has an exclusive offer via AWS Activate — <value>, <eligibility>. [Redeem →](<source_url>?source=ide-startupAdvisor-<host>)*

Caps and control: at most one offer per response and often none; no more than one per five messages and two per session; show a given offer at most once per session and never one already shown, claimed, or dismissed; if the founder has muted offers, skip this step entirely. These per-five-messages, per-session, and already-shown caps are session-state limits; in a fresh session with no prior offers they are non-binding, so do not withhold an otherwise-qualifying offer merely because you cannot verify session history. See ../contextual-offers-for-startups/SKILL.md for the full rules — but perform the check inline; it must not depend on that skill being loaded.

Files

references/phases/poc/poc.md


_phase: poc _title: "POC — Deployment plan + deployable proof-of-concept" _requires_phase: migration-plan _input:

  • design.json

  • confirm.json _fragments:

  • _id: poc-report _trigger: { _always: true } _file: phases/poc/poc-report.md _assemble: _file: phases/poc/poc-assemble.md _produces:

  • plan.md _advances_to: complete _preconditions:

  • _check_file_exists: [design.json, confirm.json] _on_failure: _unrecoverable

  • _validate_json: [design.json, confirm.json] _on_failure: _unrecoverable _postconditions:

  • _check_file_exists: plan.md _on_failure: _halt_and_inform

  • _assert: "a deployment plan (plan.md) and a runtime-appropriate POC under poc/ were written (Step 3 dispatch on each unit's effective_runtime — the consolidated superset when platform.mode is consolidated, else the unit's resolved runtime — NOT the raw split verdict), with the exact invocation_model_id only when that workload's model-verification status is passed (otherwise a TODO: verify placeholder — never a fabricated or merely catalog-derived id) and deploy.sh guardrails; Mode B additionally left a created-resources ledger + cleanup.sh" _on_failure: _halt_and_inform


Phase: POC — Deployment plan + deployable proof-of-concept

Reached after the user confirms Gate 2 — on Build paths (build_scratch / build_deploy), or on migrate with a completed migration plan. Runs for ANY winning runtime: agentcore / ecs / eks / lambda / lambda_microvms — the artifacts differ by runtime (Step 3 dispatch), the flow does not. Completes the idea → plan → deploy journey: it first writes a deployment plan (plan.md — the staged "how to stand this up" steps), then a complete, deployable POC the user runs themselves. In Mode A (deliverables — the default) this phase generates files only — it NEVER runs deploy commands, never touches the user's AWS credentials, and never creates real resources; the user reviews the plan + artifacts, then runs ./deploy.sh themselves. Mode B (assisted build) is an explicit opt-in chosen at Gate 2b (Step 0) that executes the generated deploy steps in the user's account under the Step 4 safety contract.

When this phase runs

  • entry_point ∈ {build_scratch, build_deploy}, the PRIMARY unit's effective_runtime in {agentcore, ecs, eks, lambda, lambda_microvms} (the primary is always an agent unit per Clarify's scope gate). In a MULTI-unit system every unit still gets its own POC per Step 3 dispatch, including non-agent batch/fargate/serverless_workers units (their shapes are in poc-shapes.md, and a model-less non-agent unit omits Bedrock wiring); the gate keys on the primary agent unit, but the POC generation covers all units.

  • For migrate: POC runs when phases.migration_plan == "completed" (the POC implements the produced plan), OR when the plan stage resolved not_applicable with migration_plan_unavailable == "engine_absent" in .phase-status.json — a standalone deployment that does not bundle the migration engine (migration-plan.md Step -1). In that second case the POC is design-backed: build from design.json alone and label it "not plan-backed" exactly as Step 1 already prescribes for a skipped Stage 2. Otherwise — the user declined the plan, or it is missing for any other reason — migrate has nothing to implement and the flow completes after Generate/handoff.

  • This phase is only loaded after the user confirmed Gate 2 (asked in generate.md Step 7 or migration-plan.md Step 6).

Step 0 — Gate 2b: choose the POC mode

Ask via AskUserQuestion:

"How do you want the POC delivered?"

  • Mode A — Generated deliverables (recommended): I generate the deployment plan, agent code, and deploy script; you review and run ./deploy.sh yourself. Nothing touches your AWS account until you run it.

  • Mode B — Assisted build: after generating the same deliverables, I execute the deploy steps in your AWS account with you — confirming your AWS identity first and asking before every resource-creating or billable step. Creates real, billable resources.

Record the choice. Steps 1–3 run for BOTH modes (Mode B builds on Mode A's artifacts); Step 4 runs ONLY for Mode B; Steps 5–6 run for both.

Step 1 — Read inputs

Read $RUN_DIR/design.json (verdict, deployment_model, agentcore_services, model_recommendation) and $RUN_DIR/confirm.json (confirmed deployment model + services). The recommendation doc + diagram already exist from Generate; POC builds on those decisions. If $RUN_DIR/model-verification.json exists, read it as the only live account-invocability evidence.

Plan-backed POC (Stage 2 ran): if .phase-status.json has migration_plan_ctx and phases.migration_plan == "completed", ALSO read <migration_plan_ctx.migration_dir>/aws-design-ai.json — via the recorded path ONLY, never by re-globbing .migration/ (a glob can pick up a stale run). When present, it supplies implementation detail but MUST NOT replace the advisor-confirmed model/path in design.json. If Stage 2 did not run (skipped / not applicable / failed), proceed from design.json alone — the pre-existing behavior — and label the POC "not plan-backed" in plan.md.

Framework-migration POC (the 3-F trigger): when plan-backed AND aws-design-ai.json.ai_architecture.code_migration.primary_pattern == "framework" AND migration_path is NOT "mantle" or "gpt-oss", the POC is the user's own app, migrated (Step 3-F) — not a hello-agent. In that case also read from migration_plan_ctx.repo every original source file listed in code_migration.files_to_modify[]. If a listed file does not exist in the repo, warn and skip it; if NONE of the listed files exist, fall back to the hello-agent template and label the POC "plan could not be applied — see aws-design-ai.json" in plan.md and the README. Key the trigger on primary_pattern (a schema'd, checklist-enforced field) — NOT on the migration_path string, whose value is free-form outside mantle/converse/gpt-oss.

Step 2 — Resolve the Bedrock model id per unit (verify, don't guess)

For EACH unit in design.json.units[] whose model_recommendation is non-null, resolve the Bedrock model id for that unit — the recommendation and the POC code MUST agree per unit. A multi-unit system where the POC code for one unit uses a different model than that same unit's recommendation is a bug. (This is per-unit, not per-system: it is perfectly correct for content-review to run Nova Lite while support-chat runs Sonnet — as long as EACH unit's POC matches THAT unit's recommendation.)

Model-less units. A non-agent unit (batch/service/light_io/temporal_worker_poll) can have model_recommendation: null — it calls no Bedrock model. For such a unit do NOT resolve or fabricate a model id: its POC omits all Bedrock wiring (no model env var like BEDROCK_MODEL_ID, no bedrock:InvokeModel IAM permission, no model-access prerequisite in the README, no model-invocation code) — the generated POC is the runtime shape ALONE (container/job + its trigger), never a Bedrock-calling agent. This applies to a model-less SECONDARY unit in a mixed system (the primary is always an agent unit per Clarify's scope gate). Only dereference model_recommendation.model when it is non-null.

design.json is the single source of truth for model and API path. Its per-unit model_recommendation is the accepted output of Model Recommend. Migration Plan validates that contract but never replaces it. Resolve each unit's model and api_path from ITS OWN entry; never take one unit's decision from another or from a run-wide plan scalar.

For each unit, design.json.units[<id>].model_recommendation.model carries the selected path-specific model ID (for example, anthropic.claude-sonnet-5). model_recommendation.invocation_model_id is the exact account-callable ID only after CRIS resolution. These identities must remain separate.

Use an invocation ID in runnable code only when that unit's model-verification.json record has status: passed and exactly matches the recommendation's api_path and invocation_model_id. A catalog date, an AWS MCP Server lookup, user acceptance, or a non-null CRIS-shaped string is not proof of account access. If the probe was not run, failed, or needs resolution, write a clearly marked TODO: verify model id placeholder in generated files and state that the POC has not established runnable model access.

Separate-modality entries under additional_targets (embeddings, images, audio) with status: unresolved have no chosen model id. Never invent one: emit a TODO: select and verify <capability> model/service placeholder naming the recommendation's service, and keep the capability out of the runnable text-model path.

Mode A does not access AWS credentials, so it never runs a new probe. In Mode B, if live verification is missing, ask before the billable model call and run scripts/verify_model_path.py against the recommendation. Never substitute another model when the probe fails. To change a model/path/profile, update the Model Recommend input, rerun the engine, and reconfirm.

Plan-backed cross-check (optional): when aws-design-ai.json is loaded you may confirm a unit's id against its OWN matching design block — match the block whose source_paths[] overlap that unit's evidence (NOT design_blocks[0], which is only the first unit's block). The block's target_bedrock_model and path should equal model_recommendation because Step 3.5 validated them. If they differ, stop and return to Model Recommend; do not choose one silently.

Strip environment annotations from the model id. The running assistant's model name may carry a context-window annotation like [1m] (e.g. us.anthropic.claude-sonnet-5[1m]). That suffix is a harness label, NOT a valid Bedrock model/inference-profile id — a Bedrock call with it 404s. Before writing the id into any generated file, strip any trailing [...] bracket annotation. The id you emit must be exactly what Bedrock accepts (e.g. us.anthropic.claude-sonnet-5). If unsure of the exact id, use the TODO: verify model id placeholder rather than a bracket-tagged string.

Single-unit path: when units[] length is 1, the above logic applies to the one unit — resolve from design.json.units[0].model_recommendation, not a system-level field. The model id is always per-unit.

Step 2.5 — Write the deployment plan ($RUN_DIR/plan.md)

Before generating any code, write the deployment plan — the "how to stand this up" bridge between the recommendation (what to build) and the POC files (the built artifacts). This is the plan in idea → plan → deploy. Write it to $RUN_DIR/plan.md. Keep it concrete and staged; derive every item from design.json / confirm.json — plus, when plan-backed, from aws-design-ai.json: stage the steps to implement the migration plan's design blocks (one stage per design_block where sensible), and add a final "full migration" pointer to the complete guide in migration_plan_ctx.migration_dir. Never from assumptions. Include:

The plan is the deploy source-of-truth for whatever runtime the POC actually targets — it MUST match each unit's effective runtime (Step 3 dispatch), never assume AgentCore. Key items 1–3 on the effective runtime:

  1. Goal — one line: stand up a POC of the user's agent/workload on its effective runtime to validate it. (AgentCore → "validate the agent loop"; ECS/EKS/Fargate → "validate the container + Bedrock connectivity" for a model-bearing unit, or just "validate the container runs" for a model-less unit; Lambda → "validate the function + trigger"; Lambda MicroVMs → "validate the microVM function (or standard-Lambda fallback if unverified)"; AWS Batch → "validate the job submits and runs"; Temporal worker → "validate the worker connects and picks up tasks".) Never claim "Bedrock connectivity" for a unit whose model_recommendation is null.

  2. Prerequisites — AWS account + credentials, target region, Bedrock model access for the resolved model id ONLY when the unit is model-bearing (a model-less non-agent unit — model_recommendation: null — has NO Bedrock prerequisite; omit it), plus the runtime's tooling: uv + agentcore CLI for AgentCore; Docker + AWS CLI + Terraform for ECS / Fargate / Lambda / Lambda MicroVMs / Batch; Docker + AWS CLI + kubectl + an existing EKS cluster (no Terraform) for EKS. Only list the tools the effective runtime actually needs. Mark any TODO: verify items.

  3. What gets created — the AWS resources THIS runtime's shape provisions (from poc-shapes.md): AgentCore Runtime + confirmed services for AgentCore; the resources in the shape's Terraform create-allowlist for ECS/Fargate/Lambda/Lambda MicroVMs/Batch; for EKS, the Kubernetes objects kubectl apply creates in the agent-advisor-poc-<run_id> namespace (no cluster, no Terraform-managed AWS resources) — so the user knows the blast radius and that it is billable.

  4. Staged steps — numbered, each with a verification and, where relevant, a rollback. Match the stages to the POC variant:

    • Harness (3-H): Stage 1 review generated harness.json + system prompt → values match intent. Stage 2 (Gateway) point at your existing API/MCP endpoint → endpoint reachable. Stage 3 ./deploy.sh → agentcore status shows deployed/READY. Stage 4 smoke test via agentcore invoke (pass the target flag when the aws-target is not named default). Stage 5 (Memory) validate cross-session recall — recall needs a stable actor identity across invocations and long-term extraction is asynchronous; allow a few minutes.

    • Framework migration (3-F): Stage 1 review the migrated files (diff vs your original code — the changes come from the migration plan) → changes match aws-design-ai.json. Stage 2 run the compile check locally (python -m py_compile on each .py) → all pass. Stage 3 (optional, needs deps + AWS creds) run the entrypoint server locally and POST /invocations → model responds. Stage 4 ./deploy.sh → /ping returns healthy. Stage 5 smoke test: POST /invocations with a real prompt → model responds.

    • Hello-agent (3a–3e): Stage 1 review agent.py + config → values match intent. Stage 2 ./deploy.sh → /ping returns healthy. Stage 3 smoke test: POST /invocations → model responds. Stage 4 (Memory, if enabled) validate recall. For every non-AgentCore runtime below, Stage 1 reviews the generated code + the shape's IaC against poc-shapes.md's create-allowlist, and Stage 2 runs the local compile/build check (python -m py_compile; docker build where the shape has a Dockerfile). The deploy and smoke stages differ PER RUNTIME — match the shape exactly, do not assume Terraform + run-task for all:

    • ecs / fargate (ecs-poc.tf): Stage 3 ./deploy.sh (typed-confirm, build/push image, terraform apply) → resources created. Stage 4 smoke: one-off aws ecs run-task / execute-command that curls the container's localhost endpoint → responds.

    • eks (k8s/*.yaml, requires an existing cluster): Stage 3 ./deploy.sh (build/push image, then kubectl apply -f k8s/ into agent-advisor-poc-<run_id>) → pods Ready. Stage 4 smoke: kubectl port-forward + local curl → responds. NOT Terraform, NOT run-task.

    • lambda (lambda-poc.tf): Stage 3 ./deploy.sh (terraform apply) → function created. Stage 4 smoke: aws lambda invoke (or trigger via the SQS event source) → returns.

    • lambda_microvms: Stage 3 ./deploy.sh per the lambda_microvms shape → deployed. Stage 4 smoke depends on the fallback state (poc-shapes.md lambda_microvms rule): if the MicroVMs config was MCP-verified this run (microvms.tf enabled), invoke the microVM endpoint per the shape; if NOT verified (microvms.tf.disabled stays disabled — the POC deployed as standard Lambda), use the standard Lambda smoke path (aws lambda invoke). Never assume a microVM endpoint exists when the config is unverified.

    • batch (batch-poc.tf): Stage 3 ./deploy.sh (terraform apply) → job definition/queue created. Stage 4 smoke: aws batch submit-job then poll to SUCCEEDED.

    • temporal_worker_poll: Stage 3 ./deploy.sh; Stage 4 the connectivity-and-pickup smoke worker on the isolated poc-smoke-<run_id> queue → the target result comes back.

    • Rollback — match the runtime: AgentCore code/3-F → agentcore destroy (TODO: verify); AgentCore Harness → no CLI destroy, delete the CDK CloudFormation stack (aws cloudformation delete-stack); ecs / fargate / lambda / lambda_microvms / batch → terraform destroy against the shape's .tf (plus deleting the ECR repo if the shape created one); eks → kubectl delete -f k8s/ (deletes exactly what kubectl apply created — the agent-advisor-poc-<run_id> namespace; NOT terraform destroy), per poc-shapes.md. Never tell a non-AgentCore plan to run agentcore destroy.

  5. Cost note — POC-scale is small but non-zero; point to recommendation §10, no dollar figures.

  6. Open placeholders — the TODO: verify items (model id / CLI flags / teardown) to confirm against AWS docs before deploying.

The deploy.sh and README.md generated in Step 3 must stay consistent with this plan (same stages, same placeholders). If they diverge, the plan is the source of truth for the sequence.

Step 3 — Write the POC under $RUN_DIR/poc/

Multi-unit system decision gate: The number of poc/<unit-id>/ directories equals design.json.units[].length. A Temporal system is never one poc/app/ just because Temporal orchestrates it — count the units. If units[] has MORE THAN ONE unit, the system is MULTI-UNIT and must create poc/<unit-id>/ for EACH unit and apply the per-unit runtime dispatch (below) to each unit's own verdict. This applies to Temporal systems too — a Temporal system with a temporal_worker_poll unit plus Activity-class units (agent_session / batch / lambda) IS multi-unit, NOT one app. Do NOT collapse it into a single poc/app/ via the agentcore 3-F/3-H monolith path; the 3-F/3-H/3a-e branches are the PER-UNIT shape for an agent_session unit that landed on agentcore, applied INSIDE that unit's poc/<unit-id>/ directory — never to the whole system. Only if there is exactly ONE unit → flat layout (poc/app/ or the single-unit shape), and the 3-F/3-H/3a-e agentcore branches apply to that one unit.

Multi-unit POC structure (>1 unit): Create poc/<unit-id>/ per unit and apply the per-unit runtime dispatch below to EACH unit on its effective runtime (its own verdict under split, or the consolidated superset platform.runtime under consolidated — see "Effective runtime" below) (AgentCore branches for agent units on agentcore; poc-shapes.md shapes for the rest). For each unit, use THAT unit's model id from Step 2 — the handler/agent code, deploy.sh, and README for unit content-review must use content-review's model_recommendation, NOT unit[0]'s. Then write a top-level poc/README.md with the deploy ORDER (providers before consumers), per-unit deploy.sh pointers, and interconnect stubs — env-var wiring only (queue URL / endpoint URL passed between units), no cross-unit IaC. ONE aggregated cost warning + typed deploy confirmation up front (sum the per-unit warnings); each unit's deploy.sh keeps its own guardrails.

Effective runtime (resolve BEFORE dispatch). For each unit, the runtime the POC deploys on is its effective runtime, NOT necessarily its raw verdict:

  • If design.json.platform.mode == "consolidated", EVERY unit deploys on the consolidated superset design.json.platform.runtime (e.g. the user chose "consolidate onto ECS" — all units ship on ecs, regardless of each unit's own split verdict). The unit's original verdict still describes what it would have been on its own (the report shows the trade-off), but the POC, deploy.sh, and IaC target the superset runtime.

  • Otherwise (split), the effective runtime IS the unit's own verdict (or co_recommend chosen_runtime).

Per-unit runtime dispatch — dispatch on the effective runtime resolved above (not the raw verdict):

  • temporal_worker_poll units → the "Temporal worker POC" shape in references/decision-refs/poc-shapes.md, whose BASE shape follows the unit's effective_runtime: ecs → ecs base; eks → eks base (kubectl + existing cluster, Kubernetes Secret for the connection material, NO Terraform); serverless_workers is Public Preview and smoke-deploys on the ecs base. The Temporal deltas (smoke worker, poc-smoke-<run_id> queue, connection env contract) apply on whichever base the effective_runtime selected — an EKS-selected worker gets a Kubernetes POC, not ECS Fargate.

  • agentcore → the AgentCore branches below (3-H / 3-F / 3a–3e), unchanged.

  • batch / ecs / eks / fargate / lambda / lambda_microvms → load ${CLAUDE_PLUGIN_ROOT}/skills/agent-advisor/references/decision-refs/poc-shapes.md and generate EXACTLY the shape specified for the effective runtime (artifacts, Terraform create-allowlist, auth modes, smoke path, teardown). fargate uses the ## ecs shape — ECS-on-Fargate is the ecs shape's launch type (W5/W6 map to fargate; the ecs shape already provisions Fargate tasks), so a fargate verdict resolves to the ecs shape with no separate authoring. The deploy.sh guardrails template from 3d applies to every runtime (typed deploy confirmation, cost warning, env-var parameterization, no credentials). Steps 2 (model id) and 2.5 (plan.md) already ran and their outputs feed the shape. A plan-backed 3-F migration on a container runtime ships the user's migrated app in the Dockerfile instead of the hello agent — 3-F's file-selection logic applies before containerization.

For agentcore, BRANCH NEXT — the POC must implement what the user confirmed and what the migration plan prescribes, never silently fall back to the generic code path:

  1. deployment_model == "harness" → 3-H (Harness path). The deliverable is the declarative Harness project; do NOT make agent.py + a container the deploy artifact — that is the code path the user did not choose.

  2. deployment_model == "framework_on_runtime" AND the 3-F trigger from Step 1 fired (plan-backed, primary_pattern == "framework", not mantle/gpt-oss, at least one files_to_modify[] file exists) → 3-F (Framework migration path). The deliverable is the USER'S OWN APP with the migration plan's changes applied — generating a fresh hello-agent here contradicts the plan the user just approved.

  3. Otherwise (framework_on_runtime without a usable plan, or absent) → 3a–3e (hello-agent code path).

3-H. Harness path (deployment_model == "harness")

The Harness model is declarative: the agent is a configuration (model + system prompt + tools/Gateway + Memory), not custom serving code. Generate:

  1. poc/harness.json — the deployable agent declaration itself (NOT a side artifact): model id from Step 2, a one-line system prompt, the confirmed agentcore_services from confirm.json, session limits from the AgentCore card. Mark external wiring (Gateway targets, KB sources) as TODO.

  2. poc/deploy.sh — same guardrails as 3d (cost warning + typed deploy confirmation), but the commands are the Harness CLI flow, which is DIFFERENT from the code path: Harness deploys via the Node-based @aws/agentcore CLI (agentcore create / agentcore deploy with an agentcore.json project config) — NOT via the Python starter-toolkit's configure --entrypoint agent.py + launch (that toolkit only supports the code/container path). The exact Harness CLI commands are volatile: verify via the AWS MCP Server (freshness rule); if not verified this run, write the command block with # TODO: verify Harness CLI commands against AWS docs and say so in the README.

  3. poc/README.md — per 3e, plus one line stating this is a declarative Harness deployment: "no agent serving code to maintain; the agent is defined by harness.json."

  4. No agent.py, no Dockerfile — if a smoke-test client is useful, a short poc/invoke_test.sh (curl/CLI invoke) is enough. For the Harness CLI that is agentcore invoke "<prompt>" run from the project directory agentcore create actually generated (don't hardcode a guessed directory name), passing the target flag when the aws-target is not named default.

Then skip 3a–3d and continue at Step 4 (Mode B) or Step 5.

3-F. Framework migration path (plan-backed, primary_pattern == "framework")

The POC is the migrated version of the user's own app — the migration plan's code changes applied to their real source, packaged to deploy on AgentCore Runtime. It is a disposable deployment-proof, not the authoritative migration: the user's repo is never modified; the POC lives entirely under $RUN_DIR/poc/.

3-F.1 — Copy the app. Copy the repo (migration_plan_ctx.repo) into $RUN_DIR/poc/app/, EXCLUDING: .git/, .migration/, .agent-advisor/, __pycache__/, .venv//venv/, node_modules/, caches, and binary/media files (images, gifs, archives). Unlisted source files (e.g. prompts.py) are copied as-is — imports between files keep working.

3-F.2 — Apply the plan's changes, minimally. For each code_migration.files_to_modify[] entry, apply its changes[] to the copied file with these rules:

  • Minimal interpretation — make the smallest edit that satisfies the change description.

  • Skip optional/phase-2 items — any change marked "optional", "later", "phase 2", or that services_to_migrate defers (e.g. "swap in-process memory for the AgentCore Memory API later") stays UNAPPLIED; note it in the README under "deferred by design".

  • Drift guard — if a change references code that is not present in the current file (the repo moved since Discover), do NOT guess: leave that change unapplied and add a TODO: plan drift note at the top of the file and in the README.

  • Adapt mechanically-implied edits — e.g. if the original splats a settings dict into the old client constructor and the new client takes different kwargs, fix the settings construction too; removed env vars (per env_changes.remove) must not be read anywhere.

3-F.3 — Entrypoint server (do NOT implement the plan's contract text literally). The plan's agentcore_entrypoint field (when present) describes intent, not a working design — UI-framework session handlers (Chainlit/Streamlit/Gradio) are bound to their own server's session lifecycle and CANNOT be invoked from a plain POST. Build the honest structure instead:

  1. Extract the core LLM-call logic (build messages, invoke the migrated client, windowed memory keyed by a session id) from the UI handler into a shared module (e.g. poc/app/core.py), and have the UI handler call it.

  2. Add a separate entrypoint server (e.g. poc/app/agentcore_app.py) serving POST /invocations ({"prompt": ..., "session_id": ...} → shared core → response) and GET /ping (200) — same contract as the 3a template, but calling the user's migrated logic instead of raw boto3.

  3. The container CMD runs the entrypoint server. The original UI (e.g. chainlit run app.py) remains local-dev only — AgentCore Runtime invokes /invocations; it does not host a browser UI. Say this explicitly in the README. If agentcore_entrypoint is absent from the plan, use the standard contract above anyway.

3-F.4 — Dependencies: follow the repo's own tooling, and keep versions compatible. Apply code_migration.dependency_changes to the repo's existing manifest (pyproject.toml / package.json / requirements.txt — whichever the repo uses). Do NOT introduce a second, parallel manifest. If a lockfile exists (poetry.lock, package-lock.json, uv.lock), DELETE it from the copy and note in the README that the user must re-lock (poetry lock etc.) — a stale lockfile contradicting the edited manifest is worse than none.

Version-compatibility guard: when a change adds a package that constrains a package the repo pins, update BOTH so they are compatible — do not leave a manifest that cannot resolve. The common case: langchain-aws (the Bedrock LangChain integration) requires langchain-core / langchain from the 0.3+ line; a repo pinning langchain = "^0.1.x" (from its OpenAI era) will NOT resolve against langchain-aws >= 0.2. Bump the base langchain pin to the range langchain-aws needs (verify the exact floor via the dependency-conflict-resolution helper if available, or mark it TODO: verify langchain / langchain-aws version compatibility in the README). The rule generalizes: an added integration package and the framework it plugs into must share a resolvable version range.

3-F.5 — Verify what was generated. Run python -m py_compile (or the language's equivalent syntax check) on every generated/modified source file. Fix syntax errors before finishing. If dependencies aren't installable locally, note in the README that the compile check passed but an import-level check needs poetry install first. A POC that doesn't compile is a defect — this step is not optional. Clean up compile byproducts: py_compile writes __pycache__/ next to the sources — delete any __pycache__/ and .pyc files it created so they are not shipped in the POC.

3-F.6 — Dockerfile + deploy.sh + README.

  • Dockerfile: build from the repo's manifest (e.g. Poetry install), CMD = the entrypoint server from 3-F.3.

  • deploy.sh: the 3d template, with --entrypoint pointing at the 3-F.3 server file (NOT agent.py) and any build step the manifest requires.

  • README.md: per 3e, PLUS, prominently: (a) "This is the migrated version of YOUR app (from <repo>), generated as a disposable deployment-proof — your original repo was not modified"; (b) the list of applied changes and any deferred/drifted ones; (c) "For the authoritative in-repo migration (git branch, generated tests, behavior-delta review, quality eval), run /aws-startup-advisor:llm-to-bedrock" — the POC does not replace it; (d) the local-dev note for the original UI.

Then skip 3a–3d and continue at Step 4 (Mode B) or Step 5.

Code path (deployment_model == "framework_on_runtime", no usable plan) — 3a–3e

Create these files. Keep the agent minimal but genuinely runnable — a hello-agent that really calls the recommended Bedrock model and answers the AgentCore entrypoint contract (/invocations POST + /ping GET). Do NOT build scenario-specific business logic in v1.

3a. agent.py — minimal runnable agent
  • Implements the AgentCore entrypoint contract: POST /invocations (read prompt from the request body, call Bedrock Converse with the resolved model id, return the text) and GET /ping (return 200 for health).

  • Uses boto3 bedrock-runtime. Region from an env var (AWS_REGION), no hardcoded creds.

  • Include a one-line system prompt and echo the model's reply — enough to prove the loop works.

Code-path branch (per unit): read design.json.units[<unit-id>].model_recommendation.api_path. For mantle_messages, generate an AnthropicBedrockMantle Messages client. For runtime_converse, use the boto3 Converse template. For runtime_invoke, use boto3 InvokeModel with the provider-native body. The mantle_openai_chat and mantle_openai_responses paths use their matching OpenAI-compatible clients. Never branch on one run-wide migration_path string.

The template below applies only to runtime_converse. Use it verbatim for that path, substituting <MODEL_ID> with the Step 2 invocation ID for this unit (or the TODO: verify model id placeholder if the MCP was not called). For the other API paths, keep the same /invocations and /ping HTTP wrapper but replace the imports, client construction, and run_prompt implementation with the selected path's client. Do not paste a Converse call into a Mantle or InvokeModel POC. In a multi-unit POC, each unit's agent.py uses THAT unit's model decision from design.json.units[<unit-id>].model_recommendation:

"""Minimal AgentCore POC agent — proves the Bedrock loop works end to end.
Entry contract: POST /invocations (run a prompt), GET /ping (health)."""
import json
import os
from http.server import BaseHTTPRequestHandler, HTTPServer

import boto3

MODEL_ID = os.environ.get("BEDROCK_MODEL_ID", "<MODEL_ID>")
REGION = os.environ.get("AWS_REGION", "us-east-1")
SYSTEM_PROMPT = "You are a helpful assistant running as an AgentCore POC. Be concise."

_bedrock = boto3.client("bedrock-runtime", region_name=REGION)


def run_prompt(prompt: str) -> str:
    resp = _bedrock.converse(
        modelId=MODEL_ID,
        system=[{"text": SYSTEM_PROMPT}],
        messages=[{"role": "user", "content": [{"text": prompt}]}],
    )
    text = "".join(block["text"] for block in resp["output"]["message"]["content"] if "text" in block)
    stop_reason = resp.get("stopReason", "unknown")
    if not text or stop_reason in ("max_tokens", "model_context_window_exceeded", "guardrail_intervened", "content_filtered", "refusal", "tool_use"):
        raise ValueError(f"No complete text response (stopReason={stop_reason})")
    return text


class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == "/ping":
            self.send_response(200)
            self.end_headers()
            self.wfile.write(b'{"status":"healthy"}')
        else:
            self.send_response(404)
            self.end_headers()

    def do_POST(self):
        if self.path != "/invocations":
            self.send_response(404)
            self.end_headers()
            return
        length = int(self.headers.get("Content-Length", 0))
        body = json.loads(self.rfile.read(length) or "{}")
        prompt = body.get("prompt", "Say hello from AgentCore.")
        try:
            answer = run_prompt(prompt)
            payload = json.dumps({"response": answer}).encode()
            self.send_response(200)
        except Exception as exc:  # POC: surface the error to the caller
            payload = json.dumps({"error": str(exc)}).encode()
            self.send_response(500)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(payload)


if __name__ == "__main__":
    port = int(os.environ.get("PORT", "8080"))
    HTTPServer(("0.0.0.0", port), Handler).serve_forever()
3b. requirements.txt
  • boto3 (bedrock-runtime), plus the minimal web server deps for the entrypoint contract.

  • Pin nothing exotic; keep it a starter.

3c. Deployment config
  • Keep agent.py as the entrypoint; add a short note that AgentCore runs the container and expects the /invocations + /ping contract. (Harness deployments never reach this section — they follow 3-H, where harness.json IS the deploy artifact.)

3d. deploy.sh — one-command deploy (generated, NOT executed)
  • Compute-type guard (read design.json first): when the unit's agentcore_compute_type is "instances", the standard agentcore configure/launch flow below builds the microVMs shape — which cannot honor the very property (>8h session / GPU / instance type) that routed this unit to Instances. Do NOT silently ship it as the answer. Ship it as a functional POC with an explicit banner in deploy.sh and the POC report: "validates agent logic on microVMs; the production shape is the Instances compute type (capacity provider — EC2 instance types, sessions to 14 days), which this POC does not exercise", plus a next-steps block naming the capacity-provider setup (create capacity provider → create runtime with compute type Instances → same invoke path). Verify current capacity-provider CLI/API usage via the AWS MCP Server before writing that block (freshness rule).

  • A bash script that runs agentcore configure then agentcore launch --auto-update-on-conflict (the project's standard launch invocation).

  • Guardrails baked into the script: at the top, echo a clear warning that running it creates real AWS resources in the user's account and may incur cost; require an explicit read -p "Type 'deploy' to continue: " confirmation before any agentcore call.

  • Parameterize region + model id via env vars; do NOT embed credentials.

  • The exact agentcore CLI flags are volatile — verify current configure/launch usage via the AWS MCP Server (freshness rule). If not verified this run, keep the # TODO: verify current agentcore CLI flags against AWS docs comment above the commands.

Use this template:

#!/usr/bin/env bash
set -euo pipefail

# ⚠️  This creates REAL resources in your AWS account and may incur charges.
echo "This will deploy an AgentCore POC to AWS account: $(aws sts get-caller-identity --query Account --output text 2>/dev/null || echo '<not logged in>')"
echo "Region: ${AWS_REGION:-us-east-1}   Model: ${BEDROCK_MODEL_ID:-<MODEL_ID>}"
read -r -p "Type 'deploy' to continue: " CONFIRM
[ "$CONFIRM" = "deploy" ] || { echo "Aborted."; exit 1; }

export AWS_REGION="${AWS_REGION:-us-east-1}"
export BEDROCK_MODEL_ID="${BEDROCK_MODEL_ID:-<MODEL_ID>}"

# TODO: verify current agentcore CLI flags against AWS docs (AWS MCP Server)
agentcore configure --entrypoint agent.py --name "${AGENT_NAME:-poc-agent}"
agentcore launch --auto-update-on-conflict --env AWS_REGION="$AWS_REGION" --env BEDROCK_MODEL_ID="$BEDROCK_MODEL_ID"

echo "Deployed. Test with the curl in README.md. Tear down with: agentcore destroy  # TODO: verify"
3e. README.md — the POC runbook

Top of file, a prominent notice: "Running deploy.sh creates real resources in your AWS account and may incur charges." Then:

  • Follow the plan: point to ../plan.md as the staged deployment plan — the README is the runbook for the artifacts; plan.md is the sequence to follow.

  • Prerequisites: AWS credentials configured, target region, uv, the agentcore CLI installed, model access enabled for the resolved Bedrock model.

  • Deploy: ./deploy.sh (one command).

  • Test after deploy: a sample curl/CLI call to /invocations with a prompt, and the expected shape of the response.

  • Tear down: how to remove the POC (the agentcore destroy/delete path) so the user doesn't leave resources running — mark the exact command TODO: verify if not MCP-checked.

  • Cost note: POC-scale resources are small but non-zero; point to the recommendation doc's cost-magnitude section, no dollar figures here.

Step 4 — Mode B: assisted build (ONLY if chosen at Gate 2b)

Execute the generated deployment in the user's account. Safety contract — every point is mandatory; no step may be skipped or reordered:

  1. Deployment-model fidelity gate. Before touching any tooling, restate what is about to be deployed and confirm it matches confirm.json.deployment_model and the Step 3 branch taken: a Harness POC deploys the declarative harness.json via the Harness CLI (3-H); a framework-migration POC (3-F) deploys the user's migrated app container with the 3-F.3 entrypoint server as the entrypoint — NOT agent.py; a hello-agent POC deploys agent.py as a container. If the locally available tooling cannot deploy the confirmed model (e.g. only the Python starter toolkit — code path — is installed, but the user chose Harness), STOP and tell the user explicitly: "Your confirmed deployment model is <X>, but the installed CLI only supports <Y> — deploying <Y> would contradict the recommendation." Offer: (a) install/use the correct CLI, or (b) knowingly deploy the other model as a loop-proof POC, clearly labeled as NOT the recommended deployment model in plan.md, the README, and the final brief. Never silently substitute one deployment model for the other.

  2. Identity gate. Run aws sts get-caller-identity. On failure: instruct aws configure / aws sso login (suggest ! aws sso login to run it in-session) and re-check — never proceed unconfirmed. On success show Account / Arn / UserId via AskUserQuestion: "This identity will be used to create real, billable resources. Is this the intended (non-production) account?" Record the confirmed region and profile once; pass them explicitly (--region, --profile) on every subsequent AWS command.

  3. Command boundary. Execute ONLY the commands present in the generated deploy.sh (e.g. agentcore configure, agentcore launch) plus read-only verification calls (/ping, aws sts get-caller-identity, describe/list). Anything else — ad-hoc resource creation, VPC/network changes, modifying or deleting resources this run did not create — is out of bounds.

  4. Per-step confirmation. Before each resource-creating or billable command: show the exact command and its cost implication, and get an explicit yes via AskUserQuestion.

  5. Ledger before create. Append the intended resource to $RUN_DIR/poc/created-resources.json BEFORE running its create command ({"type": ..., "name": ..., "region": ..., "status": "pending"}), then update "status": "created" after — a crash between create and record must not orphan an untracked resource. On the code path, all resource names carry the run id suffix (e.g. poc-agent-<run_id>) for idempotency and safe teardown matching. On the Harness path, the CLI names resources itself (project/agent name + generated suffix) — do not promise run-id suffixes; instead record the actual names/ARNs (and the CloudFormation stack name) in the ledger after deploy, and make those the teardown match keys.

  6. Teardown script. Regenerate $RUN_DIR/poc/cleanup.sh from the ledger after every step. It deletes only ledger-listed resources, verifies each deletion, and reports leftovers instead of exiting silently.

  7. Stop on failure. Any failed step halts the flow: report what exists (from the ledger), point at cleanup.sh, and ask the user how to proceed. No automatic retry, no automatic rollback without confirmation.

  8. Never disable safety protections (deletion protection, versioning, backup retention).

  9. Back-propagate verified facts. After the deploy succeeds, revisit every TODO: verify in plan.md, README.md, deploy.sh, and invoke_test.sh that this run resolved empirically (actual CLI commands and flags, invoke payload/target format, teardown mechanism) and rewrite those files to state the verified fact instead of the placeholder. Scripts must contain the commands that actually succeeded this run — a generated script that contradicts the executed deployment is a defect, not a leftover. (cleanup.sh is already covered by point 5; this point extends the same discipline to the other artifacts.)

After the deploy succeeds: run the smoke test from plan.md Stage 4 — POST /invocations on the code path, or agentcore invoke on the Harness path (pass the target flag when the aws-target is not named default) — show the result, then show the teardown instructions (cleanup.sh) as the LAST message — the user decides whether the POC stays up.

Step 4.5 — Generate the HTML POC report (both modes)

Load references/phases/poc/poc-report.md and follow it to produce $RUN_DIR/poc/poc-report.html and open it in the browser. Runs for BOTH Mode A and Mode B (Mode B additionally shows the deployed-resources ledger). Non-blocking — if it fails, log a warning and continue to Step 5.

Step 5 — In-chat brief

Point the user first to the deployment plan at $RUN_DIR/plan.md (idea → plan → deploy), then to the POC files at $RUN_DIR/poc/. List the files and state plainly:

  • The flow is idea → plan → deploy: plan.md is the staged how-to; poc/ is the generated artifacts; deployment is the user's own action.

  • Mode A: In Mode A, this advisor generated the files but will not deploy them — deployment is the user's explicit action via ./deploy.sh.

  • Mode B: list created resources from the ledger (created-resources.json) and point at cleanup.sh.

  • What ./deploy.sh will do and that it creates real, billable resources.

  • Any TODO: verify placeholders that remain (model id / CLI flags / teardown command) and that they should be confirmed against AWS docs before deploying.

Step 6 — Write state

Set phases.poc = completed. The advisor flow is complete.

Maturity/readiness boundary

A deployable POC proves only the bounded technical hypothesis in plan.md; it is not private-beta or production launch readiness. Read design.json.target_maturity, readiness, and release/evaluation gates before writing the plan. The plan and final brief must list unmet controls, deferred runtime verifications, and tier gates as launch blockers. A POC may proceed for learning with those items open, but it must never be presented as authorization to launch beyond the prototype scope.

Requirements and compatibility

Written for: Claude Code

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Names Claude Code tools, Needs Python

Security

What our scanner noticed· Low risk

  • Scripts that your agent may run

This skill includes scripts that your agent may run. Read them before you use it.

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
AWS
Publisher
AWS (Official)
Source
aws/agent-toolkit-for-aws · plugins/aws-startup-advisor/skills/agent-advisor · commit 0a218f8
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • NOTICE (added by AutoGineer from NOTICE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by AWS or AWS.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download agent-advisor.zip