CDE Template Library
The artifacts from across this site collected in one place - environment definitions, agent policy, decision records, and the runbook you want written before you need it
Every template links back to the page that explains it. Each one states what it is for and what it deliberately leaves out.
How to Use These
These are starting points, not finished configurations. Each is short enough to read in full before you commit it, which is the property that matters most: a template you paste without reading is a template you cannot defend in a review. Placeholders sit in angle brackets so an unedited one fails loudly rather than quietly doing something plausible.
The agent identity scheme and the egress policy are security controls. Treat them as sketches of a shape, not as hardened policy - the pages they come from carry the failure modes, which is why every template links back to one.
Environment Definitions
Baseline devcontainer.json
For: the annotated reference that shows every field you are likely to need, so you can delete down to what you actually use.
Not for: production images. It has no pinned digests, no non-root hardening, and no build cache strategy. From DevContainers.
{
"name": "My Dev Container",
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye",
// Or build from Dockerfile
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
// Features - modular add-ons
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
// Lifecycle scripts
"postCreateCommand": "npm install",
"postStartCommand": "npm run dev",
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
],
"settings": {
"editor.formatOnSave": true
}
}
},
"forwardPorts": [3000, 5432],
"containerEnv": {
"NODE_ENV": "development"
}
}Python and Go recipes
For: two concrete single-language stacks with the test and lint wiring already in place.
Not for: dependency resolution. Both call a package manager at create time, which means a slow first start and a build that can drift. Full versions, including debugger configuration, are on Quickstarts.
{
"name": "Python 3.13",
"image": "mcr.microsoft.com/devcontainers/python:3.13",
"features": {
"ghcr.io/devcontainers/features/python:1": {
"version": "3.13",
"installJupyterlab": true
},
"ghcr.io/devcontainers/features/git:1": {}
},
"customizations": {
"vscode": {
"extensions": ["ms-python.python", "charliermarsh.ruff"],
"settings": { "python.testing.pytestEnabled": true }
}
},
"forwardPorts": [8000, 8888, 5000],
"postCreateCommand": "pip3 install --user -r requirements.txt",
"remoteUser": "vscode"
}{
"name": "Go 1.23",
"image": "mcr.microsoft.com/devcontainers/go:1.23",
"features": {
"ghcr.io/devcontainers/features/go:1": {
"version": "1.23"
},
"ghcr.io/devcontainers/features/git:1": {}
},
"customizations": {
"vscode": {
"extensions": ["golang.go"],
"settings": {
"go.lintTool": "golangci-lint",
"go.testFlags": ["-v", "-race"]
}
}
},
"forwardPorts": [8080, 9000],
"postCreateCommand": "go mod download && go install -v golang.org/x/tools/gopls@latest",
"remoteUser": "vscode"
}Polyglot workspace, composed from features
For: a repository that needs several runtimes plus cluster tooling, built by composition rather than by a bespoke image.
Not for: fast starts. Every feature is an install step at build time, and docker-in-docker widens the isolation boundary. From Advanced DevContainers.
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "20"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.12"
},
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {}
}
}Multi-container stack
For: the smallest correct wiring of an application container to a database and a cache.
Not for: anything durable. There is no named volume for Postgres, no health check ordering, and the password is literally the word dev. From DevContainers.
services:
app:
build: .
volumes:
- .:/workspace
postgres:
image: postgres:15
environment:
POSTGRES_PASSWORD: dev
redis:
image: redis:7-alpineAgent Instructions, Identity, and Egress
AGENTS.md starter
For: telling an agent the things it would otherwise get wrong by guessing - which test command gates a merge, which paths are generated, what a pull request is expected to look like.
Not for: enforcement. This file is advisory context competing for attention in a context window; a line reading "do not touch" is a request, not a permission boundary. From AGENTS.md.
# AGENTS.md
## Project
Payments API. Go 1.24 service behind an internal gateway. Card
authorization only; settlement is a separate repository.
## Setup
Use `make bootstrap`, not `go mod download` - it also generates
the protobuf stubs the build needs.
## Build and test
- `make test` is fast, but it does NOT gate merges.
- `make test-integration` is what CI gates on. It needs Postgres,
which `make bootstrap` starts in a container.
- Run `make lint` first. CI rejects lint failures.
## Conventions
- Wrap errors with `fmt.Errorf("...: %w", err)`. Never return a
bare error from an exported function.
- Use `internal/clock`, not `time.Now()`, so tests control time.
## Do not touch
- `internal/gen/**` is generated. Edit the `.proto` files and
rerun `make bootstrap`.
- `deploy/prod/**` requires a platform team review.
## Pull requests
Title: `[payments] short imperative summary`. Keep changes under
roughly 400 lines; split larger work into several PRs.Agent identity and a least-privilege, short-lived credential
For: naming a single agent run so authorization and audit can both address it, then minting a credential scoped to one repository that expires with the task. The registration issues an identity only against attested selectors, so no bootstrap secret exists to steal.
Not for: copying as an API contract. The token request models the shape of a scoped installation token; its delegation and correlation fields are a local convention, not a published schema. From Agent Identity, which draws on Microsoft Security's "Least privilege for AI agents" (July 16, 2026).
# One trust domain per environment - never one per team
spiffe://dev.example.internal
# The agent workload itself
spiffe://dev.example.internal/ns/agents/sa/coding-agent
# A single execution of it. Authorization and audit
# both address this.
spiffe://dev.example.internal/ns/agents/sa/coding-agent/run/7f3c9a12
# The supervising CI runner is a DIFFERENT principal
spiffe://dev.example.internal/ns/ci/sa/pipeline-runner
# Issued only to a workload attesting to these selectors
spire-server entry create \
-spiffeID spiffe://dev.example.internal/ns/agents/sa/coding-agent \
-parentID spiffe://dev.example.internal/spire/agent/k8s_psat/dev/node-17 \
-selector k8s:ns:agents \
-selector k8s:sa:coding-agent \
-x509SVIDTTL 900{
"agent_identity":
"spiffe://dev.example.internal/ns/agents/sa/coding-agent",
"run_id": "7f3c9a12",
"on_behalf_of": "user:[email protected]",
"repositories": ["example-org/billing-service"],
"permissions": {
"contents": "read",
"pull_requests": "write",
"issues": "none",
"actions": "none",
"secrets": "none",
"administration": "none",
"packages": "none"
},
"expires_in_seconds": 900
}Egress allowlist starter
For: a default-deny egress posture in two layers - a proxy policy that separates reading from writing at the same hostname and injects credentials the workspace never sees, and the Kubernetes policy that forces all traffic through it.
Not for: deployment as written. The proxy policy is an illustrative shape rather than any vendor's schema, and method and path rules are not expressible without terminating TLS - a proxy that does so becomes the highest-value target you operate. The default-deny policy also blocks DNS, which is why port 53 is allowed back explicitly. From Agent Egress Control.
default: deny # anything unmatched is refused and logged
routes:
- name: read-github-api
match:
domain: api.github.com
method: [GET, HEAD]
inject:
header: Authorization
secret_ref: vault://agents/repo-read
log: full
- name: publish-release
match:
domain: api.github.com
method: [POST]
path: /repos/example-org/*/releases
approval: human # held until an operator approves
inject:
header: Authorization
secret_ref: vault://agents/release-write
log: fullapiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-and-egress-proxy
spec:
podSelector:
matchLabels:
role: agent-workspace
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978Decisions and Adoption
Architecture decision record
For: recording why a platform choice was made while the reasons are still fresh, so the next team does not relitigate it from scratch. Follows the format Michael Nygard described in "Documenting Architecture Decisions" (2011).
Not for: design documentation. An ADR captures one decision and its cost. It does not describe how the system works, and it is never edited after acceptance - it is superseded by a later record instead. Written for this library rather than lifted from an existing page.
# ADR-0007: <the decision, stated as a completed action>
Date: <YYYY-MM-DD>
Status: proposed | accepted | superseded by ADR-<nnnn>
Deciders: <the rota or role that owns this, not a person>
## Context
What forces a decision now. Constraints, deadlines, and the
things that are NOT negotiable. No recommendation here.
## Decision
We will <the choice>, because <the reason that survives review>.
A commitment, not a preference.
## Options considered
1. <option> - rejected because <the specific disqualifier>
2. <option> - CHOSEN
## Consequences
- What gets easier, and what gets harder.
- What we now have to operate that we did not before.
- The signal that would tell us this decision was wrong.
## Revisit when
<a concrete trigger, such as "workspace count passes 500" -
never "in six months">CDE pilot plan
For: agreeing who is in the pilot and what counts as success before anyone provisions a workspace, so the decision at the end is a reading rather than an argument.
Not for: use with the numbers as given. Every target below is a starting figure to be replaced with your own baseline; a pilot measured against someone else's benchmark proves nothing about your organization. From Pilot Program.
# Replace every target with your own measured baseline first.
team:
size: "5 to 15 developers"
lead: "a manager who will champion it and absorb the friction"
stack: "containers and standard tooling, not a legacy monolith"
roadmap: "no critical deadline, no major refactor in flight"
avoid:
- "teams under deadline pressure"
- "specialized hardware: GPU, embedded, iOS builds"
- "regions far from the cloud region you will serve"
success_criteria:
productivity:
onboarding_time: "under 4 hours"
workspace_startup: "under 5 minutes"
environment_issues_per_week: "under 2"
experience:
developer_nps: "above +30"
would_recommend: "above 70 percent"
reliability:
platform_uptime: "above 99.5 percent"
support_tickets_per_week: "under 5"
adoption:
daily_active_users: "above 80 percent"
returned_to_local: "under 5 percent"
ai_agents:
task_success_rate: "above 75 percent"
sandbox_escapes: 0
cost:
llm_cost_attribution: "100 percent"
idle_workspace_waste: "under 10 percent"
decision_gate:
go: "criteria met and the team wants to keep it"
conditional: "named gaps, named owners, one more window"
no_go: "write down why, before anyone re-proposes it"Vendor RFP scorecard
For: forcing the weighting conversation before the demos, when it is still an honest one. Five categories, weights summing to 100, each criterion scored 1 to 5. Paste it into a spreadsheet as CSV.
Not for: deciding for you. The weights encode one set of priorities and yours will differ - a regulated team pushes data residency up, a small team pushes support down. Change them first and record why. From Vendor Evaluation; the interactive version is on the readiness assessment.
Category,Criterion,Weight,Score,Weighted,Notes
Security and Compliance,Data residency control,10,,,
Security and Compliance,Authentication and SSO,8,,,
Security and Compliance,Audit logging and SIEM export,8,,,
Security and Compliance,Secrets management,5,,,
Security and Compliance,Network isolation,4,,,
Developer Experience,IDE support,8,,,
Developer Experience,Workspace startup time,6,,,
Developer Experience,DevContainer support,6,,,
Developer Experience,Port forwarding and previews,5,,,
Infrastructure and Operations,Multi-cloud support,6,,,
Infrastructure and Operations,Resource management,5,,,
Infrastructure and Operations,High availability,5,,,
Infrastructure and Operations,Template and IaC system,4,,,
Cost and Licensing,Pricing model,5,,,
Cost and Licensing,Auto-stop and idle management,5,,,
Support and Ecosystem,Documentation and community,4,,,
Support and Ecosystem,Enterprise support,3,,,
Support and Ecosystem,Roadmap and innovation,3,,,
TOTAL,,100,,,When an Agent Goes Wrong
Rogue-agent incident runbook skeleton
For: one file per incident class, written before the incident, with the containment step first and evidence preservation second. The order matters: a workspace reaped by an idle timer takes the transcript with it.
Not for: its timings. Every interval is an example value to be tuned against your own observed distributions, and the commands are placeholders rather than any product's real syntax. From Agent Runbooks; the general operational form is on Runbooks.
# Timings are EXAMPLE values. Tune to your own distributions.
name: "<short imperative title of the incident class>"
severity: "sev2" # raise for suspected compromise
owner: "platform-oncall" # a rota, never a named individual
trigger:
alert: "<alert or saved query that fires this runbook>"
condition: "<the threshold, as a rule not a feeling>"
immediate_actions: # EXAMPLE: first action within 5 min
- contain: "smallest kill switch covering the blast radius"
- preserve: "mark the workspace no-reap BEFORE anything else"
- declare: "open the channel, name an incident lead"
- revoke: "revoke the run credential; cancel is not enough"
investigation: # EXAMPLE: classified within 60 min
collect:
- "conversation and tool-call transcript for the run id"
- "egress allow/deny log for the run id"
- "token spend from the gateway, not from billing"
- "image digest, model version, granted permissions"
questions:
- "did it read untrusted content before diverging"
- "was every action inside its granted permissions"
recovery:
- "enumerate secondary credentials the run could reach"
- "revert merged changes by run id, every repository"
- "check tickets, comments, and cloud resources too"
- "restart path: <how it returns, and who approves>"
follow_up: # EXAMPLE: review within 5 days
primary_cause: "injection | model | tooling | permissions"
actions:
- "add the eval that would have caught this"
- "narrow the tool contract or the permission"
retention: "quarantine expires <date>, owner <name>"What This Library Is Not
Not a compliance artifact
Nothing here maps to a control in a published framework. For audit evidence, start from compliance and work back to configuration, not the other way round.
Not vendor-neutral by accident
Where a template names a product, that product documents the field. Anything invented for illustration is labeled as such, both here and on the source page.
Not a substitute for reading
The source pages carry the caveats that make a template safe to use; the summaries here are an index, not the argument. Every figure quoted on this site is listed at sources.
Where Each Template Is Explained
The pages these came from, and the route through them
Learning Paths
Ordered routes through this site by role, if you want the reasoning behind these artifacts
DevContainers
What each devcontainer.json field does, and where the specification stops
Agent Identity
Why attestation beats a bootstrap secret, and how to scope a run credential
Agent Egress Control
What TLS interception buys, what it costs, and when not to run a proxy at all
Vendor Evaluation
The criteria behind the scorecard, and the questions vendors would rather skip
Agent Runbooks
Containment order, evidence preservation, and classifying what actually happened
