C3 AI Documentation Home

Metadata folder structure

The metadata/ folder contains instances of Types that mix the Metadata base Type. The C3 Agentic AI Platform loads these instances at runtime to provide provisioned configuration and data for your application. This topic explains what belongs in this folder, how the C3 Agentic AI Platform discovers and validates metadata, and how instances are loaded and remixed across packages.

Understand what belongs in metadata/

The metadata folder stores instances of Types that mix Metadata. These are provisioned data instances loaded during package initialization, such as roles, translations, transforms, and other configuration data.

Examples:

Text
metadata/
  Role/
    DataAnalyst.json
    SystemAdmin.json
  
  Translation/
    en.csv
    fr.csv
  
  Transform/
    CanonicalAsset-Asset.js
    CanonicalWorkOrder-WorkOrder.js

Type requirements

Types stored in the metadata folder must meet two requirements:

  1. Mix the Metadata base type
  2. Mix either Named (using name field) or Identified (using id field)

These mixins enable the C3 Agentic AI Platform to identify and retrieve instances at runtime.

File formats

The C3 Agentic AI Platform supports three file formats for metadata:

JSON files (*.json)

JSON is the standard format for metadata instances. Each file contains a single instance or an array of instances.

JSON
metadata/Role/DataAnalyst.json
{
  "id": "DataAnalyst",
  "description": "Access to data analysis tools and reports.",
  "nestedRoles": ["BasicUser", "ReportViewer"],
  "permissions": ["allow:Dataset::read"]
}

Single instance: The key field (id or name) should match the filename.

Multiple instances: Use an array to define multiple instances in one file.

JSON
metadata/Role/AnalystRoles.json
[
  {
    "id": "DataAnalyst",
    "description": "Access to data analysis tools."
  },
  {
    "id": "ReportAnalyst",
    "description": "Access to report generation."
  }
]

CSV files (*.csv)

CSV format is efficient for bulk metadata instances. Each row after the header creates one instance of the Type. The first row defines column headers that map to Type fields.

CSV
metadata/Translation/en.csv
id,locale,key,value
button.save.label,en,button.save.label,Save Changes
button.delete.label,en,button.delete.label,Delete Item

This CSV file creates two Translation instances:

Row 1 (header): Defines the field mappings - id, locale, key, and value correspond to Translation fields.

Row 2: Creates a Translation instance with:

  • id: "button.save.label"
  • locale: "en"
  • key: "button.save.label"
  • value: "Save Changes"

Row 3: Creates a Translation instance with:

  • id: "button.delete.label"
  • locale: "en"
  • key: "button.delete.label"
  • value: "Delete Item"

JavaScript files (*.js)

JavaScript files provide metadata instances using expressions and functions. The file must set a data variable containing the instance definition.

JavaScript
metadata/Transform/CanonicalAsset-Asset.js
data = {
  name: 'CanonicalAsset-Asset',
  source: 'CanonicalAsset',
  target: 'Asset',
  projection: {
    assetId: id,
    assetName: name
  }
};

JavaScript files can:

  • Use functions and expressions for dynamic values.
  • Reference enum values.
  • Call helper functions.
  • Only work with Types that mix JsSerializable.

How metadata/ relates to other folders

Several folders depend on or interact with the content in your metadata/ folder.

  • Source folder (src/) The metadata folder references Types declared in src/. When you change a Type definition, the C3 Agentic AI Platform invalidates dependent metadata instances and revalidates them against the new Type structure. See Source Folder.

  • Test folder (test/) Test metadata in test/metadata/ remixes base metadata for testing. The C3 Agentic AI Platform merges test metadata with base metadata at the field level, allowing you to override specific fields without duplicating entire instances. See Test Folder.

  • Seed folder (seed/) Both metadata and seed store Type instances, but they serve different purposes. Metadata contains provisioned configuration loaded at runtime. Seed data contains initial persistent data loaded into the database. See Seed Folder.

These interactions make the metadata/ folder a key part of your package's runtime configuration.

Structural rules

The C3 Agentic AI Platform enforces structural rules in the metadata/ folder to discover instances, validate them, and load them reliably.

Path conventions

The directory structure determines which Type the metadata belongs to.

Standard path structure:

Text
/packageName/metadata/TypeName/instanceName.ext

The directory name (second-to-last path segment) identifies the Type. For example:

  • metadata/Role/DataAnalyst.json: The Type is Role.
  • metadata/Transform/CanonicalAsset-Asset.js: The Type is Transform.

Generic Types: Generic Types must specify their type parameters in the type field.

JSON
metadata/MyGenericType/instance.json
{
  "type": "MyGenericType<Obj>",
  "id": "instance",
  ...
}

If you omit the type parameter, the C3 Agentic AI Platform generates a validation warning.

Custom base folders: Types can declare a custom base folder using the @metadata annotation.

Type
@metadata(baseFolder='custom/path/')
type CustomMetadata mixes Metadata, Named {
  ...
}

Instances for this Type belong in custom/path/CustomMetadata/ instead of metadata/CustomMetadata/.

File naming

Instance filenames should match the key field value for single-instance files.

Correct:

Text
metadata/Role/DataAnalyst.json
{
  "id": "DataAnalyst",
  ...
}

Warning: If the filename and key field don't match, the C3 Agentic AI Platform generates a validation warning but still loads the instance.

Text
metadata/Role/Analyst.json
{
  "id": "DataAnalyst",  // Mismatched key
  ...
}

