Formations

Create a new formation

Validates the template, creates the formation record, then provisions all declared resources in dependency order.

A template-shape error is refused with 400. A deploy failure is not: the operation ran, so the formation is returned with 201 and status: "failed", and error explains why (the resources created before the failure are rolled back). Read status — a 2xx here means the deploy was attempted, not that it worked. The naturali CLI exits non-zero on that body so create-formation && … does not lie.

post/v1/projects/{project_id}/formations

Request

  • Base URL: https://api.naturali.ai
  • URL: https://api.naturali.ai/v1/projects/{project_id}/formations
  • Auth: one of:
    • HTTP bearer
    • OAuth 2 (authorization code, authorization URL https://api.naturali.ai/authorize, token URL https://api.naturali.ai/token, scopes: mcp:access)

Request body

namestring required

Human-readable name for the formation stack

parametersobject nullable

Runtime parameter values that override or supply template parameter defaults. Keys must match parameter names declared in template.parameters. Required parameters (those without a default) must be provided here.

metadataNullableMetadataBag nullable

A MetadataBag on a request field where null is meaningful: a full-replacement update that clears the bag. A record whose bag is unset leaves the field out.

Example request

{
  "name": "my-agent-stack",
  "template": {
    "metadata": {
      "author": "John",
      "revision": 2
    }
  },
  "metadata": {
    "author": "John",
    "revision": 2
  }
}

Response

Formation created

idstring

Public ID of the formation

project_idstring

Project public ID

namestring

Human-readable formation name

outputsobject nullable

Resolved output values after stack deployment. An output that resolved a credential attribute on a formation deployed before those were refused is omitted.

status'creating' | 'active' | 'updating' | 'failed' | 'deleting' | 'deleted' | 'delete_failed'

Formation status

metadataMetadataBag

Caller-owned annotations on a resource, stored as the object they were written as: the types a value was written with are the types a read returns, so a filter can ask an ordering question about a number. Unlike other body fields, keys are stored and returned verbatim in the casing supplied — they are not converted between snake_case and camelCase.

No key is reserved, and that is the point: every piece of state the platform owns lives in its own typed column, so nothing written here reaches platform state. The platform never reads the bag — it is not an IAM context, not a policy input and not part of a prompt — which is what separates it from a tag bag.

resolved_metadataobject nullable

The template's top-level metadata block after parameter (sub/param) and resource (ref) substitution at the last deploy. Null when the template declares no metadata.

resolved_parametersobject nullable

Parameter values applied at the last deploy, for auditability. no_echo parameters are masked (***). Null when the template declares no parameters.

created_atstring date-time
updated_atstring date-time

Example response

{
  "id": "form_V1StGXR8Z5jdHi6B",
  "template": {
    "metadata": {
      "author": "John",
      "revision": 2
    }
  },
  "metadata": {
    "author": "John",
    "revision": 2
  },
  "error": {
    "code": "AI_PROVIDER_ERROR",
    "message": "Provider returned 402: insufficient credits"
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.