AgentSkillsCN

understanding-transformers

在使用转换器、理解事件的验证/丰富/脱敏操作,或学习转换器链式调用时使用。内容涵盖转换器接口设计、返回值规范,以及与事件管道的集成方案。

SKILL.md
--- frontmatter
name: understanding-transformers
description:
  Use when working with transformers, understanding event
  validation/enrichment/redaction, or learning about transformer chaining.
  Covers interface, return values, and pipeline integration.

Understanding walkerOS Transformers

Overview

Transformers are middleware for validating, enriching, and redacting events in the walkerOS pipeline. They run in chains at configurable points between sources, collector, and destinations.

Core principle: Transformers transform events. They don't capture (sources) or deliver (destinations)—they modify events in-flight.

Use Cases

Use CasePurposeExample
ValidateEnsure events match schema contractsJSON Schema validation
EnrichAdd server-side data to eventsUser segments, geo data
RedactRemove sensitive data before destinationsStrip PII, anonymize IPs

Transformer Interface

See packages/core/src/types/transformer.ts for canonical interface.

Init Function (Context Pattern)

Transformers use a context-based initialization pattern:

typescript
import type { Transformer } from '@walkeros/core';

export const transformerMyTransformer: Transformer.Init<Types> = (context) => {
  const { config = {}, env, logger, id } = context;
  const settings = SettingsSchema.parse(config.settings || {});

  return {
    push(event, pushContext) {
      // Process event
      return event;
    },
  };
};

Init Context contains:

PropertyTypePurpose
configTransformer.ConfigSettings, mapping, next chain
envTypes['env']Environment dependencies
loggerLoggerLogging functions
idstringTransformer identifier
collectorCollector.InstanceReference to collector
ingestIngest (optional)Request metadata from source

Instance Methods

MethodPurposeRequired
pushProcess event, return modified/falseRequired
initOne-time initializationOptional
destroyCleanup resourcesOptional

Return Values

The push function controls event flow:

ReturnBehavior
eventContinue chain with modified event
voidContinue chain, event unchanged
falseStop chain, event dropped
typescript
push(event, context) {
  if (!event.data?.id) {
    context.logger.error('Missing required id');
    return false;  // Stop chain
  }

  event.data.enrichedAt = Date.now();
  return event;  // Continue with modified event
}

Inline Code Transformers

For simple transformations without external packages, use inline code with the $code: prefix:

json
{
  "transformers": {
    "enrich": {
      "code": {
        "push": "$code:(event) => { event.data.enrichedAt = Date.now(); return event; }"
      },
      "next": "validate"
    }
  }
}

Inline code structure:

PropertyPurpose
code.initCode run once during initialization
code.pushCode run for each event

Push code has access to:

  • event - The event being processed
  • context - Push context with logger, config, etc.

Return values in push code:

  • Return modified event to continue chain
  • Return undefined to pass event unchanged
  • Return false to drop event from chain

Example: Filtering internal events

json
{
  "transformers": {
    "filter": {
      "code": {
        "push": "$code:(event) => { if (event.name.startsWith('internal_')) return false; return event; }"
      }
    }
  }
}

Mixing inline and package transformers:

json
{
  "transformers": {
    "addTimestamp": {
      "code": {
        "push": "$code:(event) => { event.data.processedAt = new Date().toISOString(); return event; }"
      },
      "next": "validate"
    },
    "validate": {
      "package": "@walkeros/transformer-validator"
    }
  }
}

Pipeline Integration

Transformers run at two points in the pipeline:

code
Source → [Pre-Transformers] → Collector → [Post-Transformers] → Destination
          (source.next)                   (destination.before)

Pre-Collector Chain

Runs after source captures event, before collector enrichment:

typescript
sources: {
  browser: {
    code: sourceBrowser,
    next: 'validate'  // First transformer in pre-chain
  }
}

Post-Collector Chain

Runs after collector enrichment, before destination receives event:

typescript
destinations: {
  gtag: {
    code: destinationGtag,
    before: 'redact'  // First transformer in post-chain
  }
}

Chain Linking

Transformers link together via next:

typescript
transformers: {
  validate: {
    code: transformerValidator,
    config: { next: 'enrich' }  // Chain to next transformer
  },
  enrich: {
    code: transformerEnrich,
    config: { next: 'redact' }
  },
  redact: {
    code: transformerRedact
    // No next = end of chain
  }
}

Push Context

The push function receives a context with event metadata:

PropertyPurpose
configTransformer configuration
envEnvironment dependencies
loggerScoped logger for output
idTransformer identifier
collectorAccess to collector instance
ingestRequest metadata from source
typescript
push(event, context) {
  const { logger, id, ingest } = context;

  logger.debug('Processing', { transformer: id, event: event.name });

  // Access request metadata if available
  if (ingest?.ip) {
    event.data = { ...event.data, clientIp: ingest.ip };
  }

  return event;
}

Transformer Paths

PathDescription
packages/transformers/Transformer packages
packages/transformers/validator/Validator transformer

Related

Skills:

Source Files:

Package READMEs:

Documentation: