Composites
What are composites?
A composite scaffolds multiple templates into one integrated project. Instead of running npx nanohype scaffold five times and wiring things together by hand, a composite does it in a single command – it picks the right templates, nests them into a monorepo (or flat structure), flows shared variables to each one, and respects conditional flags so you only get the pieces you asked for.
Individual templates are building blocks. Composites are the blueprints that assemble them into real project architectures.
Selection guide
| Composite | What it produces | Best for |
|---|---|---|
proof-of-concept |
Minimal AI agent with eval harness and Platform tenant chart | Quick POC – validate an idea in days, not weeks |
ai-chatbot |
Full-stack chatbot with auth, evals, Platform tenant chart | Customer-facing conversational AI |
ai-web-app |
Next.js frontend with RAG, auth, database, observability, Platform tenant chart | AI-powered web applications with document search |
production-api |
TypeScript API with auth, DB, caching, rate limiting, queue, observability | Backend services that need to be production-grade from day one |
enterprise-ai |
Agents, RAG, guardrails, evals, prompts, storage, Platform tenant chart | Full enterprise AI platform with all the operational layers |
multi-agent |
A2A orchestrator, agent, MCP tools, guardrails, evals, Platform tenant chart | Systems where multiple AI agents collaborate and delegate |
rag-agent |
Agent with RAG pipeline, storage, database, evals, Platform tenant chart | AI agents that need grounded knowledge from documents |
document-intelligence |
RAG pipeline, API service, storage, database, evals, Platform tenant chart | Document search and question-answering systems |
background-processor |
Worker service with queue, database, storage, observability | Async job processing without synchronous HTTP |
safe-ai-agent |
Agent with guardrails, evals, prompt library, Platform tenant chart | Responsible AI – input filtering, output validation, testing |
eval-suite |
Eval harness, prompt library, guardrails validation | Testing AI systems without building them |
go-microservice |
Go HTTP service with evals and deployment | Lightweight, single-binary Go services |
mcp-toolkit |
MCP server with prompts and evals | Building tool servers for AI systems |
chrome-ai-extension |
Chrome extension with MCP tools and prompt library | Browser extensions with AI sidepanel |
vscode-ai-extension |
VS Code extension with MCP tools and prompt library | Editor extensions with AI integration |
internal-tool |
CLI or extension backed by MCP servers | Internal team tooling |
cost-optimized-ai |
LLM gateway with cost routing, semantic caching, observability, Platform tenant chart | Minimizing LLM spend with smart routing and caching |
ai-platform |
Service, gateway, vectors, pipeline, auth, database, billing, monitoring, Platform tenant chart | Full AI product with usage-based billing |
agent-team |
Orchestrator, specialized agents, MCP tools, evals, Platform tenant chart | Multi-agent systems with distinct roles |
client-engagement |
Proposal, battle cards, brand guidelines, campaign brief, onboarding playbook | Non-engineering client engagement workflows |
product-launch |
Next.js app, Platform tenant chart, design system, tokens, test plan, PRD, campaign, runbook | Cross-functional product launches spanning eng through marketing |
research-to-prototype |
PRD, agentic loop prototype, Platform tenant chart, optional test plan | Research-driven prototyping from idea to validated POC |
spring-boot-microservice |
Spring Boot 4 HTTP service on JDK 25 with K8s deploy, optional Grafana + Prometheus + Loki | Java services that need production posture out of the gate |
identity-aware-service |
Spring Boot 4 service with Istio mesh-edge auth + Spring Security resource server | Defense-in-depth identity against a shared OIDC issuer |
platform-tenant |
Platform tenant chart with optional LLM gateway, vector store, and audit ledger packages | Making an app a k8s-native Platform tenant |
How to scaffold a composite
npx nanohype scaffold --composite ai-chatbot --var ProjectName=my-botThe scaffolder reads the composite YAML, collects composite-level variables once, then distributes them to each template entry. Entry-level overrides can transform variable values – for example, the ai-chatbot composite takes ProjectName=my-bot and passes my-bot-api to the API service and my-bot-ai to the agentic loop.
To see all available composites before scaffolding:
npx nanohype list --compositesConditional entries are controlled by boolean variables. For example, production-api has IncludeQueue (default true) and IncludeCache (default true). To skip the queue:
npx nanohype scaffold --composite production-api \ --var ProjectName=my-api \ --var IncludeQueue=falsePost-scaffold wiring
The Platform tenant chart (infra/)
Every composite whose server-side packages default to the gateway provider carries k8s-app-tenant at infra/: the Helm chart with its per-env values and ApplicationSet entry, and platform.yaml with the Platform, BudgetPolicy and ModelGateway CRs. The ModelGateway is the stack’s model path. The eks-agent-platform operator runs it as the Service <ProjectName>-gateway in tenants-<ProjectName>, holding the Bedrock role, and the chart hands the app that endpoint as MODEL_GATEWAY_ENDPOINT with the route names MODEL_ROUTE and EMBEDDING_ROUTE, so no package holds a model key. A stack that embeds through the gateway also gets the embeddings route. chrome-ai-extension carries none: its extension runs in the browser, deploys nothing to the cluster, and reaches the ModelGateway of a Platform deployed elsewhere through a kubectl port-forward its user opens.
Tenant(defaultProjectName) is the owning team: thetenants-<team>namespace the CRs are applied in, the Platform’sspec.tenant, and the team label on the chart’s resources and telemetry.Image(defaultProjectName) is the image repository the chart deploys, and eachvalues-<env>.yamlpins its tagAppMetric(defaulthttp) is the prefix of the RED series the chart’s Grafana dashboard reads,<prefix>_requests_total,_errors_totaland_request_duration_seconds:httpis the prefix a ts-service emits them under, and a stack that deploys another service sets the prefix that service emits- Apply
infra/platform.yamlonce during tenant setup and copyinfra/gitops/applicationset-entry.yamlinto the gitops repo; ArgoCD rolls outinfra/chartfrom there - The chart’s NetworkPolicy opens no
:443, which keeps the gateway the app’s route to Bedrock; an app that calls a third-party API names it by hostname in a CiliumNetworkPolicytoFQDNsrule - The eval harness runs on a CI runner, off the substrate: its workflow assumes the IAM role the repository variable
EVAL_ROLE_ARNnames through GitHub OIDC federation, and itsbedrockprovider calls Bedrock under that role
Off the substrate (a CI runner, a CLI, a workstation) the LLM policy has a stack reach Bedrock under an IAM role it assumes, GitHub OIDC federation on a CI runner and an AWS profile on a workstation, as the eval harness’s bedrock provider does. No package reads a provider API key, on the substrate or off it: a model of another family is reached through a ModelGateway route or through Bedrock.
proof-of-concept
- Run
npm installat the project root, thennpm run devto start the agent in watch mode - The agent calls the Platform’s ModelGateway through the
gatewayprovider with no model key;infra/declares the gateway and deploys the agent’s image - The agent loop lives in
src/agent.ts– edit the system prompt and tool definitions there - Add new tools by creating files in
src/tools/and registering them in the tool index - Run
npm run evalto execute the eval suite inevals/– add fixtures as JSON files - Tune
MAX_ITERATIONSto control how many tool-call rounds the agent can take - When the eval suite passes, you have a solid foundation to build the real thing on
ai-chatbot
- Run
pnpm installat the monorepo root to install all workspace dependencies - Start the API server:
pnpm --filter *-api dev(runs on the port defined in.env) - The agentic loop in
packages/ai/calls the Platform’s ModelGateway with no model key; on the cluster the chart ininfra/hands itMODEL_GATEWAY_ENDPOINTandMODEL_ROUTE - The frontend is not included – wire your own UI to
POST /api/chaton the API service - Auth is JWT-based via
packages/auth/– generate tokens with the auth module’s helpers - If you enabled evals, run
pnpm --filter *-evals evalto validate agent behavior - Deploy through
infra/, the Platform tenant chart: the chart serves the API image on port 3000
production-api
- Run
pnpm install, thenpnpm --filter *-api devto start the API server - Set up your database: configure
DATABASE_URLin.env, run the Drizzle migration (pnpm --filter *-db migrate) - Auth tokens are JWT – set
JWT_SECRETto a strong random value (the config validator rejects the placeholder) - The cache layer (
packages/cache/) defaults to in-memory – switch to Redis by settingCACHE_PROVIDER=redisandREDIS_URL - The queue (
packages/queue/) uses BullMQ by default – requiresREDIS_URLfor the broker - Rate limiting (
packages/rate-limit/) uses token-bucket – configure per-route limits in the middleware setup - Observability (
packages/observability/) exports to OTLP – setOTEL_EXPORTER_OTLP_ENDPOINTto your collector - Deploy with
cd infra && helm upgrade --install— or swap theinfra/directory fork8s-app-tenantwhen the app is a Platform tenant
enterprise-ai
- This is the largest composite – not every component is required for every deployment
- Start minimal: get the API (
apps/api/), agent (packages/agent/), and database (packages/db/) running first - RAG (
packages/rag/) and A2A orchestration (packages/orchestrator/) are conditional – skip them if you do not need retrieval or multi-agent coordination - Guardrails (
packages/guardrails/) run as middleware – wire them into the API’s request pipeline to filter inputs and validate outputs - The prompt library (
packages/prompts/) versions your system prompts – use it from the agent and eval harness - Storage (
packages/storage/) defaults to S3 – setAWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, andS3_BUCKET - Deploy through
infra/, the Platform tenant chart: the chart serves the API image on port 3000, and withIncludeRagits ModelGateway adds theembeddingsroute the RAG pipeline calls - Scale by splitting services: run the API, agent workers, and RAG indexer as separate deployments behind the queue
multi-agent
- Run
pnpm installat the monorepo root, then start the API:pnpm --filter *-api dev - The A2A orchestrator (
packages/orchestrator/) coordinates agent-to-agent communication – it discovers peers and delegates tasks - The agentic loop (
packages/agent/) is a single agent implementation – duplicate it under a new name to add more agent types - MCP tools (
packages/tools/) are shared across agents via stdio transport – register new tools in the server’s tool index - If guardrails are enabled, wire them into the orchestrator’s request pipeline to filter inter-agent messages
- Run evals with
pnpm --filter *-evals eval– test both individual agent behavior and multi-agent coordination scenarios - Deploy through
infra/, the Platform tenant chart: the chart serves the API image on port 3000, and every agent reaches a model through its ModelGateway
cost-optimized-ai
- Run
pnpm installat the monorepo root - The LLM gateway (
packages/gateway/) routes requests to the cheapest provider that meets quality thresholds – configure routing rules in its config - The semantic cache (
packages/cache/) deduplicates similar prompts, embedding them through the gateway’sembeddingsroute, whichinfra/platform.yamldeclares - The observability package (
packages/observability/) tracks token usage and cost per request – wire it into your API layer - Tune the similarity threshold in the cache config to balance cost savings against freshness
infra/is the Platform tenant chart for the app you build on these packages, rendered fork8s-app-tenant’s default port, 8080; an app on another port sets it ininfra/chart/values.yamlunderservice,probesand the NetworkPolicy ingress rule
ai-platform
- Run
pnpm install, thenpnpm --filter *-api devto start the API server - Configure
DATABASE_URLand run migrations viapnpm --filter *-db migrate - The LLM gateway (
packages/gateway/) manages provider routing over the Platform’s ModelGateway with no model key - The data pipeline (
packages/pipeline/) handles document ingestion into the vector store, embedding through the gateway’sembeddingsroute infra/is the Platform tenant chart that serves the API image on port 3000 and declares the ModelGateway both packages call- If billing is enabled, configure Stripe keys in
packages/billing/.env– usage metering is automatic - The monitoring stack (
infra/monitoring/) provides Prometheus, Grafana, and Loki – deploy withcd infra/monitoring && docker compose up
agent-team
- Run
pnpm installat the monorepo root - The orchestrator (
packages/orchestrator/) coordinates the researcher and writer agents – configure agent roles and delegation rules in its config - Each agent (
packages/agents/researcher/,packages/agents/writer/) is an independent agentic loop with its own system prompt and tools - MCP tools (
packages/tools/) are shared across agents via stdio transport – add new tools in the server’s tool index - Run
pnpm --filter *-evals evalto validate agent behavior – add multi-agent coordination test cases - To add a new agent role, duplicate an existing agent directory and register it with the orchestrator
- The agents call the Platform’s ModelGateway with no model key;
infra/is the Platform tenant chart that declares it and deploys the stack’s image
client-engagement
- No engineering templates – this composite is entirely non-code deliverables
- Start with the proposal (
proposal/) and battle cards (battle-cards/) for the sales pitch - Brand guidelines (
brand-guidelines/) define visual identity for all client-facing materials - The campaign brief (
campaign-brief/) ties marketing to the engagement goals - If onboarding is enabled, the playbook (
onboarding-playbook/) covers post-sale customer setup
product-launch
- Run
pnpm installat the monorepo root - The Next.js app (
apps/web/) is the engineering deliverable – start withpnpm --filter *-web dev - Design system (
packages/design-system/) and tokens (packages/design-tokens/) define the visual language - QA artifacts (test plan, acceptance criteria) live alongside the PRD in
docs/ - The campaign brief and runbook are in
docs/– hand these to marketing and operations respectively - The app’s chat route calls the Platform’s ModelGateway;
infra/is the Platform tenant chart that serves the app on port 3000 and declares the gateway - This composite spans engineering, design, QA, product, marketing, and operations personas
research-to-prototype
- Start with the research framework (
docs/research/) and the PRD (docs/product/) to define the research question and success criteria - The agentic loop prototype (
apps/agent/) is a minimal AI agent – edit the system prompt and tools to match the research hypothesis - If the test plan is enabled (
docs/qa/), use it to define validation criteria before building - Run
npm install && npm run devinapps/agent/to start iterating on the prototype; it calls the Platform’s ModelGateway thatinfra/declares - When the prototype validates the hypothesis, graduate to a full composite like
ai-chatbotorenterprise-ai
Creating your own composites
Composites are YAML files in composites/ at the catalog root. See docs/spec/composite-contract.md for the full specification.
Minimal structure:
apiVersion: nanohype/v1kind: compositename: my-stackdisplayName: 'My Stack'description: > What this composite produces and who it is for.version: '0.1.0'tags: [relevant, searchable, tags]
variables: - name: ProjectName type: string placeholder: '__PROJECT_NAME__' description: 'Project name' required: true validation: pattern: '^[a-z][a-z0-9-]*$' message: 'Must be lowercase kebab-case'
templates: - template: monorepo root: true variables: ProjectName: '${ProjectName}'
- template: ts-service path: apps/api variables: ProjectName: '${ProjectName}-api'Key rules:
- At most one entry can be
root: true– its skeleton forms the top-level directory. - Entry variables reference composite variables with
${VarName}syntax. - Use
condition: SomeBoolVaron an entry to make it optional. - Templates are scaffolded in array order – put the root first, then dependencies before dependents.
Maintained in the catalog repo as docs/composites-guide.mdand rendered here from it.