<!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
<!-- Regenerate: pnpm scaffold:sync -->

﻿---
title: Add a Resource
description: Add an OM-owned workflow or agent descriptor, bind executable behavior in operations, and verify descriptor-backed deployment.
---

# Add a Resource

Resources are governed descriptors in the Organization Model. The OM owns resource identity, System membership, owner role, and lifecycle status. Operations code imports those descriptors, attaches executable workflow or agent behavior, and exports a `DeploymentSpec` for deployment.

Do not keep a second identity catalog in operations. `DeploymentSpec` is the runtime/deploy assembly artifact; it should not be the place where a workflow ID is invented.

## 1. Author the OM descriptor

Add the descriptor in `core/config/organization-model.ts`:

```ts
import { defineResources } from '@elevasis/core/organization-model'

export const resourceDescriptors = defineResources({
  myWorkflow: {
    id: 'my-workflow',
    title: 'My Workflow',
    description: 'Runs the governed work item workflow.',
    order: 10,
    kind: 'workflow',
    systemPath: 'operations',
    ownerRoleId: 'role-ops-lead',
    status: 'active',
    ontology: {
      actions: ['operations:action/my-workflow.run'],
      primaryAction: 'operations:action/my-workflow.run',
      reads: ['operations:object/work-item'],
      writes: ['operations:object/work-item'],
      usesCatalogs: ['operations:catalog/workflow-status'],
      emits: ['operations:event/my-workflow.completed']
    },
    codeRefs: [
      {
        path: 'operations/src/my-workflow/index.ts',
        role: 'entrypoint',
        symbol: 'myWorkflow'
      },
      {
        path: 'operations/src/my-workflow/my-workflow.test.ts',
        role: 'test'
      }
    ]
  }
})
```

Then expose the descriptor catalog through the Organization Model:

```ts
export const resourceGovernanceModel = {
  systems,
  resources: resourceDescriptors
} as const
```

Use `organizationModel.resources` as the Resources descriptor catalog. Graph references still use kind-prefixed IDs, such as `system:sales.crm`, `resource:lead-import`, or `action:operations.queue.review`, when runtime behavior needs semantic graph binding.

Use `codeRefs` as repo-relative implementation breadcrumbs for agents and operators. They do not define resource identity, System membership, runtime topology, or graph links; they point from the governed Resource descriptor to the files that implement, validate, or document it.

Use descriptor `title` and `description` for executable display metadata. Use nested `resource.ontology` bindings to declare which ontology actions, objects, catalogs, and events the resource performs, reads, writes, uses, or emits. `resource.ontology.primaryAction` is the default/selectable ontology action and must be included in `resource.ontology.actions`. Optional top-level resource `emits` remains readable for bridge-era event descriptors, but new descriptors should keep event bindings in `resource.ontology.emits`.

## 2. Author executable behavior

Operations code owns schemas, steps, handlers, triggers, and UI execution metadata. Import the descriptor and derive runtime identity from it at the binding boundary:

```ts
import type { WorkflowDefinition } from '@elevasis/sdk'
import { resourceDescriptors } from '@core/config/organization-model'

export const myWorkflow: WorkflowDefinition = {
  config: {
    resource: resourceDescriptors.myWorkflow,
    resourceId: resourceDescriptors.myWorkflow.id,
    name: 'My Workflow',
    type: resourceDescriptors.myWorkflow.kind,
    version: '1.0.0',
    status: 'dev',
    category: 'production'
  },
  contract: {
    inputSchema,
    outputSchema
  },
  steps: {
    run: {
      id: 'run',
      name: 'Run',
      handler: async (_input, context) => {
        context.logger.info('[my-workflow] starting')
        return { ok: true }
      },
      inputSchema,
      outputSchema,
      next: null
    }
  },
  entryPoint: 'run'
}
```

`category` is one of `production`, `diagnostic`, `internal`, or `testing`.

## 3. Register in the deployment spec

```ts
import { organizationModel } from '@core/config/organization-model'
import { myWorkflow } from './my-workflow/index.js'

export const org = {
  version: '0.1.0',
  organizationModel,
  workflows: [myWorkflow],
  agents: []
}
```

Use `.js` extensions in TypeScript source imports for ESM compatibility.

## 4. Declare runtime relationships

Use `organizationModel.topology.relationships` for durable execution topology:

```ts
topology: {
  relationships: [
    {
      source: { kind: 'trigger', id: 'daily-work-item-import' },
      target: { kind: 'resource', id: 'my-workflow' },
      kind: 'triggers'
    },
    {
      source: { kind: 'resource', id: 'my-workflow' },
      target: { kind: 'externalResource', id: 'hubspot' },
      kind: 'uses'
    }
  ]
}
```

Use relationship kinds `triggers`, `uses`, and `approval` for the initial topology vocabulary. For semantic graph binding, prefer OM ontology IDs in `resource.ontology`; keep `config.links` only when maintaining older descriptors that still need the legacy graph bridge.

## 5. Verify

```bash
pnpm -C operations check
pnpm -C operations deploy
pnpm exec elevasis describe Elevasis/my-workflow
pnpm scaffold:sync
pnpm scaffold:verify
```
