3bc7d13796 fix(aws-startup-advisor): default to bedrock-runtime in llm-to-bedrock and gcp/azure AI guidance, add a Runtime Anthropic Messages lane (#585)
* fix(aws-startup-advisor): refresh GPT-5.4/GPT-5.5 Bedrock endpoint metadata from the public model cards

The plugin recorded GPT-5.4 and GPT-5.5 as bedrock-mantle-only (no CRIS, no
inference profile, no bedrock-runtime surface) with Chat Completions
"unconfirmed", a 272K context window and no long-context price tier, and the
canonical catalog cited "internal reference" probes as provenance. The public
model cards no longer say any of that. This PR corrects the metadata only; it
does not change endpoint selection, dispatch, or add new code paths.

Sources (read 2026-11-06 via the AWS Documentation MCP tools):
- https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-54.html
- https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-55.html

What the cards state, now recorded verbatim in the catalog and prose:
- Endpoints: bedrock-runtime supported (Responses, Chat Completions, Converse;
  not Messages/Invoke) and bedrock-mantle supported (Responses, Chat
  Completions). Runtime has no in-region form; requests name
  us.openai.gpt-5.4 / global.openai.gpt-5.4 and us.openai.gpt-5.5 /
  global.openai.gpt-5.5. Mantle in-region: 5.4 = us-east-1, us-east-2,
  us-west-2, us-gov-west-1; 5.5 = us-east-1, us-east-2. US Geo CRIS from 6
  regions, Global CRIS from 33.
- Context 1,050,000 tokens shared, 128,000 max output.
- Pricing (Standard, In-Region only; Priority/Flex unsupported): 5.4 short
  2.75 / 0.275 cache read / 16.50, long 5.50 / 0.55 / 24.75, GovCloud short
  3.375 / 0.3375 / 20.25; 5.5 short 5.50 / 0.55 / 33.00, long 11.00 / 1.10 /
  49.50. No Geo/Global price rows, so prose keeps the ~10% figure for these
  two on every inference option and never claims parity.
- Runtime features: invocation logs, streaming, Guardrails and application
  inference profiles (Converse only), implicit prompt caching and structured
  outputs (Responses only); no server-side tool use.

Changes:
- skills/shared/ai/models/openai-bedrock.json: GPT-5.4/5.5 rows re-sourced to
  the public cards (no "internal reference"), mantle_openai_chat available,
  runtime_converse path with CRIS, inference_profiles (us/global),
  region_availability, pricing tiers, context/output limits; path-level
  constraints corrected.
- Canonical shared docs: ai-openai-to-bedrock.md (Tier 0 table, region gate,
  caching, Bedrock-native section, volume guidance), ai-migration-guardrails.md,
  schema-design-aws-ai.md (ban is on BARE ids paired with converse/runtime,
  not on the models), bedrock-pricing-cache.md (rows, long-context table,
  caching note, GovCloud rate).
- gcp-to-aws and azure-to-aws: references/shared/openai-on-bedrock.md,
  shared/schema-design-aws-ai.md (azure), design-ai.md, design.md/generate.md
  _assert lines (azure), generate-artifacts-ai.md (azure), generate-ai.md,
  discover-preview.md and clarify-ai-only.md (gcp), clarify-ai-only.md (azure).
- bedrock-migration-assessment clarify-ai-only.md; agent-advisor
  model-recommend.md (documents the engine's current GPT-5.x reshape as an
  engine limitation, not a model fact).
- llm-to-bedrock: resolve-bedrock-model-id.md (Case A/B), behavior-delta
  openai-to-bedrock.md, SKILL.md (two id-form sentences); docstrings/comments
  in preflight_bedrock.py, iam_policy.py, bedrock_pricing.py and the preflight
  404 remedy string. The is_mantle_model / is_mantle_gpt ID-form logic is
  unchanged.
- agents: llm2bedrock-code-rewriter.md (Converse rule is id-form-dependent),
  llm2bedrock-report-generator.md (cost text), llm2bedrock-prompt-evaluator.md.
- openai_model_recommendation.py: only the chat_completions_to_responses block
  message text (dropped the "GPT-5.x on Mantle rejects Chat Completions" claim).
- Tests: tests/test_gpt6_review_round2.py, test_gpt6_review_round5.py,
  test_gpt6_round4_findings.py and agent-advisor
  scripts/test_openai_model_recommendation.py now assert the corrected public
  facts (CRIS ids present, "mantle-only"/"no CRIS"/"unconfirmed" absent, catalog
  provenance is the public card). New regression tests in
  test_preflight_bedrock.py, test_iam_policy.py, test_bedrock_pricing.py prove
  us./global.openai.gpt-5.4|5.5 classify as runtime and bare ids as mantle in
  all three helpers.
- Vendored copies under agent-advisor, gcp-to-aws, azure-to-aws re-synced with
  tools/sync-vendored.py.

Validation (all run from the worktree with mise Python 3.12):
- mise -C plugins/aws-startup-advisor run ci: PASS
  - lint:md 0 errors; lint:model-id OK (19 retired IDs enforced);
    lint:model-staleness fresh (4d old, 45d window);
    lint:model-catalog-drift OK (3 pre-existing warnings: sonnet-5-5,
    haiku-5-5, gpt-6.1-terra not in catalog; unrelated);
    lint:startup-model-pricing OK; lint:artifacts PASS (99 checked, 0 errors);
    lint:vendored-parity PASS (62 files byte-identical);
    lint:skill-refs PASS (1482 checked, 0 missing);
    lint:consent-disclosure OK;
    test: 1395 passed, 222 subtests passed;
    test:telemetry: 311 passed; test:heroku-source-review: 44 pass, 0 fail
- agent-advisor pytest (skills/agent-advisor/scripts): 564 passed, 0 failed
  (562 at base + 2 new)
- llm-to-bedrock pytest (skills/llm-to-bedrock/scripts): 418 passed, 0 failed
  (415 at base + 3 new; needs --with httpx --with aws-bedrock-token-generator)
- root: python3 tools/validate.py "All validations passed";
  mise run lint:md 0 issues / 2763 files; lint:manifests, lint:skill-parity,
  lint:spec all pass; test:tools 6 OK. mise run build's security step fails on
  a pre-existing gitleaks false positive in upstream commit f8d09fd1
  (tests/test_bedrock_migration_assessment_discover.py:118, "claude-3.5-sonnet");
  gitleaks protect over this change set: no leaks found.
- grep over plugins/ for mantle-only / "no CRIS" / "no inference profile" /
  "no runtime path" / "unconfirmed" / "internal reference" / "no 1M tier"
  near GPT-5.4/5.5: no remaining claims (only negative test assertions and
  the bare-id rule "bare proprietary openai.gpt-* IDs use Mantle only").

Base: 0a218f8cc1 (upstream/main)

* fix(aws-startup-advisor): pin and disclose the GPT-6 Chat fallback shift caused by the GPT-5.4/5.5 catalog facts

Review round 1 (CHANGES_REQUESTED, 2 blockers) on c1944a53.

Finding 1: recording the public GPT-5.5/GPT-5.4 facts in
skills/shared/ai/models/openai-bedrock.json (mantle_openai_chat available,
region_availability) changes agent-advisor recommendations through the
unchanged catalog-order fallback in openai_model_recommendation.py
(_mantle_candidate_order -> _catalog_model_for_path): GPT-5.5 and GPT-5.4
precede GPT-6 Astra in catalog key order, so a GPT-6 Sol / 6.1 Sol Chat
Completions source outside us-east-1 now lands on
- openai.gpt-5.5 via mantle_openai_chat in us-east-2 (base: decision_required,
  mantle_region_unavailable, options mantle chat / runtime_converse)
- openai.gpt-5.4 via mantle_openai_chat in us-west-2 (base: openai.gpt-6-astra)
and a GPT-5.6 Sol Responses source in us-west-2 lands on openai.gpt-5.6-terra
(base: openai.gpt-5.5, whose cataloged footprint is us-east-1/us-east-2 only).
The previous commit message called this PR "no behavior change"; that was
wrong for these cells. The catalog facts are kept (they are what the public
cards state); the engine ordering is NOT changed in this PR. Instead:
- skills/agent-advisor/scripts/test_openai_model_recommendation.py: new
  regression tests pin all five cells so the shift is deliberate and visible
  (test_gpt6_chat_outside_own_footprint_falls_back_to_in_region_gpt5_chat x4,
  test_gpt56_sol_responses_outside_us_east_skips_gpt55_for_in_region_terra).
- skills/agent-advisor/references/phases/model-recommend/model-recommend.md:
  the engine-limitation paragraph now states that Chat fallbacks walk catalog
  order, that GPT-5.5/5.4 precede GPT-6 Astra, and that a GPT-6 Chat source
  outside us-east-1 lands on GPT-5.5 (us-east-2) / GPT-5.4 (us-west-2); a
  newer-generation source falling back to an older-generation model is an
  engine ordering limitation to resolve in the follow-up selection PR (PR 2).

Finding 2: skills/agent-advisor/scripts/openai_model_recommendation.py:118-119
still said "the (Mantle-only) GPT-5.x family". Reworded to the engine fact
(GPT-5.x sources not recognized as same-model runtime identities map to Claude
tiers; GPT-5.5/5.4 do carry a cataloged runtime_converse path via us./global.
CRIS ids). Grep over plugins/ for mantle-only / "no CRIS" / "no inference
profile" / unconfirmed / "internal reference" near GPT-5.4/5.5/5.x is now
clean apart from negative test assertions, the GovCloud Opus 5.5 pricing row,
and the bare-id rule ("bare proprietary openai.gpt-* IDs use Mantle only").

Carry-forward for PR 2 (endpoint selection): reorder / tier the
mantle_openai_chat candidate walk so a GPT-6 source does not fall back to
GPT-5.4/5.5 ahead of GPT-6 Astra; add GPT-5.5/5.4 to _SOURCE_MODEL_KEYS so
they are recognized as same-model runtime identities.

No new behavior added; no dispatch or endpoint-selection code changed.
No vendored files affected (none of the three files is in the sync manifest);
lint:vendored-parity re-run and still 62/62 byte-identical.

Sources (public model cards, read 2026-11-06 via the AWS Documentation MCP tools):
- https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-54.html
- https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-55.html

Validation (run from the worktree with mise Python 3.12):
- mise -C plugins/aws-startup-advisor run ci: PASS
  - lint:md 0 errors; lint:model-id OK (19 retired IDs enforced);
    lint:model-staleness fresh (4d old, 45d window);
    lint:model-catalog-drift OK (3 pre-existing warnings, unrelated);
    lint:startup-model-pricing OK; lint:artifacts PASS (99 checked, 0 errors);
    lint:vendored-parity PASS (62 files byte-identical);
    lint:skill-refs PASS (1482 checked, 0 missing);
    lint:consent-disclosure OK (6 checked);
    test: 1395 passed, 222 subtests passed;
    test:telemetry 311 passed; test:heroku-source-review 44 pass, 0 fail
- agent-advisor pytest (skills/agent-advisor/scripts): 569 passed, 0 failed
  (564 at c1944a53 + 5 new)
- llm-to-bedrock pytest (skills/llm-to-bedrock/scripts): 418 passed, 0 failed
- root: python3 tools/validate.py "All validations passed";
  mise run lint:md 0 issues / 2763 files; lint:manifests, lint:spec,
  lint:skill-parity pass; test:tools OK. mise run build's security step
  still fails only on the pre-existing gitleaks finding in upstream commit
  f8d09fd1 (tests/test_bedrock_migration_assessment_discover.py:118);
  gitleaks protect --staged over this change set: no leaks found.

Base: 0a218f8cc1 (upstream/main)

* fix(aws-startup-advisor): scope the in. CRIS prefix and runtime feature constraints per model for GPT-5.4/5.5

The GPT-5.4 and GPT-5.5 model cards publish only us. and global. CRIS ids;
the in. profile exists for GPT-5.6 only. The runtime_converse path strength
and both schema-design vocabulary/checklist lines attached us./in./global.
to all three models, contradicting the catalog's own next constraint and
openai-on-bedrock.md. Rewritten so in. stays on GPT-5.6 / GPT-6.

The GPT-5.6 runtime constraint ("does not support server-side tool use,
structured outputs, or application inference profiles") is now scoped to
GPT-5.6, and a separate GPT-5.4/5.5 constraint records what their cards
mark: server-side tools unsupported; structured outputs and implicit prompt
caching Responses-only; Guardrails and application inference profiles
Converse-only.

Vendored copies re-synced (62 checked, 3 synced). Regression test added.

* fix(aws-startup-advisor): stop granting GPT-5.4/5.5 an in. CRIS id in the rewriter and Design/Generate checklists

bc51f0cc scoped the in. prefix to GPT-5.6 in the catalog and schema, but
three consumers of that rule still said us./in./global. for GPT-5.4/5.5:
agents/llm2bedrock-code-rewriter.md, gcp-to-aws design-ai.md's checklist,
and azure-to-aws generate-artifacts-ai.md's checklist. Their model cards
publish only us. and global. ids. Each now reads: us./in./global. for
GPT-5.6; us./global. only for GPT-6, GPT-5.5 and GPT-5.4.

Adds tests/test_gpt54_55_cris_prefix_scope.py, which reads the catalog, the
shared/Azure schemas, the guardrails guide, and the three consumer files and
fails on any window that pairs GPT-5.4/5.5 with a grouped us./in./global.
grant without scoping in. to GPT-5.6. Verified to fail against the previous
wording of all three files.

* fix(aws-startup-advisor): grant the in. CRIS prefix to GPT-5.6 Terra and Luna only, not Sol

The GPT-5.6 Sol card (read 2026-11-07) publishes us.openai.gpt-5.6-sol and
global.openai.gpt-5.6-sol only; Terra and Luna publish us./in./us-gov./global.
Prior wording granted in. to "GPT-5.6" family-wide in the catalog strength,
the rewriter, the GCP Design and Azure Generate checklists, both schema
copies, and ai-migration-guardrails.md ("GPT-5.6 Sol/Terra/Luna
(us./in./global.)"). Each now reads: us./in./global. for GPT-5.6 Terra and
Luna; us./global. only for GPT-5.6 Sol, GPT-6, GPT-5.5 and GPT-5.4.

tests/test_gpt54_55_cris_prefix_scope.py now also scans the catalog strength
text and rejects any grouped in. grant to GPT-5.6 that does not name
Terra/Luna and place Sol in the us./global.-only set. Verified to fail
against the dfd07bdc wording of every file above.

* fix(aws-startup-advisor): address PR 583 review — GPT-5.4/5.5 default-project IAM grant, Converse for application profiles, In-Region-only pricing

Three inline findings by leon1418 on 6b873f8c, each verified against the public
GPT-5.4 / GPT-5.5 model cards (read 2026-11-07):
https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-54.html
https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-55.html

1. IAM default-project grant (iam_policy.py:29). The cards require
   bedrock:InvokeModel on arn:aws:bedrock:{region}:{account-id}:project/default in
   addition to the inference profile. iam_policy.py gated that grant on
   is_gpt6_cris_model(). Added is_gpt54_55_cris_model() (exact us./global.
   openai.gpt-5.4 / -5.5 short ids and their inference-profile ARNs; bare mantle
   ids, GPT-5.6 CRIS ids and unrelated models do not match) and
   requires_default_project_grant(); generate_policy() now emits the third ARN
   for those ids. Updated the GPT-6-only sentence in gcp generate-ai.md,
   gcp/azure generate-artifacts-ai.md Step 3, and the report generator §6.4.

2. Application inference profiles are Converse-only (gcp design-ai.md:425).
   GCP and Azure Design now require required_client_api: "converse" when
   application inference profiles are the driving need on GPT-5.5 / GPT-5.4
   (and any model whose card lists them Converse-only), forbid leaving the field
   absent, keep the responses default for a region-only move, and record a
   conflicting Responses-only need (structured outputs, implicit caching) as an
   explicit decision instead of a silent drop. Added checklist items to the GCP
   Validation Checklist and the Azure shared schema (required_client_api section
   and checklist).

3. Unpublished Geo/Global prices (ai-openai-to-bedrock.md:46). The cards publish
   commercial In-Region prices only. Scoped the verified ~10% premium to the
   In-Region option in the canonical guide (Tier 0 rows included), both
   openai-on-bedrock.md fact bases, the report generator and the pricing-cache
   rows; a CRIS plan needs a separately sourced Geo/Global price or reports the
   comparison unavailable, and an In-Region proxy is an unverified planning
   assumption with no verified premium or savings percentage.
   bedrock_pricing.lookup() already returns available:false for the CRIS ids;
   pinned with a test (short ids and profile ARNs, no PriceList call).

Tests: test_iam_policy.py TestGpt54Gpt55CrisProjectArn (short ids, profile
ARNs, bare/GPT-5.6/Anthropic controls, mixed run); test_bedrock_pricing.py
test_gpt54_55_cris_ids_are_unpriced_not_inferred_from_in_region; new
tests/test_gpt54_55_runtime_review_round3.py text contracts for all three
findings. tools/sync-vendored.py re-run (5 copies synced).

Validation (this commit, in the worktree):
- mise -C plugins/aws-startup-advisor run ci: exit 0 (test 1407 passed +
  222 subtests; test:telemetry 311 passed; heroku-source-review 44/44;
  lint:md 0 errors; vendored-parity PASS 62 files; skill-refs PASS 1482)
- llm-to-bedrock: uv run --project scripts python -m pytest: 453 passed
  (bare mise python3 shows 10 ModuleNotFoundError: httpx in
  test_astra_execution_contract.py — environment, not the change)
- agent-advisor: python3 -m pytest skills/agent-advisor: 570 passed
- tests/test_gpt54_55_cris_prefix_scope.py: still green
- python3 tools/validate.py: All validations passed (exit 0)
- tools/sync-vendored.py --check: PASS
- mise run security (gitleaks): 1 pre-existing upstream false positive at
  f8d09fd1 (tests/test_bedrock_migration_assessment_discover.py,
  generic-api-key), unrelated to this PR; nothing new flagged.

* fix(aws-startup-advisor): scope the 1.10x Geo rate to GPT-5.6

GPT-5.4 and GPT-5.5 publish an In-Region price only, so a Geo or Global plan stays unpublished.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(aws-startup-advisor): state the bedrock-runtime default endpoint policy and make Runtime the primary same-model OpenAI path in design guidance

Base: 6b873f8c (PR 1 #583 tip). Public basis: Amazon Bedrock User Guide
endpoints.html, models-endpoint-availability.html, inference-responses-api.html,
inference-chat-completions.html, inference-messages-api.html,
tool-use-server-side.html, web-search.html, projects.html, workspaces.html,
cost-mgmt-application-inference-profiles.html, model-invocation-logging.html,
monitoring-mantle-metrics.html, quotas-runtime.html, quotas-mantle.html,
scaling-throughput-best-practices.html (all read 2026-11-07).

- New canonical skills/shared/ai/bedrock-endpoint-policy.md (rule, mantle_selector
  enum, public matrix, lifecycle and quota wording), vendored into gcp-to-aws and
  azure-to-aws (README rows + sync).
- ai-openai-to-bedrock.md / ai-openrouter-to-bedrock.md: runtime_openai_cris with
  the source app's required_client_api is the Tier 0 default; mantle_* only with a
  mantle_selector; Runtime steps shown first; "smallest change" phrasing removed.
- Three schema-design-aws-ai.md copies: runtime_messages, messages,
  same_model_runtime, mantle_selector vocabulary; Runtime default stated.
- gcp/azure design-ai.md, azure design.md/generate.md _assert, gcp/azure
  generate-artifacts-ai.md, gcp generate-ai.md, gcp estimate.md, azure
  estimate-assemble.md, both openai-on-bedrock.md Client setup: Runtime first and
  labelled default, Mantle selector-gated, same_model_runtime route added.
- Fixtures: mantle_selector on the two mantle_openai_responses rows.
- Tests: new tests/test_endpoint_policy_contract.py; extended
  test_generate_mantle_dispatch.py, test_ai_only_option_c_framework_route.py,
  test_gpt6_review_round2.py, test_gpt6_round4_findings.py.

Verification (from plugins/aws-startup-advisor):
- python3 tools/sync-vendored.py --check -> PASS, 64 files
- uv run --no-project --with pytest python -m pytest tests -q -> 1406 passed
  (base 6b873f8c: 1398)
- uv run --project skills/llm-to-bedrock/scripts --with pytest python -m pytest
  skills/llm-to-bedrock/scripts -q -> 418 passed (unchanged)
- uv run --project skills/agent-advisor/scripts --with pytest python -m pytest
  skills/agent-advisor/scripts -q -> 570 passed (unchanged)
- mise run lint:md (0 errors / 823 files), lint:skill-refs (1508 refs, 0
  missing), lint:artifacts (99/0), lint:vendored-parity (64), lint:model-id -> PASS
- grep -rn -i -E 'primary path|smallest (possible )?change|remains the default|
  Mantle is the PRIMARY' skills | grep -v vendored -> every Mantle-related hit
  gone; remaining hits are pre-existing, unrelated to Bedrock endpoints
  (design-ref-harness.md:29, heroku-to-aws, gcp elastic-beanstalk.md,
  prompt-library bedrock-quota-manager.md, agent-advisor test_unit_grouping.py).
  agents/llm2bedrock-code-rewriter.md:260 is left for the execution-lane change.

* feat(aws-startup-advisor): default Anthropic SDK migrations to the bedrock-runtime Messages endpoint in the shared guide and design/generate phases

The canonical ai-anthropic-to-bedrock.md now keeps anthropic.Anthropic and
repoints it at https://bedrock-runtime.\{region\}.amazonaws.com/anthropic with a
string Bedrock token minted per client (provide_token), records
migration_path "runtime_messages" + required_client_api "messages", moves the
boto3 Converse rewrite under an explicit-alternative section, and gates Mantle
Messages behind a mantle_selector. gcp/azure design-ai.md Anthropic lines,
gcp/azure generate-artifacts-ai.md Step 0/Step 1, the estimate route lists,
skills/shared/ai/README.md, gcp SKILL.md and the behavior-delta Anthropic
reference carry the same wording; vendored copies re-synced. Public basis:
inference-messages-api.html and inference-profiles-prereq.html (read 2026-11-07).

Verification (plugins/aws-startup-advisor):
- python3 tools/sync-vendored.py --check: PASS, 64 files byte-identical
- uv run --no-project --with pytest python -m pytest tests -q: 1407 passed, 222 subtests
- uv run --project skills/llm-to-bedrock/scripts --with pytest python -m pytest skills/llm-to-bedrock/scripts -q: 418 passed
- mise run lint:md: 823 files, 0 errors; mise run lint:skill-refs: 1514 checked, 0 missing; mise run lint:vendored-parity: PASS 64
- grep -rn 'Converse client swap' skills agents | grep -v vendored: no matches

* fix(aws-startup-advisor): fail closed on runtime_openai_cris plans without an API and add the Runtime Anthropic Messages lane to llm-to-bedrock

normalize_api_path now raises for a runtime_openai_cris plan that recorded
no source API instead of silently resolving to Converse; SKILL.md resolves
that case with the user (resolved_runtime_api) and only an explicit
required_client_api "converse" reaches the Converse rewrite. Adds the
runtime_messages execution lane: create_messages_client /
probe_runtime_messages_model (Anthropic SDK on bedrock-runtime /anthropic
with a string token minted per client), --runtime-api messages,
image_input.messages_message, the BedrockGetInferenceProfile IAM
statement for CRIS targets, the rewriter's Runtime Anthropic Messages
lane (Mantle express lane is now selector-gated, Converse rewrite is for
explicit converse plans), evaluator §6b/§9.5b and the §10 messages
branch, report-generator §6.4 and resolver notes, plus the endpoint
policy section in SKILL.md. Pins anthropic>=0.75,<1 in the scripts
project. Also un-indents the Converse snippet in the shared Anthropic
guide so the agent-advisor snippet test executes the right block.

Public sources (read 2026-11-07):
https://docs.aws.amazon.com/bedrock/latest/userguide/inference-messages-api.html
https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-prereq.html
https://docs.aws.amazon.com/bedrock/latest/userguide/endpoints.html

Verification (plugins/aws-startup-advisor):
- uv run --project skills/llm-to-bedrock/scripts --with pytest python -m pytest skills/llm-to-bedrock/scripts -q
  -> 431 passed (418 + 13 new), 0 failed
- uv run --project skills/agent-advisor/scripts --with pytest python -m pytest skills/agent-advisor/scripts -q
  -> 570 passed; git diff --stat 6b873f8c..HEAD -- skills/agent-advisor is empty
- python3 tools/sync-vendored.py --check -> PASS 64 files
- mise run ci -> exit 0 (lint:md 0 errors; lint:skill-refs 1517/0 missing;
  lint:vendored-parity 64; lint:artifacts 99/0; test 1408 passed + 222 subtests;
  test:telemetry 311; test:heroku-source-review 44)
- root: python3 tools/validate.py -> All validations passed; mise run validate -> exit 0
- root: mise run build -> lint + validate pass; security fails only on the
  pre-existing gitleaks finding in upstream f8d09fd1
  (tests/test_bedrock_migration_assessment_discover.py:118); not from this change
- gitleaks protect --staged -> no leaks found
- residual Mantle-default grep over plugins/*.md|*.json -> no hits

* fix(aws-startup-advisor): probe embedding ids via InvokeModel under a runtime_messages plan and align the Mantle Messages snippet with the public page

Review iteration 1 findings (review.json CHANGES_REQUESTED):

- major: preflight_bedrock.main() routed every non-Mantle id to the Messages
  probe when --runtime-api messages was set, so a runtime_messages plan whose
  $TARGET_MODELS also carried an embedding id (B1 collects every
  bedrock_models[].aws_model_id) failed preflight spuriously. Embedding ids now
  fall through to probe_model (InvokeModel) before the messages branch. New
  test_main_messages_plan_probes_embedding_ids_via_invoke_model covers a
  Claude profile + amazon.titan-embed-text-v2:0 list.
- minor: agents/llm2bedrock-code-rewriter.md Mantle express lane Anthropic row
  and snippet used base_url .../anthropic/v1 with auth_token=; the SDK appends
  /v1/messages, so that resolved to /anthropic/v1/v1/messages. Now
  base_url .../anthropic with api_key=, matching the public Messages API page
  (inference-messages-api.html, read 2026-11-07) and the shared guide.
- minor: evaluator §6b and §9.5b heredocs are now executed by
  test_runtime_messages_connectivity_snippet_uses_the_messages_client and
  test_runtime_messages_vision_snippet_sends_a_base64_source_block.
- minor: preflight_bedrock.py module docstring now scopes in. to GPT-5.6
  Terra and Luna, with GPT-5.6 Sol and GPT-6 Astra us./global. only.
- minor: the mantle_selector enum paraphrase is removed from
  skills/shared/ai/ai-openai-to-bedrock.md and gcp design-ai.md; both now
  point at references/vendored/ai/bedrock-endpoint-policy.md. The
  llm-to-bedrock SKILL.md section stays as the one permitted restatement.
  Vendored copies re-synced (tools/sync-vendored.py).

Verification (plugins/aws-startup-advisor, 2026-11-07):
- sync-vendored --check: PASS 64 (2 re-synced)
- llm-to-bedrock scripts: 435 passed (431 + 4 new)
- agent-advisor scripts: 570 passed; no non-vendored agent-advisor change
- mise run ci: exit 0 (lint:md 0 errors, lint:skill-refs 1520/0 missing,
  lint:vendored-parity PASS 64, lint:artifacts 99/0, test 1408 passed +
  222 subtests, test:telemetry 311, test:heroku-source-review OK)
- root python3 tools/validate.py: All validations passed; mise run validate: exit 0
- residual Mantle-default grep over plugins/aws-startup-advisor *.md/*.json: nothing
- gitleaks protect --staged: no leaks found

* fix(aws-startup-advisor): address PR 585 review round 1 — default-project grant by id form/API, per-row preflight APIs, mantle_messages lane gate, resolved_runtime_api in resume context

Re-checked each leon1418 finding against 6ca403b6 (post-rebase onto 8c37ef0f):

1. Default-project grant (ai-openai-to-bedrock.md:339). Partly satisfied by the
   rebase: 8c37ef0f grants project/default for GPT-6 and the GPT-5.4/5.5 CRIS
   ids, but GPT-5.6 Sol/Terra/Luna were still excluded and the grant was
   model-family-based. The public Responses API page
   (https://docs.aws.amazon.com/bedrock/latest/userguide/inference-responses-api.html,
   "Permissions", read 2026-11-07) authorizes bedrock:InvokeModel on the default
   project for every Responses request on bedrock-runtime, and the GPT-5.6
   Sol/Terra/Luna cards (read 2026-11-07) repeat it for their runtime CRIS ids
   (Chat tab included). iam_policy.py now classifies by id form
   (is_runtime_openai_cris_model: us./in./us-gov./global. openai.gpt-* ids and
   their inference-profile ARNs; _GEO_PREFIX gains in. and us-gov.) and decides
   the grant by the selected API (--runtime-api responses|chat_completions emit
   it, converse/messages do not, id-only keeps it). GCP generate-ai.md /
   generate-artifacts-ai.md, Azure generate-artifacts-ai.md, both
   openai-on-bedrock.md fact bases, the shared guide (+vendored copies) and the
   report-generator §6.4 recipe now state the rule and cite the page.
2. Mixed-model preflight (preflight_bedrock.py:417). Confirmed open: one
   --runtime-api was applied to every id. preflight gains --target ID=API pairs
   (per-row required_client_api; invoke for embeddings) and fails closed with
   reason unknown_runtime_api before any probe when a row's API is missing or
   unknown; --models/--runtime-api stays as the legacy single-API form. B1/B4
   pass each row as its own pair.
3. mantle_messages stop (SKILL.md:936). Confirmed open. New lane gate
   `preflight_bedrock.py --check-lanes aws-design-ai.json` (unsupported_lane_stop)
   halts before B2/B4/Phase C with a structured unsupported_lane result naming
   the deferred Mantle Messages lane and the workspaces selector; iam_policy
   --migration-path mantle_messages refuses to emit runtime permissions for the
   bare Claude id; the context rule no longer labels it converse. GCP
   generate-artifacts-ai.md Step 0: the broad Mantle branch is scoped to the
   three OpenAI-SDK spellings so mantle_messages matches exactly one branch and
   runtime_messages keeps Messages. The lane is not implemented.
4. resolved_runtime_api (SKILL.md:913). Confirmed open. The field is now in the
   C0 current-context field list (always present), resolved in B4 before
   preflight (read back from run-context.json on resume), and has an
   invalidation row (EVAL, REWRITE, REPORT archived; ANALYSIS, INGESTION kept).

Rebase-review non-blocking items: reworded the "keeps the `responses` default"
checklist sentences (gcp design-ai.md, azure shared schema-design-aws-ai.md) to
the source-API default rule; removed the EOF blank line in
tests/test_ai_only_option_c_framework_route.py.

Tests: test_iam_policy.py (id-form x API matrix incl. in./us-gov., Converse-only
and Anthropic/oss controls, CLI flags, mantle_messages refusal),
test_preflight_bedrock.py (offline fake SDK clients: Claude/Messages + GPT/Chat,
Claude/Messages + Nova/Converse + embeddings, fail-closed unknown API,
--check-lanes), test_validate_result.py (actual comparator: unchanged resume
matches, dropped field reproduces the reviewer's MISMATCH, changed API named),
tests/test_runtime_default_review_round1.py (text contracts + comparator).
Existing GPT-5.6 "no grant" assertions in test_iam_policy.py were flipped to
match the 2026-11-07 card read.

Validation (worktree fix-llm-to-bedrock-runtime-default):
- mise -C plugins/aws-startup-advisor run ci: EXIT 0 (lint:md 0 errors;
  vendored-parity 64 PASS; skill-refs 1521 PASS; artifacts 99 PASS; test
  1429 passed + 222 subtests; test:telemetry 311 passed; heroku 44 pass)
- llm-to-bedrock scripts pytest: 599 passed
- agent-advisor scripts pytest: 570 passed
- python3 tools/validate.py: All validations passed
- tools/sync-vendored.py --check: PASS 64 byte-identical
- git diff --check: clean
- mise run build (gitleaks): fails ONLY on pre-existing upstream f8d09fd1
  (tests/test_bedrock_migration_assessment_discover.py:118 generic-api-key,
  leaks found: 1) — not introduced by this branch

* fix(aws-startup-advisor): grant the default project per bedrock_models[] row in iam_policy (--target ID=API) so a GPT secondary under a Claude Messages primary keeps it

Review-gate finding B1 (pr585-review-round-1): the §6.4 report-generator recipe
passed the primary's single `Target API surface` as --runtime-api for every id,
and generate_policy applied it to all ids, so a runtime_messages plan with a GPT
Chat/Responses secondary emitted no arn:...:project/default for that secondary
(a regression against 6ca403b6's id-only call).

- iam_policy.py: new repeatable `--target <aws_model_id>=<required_client_api>`
  form (parse_targets, fails closed with reason unknown_runtime_api before any
  policy is built) and a `target_apis` kwarg on generate_policy; each row's own
  API decides requires_default_project_grant for that id, overriding the
  plan-wide runtime_api. `--models --runtime-api` stays as the legacy single-API
  form; --models/--target are mutually exclusive; the mantle_messages lane stop
  still wins over every other check.
- llm2bedrock-report-generator.md §6.4: recipe passes one --target pair per
  bedrock_models[] row read from aws-design-ai.json (primary row = Target API
  surface; `invoke` for embedding rows), explicitly forbids applying the
  primary's surface to other rows, reports unknown_runtime_api verbatim, and
  documents the legacy form as single-row only.
- Shared guide IAM step, GCP generate-ai.md / generate-artifacts-ai.md and Azure
  generate-artifacts-ai.md recipes name the per-row form; both vendored copies
  of the shared guide re-synced (byte-identical).
- Tests: test_iam_policy.py TestPerRowTargetApis (reviewer's spot-check as the
  regression; Claude/messages + GPT/chat -> project/default exactly once;
  Claude/messages + Nova/converse + embeddings/invoke -> absent; GPT chat row
  beside GPT converse row -> once; row API overrides plan-wide; fail-closed
  parse; CLI --target grant / unknown API exit 1 / mutual exclusion).
  tests/test_runtime_default_review_round1.py: text contract pinning the §6.4
  recipe (--target per row, no --runtime-api in the command, per-row warning,
  unknown_runtime_api) and the four setup recipes; mixed plan driven through
  parse_targets + generate_policy.

Validation (run in this worktree, mise python 3.12):
- mise -C plugins/aws-startup-advisor run ci: exit 0 -- test 1431 passed + 222
  subtests; test:telemetry 311 passed; vendored parity 64 PASS
- uv run --project skills/llm-to-bedrock/scripts pytest skills/llm-to-bedrock:
  614 passed (bare mise python without the uv project: 603 passed, 11 failed
  on ModuleNotFoundError httpx in test_astra_execution_contract -- environment,
  not code)
- pytest skills/agent-advisor: 570 passed (no agent-advisor files touched)
- pytest tests/test_gpt54_55_cris_prefix_scope.py: 3 passed
- python3 tools/validate.py: All validations passed
- tools/sync-vendored.py --check: PASS, 64 byte-identical
- git diff --check: clean
- mise run build: gitleaks fails only on pre-existing upstream commit f8d09fd1
  (tests/test_bedrock_migration_assessment_discover.py:118 generic-api-key);
  unrelated to this branch

* fix(aws-startup-advisor): grant the default project any-row-wins when one Bedrock id sits in several --target rows

PR 585 review round 1, pass 2, blocker B2: `target_apis = dict(targets)` kept only
the LAST row's API per id, so `--target us.openai.gpt-5.6-sol=chat_completions
--target us.openai.gpt-5.6-sol=converse` emitted 0 project/default while the reverse
order emitted 1. The §6.4 recipe emits one pair per bedrock_models[] row without
deduplicating, and the schema lets a GPT CRIS id appear on a converse row (Guardrails /
application-inference-profile call site) and a chat_completions/responses row for a
second source model.

- iam_policy.py: new pure `target_apis_by_id(pairs) -> dict[str, set[str]]` groups
  every API an id is called on; `generate_policy(target_apis=)` accepts a str or a set
  per id, validates each API in the set (fail closed on an unknown one), and grants
  `project/default` once when ANY of the id's rows is responses/chat_completions.
  CLI `--target` now builds the set instead of `dict(targets)`.
- test_iam_policy.py::TestPerRowTargetApis: [gpt=chat,gpt=converse] and the reverse
  order and [gpt=converse,gpt=responses] all grant exactly once; [gpt=converse,
  gpt=converse] grants none; target_apis_by_id keeps every row's API; an unknown API
  inside a row set fails closed; CLI duplicate-id rows grant once in both orders (the
  reviewer's spot-check).
- llm2bedrock-report-generator.md §6.4: tell the agent not to deduplicate rows and
  that a duplicated id is granted once if any row is responses/chat_completions.

Validation (run in this worktree, 2026-11-07):
- mise -C plugins/aws-startup-advisor run ci: exit 0 — [test] 1431 passed, 222
  subtests passed; [test:telemetry] 311 passed; lint:md 0 errors; vendored-parity
  PASS 64; artifacts PASS 99; skill-refs PASS 1521. (A stale gitignored
  skills/llm-to-bedrock/scripts/.venv from the previous step broke lint:md on the
  first run; it was removed, not committed.)
- pytest skills/llm-to-bedrock (uv project env): 622 passed (was 614; +8 new).
- pytest skills/agent-advisor: 570 passed (no agent-advisor files touched).
- pytest tests/test_gpt54_55_cris_prefix_scope.py: 3 passed.
- python3 tools/validate.py: All validations passed.
- tools/sync-vendored.py --check: PASS, 64 byte-identical.
- git diff --check: clean.
- mise run build: exit 1 ONLY on gitleaks' pre-existing upstream finding at
  f8d09fd1 (tests/test_bedrock_migration_assessment_discover.py:118, generic-api-key);
  not introduced by this branch.
- CLI spot-check: sol=chat+converse -> 1 project/default; converse+chat -> 1;
  converse+converse -> 0.

* fix(aws-startup-advisor): address PR 585 review round 2 — validated ids in the §6.4 IAM recipe, project-scoped GetInvoke for retained stored-response ops, identity-checked saved-API reuse in B4

Three P2 findings from leon1418 on f3c01556 (threads 4505069045, 4505069047, 4505069050).

1. Report §6.4 IAM recipe reloaded aws-design-ai.json's ORIGINAL ids, so a C4 target change
   (Sol → Terra, recorded in resolved_model_overrides) emitted Sol permissions and omitted the
   Terra profile. The recipe now joins each bedrock_models[] row's required_client_api to the
   validated analysis target_models (overrides applied) and never falls back to the row's
   aws_model_id; iam_policy.validated_target_pairs() does the join and fails closed on a row
   without a validated entry or an API. Regression: a C4 Sol → Terra change yields a C6 policy
   naming Terra (+ project/default) and no Sol resource; the pre-fix design-row path is kept as
   the failing control.

2. Retained client.responses.retrieve(id) / cancel / delete on bedrock-runtime authorize
   bedrock:GetInvoke / CancelInvoke / DeleteInvoke on project/default, separately from the
   InvokeModel creation needs (inference-responses-api.html "Permissions", read 2026-11-08).
   analysis.json gains optional stored_response_ops (enum retrieve|cancel|delete); the
   analyzer §8.3 scans for the call sites; iam_policy.py gains --stored-response-ops and emits a
   BedrockStoredResponseOps statement with ONLY the retained actions on project/default, and
   only when a --target row is a runtime GPT CRIS id on `responses` — Converse, Anthropic
   Messages, Chat Completions, embeddings, bare mantle ids and id-only legacy calls are refused
   (reason stored_response_ops_no_responses_row). The report recipe passes the field through,
   the How to Apply checklist gains a create-plus-retrieve permission check, and the GCP /
   Azure setup_bedrock contracts, GCP generate-ai and the shared OpenAI guide (vendored copies
   re-synced) name the grant, its controls and the create-plus-retrieve verification.

3. SKILL.md B4 read the saved resolved_runtime_api before C0's assess_design_sha256 check, so a
   cached `messages` answer could send a new GPT row to the Anthropic endpoint. B4 now runs
   preflight_bedrock.py --resume-runtime-api <run-context> --design <aws-design-ai.json>, which
   reuses the saved answer only when it exists AND the saved assess_design_sha256 and
   target_models (source, aws_model_id) identity match the current design; any mismatch,
   missing context or missing field forces re-resolution before any probe. The context-block
   recovery sentence points at the same gate.

Validation (worktree fix-llm-to-bedrock-runtime-default):
- mise -C plugins/aws-startup-advisor run ci: exit 0 — test 1441 passed (+222 subtests),
  test:telemetry 311 passed, lint:md 0 errors, vendored-parity PASS (64), skill-refs PASS,
  model-id OK, artifacts PASS, consent-disclosure OK, model-catalog-drift OK (3 pre-existing warns)
- llm-to-bedrock scripts pytest (uv run --project .): 655 passed (622 baseline + 33 new)
- agent-advisor scripts pytest: 570 passed (unchanged; no agent-advisor edits)
- tests/test_gpt54_55_cris_prefix_scope.py and test_runtime_default_review_round1.py green
- python3 tools/validate.py: All validations passed
- tools/sync-vendored.py --check: PASS
- git diff --check: clean
- mise run build: exit 1 ONLY on the pre-existing gitleaks finding at upstream f8d09fd1
  (tests/test_bedrock_migration_assessment_discover.py:118, generic-api-key on the string
  "claude-3.5-sonnet"); lint:manifests passed. Not introduced or touched by this commit.

* feat(aws-startup-advisor): detect Mantle-only selectors in Discover and record them as mantle_signals

Discover now records the five code-detectable bedrock-mantle selectors
(background_inference, web_search, server_side_tools, projects, workspaces)
with file:line evidence so Clarify can confirm them instead of guessing the
endpoint from source code alone. mantle_only_model_or_api stays Design-derived
and in_region_processing is never detected (always asked).

- skills/shared/ai/bedrock-endpoint-policy.md: new "## How a selector is
  learned" section (positive/negative constructs per selector, cites
  inference-responses-api.html read 2026-11-07); vendored copies re-synced
  (gcp-to-aws, azure-to-aws references/vendored/ai).
- gcp-to-aws discover-app-code.md: Step 5C "Mantle-Only Selector Signals"
  (table + workloads[].mantle_signals[] output), Step 5B example, checklist.
- azure-to-aws discover-app-code.md: Step 5C (bullet style), checklist.
- gcp/azure schema-discover-ai.md: workloads[].mantle_signals[] shape,
  CRITICAL field bullet / enum, validation rule.
- discover-openai-api.md / discover-anthropic-api.md /
  discover-openrouter-api.md (gcp + azure): Step 4 merge adds a projects /
  workspaces / web_search (:online) signal with the <usage_api>/line 0
  sentinel; OpenRouter workspace_id is explicitly NOT a workspaces signal.
- bedrock-migration-assessment discover-app-code.md: Step 4.5 with top-level
  mantle_signals[] output; Step 5 example and closing rule allow the key.
- scripts/contracts/ai-workload-profile.schema.json (+ byte-identical BMA
  copy): optional root mantle_signals[] and mantleSignal definition.
- validate-ai-profile.py: _check_mantle_signals (unmatched_mantle_signal)
  and mantle_signals_detected in the summary.
- fixtures/bma-scan-openai-mantle-signals: positives on app/llm.py:5,9,14,21;
  negatives (function tool named web_search, store=True) on lines 30 and 37.
- tests/test_mantle_selector_discovery.py (15 tests);
  test_bedrock_migration_assessment_core.py summary key set updated.

Verification (plugins/aws-startup-advisor):
- python3 tools/sync-vendored.py && --check: PASS (64 files, 2 synced)
- python3 scripts/validate-artifacts.py --fixtures: PASS, 100 artifacts,
  0 errors, no new baseline entries
- python3 tools/check-skill-refs.py --check: PASS (1525 refs)
- markdownlint-cli2 (823 tracked files): 0 errors
- uv run --no-project --with pytest python -m pytest tests -q:
  1456 passed, 222 subtests passed, 1 failed — the one failure is
  test_model_id_lint::test_real_plugin_passes flagging a retired model id
  inside the gitignored, untracked skills/llm-to-bedrock/scripts/.venv/
  (anthropic SDK constants); pre-existing local environment, not a tracked
  file. Acceptance subset (6 files): 253 passed.
- python3 tools/validate.py (repo root): All validations passed
- git diff --check: clean

* feat(aws-startup-advisor): ask Mantle-only requirements in Clarify (Q22b / Q10.5) and persist ai_constraints.mantle_requirements

PR #585 defined the mantle_selector enum but nothing populated it from the user.
Add one question block with four sub-questions (asynchronous/background
inference; provider-run server-side or pre-configured tools incl. web search;
customer-created Projects/Workspaces; strict single-Region processing + Region):

- gcp-to-aws clarify-ai.md: Q22b (ESSENTIAL, Gate-2 AI batch, prefilled from
  workloads[].mantle_signals), Mantle-only signals line in the AI Context
  Summary, Preferences Output block, question budget 4 -> 5 globals
- gcp-to-aws clarify-assemble.md: Q22b in the AI/agentic batch, its "use
  defaults" bullet and defaults-table row
- gcp-to-aws / bedrock-migration-assessment clarify-ai-only.md: Q10.5 between
  Q10 and Q11 with identical table rows and Interpret line (BMA parity); BMA
  prefills from the validator summary's mantle_signals_detected; gcp fast path
  now presents Q10.5 (never dropped); Step 3 field row mantle_requirements
- azure-to-aws clarify-ai.md: Q22b Category F bullet, Step 3 rows entry,
  Who-consumes row; azure clarify-ai-only.md: Q10.5 paragraph, fast path,
  Step 3 bullet, AI-only example block entry (shows web_search + region)
- schema-preferences.md (gcp + BMA): mantle_requirements catalog rows
  (Q22b (AI-only: Q10.5) / ai_constraints Q10.5)
- fixtures/bma-ai-only-clarify/preferences.json: mantle_requirements answer
  and Q10.5 in questions_asked
- tests/test_mantle_requirements_clarify_contract.py: 13 new contract tests

Wrapper: ai_constraints.mantle_requirements.value = [{ workload_id, selector,
source, evidence?, region? }], selector in background_inference |
server_side_tools | web_search | projects | workspaces | in_region_processing |
none, source in detected | user | none; chosen_by user or default
(source default:<Qid> + report caveat), never extracted.

Verification (plugins/aws-startup-advisor):
- pytest tests/test_mantle_requirements_clarify_contract.py
  tests/test_bedrock_migration_assessment_core.py
  tests/test_validate_artifacts.py tests/test_azure_clarify_fast_path_contracts.py
  tests/test_estimate_clarify_volume_resolution.py
  tests/test_live_cli_ai_metrics.py: 243 passed
- pytest tests (full plugin suite): 1475 passed, 222 subtests, 1 failed =
  tests/test_model_id_lint.py::test_real_plugin_passes flagging the untracked
  skills/llm-to-bedrock/scripts/.venv (pre-existing local env, not a tracked file)
- validate-artifacts.py --fixtures: PASS 100 artifacts, 0 errors, baseline unchanged
- validate-artifacts.py --run-dir fixtures/bma-ai-only-clarify --skill
  bedrock-migration-assessment --no-baseline: PASS
- markdownlint-cli2: 0 errors on 823 files; sync-vendored --check PASS (64);
  check-skill-refs --check PASS (1525); tools/validate.py passed; git diff --check clean

* feat(aws-startup-advisor): derive mantle_selector from ai_constraints.mantle_requirements in Design and disclose the bedrock-runtime assumption

Design no longer infers the Bedrock endpoint from the source API, the model or a
guess: gcp-to-aws and azure-to-aws design-ai.md gain Step 0.8, which reads
preferences.json -> ai_constraints.mantle_requirements (Clarify Q22b / Q10.5),
derives bedrock_models[].mantle_selector only from a detected|user entry (plus
the catalog for mantle_only_model_or_api), records the cited entry as
bedrock_models[].mantle_requirement on every mantle_* row, and writes the
verbatim endpoint_assumption sentence ("No Mantle-only requirement was recorded
for <workload_id>; bedrock-runtime selected. ... re-run Clarify.") on every
runtime row. Generate echoes whichever field is present in the script/adapter
header; the llm-to-bedrock report renders an Endpoint line from a new
"Endpoint basis:" context line and cites the public Responses API page for the
Runtime background=true 400.

Design:   skills/gcp-to-aws/references/phases/design/design-ai.md (Step 0.8,
          Part 5, Part 6 table, Validation Checklist, Present Summary item 6)
          skills/azure-to-aws/references/phases/design/design-ai.md (Step 0.8,
          Parts 3/5, Completion gate, Present summary)
Schema:   skills/shared/ai/schema-design-aws-ai.md (bedrock_models[] bullet,
          new "mantle_requirement and endpoint_assumption" section, 2 checklist
          items) + vendored copies in gcp-to-aws/azure-to-aws references/vendored/ai
          skills/gcp-to-aws/references/shared/schema-design-aws-ai.md
          skills/azure-to-aws/references/shared/schema-design-aws-ai.md
Generate: skills/gcp-to-aws/references/phases/generate/generate-artifacts-ai.md
          skills/gcp-to-aws/references/phases/generate/generate-ai.md
          skills/azure-to-aws/references/phases/generate/generate-artifacts-ai.md
Report:   skills/llm-to-bedrock/SKILL.md (Endpoint policy paragraph, B1 tuple,
          Endpoint basis: context line)
          agents/llm2bedrock-report-generator.md (Executive Summary Endpoint
          line, Model Mapping notes, Limitations)
Fixtures: fixtures/aws-design-ai/multi-provider-direct (detected web_search
          Mantle row + runtime endpoint_assumption), openrouter-gateway-multi-
          upstream (in_region_processing mantle_requirement + 2 assumptions),
          new runtime-default-no-requirement (runtime-only design)
Tests:    tests/test_mantle_requirements_design_contract.py (17 tests)

Verification (all run on this commit's tree):
- python3 tools/sync-vendored.py && --check: PASS, 64 files (2 re-synced)
- python3 scripts/validate-artifacts.py --fixtures: PASS, 101 artifacts, 0 errors,
  baseline unchanged (MISSING_REQUIRED=6, UNKNOWN_KEY=44)
- mise -C plugins/aws-startup-advisor run ci: exit 0 — lint:md 0 errors/823
  files, lint:artifacts PASS, lint:vendored-parity PASS, lint:skill-refs PASS
  (1532 refs), model-id/staleness/catalog-drift/pricing/consent PASS,
  test 1496 passed + 222 subtests, test:telemetry 311 passed,
  test:heroku-source-review PASS
- skills/llm-to-bedrock/scripts: 655 passed (unchanged)
- skills/agent-advisor/scripts: 570 passed (no file under agent-advisor changed)
- python3 tools/validate.py: all validations passed; git diff --check clean

* fix(aws-startup-advisor): align Mantle selector vocabulary across Discover, Clarify and Design

Cross-FEAT integration pass over a6f9ef1a (mantle_signals), 73835b14
(ai_constraints.mantle_requirements) and 922687ea (mantle_requirement /
endpoint_assumption):

- endpoint_assumption sentence: the shared schema-design-aws-ai.md and the gcp
  design-ai.md Step 0.8 rendered the placeholder as `<workload_id>` in
  backticks while the azure docs, the aws-design-ai fixtures and
  tests/test_mantle_requirements_design_contract.py expect a plain id. The
  placeholder is now unquoted in both and the "where <workload_id> is" note
  says the id is written plain (no backticks or quotes).
- gcp clarify-ai.md Q22b Preferences Output example: the `evidence` of the
  detected `projects` entry now copies the Step 5B/5C construct verbatim
  (src/ai/openai_client.py:9 default_headers={"OpenAI-Project": ...}) so the
  example matches the "copy the signal's file:line construct" rule.
- gcp and azure discover-app-code.md output checklists: the "real line that
  contains the construct" rule now names the `"<usage_api>"` / `line: 0`
  sentinel that the usage-API Step 4 merges append, matching
  schema-discover-ai.md.
- bedrock-endpoint-policy.md "How a selector is learned": names the Clarify
  question ids (Q22b / Q10.5) and the Design outputs (mantle_requirement /
  endpoint_assumption) so the policy describes the whole chain.
- Vendored copies re-synced (gcp-to-aws and azure-to-aws
  references/vendored/ai/bedrock-endpoint-policy.md and
  schema-design-aws-ai.md).

Verification (worktree fix-llm-to-bedrock-runtime-default):
- mise -C plugins/aws-startup-advisor run ci: exit 0 (lint:md 0 errors,
  lint:artifacts PASS 101 artifacts 0 errors, lint:vendored-parity PASS 64,
  lint:skill-refs PASS 1532, model-id / staleness / catalog-drift /
  startup-model-pricing / consent-disclosure PASS, test 1496 passed + 222
  subtests, test:telemetry 311 passed, test:heroku-source-review PASS). The
  gitignored local skills/*/scripts/.venv dirs were parked outside the tree
  for the run (markdownlint and model-id-lint walk into them) and restored.
- python3 tools/sync-vendored.py --check: PASS 64
- python3 scripts/validate-artifacts.py --fixtures: PASS 101 artifacts, 0 errors
- skills/llm-to-bedrock/scripts: 655 passed
- skills/agent-advisor/scripts: 570 passed (no file under agent-advisor changed)
- python3 tools/validate.py: All validations passed
- git diff --check: clean
- mise run build (gitleaks) not run: it fails on pre-existing upstream
  commit f8d09fd1, unrelated to this branch.

* fix(aws-startup-advisor): define Step 0.8 for a Mantle requirement on a source with no Mantle path; widen the Anthropic and report-fallback wording

Review round (verdict.json CHANGES_REQUESTED, 1 major + 2 minor):

- major — Step 0.8 (gcp and azure design-ai.md) and the derivation section of
  skills/shared/ai/schema-design-aws-ai.md now define the outcome for a
  matched ai_constraints.mantle_requirements entry on a workload whose source
  API has no Mantle path (Gemini / Vertex AI via google-genai, or a workload
  whose target is a cross-family direct / converse / gpt-oss row): the row
  keeps bedrock-runtime and the verbatim endpoint_assumption sentence, and
  discloses the unhonored selector with its source and evidence in rationale
  and capability_gaps[] (a regional_warnings[] entry for in_region_processing);
  a Mantle path is never invented and the answer is never dropped. The gcp and
  azure shadow schema-design-aws-ai.md docs carry the same clause; the Present
  Summary endpoint line (gcp item 6, azure summary) names the gap. The Clarify
  copy (gcp Q22b, gcp/BMA Q10.5 identical sentence, azure Q22b bullet and
  Q10.5 paragraph) tells the user up front that a "yes" for such a workload
  records a capability gap rather than an endpoint change.
  tests/test_mantle_requirements_design_contract.py now asserts the Step 0.8
  slice names the no-Mantle-path case and capability_gaps.
- minor — gcp design-ai.md Step 0 Anthropic bullet and Part 5 Anthropic row,
  and azure design-ai.md Part 5: "(a `workspaces` entry)" -> "(any matched
  entry, typically `workspaces`)", matching Step 0.8 and the scanners (Anthropic
  web_search_20250305 -> web_search, code_execution_* -> server_side_tools).
- minor — llm-to-bedrock SKILL.md emits the C6 "Endpoint basis:" line whenever
  any bedrock_models[] row carries migration_path mantle_*, mantle_selector,
  mantle_requirement or endpoint_assumption, rendering a Mantle row without
  mantle_requirement as "bedrock-mantle (<selector or 'selector unrecorded'>;
  source unknown — plan predates mantle_requirements)"; B1 keeps
  migration_path / mantle_selector for that purpose. The report generator's
  Endpoint line renders that form and falls back to the runtime wording only
  when the line is absent (no row carries any marker).
- Vendored copies re-synced (gcp-to-aws and azure-to-aws
  references/vendored/ai/schema-design-aws-ai.md).

Verification (worktree fix-llm-to-bedrock-runtime-default):
- mise -C plugins/aws-startup-advisor run ci: exit 0 (lint:md 0 errors,
  lint:artifacts PASS 101 artifacts 0 errors, lint:vendored-parity PASS 64,
  lint:skill-refs PASS 1532, model-id / staleness / catalog-drift /
  startup-model-pricing / consent-disclosure PASS, test 1496 passed + 222
  subtests, test:telemetry 311 passed, test:heroku-source-review PASS). The
  gitignored local skills/*/scripts/.venv dirs were parked outside the tree
  for the run and restored.
- python3 tools/sync-vendored.py --check: PASS 64
- python3 scripts/validate-artifacts.py --fixtures: PASS 101 artifacts, 0 errors
- skills/llm-to-bedrock/scripts: 655 passed
- skills/agent-advisor/scripts: 570 passed (no file under agent-advisor changed)
- python3 tools/validate.py: All validations passed
- git diff --check: clean
- mise run build (gitleaks) not run: it fails on pre-existing upstream
  commit f8d09fd1, unrelated to this branch.

* fix(aws-startup-advisor): stop quoting one per-token price for both Bedrock endpoints

The GPT-5.4 and GPT-5.5 cards publish an In-Region rate only, so a missing Geo or Global row stays unpublished.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(aws-startup-advisor): iam_policy dispatches stored-response grants by endpoint and emits Web Search grants for a web_search row (PR 588 F12, F15)

F12 — `generate_policy` now splits `responses` rows by endpoint: a runtime GPT CRIS row
keeps `bedrock:GetInvoke` / `CancelInvoke` / `DeleteInvoke` on `project/default`; a bare
Mantle id on `responses` is covered by the `BedrockMantleInference` statement (Mantle
inference, stored-response retrieval at `GET /v1/responses/{id}` included, authorizes
`bedrock-mantle:CreateInference`) and no longer raises
`stored_response_ops_no_responses_row`. Converse / Messages / Chat / embedding / id-only
plans still fail closed. Public basis: inference-responses-api.html "Permissions",
read 2026-11-09.

F15 — new `--mantle-selector` (repeatable; `parse_mantle_selectors` fails closed with
reason `unknown_mantle_selector`) and `--external-web-access`. A `web_search` selector with
a Mantle row appends `BedrockWebSearch`: `bedrock-websearch:InvokeSearch` + `InvokeFetch`
on `*` with an `aws:RequestedRegion` condition (the service's only condition key; all three
actions take `*`), plus `bedrock-websearch:ExternalWebAccess` only when the user confirmed
external access. `web_search` without a Mantle row → `web_search_without_mantle_row`;
`--external-web-access` without `web_search` → `external_web_access_without_web_search`.
Other selectors add nothing. Public basis: web-search.html, security-web-search.html,
read 2026-11-09 (`external_web_access` defaults to true; without the action every Fetch
fails authorization while the request still returns 200).

Recipes: report §6.4 command block gains both flags; the stored-response paragraph keeps
its pinned sentences and adds the Mantle dispatch; new "Web Search needs its own grants"
paragraph; How-to-Apply gains the Mantle create-plus-retrieve variant and a conditional
"Tool-level permission check" bullet. GCP / Azure generate-artifacts-ai.md and the canonical
OpenAI guide (+ vendored copies via sync-vendored) carry the same facts and a Step-5
tool-level check.

Tests: test_iam_policy_round2.py — TestStoredResponseOps replaces the bare-Mantle raise test
with all-Mantle retained-retrieve (Mantle policy, no GetInvoke, legacy form too), runtime
control, mixed runtime+Mantle (GetInvoke once + Mantle sids), Mantle Chat-only still fails
closed, CLI all-Mantle exits 0; new TestWebSearchGrants (grant shape, external action,
parametrized absence, runtime-only raise, unknown selector, CLI emit / refuse / reasons).
New tests/test_runtime_default_review_round3.py pins the recipe strings.

Validation: skills/llm-to-bedrock/scripts `uv run --group dev pytest -q` 672 passed
(was 655); plugin `pytest tests -q` 1532 passed, 1 failed (known
test_model_id_lint::test_real_plugin_passes local .venv noise, pre-existing);
tools/sync-vendored.py --check PASS (64); markdownlint-cli2 0 issues.

* fix(aws-startup-advisor): Anthropic computer_/text_editor_/bash_ client tools are not server_side_tools signals (PR 588 F13)

The Sonnet 5 and Opus 5.5 model cards list `computer_20251124`, `computer_toolset_20260801`,
`browser_toolset_20260801`, `bash_20250124`, `text_editor_20250728` and `memory_20250818`
under "Computer use" and "Client tools and toolsets using `bedrock-runtime` and
`bedrock-mantle` endpoints" (model-card-anthropic-claude-sonnet-5.html,
model-card-anthropic-claude-opus-5-5.html, read 2026-11-09): they are client-executed and
available on both endpoints, so they must not select Mantle.

bedrock-endpoint-policy.md (canonical + 2 vendored mirrors via sync-vendored) and the
gcp / azure / bedrock-migration-assessment discover-app-code.md scanners: the
`server_side_tools` positive list keeps `"type": "mcp"`, `code_interpreter`, `file_search`,
`computer_use_preview`, `image_generation` and Anthropic `code_execution_*`
(provider-executed); `computer_*` / `text_editor_*` / `bash_*` (+ toolsets, `memory_*`) move
to "Not a signal" with the card citation; both cards added to § Sources.

New fixture fixtures/bma-scan-anthropic-client-tools (Anthropic SDK `claude-sonnet-5` with
computer / text_editor / bash tools, profile with no `mantle_signals`).

Tests (tests/test_mantle_selector_discovery.py):
test_policy_and_scanners_keep_anthropic_client_tools_out_of_server_side_tools and
test_client_tool_only_anthropic_fixture_has_no_mantle_signal_and_reaches_runtime_messages
(validator ok, `mantle_signals_detected == []`, and iam_policy on `runtime_messages`
emits `BedrockInvokeModelScoped` — the lane reaches IAM/preflight, not unsupported_lane).

Validation: plugin `pytest tests -q` 1532 passed, 1 failed (known
test_model_id_lint::test_real_plugin_passes .venv noise); scripts/validate-artifacts.py
--fixtures PASS (103); tools/sync-vendored.py --check PASS (64).

* docs(aws-startup-advisor): Azure Design/schema and the code-rewriter carry the per-model Guardrails API rule (PR 588 F3, Azure half)

The blanket "`converse` / `chat_completions` / `invoke` (never `responses`) for 6.1 Sol and
the other GPT-6/5.6 CRIS models" in skills/azure-to-aws design-ai.md (Part 2 Guardrails
block) and references/shared/schema-design-aws-ai.md (§ required_client_api) is replaced
with the per-model rule GCP already carries on #588: `converse` for GPT-6 Astra, GPT-5.6
Sol / Terra / Luna, GPT-5.5, GPT-5.4 and GPT-6.1 Terra (Converse-only); `responses` /
`chat_completions` / `invoke` / `converse` for GPT-6 Sol and GPT-6 Luna; `chat_completions`
/ `invoke` / `converse` (never `responses`) for GPT-6.1 Sol; the nine card URLs are listed
and "Do not leave the client on `responses` when Guardrails is required on a model whose
card excludes Responses." closes the block.

agents/llm2bedrock-code-rewriter.md: "note Guardrails are Converse-only and prompt caching
Responses-only on runtime" becomes the per-card scope carried by
`bedrock_models[].required_client_api` (GPT-6 Sol / Luna on Responses, Chat Completions,
InvokeModel and Converse; GPT-6.1 Sol not on Responses; GPT-5.6 / 5.5 / 5.4 / Astra Converse
only; implicit caching Responses-only on runtime for GPT-5.5 / 5.4, broader for 5.6 / 6).

Public basis, read 2026-11-09: model-card-openai-gpt-6-sol.html "Guardrails (Responses,
Chat Completions, InvokeModel, and Converse APIs)"; -6-luna same; -6-1-sol "Chat
Completions, InvokeModel, and Converse APIs; not supported with Responses"; -6-astra,
-56-sol/-terra/-luna, -55, -54 "Converse API only". The canonical and GCP shadow schema
docs contain no blanket wording (grep verified); the GCP design block is replaced by
#588's ea0798b3 when it rebases.

Tests (tests/test_runtime_default_review_round3.py): blanket strings absent in Azure
design, Azure/canonical/GCP schema docs and the rewriter; per-model lines + nine cards
present in the Azure design and schema; rewriter sentence pinned.

Validation: plugin `pytest tests -q` 1532 passed, 1 failed (known model-id-lint .venv
noise); markdownlint-cli2 0 issues.

* fix(aws-startup-advisor): Step 0.8 validates a matched selector against its required API; Responses-only selectors on a Chat/Messages source are an explicit decision (PR 588 F4, cloud half)

GCP and Azure design-ai.md Step 0.8 gain rule 1b between rules 1 and 2, and rule 2 now
reads "Any match that passes 1b": `web_search` and `background_inference` require the
Responses API (web-search.html; inference-responses-api.html, read 2026-11-09);
`workspaces` requires the Anthropic Messages API (`anthropic-workspace-id`); `projects`
requires an OpenAI-compatible API (`OpenAI-Project`). A provider mismatch (`workspaces` on
an OpenAI SDK workload, `projects` on an Anthropic SDK workload) keeps `bedrock-runtime`,
records `endpoint_assumption`, discloses it in `rationale` / `capability_gaps[]` and re-runs
Clarify. A Chat Completions or Anthropic Messages source matched by a Responses-only
selector is an explicit API-continuity decision recorded in the plan and the Present
Summary — keep the API on `bedrock-runtime` and drop the requirement (capability gap), or
move to `mantle_openai_responses` with the Chat → Responses reshape — never a silent
`mantle_openai_chat` / `mantle_messages` row. Same rule in prose in the canonical
schema-design-aws-ai.md (+ 2 vendored copies via sync-vendored) and the GCP / Azure shadow
schema docs.

New fixture fixtures/aws-design-ai/chat-source-web-search-continuity-kept: GPT-5.5 Chat
Completions source, `runtime_openai_cris` / `chat_completions`, verbatim
`endpoint_assumption`, `capability_gaps[]` naming the dropped `web_search` and the rule-1b
decision. fixtures/README.md counts 4 aws-design-ai fixtures and names the new case.

Tests (tests/test_runtime_default_review_round3.py): Step 0.8 phrases in both design files
(and that rule 2 depends on 1b); the decision sentence in all five schema docs; vendored
schema docs byte-identical; the new fixture validates against aws-design-ai.schema.json
with the expected row shape; corpus invariant — no `mantle_openai_chat` row with
`web_search` / `background_inference`, no `mantle_messages` row with
`background_inference` / `projects`.

Validation: plugin `pytest tests -q` 1532 passed, 1 failed (known
test_model_id_lint::test_real_plugin_passes local .venv noise, pre-existing);
skills/llm-to-bedrock/scripts 672 passed; skills/agent-advisor/scripts 570 passed
(unchanged); scripts/validate-artifacts.py --fixtures PASS (103 artifacts);
tools/sync-vendored.py --check PASS (64); tools/check-skill-refs.py --check PASS;
git diff --check clean; markdownlint-cli2 0 issues.

* fix(aws-startup-advisor): price the web_search continuity fixture on GPT-5.6 Terra, whose Geo CRIS rate is published (review A, B1)

The chat-source-web-search-continuity-kept design fixture quoted a parity
"2.50/15.00" Bedrock price for us.openai.gpt-5.5, but the GPT-5.5 card
publishes a commercial In-Region price only and no Geo/Global CRIS row
(model-card-openai-gpt-55.html, read 2026-11-09); bedrock-endpoint-policy.md
and openai-on-bedrock.md say such rows must never report parity. Switch the
fixture to a same-model GPT-5.6 Terra move: source gpt-5.6-terra at OpenAI's
$2.00/$12.00 standard list, target us.openai.gpt-5.6-terra at the published
US Geo CRIS $2.20/$13.20 (model-card-openai-gpt-56-terra.html, read
2026-11-09; Global CRIS $2.00/$12.00), price_comparison "unfavorable", with
the 1.10x Geo premium named in the rationale. The Step 0.8 rule 1b
continuity decision, dropped web_search capability gap, chat_completions
API and verbatim endpoint_assumption are unchanged. Round-3 test now pins
the Terra ids and prices and asserts price_comparison is not parity;
fixtures/README.md names the Terra source.

Validation (plugins/aws-startup-advisor):
- uv run --no-project --with pytest --with jsonschema python -m pytest tests -q:
  1532 passed, 1 failed (known tests/test_model_id_lint.py::test_real_plugin_passes,
  local .venv noise)
- python3 scripts/validate-artifacts.py --fixtures: PASS (103 artifacts, 0 errors)
- python3 tools/sync-vendored.py --check: PASS (64 files)
- git diff --check: clean

* fix(aws-startup-advisor): write the Mantle scan fixtures as schema 1.1 profiles

The 1.1 scan contract requires workloads and integration. These two fixtures still said 1.0, so the fixture sweep failed after the main merge.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Logan Kleier <lkleier@amazon.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-12 22:18:49 +00:00
2026-04-23 12:44:11 +00:00
2026-04-23 12:44:11 +00:00

Agent Toolkit for AWS

License Build Status

Help AI coding agents build, deploy, and manage applications on AWS.

The Agent Toolkit for AWS gives AI coding agents the tools, knowledge, and guardrails they need to work with AWS services. It works with the coding agents developers already use — including Claude Code, Codex, Cursor, Devin, Kiro, and fx.

Quick start

AWS CLI

Use the Agent Toolkit directly from your terminal with the AWS CLI:

aws configure agent-toolkit

See the AWS CLI integration guide for setup, configuration, and usage instructions.

Claude Code

The plugins are available on the official Anthropic marketplace (claude-plugins-official) which is added to your Claude Code installation by default. Use the following commands to install supported plugins from the toolkit:

For aws-core that covers service selection, CDK/CloudFormation, serverless, containers, storage, observability, billing, SDK usage, and deployment:

/plugin install aws-core@claude-plugins-official

Tip: If you get Plugin not found, update your local marketplace index first:

/plugin marketplace update claude-plugins-official

For aws-agents that covers building AI agents on AWS with Amazon Bedrock and AgentCore:

/plugin install aws-agents@claude-plugins-official

For aws-data-analytics that covers data lake, analytics, and ETL workflows with S3 Tables, AWS Glue, and Athena:

/plugin install aws-data-analytics@claude-plugins-official

For aws-agents-for-devsecops used to investigate incidents, review code and execute UAT for release readiness, scan code for vulnerabilities, and run penetration tests with AWS DevOps Agent and AWS Security Agent.

/plugin marketplace add aws/agent-toolkit-for-aws
/plugin install aws-agents-for-devsecops
/reload-plugins

# Or from Claude's official marketplace:
/plugin install aws-agents-for-devsecops@claude-plugins-official
/reload-plugins

# Setup:
/aws-agents-for-devsecops:setup

For aws-startup-advisor that covers startup-focused architecture, cost, security, and AWS Activate guidance, plus migrations to AWS from Azure, GCP, Heroku, and AI stacks such as OpenAI and Gemini, install from this repository's marketplace:

/plugin marketplace add aws/agent-toolkit-for-aws
/plugin install aws-startup-advisor@agent-toolkit-for-aws
/reload-plugins

Codex

In your terminal:

codex plugin marketplace add aws/agent-toolkit-for-aws

Then launch Codex and run /plugins to browse and install the aws-core plugin.

Cursor

Add this repository as a team marketplace from Settings → Plugins → Team Marketplaces → Add Marketplace → Import from Repo, pointing it at aws/agent-toolkit-for-aws. Cursor indexes the plugins listed in .cursor-plugin/marketplace.json on import.

Then open the Plugins panel and install the aws-core plugin (start here), or aws-agents and aws-data-analytics as needed. Each plugin bundles the AWS MCP Server configuration and agent skills.

Devin

In your terminal:

devin plugins install aws/agent-toolkit-for-aws#plugins/aws-core

This requires devin auth login and adds the plugin to your personal plugins, so it also loads in Devin cloud sessions and Devin Desktop. Add --local to install on this machine only. To install a different plugin, replace aws-core with its name from Plugins, such as aws-agents or aws-data-analytics.

In the Devin web app, choose Customize → Plugins → Add plugin → From repository, enter aws/agent-toolkit-for-aws, and set the subdirectory to plugins/aws-core (or another plugin's directory). Personal plugins added there are also available in the Devin CLI and Devin Desktop.

Kiro

Kiro setup has two independent parts: the AWS MCP Server (for runtime AWS API access and documentation search) and local skills (for task-specific agent guidance). They complement each other but work independently — skills don't require the MCP server, and the MCP server doesn't serve locally-installed skills.

1. Add the AWS MCP Server to your Kiro MCP configuration (.kiro/settings/mcp.json):

{
  "mcpServers": {
    "aws": {
      "command": "uvx",
      "args": [
        "mcp-proxy-for-aws-cli@latest",
        "https://aws-mcp.us-east-1.api.aws/mcp",
        "--metadata",
        "AWS_REGION=us-west-2"
      ]
    }
  }
}

The MCP server gives your agent access to AWS APIs, sandboxed script execution, and real-time documentation search.

2. Install skills from this repository:

npx skills add aws/agent-toolkit-for-aws/skills

This installs skill files to ~/.kiro/skills/ (global) or .kiro/skills/ (project-level). Each skill is a directory containing a SKILL.md file and optionally a references/ subdirectory with additional context the agent reads from the local filesystem when needed. Kiro discovers installed skills automatically and activates them on demand when a task matches.

Prerequisites: You need uv installed. An AWS account with credentials configured locally is required for API calls and script execution, but not for documentation search or skill discovery. See the user guide for detailed setup instructions.

fx

fx setup has the same two independent parts as Kiro: the AWS MCP Server (for runtime AWS API access and documentation search) and local skills (for task-specific agent guidance). Skills don't require the MCP server, and the MCP server doesn't serve locally-installed skills.

1. Add the AWS MCP Server from your terminal. fx stores MCP servers in ~/.fx/mcp.json, so the server is available in every project:

fx mcp add aws uvx mcp-proxy-for-aws-cli@latest https://aws-mcp.us-east-1.api.aws/mcp --metadata AWS_REGION=us-west-2

Or add it to ~/.fx/mcp.json by hand. fx uses the mcp key rather than mcpServers, type to select the transport, and a single command array holding the executable and its arguments:

{
  "mcp": {
    "aws": {
      "type": "local",
      "command": [
        "uvx",
        "mcp-proxy-for-aws-cli@latest",
        "https://aws-mcp.us-east-1.api.aws/mcp",
        "--metadata",
        "AWS_REGION=us-west-2"
      ]
    }
  }
}

If a session is already open when you edit the file, run /mcp reload to pick up the change. The MCP server gives your agent access to AWS APIs, sandboxed script execution, and real-time documentation search.

2. Install skills from this repository:

npx skills add aws/agent-toolkit-for-aws/skills -a fx

This installs skill files to .fx/skills/ (project-level); add -g to install to ~/.fx/skills/ (global). fx also discovers skills already installed for other agents in .agents/skills/, .claude/skills/, and .codex/skills/, so a project set up for Codex or Claude Code needs no second copy. Each skill is a directory containing a SKILL.md file and optionally a references/ subdirectory with additional context the agent reads from the local filesystem when needed. fx reads skill metadata at startup and loads a skill's instructions when you or the agent invokes it; type $ in the composer or run /skills to browse what's installed.

Prerequisites: You need uv installed. An AWS account with credentials configured locally is required for API calls and script execution, but not for documentation search or skill discovery. See the user guide for detailed setup instructions.

Other agents

See the AWS MCP Server getting started guide for instructions on configuring the AWS MCP Server with your agent.

Then install skills from this repository:

npx skills add aws/agent-toolkit-for-aws/skills

Prerequisites: You need uv installed. An AWS account with credentials configured locally is required for API calls and script execution, but not for documentation search or skill discovery. See the user guide for detailed setup instructions.

What's included

Plugins

Plugins bundle the AWS MCP Server configuration and agent skills into a single install for your coding agent.

Plugin Description
aws-core Core AWS skills and MCP Server configuration. Covers service selection, CDK/CloudFormation, serverless, containers, storage, observability, billing, SDK usage, and deployment. Start here.
aws-agents Skills for building AI agents on AWS with Amazon Bedrock and AgentCore.
aws-data-analytics Skills for data lake, analytics, and ETL workflows with S3 Tables, AWS Glue, and Athena.
aws-agents-for-devsecops Investigate incidents, review code and execute UAT for release readiness, scan code for vulnerabilities, and run penetration tests with AWS DevOps Agent and AWS Security Agent.
aws-startup-advisor Puts an AWS Startups Solutions Architect in your coding assistant. Recommends the smallest architecture for your stage, credits, and team, then can scaffold it, migrate you from Azure, Google Cloud, or Heroku, move model calls to Amazon Bedrock, investigate production incidents, answer AWS Activate credits eligibility questions, and find startup offers you can use.

Plugins are currently available for Claude Code, Codex, Cursor, and Devin. For other agents, configure the AWS MCP Server directly and install skills from this repository.

Skills

Agent skills are curated packages of instructions and reference materials that help agents complete specific AWS tasks. Skills are loaded on demand — agents discover and retrieve only what's relevant to the current task.

npx skills add aws/agent-toolkit-for-aws/skills

Browse the skills/ directory to see all available skills.

Rules files

Recommended project-level configuration files that tell agents how to use AWS most effectively — for example, by using the AWS MCP Server, discovering available skills, or searching documentation before acting.

See rules/ for details.

AWS MCP Server

The AWS MCP Server is a managed server that gives agents access to AWS through the Model Context Protocol. It provides:

  • Full AWS API coverage — Interact with any of the 300+ AWS services through a single authenticated endpoint.
  • Sandboxed script execution — Agents can run Python scripts in an isolated environment for complex multi-step operations.
  • Real-time documentation access — Search and retrieve current AWS documentation, API references, and service capabilities without authentication.
  • Enterprise controls — Amazon CloudWatch metrics, IAM context keys for agent-specific policies, and AWS CloudTrail audit logging.

For details on operation, available tools, authentication, and supported Regions, see the AWS MCP Server documentation.

Documentation

How the Agent Toolkit relates to the MCP servers, skills, and plugins in AWS Labs

In 2025, AWS began releasing MCP servers, skills, and plugins as part of AWS Labs. The Agent Toolkit for AWS is the successor to those tools. We recommend using the Agent Toolkit for AWS, because it offers key features including:

  • IAM condition keys that distinguish between agent actions and human actions, so you can write policies that apply only to agents. For example, you can write policies that only allow read-only actions through the MCP server, even if the user’s underlying IAM role can take write actions).
  • CloudWatch metrics and CloudTrail audit logging for every request, so you can monitor and audit coding agent activity.
  • Agent skills that have undergone thorough end-to-end evaluations, so you can be confident that workflows will complete successfully.

AWS Labs MCP servers, skills, and plugins will continue to work and accept contributions, and over time the best of AWS Labs will be transitioned to the Agent Toolkit for AWS to ensure that customers can access the broadest array of tooling and guidance for their agents.

License

This project is licensed under the Apache-2.0 License. See LICENSE for details.

S
Description
GitHub Trending: aws/agent-toolkit-for-aws
Readme
24 MiB
Languages
Python 90.4%
TypeScript 3.5%
Shell 2.6%
HTML 1.2%
JavaScript 1.1%
Other 1.2%