AgentSkillsCN

Flexible Assets

当您需要管理IT Glue灵活资产时,可使用此技能:针对结构化文档需求,定制灵活资产类型。本技能涵盖灵活资产类型、字段定义、实例创建与管理、与其他资源的交叉链接,以及根据MSP需求构建自定义文档架构。

SKILL.md
--- frontmatter
description: >
  Use this skill when working with IT Glue flexible assets - custom asset types
  for structured documentation. Covers flexible asset types, field definitions,
  creating and managing instances, cross-linking with other resources, and
  building custom documentation schemas for MSP needs.
triggers:
  - it glue flexible asset
  - custom asset
  - flexible asset type
  - it glue custom documentation
  - flexible asset field
  - custom documentation
  - structured asset
  - it glue template

IT Glue Flexible Assets Management

Overview

Flexible Assets in IT Glue provide customizable, structured documentation templates. Unlike free-form documents, flexible assets have defined fields and types, enabling consistent documentation across organizations and powerful filtering/searching capabilities.

Key Concepts

Flexible Asset Types

Flexible Asset Types define the schema for a category of documentation:

code
Flexible Asset Type: Network Overview
├── Fields:
│   ├── Primary ISP (Text)
│   ├── Backup ISP (Text)
│   ├── Public IP Addresses (Textarea)
│   ├── Firewall (Tag - Configuration)
│   ├── Network Diagram (Upload)
│   └── DNS Provider (Select)

Field Types

TypeDescriptionUse Case
TextSingle line textNames, identifiers
TextareaMulti-line textDescriptions, notes
NumberNumeric valueQuantities, counts
DateDate pickerExpiration dates
CheckboxBoolean true/falseFlags, toggles
SelectDropdown selectionPredefined options
TagLink to IT Glue resourceConfigurations, contacts
PasswordPassword fieldEmbedded credentials
UploadFile attachmentDiagrams, documents
PercentPercentage valueUtilization, progress
HeaderSection headerVisual organization

Tag Fields

Tag fields create relationships to other IT Glue resources:

Tag TypeLinks To
ConfigurationConfiguration items
ContactContacts
PasswordPasswords
DocumentDocuments
Flexible AssetOther flexible assets
LocationLocations

Field Reference

Flexible Asset Type Fields

FieldTypeDescription
idintegerType identifier
namestringType name
descriptionstringType description
iconstringDisplay icon
enabledbooleanType enabled status

Flexible Asset Fields

FieldTypeDescription
idintegerAsset instance identifier
organization-idintegerParent organization
flexible-asset-type-idintegerType definition
namestringAuto-generated from name field
traitsobjectField values

Traits (Field Values)

json
{
  "traits": {
    "primary-isp": "Comcast Business",
    "backup-isp": "Verizon FiOS",
    "public-ip-addresses": "203.0.113.10\n203.0.113.11",
    "firewall": {
      "type": "Tag",
      "values": [{"id": 12345, "type": "Configuration"}]
    },
    "dns-provider": "Cloudflare"
  }
}

API Patterns

List Flexible Asset Types

http
GET /flexible-asset-types
x-api-key: YOUR_API_KEY
Content-Type: application/vnd.api+json

Get Flexible Asset Type Details

http
GET /flexible-asset-types/123
x-api-key: YOUR_API_KEY

With Field Definitions:

http
GET /flexible-asset-types/123?include=flexible-asset-fields

List Flexible Assets

http
GET /flexible-assets
x-api-key: YOUR_API_KEY

By Organization:

http
GET /organizations/456/relationships/flexible-assets

By Type:

http
GET /flexible-assets?filter[flexible-asset-type-id]=123

By Organization and Type:

http
GET /flexible-assets?filter[organization-id]=456&filter[flexible-asset-type-id]=123

Get Single Flexible Asset

http
GET /flexible-assets/789
x-api-key: YOUR_API_KEY

With Includes:

http
GET /flexible-assets/789?include=organization,flexible-asset-type

Create Flexible Asset

http
POST /flexible-assets
Content-Type: application/vnd.api+json
x-api-key: YOUR_API_KEY
json
{
  "data": {
    "type": "flexible-assets",
    "attributes": {
      "organization-id": 456,
      "flexible-asset-type-id": 123,
      "traits": {
        "name": "Acme Corp Network Overview",
        "primary-isp": "Comcast Business",
        "backup-isp": "Verizon FiOS",
        "public-ip-addresses": "203.0.113.10\n203.0.113.11",
        "dns-provider": "Cloudflare"
      }
    }
  }
}