Multi-instance files: Files containing arrays can use any filename since they define multiple instances.

Validation rules

The C3 Agentic AI Platform validates metadata files during package loading and reports issues through Pkg.Issue.

Below are examples of validation rules:

Required fields: Missing required fields generate errors.

JSON
// Error: Missing required field
{
  "id": "DataAnalyst"
  // Missing required "description" field
}

Invalid fields: Fields not declared in the Type generate errors.

JSON
// Error: Invalid field
{
  "id": "DataAnalyst",
  "description": "Analyst role",
  "invalidField": true  // Type does not declare this field
}

Type mismatches: Field values must match the declared Type.

JSON
// Error: Type mismatch
{
  "id": "DataAnalyst",
  "permissions": "should be array"  // Field expects Array<string>
}

Syntax errors: Invalid JSON or JavaScript syntax generates errors.

JavaScript
// Error: Syntax error
data = {
  name: 'Transform'
  source: 'Missing comma'  // Syntax error
}

How metadata is loaded

The C3 Agentic AI Platform loads metadata through file discovery, caching, and remix resolution. These processes determine which instances are available at runtime and ensure changes appear immediately during development.

How metadata files load

The C3 Agentic AI Platform loads metadata during package initialization. Once loaded, instances are cached until a Type or file change invalidates them.

Initial load: When you start an application or the C3 Agentic AI Platform loads a package, it:

  1. Discovers all metadata files for Types mixing Metadata.
  2. Parses and validates each file.
  3. Creates instances and caches them by Type and key.
  4. Makes instances available through forName(), forId(), and metadata() APIs.

Hot reloading: In development mode, changes to metadata files trigger immediate revalidation and cache invalidation. Your changes appear instantly in the Console and through APIs.

Example:

Text
save metadata/Role/DataAnalyst.json  -> UPDATE event
invalidate Role instances  -> reload  -> new instance available in Console and through APIs

Cache invalidation: The C3 Agentic AI Platform invalidates cached instances when:

  • The metadata file changes.
  • The Type definition changes.
  • A referenced Type changes (cascading invalidation).

Remix and overlays

When multiple packages define metadata for the same Type and key, the C3 Agentic AI Platform merges them into a single effective instance using field-level merging.

Remix ordering: The C3 Agentic AI Platform applies remixes in reverse dependency order—dependent packages can override base package metadata.

Example package dependency chain:

Text
yourPkg
 └─ depends on basePkg

basePkg/metadata/Transform/CanonicalWorkOrder-WorkOrder.json (base definition):

JSON
{
  "name": "CanonicalWorkOrder-WorkOrder",
  "source": "CanonicalWorkOrder",
  "target": "WorkOrder",
  "projection": {
    "workOrderNumber": "workOrderNum",
    "type": "workOrderType",
    "priority": "priority",
    "startDate": "actualStartDatetime"
  }
}

yourPkg/metadata/Transform/CanonicalWorkOrder-WorkOrder.json (remix adds field):

JSON
{
  "name": "CanonicalWorkOrder-WorkOrder",
  "projection": {
    "finishDate": "actualFinishDatetime",
    "location": "functionalLocation"
  }
}

Effective merged instance at runtime:

JSON
{
  "name": "CanonicalWorkOrder-WorkOrder",
  "source": "CanonicalWorkOrder",
  "target": "WorkOrder",
  "projection": {
    "workOrderNumber": "workOrderNum",
    "type": "workOrderType",
    "priority": "priority",
    "startDate": "actualStartDatetime",
    "finishDate": "actualFinishDatetime",
    "location": "functionalLocation"
  }
}

The dependent package extends the instance without modifying the base definition. Fields from later packages override earlier ones if they conflict.

Test overlays: Metadata in test/metadata/ remixes base metadata in test mode only. This pattern lets you override configuration for testing without affecting production.

Text
metadata/Transform/CanonicalAsset-Asset.json  (base)
test/metadata/Transform/CanonicalAsset-Asset.json  (test overlay)

In test mode, the C3 Agentic AI Platform merges both files using JSON merging. In production mode, only the base file loads.

Runtime operations

The C3 Agentic AI Platform provides APIs for accessing, updating, and removing metadata instances at runtime.

Access instances

Retrieve instances by key using the Named or Identified mixin methods.

JavaScript
// Access by name (for Types mixing Named)
Role role = Role.forName("DataAnalyst");

// Access by id (for Types mixing Identified)
Transform transform = Transform.forId("CanonicalAsset-Asset");

// Get all instances for a Type
Map<string, Role> roles = pkg().metadata(Role.myType());

Update instances

In development mode, use upsert() to create or update metadata instances. The C3 Agentic AI Platform writes changes to the metadata file immediately.

JavaScript
// Create or update instance
Role.make()
  .withId("NewAnalyst")
  .withDescription("New analyst role")
  .upsert();

This creates or updates metadata/Role/NewAnalyst.json in your package.

Remove instances

Use remove() or removeAll() to delete metadata instances. The C3 Agentic AI Platform deletes the actual files from your package.

JavaScript
// Remove single instance
Role analyst = Role.forName("DataAnalyst");
analyst.remove();

// Remove all matching instances
Role.removeAll("description contains 'analyst'");

Dependency tracking: When you remove an instance that other instances reference, the C3 Agentic AI Platform invalidates dependent instances and triggers revalidation.

See also

Was this page helpful?