Skip to content

RFC 972: Structured design context in synthesized templates - #981

Open
satyakigh wants to merge 7 commits into
aws:mainfrom
satyakigh:context-rfc
Open

RFC 972: Structured design context in synthesized templates#981
satyakigh wants to merge 7 commits into
aws:mainfrom
satyakigh:context-rfc

Conversation

@satyakigh

@satyakigh satyakigh commented Aug 4, 2026

Copy link
Copy Markdown

This is a request for comments about Structured design context in synthesized templates. See #972 for
additional details.

APIs are signed off by @iliapolo


By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache-2.0 license

Comment thread text/0972-metadata-context.md
Comment thread text/0972-metadata-context.md Outdated
Context added on an outer scope cascades to all primary resources beneath it
with nearest-wins semantics: scalar fields (`why`, `mutable`, `trust`, `ops`)
from scopes closer to a resource override outer scopes, while list fields
(`must`, `gaps`, `deps`, `failureModes`) accumulate and de-duplicate. Like

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is this intended to propagate down the construct tree? For instance, in an L3 construct, would list fields accumulate on every resource within the construct?

A further question is - could this lead to biasing the user's AI agent? If they see a single string in a field repeated for each resource?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Applying information to descendants is now explicit rather than automatic. The RFC also explains that repetition can make one fact appear disproportionately important and directs template-wide information to TemplateMetadataContext.

Comment thread text/0972-metadata-context.md Outdated

Every resource context block records where it came from and how much to trust it.
When the caller omits `trust`, CDK emits `source: AUTHORED` and chooses confidence
from the declaration: `HIGH` when `why` or a non-empty `must` is present, otherwise

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Could you give more clarity on when a user needs to be using a specific field. For instance, guidance in the README like

A human's preferred option should be .... On the other hand, an agent should be using .... by default.

One suggestion could be keeping AUTHORED primarily for humans, and INFERRED for agents to make it simpler.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added explicit guidance: people use AUTHORED for information they write or confirm. Automated producers use COMMENT, COMMIT, or INFERRED according to their evidence and must supply confidence explicitly.

@iliapolo iliapolo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@satyakigh Are you also looking for feedback on the schema itself, or just the CDK part of things?

Comment thread text/0972-metadata-context.md Outdated

Add resource-level context on any construct scope. It is rendered onto the
scope's *primary* resources (the `defaultChild` chain of each construct),
skipping incidental helper resources like auto-created IAM policies:

@iliapolo iliapolo Aug 26, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What if the customer does want some context on these incidental resources? For example, a lambda.Function may implicitly create a dead letter queue. For completes, lets add an example of that:

MetadataContext.of(func).add(...); // primary resource context

MetadataContext.of(func.deadLetterQueue).add(...) // helper resources context

This then begs the question of can we apply some default context. For example:

{
  "Type": "AWS::SQS::Queue",
  "Metadata:" : {
    "com.aws.cloudformation.Context": {
      "why": "Created by function MyFun to store failed invocation payloads",
      "must": ["Size === 0"]
    }
  }
}

Now the agent knows to see it as part of the same functionality vs just a floating resource. It would require a lot of code changes to aws-cdk-lib - if you agree it would be worth while, lets add it as a possible follow up / future enhancement.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Mainly the CDK side of things, we can update the schema if required as well if you guys have suggestions

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added examples for targeting an exposed helper directly, including a function's dead-letter queue. applyToAllResources supports intentionally including every helper. Selecting or populating helpers automatically by relationship remains future work.

}
}
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As a customer reading up to here I immediately wonder what keys are available and what they mean. Put a link to the schema appendix right here for quicker access (when we publish, the link should point to a proper page on the dev guide).

@satyakigh satyakigh Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added an early link to Appendix A and the published CloudFormation Metadata Context schema. Appendix A and the CDK API docs mirror that schema; the CloudFormation authoring skill provides non-enforced guidance.

Comment thread text/0972-metadata-context.md Outdated

Resource-level (`Resources.<LogicalId>.Metadata["com.aws.cloudformation.Context"]`):

| Field | Type | Meaning |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Add an Example column please (real life).

Comment thread text/0972-metadata-context.md Outdated
| `must` | string[] | Hard invariants; violating any entry breaks something (data loss, outage, security, corruption, coupling). |
| `mutable` | enum | Resource-default change-safety: `must-never-change` \| `change-with-constraints` \| `review-required` \| `free-to-tune`. |
| `mutability` | map\<property, enum\> | Sparse per-property overrides; only properties deviating from the default or high-stakes. |
| `trust` | object | Provenance: `src` (`authored`\|`comment`\|`commit`\|`infer`), `conf` (`high`\|`medium`\|`low`), optional `cite`, `note`. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Elaborate on the possible values of src, conf, cite, note (with examples).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added a dedicated trust-field table covering src, conf, cite, and note, including requiredness, allowed values, meanings, and examples.

Comment thread text/0972-metadata-context.md Outdated
| `failureModes` | string[] | Failure/recovery paths (retries, timeouts, DLQs, circuit breakers). |

