Skip to content

Adr 022 agent asset registry

Status: proposed Date: 2026-07-08 Last-updated: 2026-08-11

Adding a new runtime artifact to ABCA today — an MCP server, a Cedar policy module, a skill, a prompt fragment — is a core-code change plus a CDK deploy. Artifacts are either vendored into the container image (built-in MCP servers, first-party workflows), inlined on the Blueprint construct (Cedar policies), or served from repo-local files (.mcp.json, AGENTS.md). There is no versioned catalog, no immutability guarantee at a given version, and no audit trail of “which asset versions did this task actually run.”

This has three costs:

  1. Every new tool/skill/policy costs a deploy. Rolling out a new MCP server to N repos is N Blueprint edits + a CDK deploy. Teams can’t publish autonomously.
  2. No pin, no reproducibility. Because assets aren’t versioned, “the tool the agent used on 2026-05-01” can’t be reconstructed from the task record.
  3. The vocabulary already anticipates a registry. ADR-014 and WORKFLOWS.md already:
    • Coined registry://kind/name refs (grammar in agent/src/workflow/validator.py _REGISTRY_REF).
    • Modeled agent_config asset kinds (mcp_servers, skills, plugins, subagents, prompt_fragments, cedar_policy_modules) 1:1 with the vocabulary this ADR needs.
    • Designed a resolver interface as a drop-in swap — filesystem-backed today, registry-backed later (agent/src/workflow/loader.py:107, WORKFLOWS.md §“Registry integration (#246)”).
    • Left validator rule 8 as a deferred check: every asset ref resolves — builtins today, registry refs when the registry lands.

Issue #246 proposes closing this gap with a central versioned asset registry: a catalog of typed, immutable-at-version artifact records that blueprints pin by registry://kind/name@constraint, that the orchestrator resolves at task start, and that the agent receives as a resolved bundle. Six acceptance criteria — asset kinds enumerated, publish+resolve with semver+immutability, blueprint reference of at least one kind, agent E2E for one kind, descriptor validation at publish, tests + docs.

Two forces shape the decision:

  • Prior art exists at AWS. AWS Agent Registry (Bedrock AgentCore) is a managed service — public preview — whose native resource types (MCP servers, agents (A2A), skills, plus custom resources with a caller-defined JSON schema) map directly onto #246’s asset-kind list. It ships governance (approval workflow), audit (CloudTrail), notifications (EventBridge), discovery (hybrid semantic + keyword search), MCP-native discovery endpoint, and IAM-or-JWT authorization out of the box. Two caveats: (a) it does not commit to semver constraint resolution — records carry a version string and support revisions, but the resolution semantics WORKFLOWS.md commits to (^/~/exact, “highest matching version wins”, reject */latest) are an ABCA-side concern; (b) it is in public preview under bedrock-agentcore and moves to a new agent-registry namespace on 2026-08-06 — a hard cutover affecting API endpoints, IAM actions, SDK client names, CLI commands, and registry data itself.
  • Substrate is not the invariant. The invariants #246 needs — semver grammar, immutability per version, resolve-at-task-start, fail-closed on missing pin, descriptor validation at publish (non-bypassable by caller-supplied fields), and read-path confidentiality (no inlined credentials; allowlist redaction on the open read surface) — are contract-level, independent of whether the data lives in AgentCore Registry or in DynamoDB + S3. ABCA has a precedent for this factoring: ADR-014’s resolver interface deliberately abstracts filesystem-vs-registry so the substrate is swappable.

Adjacent decisions the ADR must respect but not re-open:

  • #381 — ADR↔Persona↔Skill graph. #381 wires bidirectional frontmatter edges between ADRs, personas, and skills as docs/ and plugin markdown, enforced by a parity linter. Both #246 and #381 mention “skills,” but they mean different things: #381 is documentation graph consistency; #246 is a runtime artifact catalog. This ADR keeps them cleanly separated.
  • ADR-014. Workflows are the registry’s first capability-kind consumer; the workflow_ref field’s resolution semantics are the model this ADR generalizes to all asset kinds. Workflows themselves stay filesystem-backed in the MVP — they already ship and are validated; migrating them to the registry is a separate follow-up, not part of #246.

ABCA gains a central agent asset registry: a versioned, immutable-per-version, platform-managed catalog of runtime artifacts. Blueprints reference assets via registry://kind/namespace/name@constraint; the orchestrator resolves refs at the create-task boundary; resolved {kind, id, version} triples are stamped on the task record; the agent receives a resolved bundle alongside the workflow file.

The ADR fixes the contract. The substrate ranking below was written to defer the choice to the design PR, with a preferred direction and a documented fallback. That selection has resolved to the preferred substrate, AWS Agent Registry (Bedrock AgentCore), behind the RegistryClient seam (sub-decision 8); the implementation lands in design PRs #664 (catalog) and #665 (resolve/load). The ranking, alternatives, and flip-conditions are retained below as the record of why AgentCore was chosen and when to fall back to DynamoDB + S3 — the falsifiable conditions still govern any future substrate change.

Status. This ADR stays proposed until #664/#665 merge, per the docs/decisions/README.md rule that an ADR flips to accepted when its implementing PR lands. Statements below about what the MVP ships, validates, or proves end-to-end describe the behavior those PRs implement and are under active review — treat them as the intended contract, not as merged-to-main facts, until the status flips. The Changelog records that flip when it happens.

  1. URI grammar and kinds. registry://<kind>/<namespace>/<name>@<constraint>. MVP kinds: mcp_server, cedar_policy_module, skill. Schema declares — but does not yet load — plugin, subagent, prompt_fragment, capability (capability = workflow, ADR-014 vocabulary). This grammar extends the shape pre-declared for ADR-014 at agent/src/workflow/validator.py _REGISTRY_REF, which admitted a 2-segment registry://kind/name form but not the @<constraint> suffix or _ (snake_case) in the kind segment. The implementation widens that lenient acceptance check and lands the authoritative, strict grammar in a dedicated parser mirrored byte-for-byte across both languages (cdk/src/handlers/shared/registry/ref.ts and agent/src/registry/ref.py); validator.py remains a lenient pre-flight admitting both forms.

    Short vs long forms (migration note). WORKFLOWS.md illustrates refs in a short 2-segment form with no constraint (registry://prompt/web-research-workflow, registry://mcp/web-search-v1, registry://skill/research-synthesis-v1). Those are forward-declarations — the WORKFLOWS spec explicitly marks registry:// refs as “declared in the schema now but ignored by the runner until the registry (#246) can resolve them.” This ADR’s strict grammar is the long form: 3 segments (<kind>/<namespace>/<name>), snake_case kinds (mcp_server, not mcp; prompt_fragment, not prompt; cedar_policy_module, not cedar), and a mandatory @<constraint>. Only the long form resolves. The short form stays lenient-only — accepted syntactically by validator.py’s pre-flight so existing illustrative workflows don’t fail validation, but not resolvable by the registry until rewritten to the long form. There is no automatic aliasing (mcpmcp_server) at resolve time: a ref must be long-form to load. Migrating the WORKFLOWS examples to long form is doc-only cleanup tracked with the workflow/registry integration, not a blocker for #246.

  2. Semver, not floating. Allowed constraints: exact (1.4.1), caret (^1.4.1), tilde (~1.4.1). Rejected at validation time: *, latest, >=, and bare prerelease modifiers. Resolution rule: highest semver-comparable version matching the constraint; prereleases rank below their base version.

  3. Immutable per version. (kind, namespace, name, version) is immutable once published. Republish attempts fail 409 REGISTRY_VERSION_EXISTS. Content changes require a new version. Mutable metadata is confined to a lifecycle status field.

  4. Lifecycle status. Full set: draftsubmitted → (approved/rejected) → deprecatedremoved. submitted is the ABCA token; the AgentCore substrate names that state PENDING_APPROVAL — one state, two names, mapped once here and referred to as submitted throughout. approved is the single canonical “resolvable” token (the substrate names it APPROVED); it resolves silently. deprecated resolves with a warning event on the task record; submitted, draft, rejected, and removed all fail resolution. See sub-decision 10 for the governance transitions between these states. Immutability of the artifact bytes is orthogonal — status transitions do not rewrite content.

  5. Resolve at the create-task boundary; the TypeScript orchestrator owns resolution. Refs resolve in the same place workflow_ref resolves today (cdk/src/handlers/shared/). Catalog lookup + semver selection is owned by the orchestrator (TypeScript): it turns each registry://…@constraint ref into a fully-pinned {kind, id, version} triple plus the resolved runtime payload, stamps resolved_assets: [{kind, id, version}] on the task record for audit, and threads the runtime bundle into the agent payload. The Python agent receives that already-resolved bundle and loads it (sub-decision 6); it does not re-run catalog resolution in the normal flow. Python nonetheless carries a mirrored RegistryClient + semver resolver (sub-decision 8) — required for the two-language parity contract and for any direct lookup path — but resolution authority at the task boundary is single-owner (TypeScript), which is what keeps sub-decision 6 (no re-resolution) true.

  6. Fail-closed. A ref that does not resolve fails admission with REGISTRY_RESOLUTION_FAILED and a specific reason (NO_MATCHING_VERSION, REMOVED, INVALID_CONSTRAINT). No implicit fallback to a “latest” version. A running task never silently downgrades or substitutes a resolved asset.

  7. Descriptor validation at publish. Every published asset carries a typed descriptor validated at publish; malformed descriptors reject publish; the descriptor lives in the record, the artifact bytes are separate.

    Validation must be non-bypassable by any caller-supplied field. The validated runtime descriptor MUST be carried in a channel isolated from caller-controlled discovery prose — either structurally serialized (not line-oriented text concatenation), or recovered with a parser that is last-wins / rejects duplicate keys and escapes every caller-supplied value. A carrier where a free-text discovery field (e.g. a skill description) can inject or shadow the runtime key defeats this invariant: it lets a publisher smuggle a runtime payload the validator never inspected. This requirement applies equally to CUSTOM records — a CUSTOM body’s structural fields (including the custom flag itself) are validated, not passed through verbatim.

    MVP: validation is delegated to the substrate’s native descriptor types — MCP records are stored as a protocol-validated server.json (schema-checked by AgentCore), skills as Markdown frontmatter whose runtime key is emitted and recovered through a real YAML serializer (never string concatenation, so a description newline cannot inject a key), and anything without a native type as CUSTOM (verbatim artifact bytes, but with its ABCA descriptor fields structurally validated). This gives publish-time rejection for the MVP kinds without ABCA authoring its own schema.

    Future scope: the rich ABCA capability descriptor originally described here — a cross-kind contract declaring tool surface, egress domains, Cedar actions introduced, minimum compute profile, and permissions required, with a shared JSON Schema as the single source of truth consumed by both languages (mirroring the workflow-schema decision in ADR-014) — is not in the MVP. The MVP relies on native/CUSTOM shape checks only; the shared-schema capability descriptor lands with the capability-descriptor issue (#481).

  8. Resolver interface as the seam. Both #246 sides — the CDK/TypeScript orchestrator and the Python agent runtime — talk to a RegistryClient abstraction, not to a specific AWS SDK client. This mirrors ADR-014’s filesystem-vs-registry seam and confines any substrate change (or the AgentCore Aug 2026 rename) to one implementation file per language.

  9. MVP E2E path is at minimum one asset kind: MCP server. Per issue AC4, one end-to-end path is sufficient for MVP. MCP server is the primary target because it is the most heavily used asset kind (already vendored built-in in the container) and because AgentCore Registry has native, protocol-validated support for it. (Implementation note: #664/#665 target all three MVP kinds — a single task loading an MCP server, a Cedar policy module, and a skill together — exceeding the one-kind AC4 bar; verified on a dev stack during review. Cedar/skill hardening continues under the child issues #478/#479/#480/#481.)

  10. Governance lifecycle is a first-class concern; the MVP surface is deliberately thin. Publishing follows a lifecycle: draft → submitted → approved | rejected → deprecated → removed. Only approved records resolve; submitted/rejected/draft records exist but do not resolve. Governance is what separates a registry from a directory; deferring the machinery entirely would drop ABCA into the “partial-match” tier that community catalogs occupy. Choosing AgentCore as the substrate is precisely what lets ABCA claim the lifecycle at MVP without building a state machine: the substrate provides the state model, the CreateRecord → SubmitForApproval → UpdateRecordStatus transitions, CloudTrail control-plane audit, and EventBridge transition notifications natively.

    What the ABCA MVP surface actually exposes (shipped): publish, resolve, list, show. Publish creates a record and — when the caller holds approver rights and passes auto_approve — drives it DRAFT → PENDING_APPROVAL → APPROVED inline so it resolves immediately. Resolvers match only APPROVED records. Rich audit metadata (approver identity, timestamp, statusReason) rides on the substrate transition.

    Future scope (not in the ABCA MVP surface): (a) a standalone approve/reject/deprecate endpoint so a normal submitted record can be promoted after publish without auto_approve — today a non-auto-approved record stays PENDING_APPROVAL from ABCA’s side until acted on out-of-band; (b) environment-gating of auto_approve (it is approver-gated but not restricted to dev environments); (c) first-class consumption of the substrate’s transition events by an ABCA-side review pipeline. These are tracked under the lifecycle child issue (#478) and event-governance (#230).

  11. MVP access control, and read-path confidentiality. Two Cognito groups: RegistryPublisher (may publish, creating a record that awaits approval) and RegistryApprover (may additionally auto_approve on publish — driving the record to APPROVED in one call). Resolve/read is available to any authenticated caller. Standalone post-publish promote/reject/deprecate is future scope (sub-decision 10). Cedar-governed publish/promote ACLs are Phase 3 (#480/#481). No per-namespace ACL granularity in MVP; the two-role split is the minimum that makes sub-decision 10’s approval workflow meaningful.

    Because resolve/read is open to any authenticated caller, two confidentiality invariants bound what the read surface may return: (a) runtime payloads MUST NOT carry credential material — credentials are referenced (e.g. a Secrets Manager ARN the orchestrator dereferences at connect time), never inlined into the stored runtime; and (b) any read surface reachable by a non-approver caller redacts by allowlist — it projects the known-safe fields for the asset kind and drops everything else, rather than masking a fixed denylist of field names. A denylist over field names is fail-open by construction against a payload whose key space is open (a publisher can attach api_key, env, or a token in a url query string), so the allowlist is what makes the redaction fail-closed. Publish-time validation enforces the same closed key set (unknown runtime keys reject), closing the payload at both the write and read boundaries. The orchestrator connect-path is exempt: it resolves through the RegistryClient port (not the human-facing read API) and receives the full referenced-credential-resolved payload it needs to connect.

  12. Workflows do not migrate to the registry in this ADR. ADR-014 first-party workflows stay filesystem-backed in the container image. The resolver interface leaves the door open (the vocabulary is aligned 1:1), but the migration is a separate decision not needed to close #246.

  13. Split cleanly from #381. Registry stores skill runtime artifacts — prompt+tools bundles the agent loads at task start. #381’s ADR↔Persona↔Skill documentation graph stays in docs/ and plugin markdown with frontmatter edges + parity linter. The two must not conflate: an operator publishing a skill artifact is not the same act as an author linking a skill markdown to an ADR. If a skill record’s descriptor eventually cites an ADR, that citation is metadata, not a graph edge #381 owns.

Substrate: preferred choice, fallback, and considered alternatives

Section titled “Substrate: preferred choice, fallback, and considered alternatives”

This section ranks the candidates by fit for ABCA and records the flip-conditions that govern the choice. It was originally written to defer the substrate selection to the design PR (which had to prototype the top-ranked candidate before committing); that selection has since resolved to option 1, AWS Agent Registry (Bedrock AgentCore). The ranking below is retained as the decision record — why AgentCore won and when to fall back — and continues to govern any future substrate change.

Across the registry platforms available as of mid-2026, the five requirements this ADR treats as invariants (publishing, searchable catalog, governance, access control, and multi-resource type support) narrow the field to a small number of viable options. All meaningful candidates remain in preview or early maturity, which reinforces that the RegistryClient seam (sub-decision 8) is the substrate-independent hedge — ABCA should not be locked to any one substrate while the ecosystem is still moving.

1. Preferred: AWS Agent Registry (Bedrock AgentCore). Rationale:

  • Native resource types map 1:1 onto MVP kinds: mcp_server (MCP protocol-validated), skill, custom (Cedar module, prompt fragment via caller-defined JSON schema). Five native types — the broadest coverage of any managed offering in the current field.
  • Governance ships as a first-class lifecycle — Draft → Pending Approval → Approved/Rejected with deprecation support — driven by EventBridge notifications and an UpdateRegistryRecordStatus API that lets external review pipelines (ticketing, security scan, human approval) close the loop programmatically. Auto-approve mode is available for dev environments. This is a direct match for sub-decision 10.
  • Hybrid semantic + keyword search with weighted relevance ranking.
  • MCP-native discovery endpoint — an agent can query the registry via MCP without ABCA-specific glue.
  • IAM or JWT (Cognito) authorization — ABCA already uses Cognito, so JWT drops in for the resolve path. Fine-grained IAM actions like bedrock-agentcore:InvokeRegistryMcp support the two-role model in sub-decision 11.
  • CloudTrail control-plane audit trail.
  • Multi-registry organizational scoping — separate registries per team / environment / business unit are first-class, matching how ABCA operators would isolate dev from production catalogs.
  • Available in five regions during preview at no charge; cost is not a factor for MVP.
  • AWS-managed. No new operational surface (no MongoDB, no auth server, no self-run gateway). A support contract exists.
  • Best fit for an AWS-native platform, which ABCA is by construction.

2. Fallback: DynamoDB (metadata) + S3 (artifacts). Use when preferred is blocked. Rationale:

  • Matches existing ABCA patterns (RepoTable, attachments-bucket).
  • Full control over semver resolution and immutability semantics — no gap between what WORKFLOWS.md commits to and what the substrate enforces.
  • No preview-status risk. No third-party dependency to trust.
  • Cost: extra code to write and maintain (publish handler, resolve handler, IAM grants, descriptor validators, governance state machine, discovery/search). The governance flow in sub-decision 10 is essentially a re-implementation of what AgentCore ships.

3. Considered — not adopted for MVP: mcp-gateway-registry (open-source, Apache-2.0, self-hosted). An Apache-2.0 project combining a gateway (nginx data plane) and registry (FastAPI control plane, MongoDB-backed) with native support for MCP servers, A2A agents, skills, and admin-defined custom entities. Federation to AWS Agent Registry, Anthropic MCP Registry, and peer instances is built in. Published on the AWS Open Source Blog (June 2026), which materially raises its credibility beyond the typical community project. Reasons it ranks below the preferred and fallback options for ABCA:

  • New operational surface. ABCA is DynamoDB-native. This project introduces MongoDB (or Amazon DocumentDB), a FastAPI service, an nginx proxy, and an auth server — four new components to deploy, patch, monitor, back up, restore, and reason about at incident time. That is a substantial addition for a sample/reference project whose current stack is intentionally slim.
  • Scope mismatch. The gateway/proxy features (per-user 3LO OAuth, virtual MCP servers, gateway-brokered egress) are valuable capabilities, but they solve problems #246 does not ask us to solve in MVP. Paying the operational cost for capabilities MVP does not require is over-scoping.
  • Federation is real, but hedged elsewhere. Its ability to federate to AWS Agent Registry + others behind one API is architecturally interesting, but the substrate-independence property that federation provides is already delivered by sub-decision 8 (the RegistryClient interface). ABCA does not need a second layer of indirection for the same purpose.
  • Governance model is webhook-based rather than a fully-integrated lifecycle. Wiring the webhook approval into ABCA’s own workflows is additional glue we do not need to write.

If preferred and fallback are both blocked, or if a future issue explicitly needs the gateway/federation capabilities, this candidate should be re-evaluated then.

4. Considered and not adopted: agentregistry.ai (Solo.io). Kubernetes-native, multi-cloud, four resource types (agents, MCP, skills, prompts) with a full artifact approval mode. Best suited to Kubernetes-first / multi-cloud platforms. ABCA is neither — it is single-cloud (AWS), CDK-deployed, not Kubernetes-first. Adopting this substrate would inherit a K8s-shaped model ABCA does not use elsewhere.

5. Considered and not adopted: Microsoft Entra Agent Registry + Agent Governance Toolkit. Treats agents as first-class identities via Entra Conditional Access, supports 20+ agent types, provides shift-left CI/CD governance and multi-cloud agent surfacing (including AWS Bedrock). Best suited to Microsoft-ecosystem platforms. ABCA has no Entra / Microsoft-ecosystem alignment; adopting this substrate would force introducing that ecosystem for a single subsystem.

The following platforms were reviewed but did not warrant a full write-up above, because each falls short of the invariants this ADR fixes (typically on governance, resource-type breadth, or fit for an AWS-native, non-Kubernetes-first, non-Microsoft-ecosystem platform). Named here so future readers see they were weighed and disqualified.

  • Google Cloud Agent Registry — GCP-native, launched preview April 2026. Supports agents, MCP servers, endpoints. Ruled out: GCP-only (ABCA is AWS-native); keyword-only search (no semantic); IAM-only governance with no explicit approval workflow.
  • Smithery — largest open MCP server registry (3,000+ servers), community-driven, SaaS + managed gateway. Ruled out: relies on a “verified” flag rather than a formal pre-publication review workflow; October 2025 supply-chain incident illustrated the risk of that model for a governed platform. Useful as a discovery source, not a governed catalog.
  • Glama — very large community MCP directory (23,000+ servers). Ruled out for the same reason as Smithery: discovery-only, no governance.
  • PulseMCP — community MCP directory. Ruled out: directory, not a registry.
  • ACI.dev — 600+ integrations, semantic search, hierarchical access control. Ruled out: tool-calling platform, not a governed registry; no submit/review/approve workflow; agents not first-class resources.
  • Composio — 1,000+ toolkits, 20,000+ tools, granular per-user OAuth. Ruled out: same shape as ACI.dev — tool-calling catalog, no governance workflow, agents not first-class.
  • Toolhouse — 40+ built-in MCP servers with agent deployment. Ruled out: minimal registry semantics (no semantic search, no RBAC, no governance workflow).
  • Docker MCP Catalog — Docker-published catalog with commit pinning, publisher trust tiers, cosign signature verification. Ruled out as a substrate: single-vendor curated catalog rather than a self-hostable registry ABCA operators can publish to. Its supply-chain patterns (commit pinning, cosign) inform sub-decisions 3 (immutability) and 7 (descriptor validation) even though the platform itself is not adopted.
  • Jozu Hub — MCP registry with cryptographic signing, security scanning, and runtime policy gating via Jozu Agent Guard. Ruled out: narrower scope than the AWS-native option, unclear alignment with ABCA’s Cognito/IAM auth model, and treating it as a substrate would introduce a second vendor on the critical path.
  • Stacklok / ToolHive — open-source local registry with strong audit/OTEL story and vMCP for curated tool sets. Ruled out as a substrate for the same operational-surface reason as mcp-gateway-registry: adopting it introduces new components (registry service, its own auth/audit paths) without covering the governance workflow (sub-decision 10) as well as the preferred managed option. Its audit-trail patterns inform observability decisions in the design PR.

Design PR decision framework. Choose the fallback (option 2) when any of the following is true:

  • AgentCore Registry is not GA in every target ABCA deployment region.
  • AgentCore’s revision model cannot be constrained to enforce (name, version) immutability with acceptable client-side guards.
  • Semver resolution added on top of AgentCore’s version string materially complicates the resolver or breaks the parity contract with WORKFLOWS.md.
  • The 2026-08-06 namespace migration cost, weighed against ABCA’s release timeline, exceeds the cost of building DDB+S3 once.

Hard gate on the 2026-08-06 cutover. This date is imminent relative to the build, so it is a gate, not just a cost input: do not take a production dependency on AgentCore Registry until the bedrock-agentcoreagent-registry namespace migration is complete and GA in every target region. Until then the dependency is dev/preview only; the RegistryClient seam (sub-decision 8) confines the code change, but the data migration and IAM-action renames are the operator’s responsibility and must be rehearsed before any prod cutover. If GA slips past ABCA’s release timeline, fall back to DDB+S3 per the conditions above.

Regardless of substrate, the invariants above (semver, immutability, resolve-at-boundary, descriptor validation, governance workflow, fail-closed, resolver interface as the seam) hold.

  • (+) New tools/skills/policies do not require CDK deploys. Publishers push new versions to the registry; blueprints re-pin when ready. The compile-and-deploy path is only for platform-level changes.
  • (+) Per-task audit. resolved_assets on every task record answers “what did this task actually run” from a single field, without excavating deploy timestamps or Git blame.
  • (+) Reproducibility. A task’s pins fully determine its asset surface. Re-running the same task with the same pins produces the same asset load, modulo LLM nondeterminism.
  • (+) Registry vocabulary was pre-declared. The URI grammar, asset kinds, and resolver interface were anticipated in ADR-014 / WORKFLOWS.md, so this ADR extends a committed shape rather than opening a new one. The pre-existing _REGISTRY_REF check accepted a lenient registry://kind/name form; the implementation widens it (adding @<constraint> and snake_case kinds) and lands the authoritative strict grammar in registry/ref.{ts,py} (sub-decision 1).
  • (+) Preferred-substrate direction gives implementers a clear default. Reviewers and future contributors don’t need to re-litigate AgentCore-vs-native from first principles; the trade-off is captured with an explicit fallback rule.
  • (+) Aligned with AWS-native architecture. AgentCore Registry is a managed AWS service that natively covers the invariants (governance lifecycle, audit, discovery, MCP-native endpoint, IAM/JWT auth). ABCA is AWS-native by construction, so this alignment avoids re-implementing what AWS already ships.
  • (+) Governance machinery is available at MVP via the substrate. Choosing AgentCore means the lifecycle state model, transition APIs, CloudTrail audit, and EventBridge notifications exist from day one without ABCA building a state machine (sub-decision 10). The ABCA surface over that machinery is intentionally thin at MVP — publish + auto_approve + read — with standalone promote/reject/deprecate endpoints, environment-gated auto-approve, and ABCA-side event consumption deferred to #478/#230.
  • (+) Clean handoff to child issues. #478 (lifecycle), #479 (versioning + immutability), #480 (Blueprint integration + ACLs), #481 (capability descriptors) each map to a specific sub-decision above, giving each a scoped, non-overlapping mandate.
  • (−) Two-language resolver contract. The RegistryClient interface and the semver rules must agree between the TypeScript orchestrator and the Python agent. This is the same class of parity hazard the repo has learned from twice (Cedar bindings, workflow validation). Mitigation: publish the resolver contract as a golden corpus (contracts/registry-resolution/) mirroring the existing contracts/cedar-parity/ and contracts/workflow-validation/ mechanisms — annotated (ref, catalog) → verdict fixtures run against every implementation in CI.
  • (−) A rich descriptor schema is a new maintained surface — deferred. A cross-kind capability descriptor (tool surface, egress, Cedar actions, compute, permissions) would need to be authored, versioned, and evolved compatibly, with JSON Schema as the single source of truth both languages consume (mirroring the workflow-schema decision in ADR-014). The MVP does not build this: it leans on the substrate’s native descriptor validation (MCP server.json, skill frontmatter, CUSTOM shape checks) per sub-decision 7. The shared-schema capability descriptor lands with #481.
  • (−) MVP access control is coarse-grained. Two Cognito groups (RegistryPublisher, RegistryApprover) are a single tenant boundary — no per-namespace ACL, no publisher-per-team. Acceptable for MVP because it makes the sub-decision 10 approval workflow meaningful; Phase 3 Cedar-governed ACLs (#480/#481) close it.
  • (−) Substrate selection required a spike. The choice was made with evidence: a DDB+S3 fallback was prototyped and an AgentCore implementation was built and exercised on a dev stack during review (design PRs #664/#665); AgentCore was selected per the flip-conditions below. The RegistryClient seam keeps the fallback a live option if a flip-condition later trips.
  • (!) AgentCore Registry preview + 2026-08-06 namespace migration. If preferred substrate is chosen, ABCA inherits the rename: API endpoints, IAM policies, SDK clients, CLI scripts, and registry data must all move on cutover. Mitigation: the RegistryClient interface (sub-decision 8) confines the change to one implementation file per language; the CI parity corpus catches semantic drift. Design PR MUST record which target regions have GA before merging a production dependency on AgentCore, and MUST document a rollback path to the DDB+S3 fallback if preview constraints materialize.
  • (!) Semver-on-a-non-semver-substrate. AgentCore Registry’s version field is a string, not a semver-aware column. The ABCA-side resolver has to (a) query candidate records and (b) rank them by parsed semver. This is safe when catalogs are small, but a large catalog could pay a list-cost per resolve. Mitigation: cache resolved pins per (ref, catalog-fingerprint) at the create-task boundary; measure at MVP scale before optimizing.
  • (!) “Removed” vs GDPR-style deletion are different. removed means “fails to resolve, refuse to run tasks pinned to this”; it does not necessarily mean the bytes are gone. If a compliance-driven true deletion is ever required, it is a separate operation on the substrate and outside the resolver contract. Design PR to note.
  • (!) Non-goal drift. MVP does not include: transitive registry-asset dependencies, EventBridge as a primary bus for asset events, replacing repo-local .mcp.json/AGENTS.md, publisher-per-team ACL, or the meta-agent path from #99. Any of these arriving via scope-creep undermines the “resolve at task start” boundary and should be pushed to a follow-up ADR.
  • (!) Federation / “registry of registries” is out of scope. ABCA runs a single, operator-curated catalog — assets are published into ABCA’s own registry by trusted operators (sub-decision 11), not federated from external indexes. External registries (the MCP Registry, PyPI/npm/Docker-Hub-style hubs, or peer ABCA instances) are treated as discovery sources only: an operator may find an asset there and then publish it into the ABCA catalog, but the agent never resolves a registry:// ref against an external index at task time. There is no cross-registry federation layer, and none is planned in #246 — the RegistryClient seam (sub-decision 8) already delivers the substrate-independence that federation is sometimes reached for, without a second indirection. If a future need for true federation emerges, it is a new ADR, not a scope-creep of this one. (Raised in review: whether a CNCF/community “registry of registries” abstraction should be adopted instead of a bespoke catalog — deferred with the rest of federation; the MVP’s single curated catalog is deliberately the smaller surface.)
  • (!) Governance for production publish is a trust decision. Until Cedar-governed ACLs land, publish rights are keyed by Cognito group membership — a coarse gate. Any exposure of the publish endpoint outside a trusted operator group is a security decision, not a convenience decision.
  • 2026-08-11 — renumbered 018 → 022; added read-path + descriptor-integrity invariants. Renamed the file ADR-018 → ADR-022: ADR-018 was taken by the Linear agent-session-interaction ADR on main, and 019/020/021 were claimed (open PR #663 + merged ADRs), so docs/decisions/README.md’s “numbers are never reused” rule required the next free number, 022. Also, from a second implementation-review pass on #664/#665 (@scottschreckengaust): added read-path confidentiality invariants to sub-decision 11 and the substrate-invariant list — runtime payloads reference credentials (never inline them) and open read surfaces redact by allowlist, not denylist; and strengthened sub-decision 7 to require the validated descriptor be carried isolated from caller-controlled discovery prose (non-bypassable validation), covering CUSTOM too. Bumped Last-updated.
  • 2026-07-28 — kept proposed; qualified implementation claims. Reverted a premature proposed → accepted flip: per docs/decisions/README.md an ADR flips to accepted when its implementing PR merges, and the implementation is still in review (#664/#665). Softened “shipped / proven E2E on a live stack” language to “targeted by #664/#665, exercised on a dev stack during review,” and stopped citing the parked DDB+S3 PRs (#632–#634) as current. Added a Status note in the Decision section. The ADR flips to accepted — with a Changelog entry pointing at the merged SHAs — once #664/#665 land. Landed in this round: the kind-vocabulary alias note (short vs long forms), the federation Non-goal, and the 2026-08-06-cutover gate.
  • 2026-07-27 — refinements from implementation review. The substrate selection the ADR deferred resolved to the preferred option, AWS Agent Registry (Bedrock AgentCore), behind the RegistryClient seam. The decision and its invariants are unchanged; the edits below reconcile the design-of-record with the implementation and are refinements, not a reversal (the substrate ranking, alternatives, and flip-conditions are retained verbatim as the record of why). Prompted by review on the ADR PR (@scottschreckengaust, @isadeks):
    • Grammar (sub-decision 1, Consequences, References). Reframed “matches the shape already committed” → “extends the committed shape.” The pre-existing _REGISTRY_REF admitted a lenient 2-segment form but not @<constraint> or snake_case kinds; the implementation widens it and lands the authoritative strict grammar in registry/ref.{ts,py} (parity-tested via contracts/registry-resolution/).
    • Resolution owner (sub-decision 5). Made explicit that the TypeScript orchestrator owns catalog/semver resolution at the create-task boundary and the Python agent loads the already-resolved bundle; Python’s mirrored resolver exists for the parity contract and direct lookups, not to re-resolve at task time (keeps sub-decision 6 true).
    • Governance surface (sub-decisions 10/11, Consequences). Separated the substrate-provided lifecycle machinery (available at MVP via AgentCore) from the thin ABCA surface actually shipped (publish + auto_approve + resolve/list/show). Standalone post-publish promote/reject/deprecate endpoints, environment-gated auto-approve, and ABCA-side consumption of transition events are named as future scope (#478/#230).
    • Descriptor validation (sub-decision 7, Consequences). MVP delegates to the substrate’s native descriptor validation (MCP server.json, skill frontmatter, CUSTOM shape checks); the rich cross-kind capability descriptor with a shared JSON Schema is future scope (#481).
    • Status token. Collapsed the dual approved/active naming to the single canonical approved (substrate: APPROVED) to remove a two-language parity hazard.
    • Accuracy fixes. #381-split cross-reference corrected (sub-decision 13, not 12); reference URLs normalized (cloud.google.com, learn.microsoft.com).