Create with Tag Fields

json
{
  "data": {
    "type": "flexible-assets",
    "attributes": {
      "organization-id": 456,
      "flexible-asset-type-id": 123,
      "traits": {
        "name": "Main Office Network",
        "firewall": [12345],
        "core-switch": [67890],
        "network-admin": [11111]
      }
    }
  }
}

Update Flexible Asset

http
PATCH /flexible-assets/789
Content-Type: application/vnd.api+json
x-api-key: YOUR_API_KEY
json
{
  "data": {
    "type": "flexible-assets",
    "attributes": {
      "traits": {
        "backup-isp": "AT&T Business",
        "last-reviewed": "2024-02-15"
      }
    }
  }
}

Delete Flexible Asset

http
DELETE /flexible-assets/789
x-api-key: YOUR_API_KEY

Common Flexible Asset Types

Network Overview

code
Fields:
├── Name (Text) - Required, Name field
├── Primary ISP (Text)
├── Backup ISP (Text)
├── Public IP Addresses (Textarea)
├── Internal IP Scheme (Textarea)
├── Firewall (Tag - Configuration)
├── Core Switch (Tag - Configuration)
├── Network Diagram (Upload)
├── DNS Provider (Select)
└── Last Reviewed (Date)

Application Documentation

code
Fields:
├── Name (Text) - Required, Name field
├── Description (Textarea)
├── Version (Text)
├── Vendor (Text)
├── Support Contact (Tag - Contact)
├── Primary Server (Tag - Configuration)
├── Database Server (Tag - Configuration)
├── Admin URL (Text)
├── Admin Credentials (Password)
├── License Key (Password)
├── License Expiration (Date)
├── Documentation URL (Text)
└── Notes (Textarea)

Backup Overview

code
Fields:
├── Name (Text) - Required, Name field
├── Backup Solution (Select)
├── Backup Server (Tag - Configuration)
├── Retention Policy (Textarea)
├── Backup Schedule (Textarea)
├── Data Protected (Textarea)
├── Recovery Time Objective (Text)
├── Recovery Point Objective (Text)
├── Last Test Date (Date)
├── Backup Admin Credentials (Password)
└── Notes (Textarea)

Microsoft 365 Tenant

code
Fields:
├── Name (Text) - Required, Name field
├── Tenant ID (Text)
├── Primary Domain (Text)
├── Additional Domains (Textarea)
├── License Summary (Textarea)
├── Admin Portal URL (Text)
├── Global Admin (Tag - Contact)
├── Admin Credentials (Password)
├── MFA Status (Select)
├── Conditional Access (Checkbox)
└── Notes (Textarea)

Common Workflows

Create Flexible Asset from Template

javascript
async function createFlexibleAssetFromType(orgId, typeId, fieldValues) {
  // Get the type definition to understand fields
  const assetType = await getFlexibleAssetType(typeId, {
    include: 'flexible-asset-fields'
  });

  // Validate required fields
  const requiredFields = assetType.included?.filter(
    f => f.attributes.required
  ) || [];

  for (const field of requiredFields) {
    const fieldKey = field.attributes['name-key'];
    if (!fieldValues[fieldKey]) {
      throw new Error(`Required field missing: ${field.attributes.name}`);
    }
  }

  // Create the flexible asset
  return await createFlexibleAsset({
    'organization-id': orgId,
    'flexible-asset-type-id': typeId,
    traits: fieldValues
  });
}

Find Flexible Assets by Type

javascript
async function findFlexibleAssetsByType(orgId, typeName) {
  // First, find the type by name
  const types = await fetchFlexibleAssetTypes();
  const type = types.find(t =>
    t.attributes.name.toLowerCase() === typeName.toLowerCase()
  );

  if (!type) {
    throw new Error(`Flexible asset type not found: ${typeName}`);
  }

  // Then fetch assets of that type for the org
  return await fetchFlexibleAssets({
    filter: {
      'organization-id': orgId,
      'flexible-asset-type-id': type.id
    }
  });
}

Update Tagged Resources

javascript
async function updateFlexibleAssetTags(assetId, fieldName, newTagIds) {
  return await updateFlexibleAsset(assetId, {
    traits: {
      [fieldName]: newTagIds
    }
  });
}

