Skip to content

Desired-State Resources

How Compozy stores extensible runtime resources, validates mutations, and reconciles projected runtime state.

For people running agent work2 pages in this section

Resources are Compozy's desired-state layer for runtime objects that must be extensible and agent-manageable. Instead of letting every subsystem invent its own private storage shape, Compozy writes canonical resource records, validates their specs through registered codecs, and reconciles them into runtime state.

Use this page when you need to understand why a tool, MCP server, agent definition, package-owned agent sidecar, skill, automation job, trigger, window layout, bridge instance, or bundle activation can be managed through the same control plane.

Mental model

Rendering diagram…

Desired-state resources pass through validation, storage, and reconcile before they affect runtime subsystems.
TermMeaning
KindResource family, such as tool, agent, automation.job, or bundle.
IDStable resource identity inside the kind.
Scopeglobal or workspace; workspace scope requires a workspace id.
OwnerWho owns the record, such as daemon control or a bundle activation.
SourceWhere the record came from, such as an extension, daemon, or session.
VersionOptimistic mutation version used to prevent blind overwrites.
SpecCanonical JSON payload for the resource kind.

Registered resource kinds

The daemon registers typed codecs for these resource families at boot:

KindProjects into
hook.bindingHook registry bindings.
toolTool Registry entries.
mcp_serverMCP server declarations.
agentAgent catalog definitions.
agent.soulPackage-owned SOUL.md defaults for resource-backed agents.
agent.heartbeatPackage-owned HEARTBEAT.md defaults for resource-backed agents.
skillSkill catalog entries.
automation.jobScheduled or claimable automation jobs.
automation.triggerAutomation trigger definitions.
window_layoutStrict declarative desktop and tiled-group layout templates.
bridge.instanceBridge runtime instances.
bundleExtension-provided bundle catalog entries.
bundle.activationActive bundle profiles that project agents, sidecars, automation, layouts, and bridges.

Write flow

PUT /api/resources/automation.job/nightly-resource-audit
Content-Type: application/json

{
  "scope": { "kind": "global" },
  "expected_version": 0,
  "spec": {
    "id": "nightly-resource-audit",
    "name": "Nightly resource audit",
    "target_kind": "agent",
    "agent_name": "general",
    "prompt": "Inspect desired-state resource health.",
    "schedule": { "mode": "every", "interval": "24h" },
    "enabled": false
  }
}

What happens:

  1. Compozy validates the path kind and id.
  2. Compozy validates the scope binding.
  3. If a codec is registered for that kind, Compozy canonicalizes the spec.
  4. The record is written with an owner, source, version, and timestamps.
  5. Reconcile is triggered for that kind.

Use expected_version = 0 when creating a new record. Use the returned version on update or delete so stale operators and agents do not overwrite each other silently.

bundle.activation is service-owned. You can read it through the resource surface, but direct PUT and DELETE requests return 403. Use POST /api/bundles/activations, the matching update and delete routes, or compozy bundle so bundle requirements and projected resources stay coherent.

Read and filter

GET /api/resources
GET /api/resources/automation.job
GET /api/resources/automation.job/nightly-resource-audit
GET /api/resources/automation.job?scope_kind=workspace&scope_id=ws_project

Filters can narrow by kind, scope_kind, scope_id, owner_kind, owner_id, source_kind, source_id, and limit.

Delete

DELETE /api/resources/automation.job/nightly-resource-audit
Content-Type: application/json

{ "expected_version": 3 }

Deletes also trigger reconcile for the kind. If the resource was owned by a bundle activation, remove or update the activation instead of deleting the projected child record by hand.

Failure guide

SymptomLikely causeFirst check
400 on writeThe request body is malformed JSON or cannot be decoded.Response body and submitted payload.
403 on write/deleteThe resource kind has a dedicated lifecycle service.Use the kind-specific API or CLI.
422 on writeInvalid kind, scope binding, or registered-codec spec validation.Response body and kind-specific docs.
409 on update/deleteexpected_version is stale.GET /api/resources/:kind/:id for the current version.
Record exists but runtime did not changeReconcile failed or is degraded.Observe resource/reconcile health and daemon logs.
Projected record reappearsA bundle activation or extension owns it.owner and source fields on the resource record.
Workspace write failsscope.id does not name a valid workspace.compozy workspace list -o json.

Next

  • Bundles explains the bundle activation layer built on top of resources.
  • Extensions explains how installed packages publish resource records.
  • API Reference lists the current resource and bundle route families.

On this page