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_pathis 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 create —
name,parent_ou_path,agent_kind,template. Changing them requires destroy + recreate. - Defaults apply at apply-time, not load-time — a manifest with no
descriptionlands withdescription: 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.