Export Flexible Asset Data

javascript
async function exportFlexibleAssets(orgId, typeId) {
  const assets = await fetchFlexibleAssets({
    filter: {
      'organization-id': orgId,
      'flexible-asset-type-id': typeId
    }
  });

  const type = await getFlexibleAssetType(typeId, {
    include: 'flexible-asset-fields'
  });

  const fieldNames = type.included?.reduce((acc, f) => {
    acc[f.attributes['name-key']] = f.attributes.name;
    return acc;
  }, {}) || {};

  return assets.map(asset => {
    const exportData = { id: asset.id };
    Object.entries(asset.attributes.traits || {}).forEach(([key, value]) => {
      const fieldName = fieldNames[key] || key;
      exportData[fieldName] = value;
    });
    return exportData;
  });
}

Flexible Asset Health Check

javascript
async function flexibleAssetHealthCheck(orgId) {
  // Get all flexible asset types
  const types = await fetchFlexibleAssetTypes();

  const results = [];

  for (const type of types) {
    const assets = await fetchFlexibleAssets({
      filter: {
        'organization-id': orgId,
        'flexible-asset-type-id': type.id
      }
    });

    results.push({
      type: type.attributes.name,
      count: assets.length,
      hasAssets: assets.length > 0
    });
  }

  return {
    totalTypes: types.length,
    typesWithData: results.filter(r => r.hasAssets).length,
    details: results
  };
}

Clone Flexible Asset to Another Org

javascript
async function cloneFlexibleAsset(sourceAssetId, targetOrgId) {
  // Get source asset
  const source = await getFlexibleAsset(sourceAssetId);

  // Clone traits (remove tag fields that won't be valid in new org)
  const traits = { ...source.attributes.traits };

  // Note: Tag fields reference resources in the source org
  // You may need to map or remove these

  return await createFlexibleAsset({
    'organization-id': targetOrgId,
    'flexible-asset-type-id': source.attributes['flexible-asset-type-id'],
    traits: traits
  });
}

Error Handling

Common API Errors

CodeMessageResolution
400Organization requiredInclude organization-id
400Type requiredInclude flexible-asset-type-id
401Invalid API keyCheck IT_GLUE_API_KEY
404Asset not foundVerify asset ID
422Invalid trait valueCheck field type requirements
422Required field missingProvide all required traits

Validation Errors

ErrorCauseFix
Organization requiredNo org IDInclude organization-id
Type requiredNo type IDInclude flexible-asset-type-id
Invalid traitWrong data typeMatch field type
Required traitMissing required fieldAdd trait value
Invalid tagBad resource IDVerify tagged resource exists

Error Recovery Pattern

javascript
async function safeCreateFlexibleAsset(data) {
  try {
    return await createFlexibleAsset(data);
  } catch (error) {
    if (error.status === 422) {
      const errors = error.errors || [];

      // Handle missing required fields
      const missingFields = errors.filter(e =>
        e.detail?.includes('required') || e.detail?.includes("can't be blank")
      );

      if (missingFields.length > 0) {
        console.log('Missing required fields:',
          missingFields.map(e => e.source?.pointer)
        );

        // Get type definition to see required fields
        const type = await getFlexibleAssetType(data['flexible-asset-type-id'], {
          include: 'flexible-asset-fields'
        });
        const required = type.included?.filter(f => f.attributes.required);
        console.log('Required fields:', required?.map(f => f.attributes.name));
      }

      // Handle invalid tag references
      const invalidTags = errors.filter(e =>
        e.detail?.includes('invalid') && e.source?.pointer?.includes('traits')
      );

      if (invalidTags.length > 0) {
        console.log('Invalid tag references found. Removing...');
        // Remove invalid tags and retry
        // (implementation depends on which fields are tags)
      }
    }

    throw error;
  }
}

Best Practices

  1. Plan type structure - Design flexible asset types before creating
  2. Use consistent naming - Follow conventions for field names
  3. Leverage tags - Link to configurations, contacts for relationships
  4. Required fields - Mark essential fields as required
  5. Use appropriate types - Match field type to data (date for dates, etc.)
  6. Document types - Add descriptions to types and fields
  7. Standardize across orgs - Use same types for all clients
  8. Regular reviews - Update flexible asset content periodically
  9. Avoid duplicates - One flexible asset per topic per org
  10. Export capability - Build export for reporting needs

Related Skills