DocsManifest schema
§ reference · developers

Manifest schema

Every Powerloom resource is declared as YAML and applied through the same weave plan / weave apply path. This page lists every supported Kind, the fields each one takes, and where defaults come from.

The canonical schema source lives in the loomcli repository — pip install loomcli ships JSON Schema for every Kind. weave validate -f <file> checks any manifest against the bundled schema before you apply.


Manifest envelope

Every manifest looks the same on the outside.

apiVersion: powerloom/v1
kind: <Kind>
metadata:
  ...kind-specific fields...

apiVersion is powerloom/v1 for every resource currently shipping. The schema versioning lives at the resource level — older manifests stay applicable across CLI bumps until a powerloom/v2 cutover lands (none planned today).

kind is one of the eleven listed below.

metadata carries the resource definition. Powerloom doesn't separate spec from metadata the way Kubernetes does; everything you declare lives at the top level under metadata to keep the file flat and the diff small.

Multi-document files (--- separator between manifests) work — weave apply -f bundle.yaml applies them in order.


Kind: OU

Organizational unit. Container for principals, agents, MCP deployments, and credentials.

apiVersion: powerloom/v1
kind: OU
metadata:
  name: engineering              # required, DNS-label-shaped
  parent_ou_path: /acme          # required for non-root; root is implicit
  display_name: Engineering      # optional, free-form
  description: Engineering teams # optional

parent_ou_path resolves the parent at apply time. The first OU you create in a workspace lives at root; everything else nests below something.


Kind: Group

Security group. Holds principals (users, other groups, OUs).

apiVersion: powerloom/v1
kind: Group
metadata:
  name: eng-leads
  scope_ou_path: /acme/engineering
  display_name: Engineering leads
  description: Folks who can approve agent deployments to engineering

Membership is managed via GroupMembership (next).


Kind: GroupMembership

A user (or another group) added to a group.

apiVersion: powerloom/v1
kind: GroupMembership
metadata:
  group_ref: group:/acme/engineering/eng-leads
  member_ref: user:alice@acme.com

member_ref accepts user:, group:, or ou: prefixes. Nested groups resolve transitively through a closure table; permission checks stay constant-time regardless of nesting depth.


Kind: RoleBinding

Grants or denies a role at a scope. The core primitive of RBAC.

apiVersion: powerloom/v1
kind: RoleBinding
metadata:
  principal_ref: group:/acme/engineering/eng-leads
  role: OUAdmin
  scope_ou_path: /acme/engineering
  decision_type: allow            # 'allow' | 'deny' — deny wins
  conditions:                     # optional, role-specific
    tool_names: [query, describe_schema]

Built-in roles: OrgAdmin, OUAdmin, AgentAuthor, DeploymentOperator, Viewer, ToolUser. Custom roles via Role manifests (rare; the built-ins cover most needs).

scope_ou_path is the inheritance anchor — a binding at /acme/engineering applies to that OU and every descendant. For binding to a specific resource (e.g., one MCP deployment), use scope_resource: instead.

Deny always wins at the same scope. A deny binding at /acme/engineering overrides an allow at the same scope; an allow at /acme/engineering/platform doesn't override the parent's deny.


Kind: Agent

A Claude (or other-runtime) agent registered under an OU.

apiVersion: powerloom/v1
kind: Agent
metadata:
  name: code-reviewer
  scope_ou_path: /acme/engineering
  display_name: Code reviewer
  description: Reviews PRs for the platform team
  model: claude-sonnet-4-6        # any supported runtime model id
  agent_kind: cma                 # 'cma' | 'cc' | 'direct' (most users: cma)
  system_prompt: |
    Multi-line system prompt.
    Indented under |.
  attached_skill_refs:            # optional list of Skill resources
    - skill:/acme/engineering/python-lint
  attached_mcp_refs:              # optional list of MCP deployments
    - mcp-deployment:/acme/engineering/dev-postgres
  capability_tags:                # optional, used by workflow agent nodes
    - pr_review
    - code_summary

The reconciler picks new agents up within seconds and registers them with the upstream runtime (Anthropic CMA by default). Status flips from pending to synced once the round-trip succeeds.


Kind: Skill