`authored` means explicitly declared through the API; it does not imply that a human was
the producer. A producer deriving context from comments, commits, or code structure must

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

it does not imply that a human was the producer

But if its an agent producing this context - isn't it always inferred from something? Give a concrete example of when each value here would be used?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Clarified the source meanings with examples: authored is written or confirmed by a person, comment comes directly from a source comment, commit comes from version-control history, and infer is concluded from code or behavior.

Comment thread text/0972-metadata-context.md Outdated
```

Every resource context block records where it came from and how much to trust it.
When the caller omits `trust`, CDK emits `source: AUTHORED` and chooses confidence

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I assume that AUTHORED carries more trust than INFERRED? What prevents agents inferring context from using AUTHORED? or just not providing trust at all and then having CDK default to AUTHORED?

I think there needs to be a clearer definition and guidance. What is the main use-case for using AUTHORED? is it not human authored? if so - lets double down on that and provide agents with instructions to always use INFERRED when setting context.

@satyakigh satyakigh Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Removed the automatic AUTHORED default. trust is optional and may be used alone; when present, both source and confidence are required. AUTHORED means human-written or human-confirmed, though the API cannot prevent a caller from claiming it incorrectly.

Comment thread text/0972-metadata-context.md Outdated
Resource-level (`Resources.<LogicalId>.Metadata["com.aws.cloudformation.Context"]`):

| Field | Type | Meaning |
|----------------|-----------------------|--------------------------------------------------------------------------------------------------------------------------|

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is everything optional here? add an Optionality column

@satyakigh satyakigh Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added requiredness columns. All top-level Resource and Template Context fields are optional. When present, trust requires source and confidence, and an object-form ref requires at; CDK adds no other top-level requiredness.

Comment thread text/0972-metadata-context.md Outdated

Every resource context block records where it came from and how much to trust it.
When the caller omits `trust`, CDK emits `source: AUTHORED` and chooses confidence
from the declaration: `HIGH` when `why` or a non-empty `must` is present, otherwise

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So both why and must are optional? I don't think we should allow for context that doesn't specify why. Why are we trying confidence solely to the must field? I'd think a citation is more evidence for context than some invariants the agent may have inferred incorrectly. My proposal:

  • HIGH: Both must and citation are present.
  • MEDIUM: Only one is present.
  • LOW: None are present.

@satyakigh satyakigh Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The published schema keeps why and must optional, so CDK does too. The RFC recommends why for significant resources and a must entry to explain constrained mutability, but does not enforce either. Confidence remains explicit whenever trust is supplied.

Comment thread text/0972-metadata-context.md Outdated
```ts
declare const stack: Stack;

