Skip to content

cloudgrid.yaml reference

cloudgrid.yaml is the manifest at the root of your project. It declares the services your entity runs, the infrastructure it needs, and how it behaves. grid new creates it; grid plug reads it to build and deploy.

The file is portable — it carries no identity and no secrets — so it is safe to commit. The .cloudgrid/ folder (which does hold identity) is gitignored.

A single static page:

name: landing-page
services:
web:
type: static
path: /

A Next.js app with a database:

name: my-app
services:
web:
type: nextjs
path: /
needs:
database: true

See Service types for node, python, and cron, and Infrastructure needs for the full needs: vocabulary.

Every supported field, commented. No real project uses all of these at once — this is a reference.

# ─── Identity ───────────────────────────────────────────────
name: my-app # Required. Entity slug. 2-42 chars, lowercase a-z 0-9 and hyphens.
description: Order API # Optional. One-line summary (max 280 chars).
icon: "📦" # Optional. Single emoji or short text (max 64 chars).
kind: app # Optional. 'app' (default) or 'agent'.
# ─── Networking ─────────────────────────────────────────────
expose: true # Optional. Serve public HTTP (default true). false = internal-only.
custom_domains: # Optional. Additional FQDNs the entity serves on.
- orders.example.com
# ─── Health probe (entity-level override) ───────────────────
probe: # Optional.
path: /healthz # Probe path (default /).
expected: "<500" # Expected status: '<500' (default), '200', '2xx'.
# ─── Deploy notifications ───────────────────────────────────
notify: true # Optional. Notify on deploy failure (default true).
# ─── Scaling ────────────────────────────────────────────────
scale: auto # Optional. 'auto' (default), 'alert', or an integer 1-10.
# ─── Infrastructure needs (canonical) ───────────────────────
needs: # Optional. The deployer injects connection env vars from these.
database: true # Mongo. Injects DATABASE_MONGODB_URL.
cache: true # Redis (LRU eviction). Injects CACHE_REDIS_URL.
kv: true # Redis (no eviction). Injects KV_REDIS_URL.
queue: true # Redis for queues. Injects QUEUE_REDIS_URL.
pubsub: true # Redis pub/sub. Injects PUBSUB_REDIS_URL.
vector: pgvector # pgvector. Injects VECTOR_PGVECTOR_URL.
object_storage: true # GCS bucket. Injects OBJECT_STORAGE_GCS_BUCKET / _REGION.
disk: true # Persistent filesystem. Injects DISK_PATH (default /data).
ai: true # AI Gateway access. Injects AI_GATEWAY_URL.
# ─── Inter-entity communication ─────────────────────────────
calls: # Optional. Entities this app calls (outbound grants).
- org:atomic/billing-api
callers: # Optional. Inbound caller policy.
policy: auto # 'auto' or 'manual' (default 'manual').
scope: org # 'org', 'space', or 'explicit' (default 'org').
fallback: deny # 'deny' or 'warn' (default 'deny').
allowed_apps: # Required when scope is 'explicit'.
- org:atomic/calling-app
# ─── Vault (external secret mapping) ────────────────────────
vault: # Optional. Map ENV_VAR -> vault item key.
STRIPE_KEY: stripe-live-key
# ─── Connectors and hooks ───────────────────────────────────
connectors:
- id: team-slack
target: org # 'system' or 'org'.
channel: "#deploys"
hooks: # Outbound events.
- on: deploy.failed # release.published | deploy.failed | feedback.received | entity.created
via: team-slack # Must match a connector id.
template: "Deploy failed for {entity_name}: {error}"
triggers: # Inbound events routed into your app.
- from: team-slack
event: message
channel: "#support"
route: /webhooks/slack
# ─── Local development ──────────────────────────────────────
dev:
snapshot:
mask: # Fields to redact in dev snapshots (collection.field).
- users.email
# ─── Services ───────────────────────────────────────────────
services: # Required. Map of service name to config.
web:
type: nextjs # 'node', 'nextjs', 'python', 'static', or 'cron'.
path: / # HTTP route prefix. false = internal-only.
port: 3000 # Container port (default 8080).
env: # Static env vars (not secrets).
LOG_LEVEL: info
health: # Health probe config.
path: /api/health
expected: "200"
depends_on: # Wait for these siblings before starting.
- worker
needs: # Per-service needs override (merged per key).
queue: true
# ─── Agent block ────────────────────────────────────────────
agent: # Optional. Present makes the entity an agent.
purpose: Triage tickets
schedule: "*/15 * * * *"
memory:
collection: triage_history
retention: 90d
budget:
tokens_per_month: 100000
hard_stop: true
  • Name: 2–42 chars, lowercase letters, numbers, and hyphens, no leading or trailing hyphen.
  • Reserved names cannot be used as an entity name — including default, cloudgrid, and common Kubernetes system names.
  • Port: an integer 1–65535 (default 8080).
  • Env var keys: uppercase letters, numbers, and underscores; must start with a letter or underscore.
  • Connector IDs: 3–40 chars, lowercase letters, numbers, and hyphens.

Connectors, hooks, and triggers let an entity talk to the outside world — posting to Slack on a deploy, or routing an inbound message into your app. They are declared in cloudgrid.yaml and wired to your org’s connectors. The grid webhooks and grid wire commands manage the same surface from the CLI.

A connector names an external destination and where it lives:

connectors:
- id: team-slack # 3-40 chars, lowercase letters, numbers, hyphens.
target: org # 'org' (org-scoped) or 'system' (platform-provided).
channel: "#deploys" # Destination within the connector (e.g. a Slack channel).

A hook sends an outbound event through a connector. The on: field is the event; via: must match a connector id; template: is the message, with {...} placeholders filled from the event payload:

hooks:
- on: deploy.failed # release.published | deploy.failed | feedback.received | entity.created
via: team-slack # Must match a connector id declared above.
template: "Deploy failed for {entity_name}: {error}"

A trigger routes an inbound event from a connector into one of your app’s HTTP paths:

triggers:
- from: team-slack # A connector id.
event: message # The inbound event to listen for.
channel: "#support" # Optional filter within the connector.
route: /webhooks/slack # The path in your app the event is POSTed to.

Events fire whether they are declared here or subscribed with grid webhooks — the YAML form keeps the wiring in the manifest so it deploys with the entity.

The vault: block maps an environment variable your app reads to a secret stored in your org’s vault. The secret value never appears in cloudgrid.yaml — only the key that points at it — so the manifest stays safe to commit.

vault:
STRIPE_KEY: stripe-live-key # ENV_VAR: vault-item-key
SENDGRID_KEY: sendgrid-prod

At deploy time the platform resolves each vault item and injects its value as the named environment variable into every service. Your code reads process.env.STRIPE_KEY and never sees the underlying store.

Use vault: for shared secrets managed at the org level. For one-off secrets scoped to a single entity, set them with grid secrets instead — both end up as environment variables at runtime.

needs: is the canonical, current schema — the deployer injects connection details from it. requires: is the deprecated v1 alias. Do not author new YAML with requires:, and never set both needs: and requires: in the same file (the validator rejects the combination). See Infrastructure needs for the full mapping.

An agent is an app with an agent: block — same entity, same deploy path.

name: daily-report
kind: agent
services:
worker:
type: cron
schedule: "0 8 * * *"
needs:
database: true
ai: true
agent:
purpose: Generate and email daily sales reports
schedule: "0 8 * * *"

The block supports purpose (plain text), schedule (a cron expression), memory (a collection and retention for persisting state across runs), and budget (tokens_per_month and hard_stop).