A versioned bundle of code, docs, or prompts that an agent can attach. Skills land in S3 as archives; agents reference them by name.

apiVersion: powerloom/v1
kind: Skill
metadata:
  name: python-lint
  scope_ou_path: /acme/engineering
  display_name: Python lint runner
  description: Wraps ruff + pyright into a single tool an agent can call
  archive_ref: skill-archive:/acme/engineering/python-lint/v3

The archive is uploaded separately via weave skill upload (versioned each time). The Skill manifest just points at the latest version.


Kind: MCPDeployment

A running MCP server scoped to an OU. See /docs/mcp-deployment for the deployment model.

apiVersion: powerloom/v1
kind: MCPDeployment
metadata:
  name: support-postgres
  scope_ou_path: /acme/support
  template: postgres
  parameters:
    connection_string_credential_ref: cred:/acme/support/support-readonly-db
    schema: public
  description: Read-only access to the support database

template selects from the catalog (15 today). parameters shape is template-specific — weave describe template/<name> shows the schema.


Kind: MCPServerRegistration

Registers a pre-existing MCP server (one you run yourself, not via a Powerloom-managed deployment) so it shows up in agent attachment lists.

apiVersion: powerloom/v1
kind: MCPServerRegistration
metadata:
  name: internal-orders
  scope_ou_path: /acme/support
  endpoint_url: https://orders-mcp.internal.acme.com/mcp
  auth_credential_ref: cred:/acme/support/orders-bearer
  tool_schema:
    - name: lookup_order
      input_schema: { ... }

Use this when you have an MCP server already running outside Powerloom and just want to govern who can call its tools without taking over the runtime.


Kind: Credential

A secret (API key, bearer token, connection string) referenced by other resources. Powerloom never returns the raw value over the API after creation; only wrapped ciphertext.

apiVersion: powerloom/v1
kind: Credential
metadata:
  name: support-readonly-db
  scope_ou_path: /acme/support
  description: Read-only Postgres for support agents
  value_envelope_ref: secrets-manager:arn:aws:secretsmanager:us-east-2:1234:secret:abc/support-db

Credentials carry only a reference to where the secret lives. Powerloom resolves the reference at use-time, decrypts under the per-tenant KMS CMK, hands the plaintext to whatever consumer needs it, and never logs the cleartext.

For a key you want to paste in directly (vs reference an existing AWS Secret), use the console at /settings/credentials — the value is encrypted in-flight and never round-trips through your manifest tree.


Kind: ApprovalPolicy

Declares which mutations require an approver. Used by the Phase 12 approval gate.

apiVersion: powerloom/v1
kind: ApprovalPolicy
metadata:
  name: production-agent-creation-needs-approval
  scope_ou_path: /acme/production
  resource_kind: agent
  action: create
  approver_role: OUAdmin
  ttl_seconds: 86400
  justification_required: true

Any matching mutation (here: creating an Agent anywhere in /acme/production) lands in pending until an approver in OUAdmin scope acts. Auto-deny fires after ttl_seconds.


Kind: WorkflowDefinition

A declarative DAG. See /docs/workflows for the node kinds.

apiVersion: powerloom/v1
kind: WorkflowDefinition
metadata:
  name: pr-triage
  scope_ou_path: /acme/engineering
  description: Review + approve + merge incoming PRs
spec:
  nodes:
    - node_id: start
      kind: trigger
      next: review
    # ... rest of the DAG ...

Workflows are the only Kind that uses spec: instead of putting everything under metadata — the nodes array is large enough that nesting it makes the diff easier to read.


Defaults and immutability

A few rules that apply across every Kind:

  • Names are DNS-label-shaped — lowercase alphanumeric and hyphens, 1-63 chars, no leading/trailing hyphen.
  • name + scope_ou_path is the unique identity — re-applying a manifest with the same name + scope is an update; with a different scope is an error.
  • Some fields are immutable after createname, parent_ou_path, agent_kind, template. Changing them requires destroy + recreate.
  • Defaults apply at apply-time, not load-time — a manifest with no description lands with description: null, not the empty string.

weave plan shows the full diff (including defaults that would be filled in) before any apply. Always safe to run.