MetadataContext.of(stack).addToTemplate({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

addToTemplate is an API thats going to be used far less than add - so lets not put them under the same object - to reduce cognitive load. Proposal:

  • TemplateMetadataContext.of(stack).add() // accets Stack
  • ResourceMetadataContext.of(stack).add() // accepts Construct

This keeps things consistent. If construct vendors want to add template metadata (though they really shouldn't), they can use:

TemplateMetadataContext.of(Stack.of(construct)).add(...)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Split the API as proposed: ResourceMetadataContext.of(scope).add() handles resource information, and TemplateMetadataContext.of(stack).add() handles template information. MetadataContextMixin remains resource-only.

Comment thread text/0972-metadata-context.md Outdated
`Metadata["com.aws.cloudformation.Context"]` is included in that measurement. This RFC adds no
context-specific size validator and never silently trims declared context. The
existing warning remains the synth-time signal; authoring tools may respond
using the advisory schema's tier/drop order described in appendix A.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How would agents know to consult this schema if cdk synth doesn't provide this guidance? we can at least print a link to the schema for the to follow.

@satyakigh satyakigh Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added an early link to the published schema and documented the fields in the README and API reference. I did not add a notice to every cdk synth: it would be repetitive and unavailable to later GetTemplate readers. The stable metadata key and published documentation provide the durable reference.

Comment thread text/0972-metadata-context.md Outdated
`must: ["VisTimeout >= 6x fn timeout, else dup on retry"]` in the template itself.
* **Operational handoff and incident response** - `why`, `ops` and `failureModes` carry
the on-call knowledge that normally lives in tribal memory: what the resource is for,
what to check before touching it, and what the failure/recovery paths are.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What do you mean by failure/recovery paths? For example if failure mode is retry 3x w/ exp backoff before DLQ - what is the agent expected to do? look at the DLQ?

@satyakigh satyakigh Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Removed failureModes because it is not in the published schema. Failure behavior that must be preserved belongs in must, design reasoning belongs in why, and external operational procedures can be linked through template-level ref.

modifies your stack six months from now often has the template and the live stack - not
your source repository, your design doc, or you.

Concrete situations this feature addresses:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This answers why the context is needed, not why it should be provided as a concrete API in the CDK.

I'd expect also something like "CDK customers will have a hard time defining the correct context without this feature" (because escape hatches suck).

Also needs to touch on the cascading mechanism you're proposing.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added a dedicated explanation. Low-level metadata methods provide no typed fields, allowed-value checks, required trust checks, primary-resource selection, descendant selection, merge behavior, or generated documentation across CDK languages. The dedicated APIs provide those behaviors.

keeping heuristic inference and its review outside the core API contract.

If you already maintain design context in READMEs or wikis, this feature does not replace
them - it puts the *operationally relevant* subset where every consumer of the deployed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

But this also creates duplication. I'm wondering why not use ref as a way to also point to the artifacts in the repo (design doc/runbook). Why would ref be suitable for org-wide rules but not for the repository URL for example?

@satyakigh satyakigh Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated ref to match the published schema: references may use relative paths, s3://, or https://. CDK does not fetch or restrict those locations. Referenced content is untrusted, and inline template context remains authoritative.

Comment thread text/0972-metadata-context.md Outdated

* **Stale context is worse than no context.** Rationale written once and never updated
actively misleads the consumers it was meant to help. Co-location in reviewed CDK source
and the `trust`/`gaps` fields reduce the risk but do not remove it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How do trust / gaps reduce the risk?

@satyakigh satyakigh Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Removed gaps, which is not in the published schema. trust communicates provenance and confidence; it does not prevent drift. Keeping context beside reviewed CDK code helps readers assess it, but does not guarantee that it stays current.

Comment thread text/0972-metadata-context.md Outdated
`must`. Explicit trust values always win.

Change-safety uses a closed four-level enum: `must-never-change`,
`change-with-constraints`, `review-required`, `free-to-tune`. In the CDK API this is the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What does change-with-constraints mean exactly? the other ones are pretty sefl explanatory.

@satyakigh satyakigh Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Defined change-with-constraints as allowing change only while the stated rules remain true. The RFC recommends documenting those rules in must, but the published schema and CDK do not require it.

* Sibling metadata namespaces remain untouched, and Context has no deployment-behavior
effect because CloudFormation ignores advisory metadata.

### What alternative solutions did you consider?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What about having the context just be a bunch refs in the that point to source code, design docs, runbooks, etc for agents to follow? This prevents the risk of drift.

@satyakigh satyakigh Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Documented the trade-off: ref entries can point to relative paths, s3://, or https:// and reduce duplication or drift. They supplement rather than replace irreducible inline context, so an unavailable reference does not block safe use.

Comment thread text/0972-metadata-context.md Outdated
confident-sounding context. The `trust` field exists precisely so generated context can
self-identify (`src: infer`, low confidence, citation) — but the API cannot force
honesty, and a caller is free to claim `authored`.
* **Merge-semantics complexity.** Nearest-wins plus accumulate-and-dedupe is more to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Its not just about learning curve - its about wether the customer actually wants the cascading effect. I can see scenarios where context is being added to an L3 with a very specific construct in mind, but then having in travel to a bunch of other resources as well might create unexpected results.

I'd say there is a risk of out-of-place context being added. This won't happen with pure CFN because the customer has no choice but to explicitly add the right context to each resource they want.

To evaluate this risk I think we need more examples of L3s

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Addressed this by making descendant selection explicit. The default selects only a CfnResource or a construct's defaultChild resource. applyToDescendants, applyToAllResources, and resource-type filters must be requested explicitly, and a declaration selecting zero resources is defined to fail.

Comment thread text/0972-metadata-context.md Outdated
[aws/aws-cdk#38381](https://github.com/aws/aws-cdk/pull/38381).

The feature ships under the standard core review bar: it is small, opt-in, and has no
feature-flag interaction. Nothing about it needs to bake behind an experimental gate:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why not have a bake period though? it could help hone the corresponding skill so we don't have to break the schema often.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added concrete stability requirements: review the public documentation, test the authoring and reading tools on real stacks, and obtain API Bar Raiser approval. A runtime feature flag is unnecessary because applications produce no additional Context unless they call the new APIs.

feature-flag interaction. Nothing about it needs to bake behind an experimental gate:
the feature emits nothing until its APIs are adopted, so existing output remains unchanged.

### Are there any open issues that need to be addressed later?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These are future enhancements really more than open issues. Is there anything we still need to discuss to move along with the implementation - is the spirit of this question.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Split the section into requirements before declaring the API stable and separate future enhancements. The future list now covers automatic dependency discovery, automatic change-safety guidance, helper-resource selection, and properties on higher-level constructs.

Comment thread text/0972-metadata-context.md Outdated
externalization `ref` are never dropped). CDK warns on the whole serialized template but
does not automatically apply this drop order.

### Appendix B - Benchmark and implementation evidence

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you share the actual data as well?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added the data and methodology: 33 tasks, three runs per condition. Scores were 65.20% without added information, 93.56% with template comments, 94.70% with structured metadata but no special instructions, and 98.63% with structured metadata plus instructions. The RFC also documents the scoring and task-selection limitations.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants