Map Transitions – Data Transformation in AgetnticOS
While Pass transitions route tokens unchanged, Map transitions transform token data through templates. They’re the workhorses of data reshaping – adding fields, removing fields, restructuring, enriching, and preparing data for downstream processing.
Map transitions take input token data, apply a template transformation, and emit the result as @response.
The Critical Difference: emit.from = @response
This is the most important thing to understand about Map transitions:
The when condition evaluates what from resolves to. For Map transitions, that’s the transformed data (@response), not the original input.
Basic Map Inscription Structure
{
"id": "t-transform",
"kind": "map",
"mode": "SINGLE",
"presets": {
"input": {
"placeId": "input-place",
"host": "myModel@localhost:8080",
"arcql": "FROM $ LIMIT 1",
"take": "FIRST",
"consume": true
}
},
"postsets": {
"output": { "placeId": "output-place", "host": "myModel@localhost:8080" }
},
"action": {
"type": "map",
"template": {
"orderId": "${input.data.orderId}",
"amount": "${input.data.amount}",
"status": "processed",
"_processedAt": "${now()}",
"_originalTokenId": "${input._meta.id}"
}
},
"emit": [
{ "to": "output", "from": "@response", "when": "status == 'processed'" }
]
}
Key differences from Pass:
kind: "map"– identifies this as a Map transitionaction.type: "map"– uses the map action handleraction.template– defines the output structure with interpolationemit.from: "@response"– emits the transformed result, not input
Template Interpolation Syntax
Templates use ${...} syntax to access input token data:
// Access user data fields
"${input.data.orderId}" // → "ORD-123"
"${input.data.amount}" // → 99.99
"${input.data.customer.name}" // → "John" (nested)
// Access token metadata
"${input._meta.id}" // → "uuid-abc-123"
"${input._meta.name}" // → "order-token-1"
"${input._meta.parentId}" // → "place-uuid"
// Static values (no interpolation)
"status": "processed" // → "processed"
"version": 2 // → 2
Routing Based on Transformed Data
Since when evaluates @response (the transformed data), you can route based on fields you add in the template:
{
"id": "t-enrich-and-route",
"kind": "map",
"action": {
"type": "map",
"template": {
"orderId": "${input.data.orderId}",
"amount": "${input.data.amount}",
"category": "${input.data.amount > 1000 ? 'premium' : 'standard'}",
"enrichedAt": "${now()}"
}
},
"emit": [
{ "to": "premium", "from": "@response", "when": "category == 'premium'" },
{ "to": "standard", "from": "@response", "when": "category == 'standard'" }
]
}
Important: The when condition checks category from @response – a field that only exists after the template transformation!
Common Map Patterns
Pattern 1: Field Restructuring
// Input: { "firstName": "John", "lastName": "Doe", "age": 30 }
"template": {
"fullName": "${input.data.firstName} ${input.data.lastName}",
"isAdult": "${input.data.age >= 18}"
}
// Output: { "fullName": "John Doe", "isAdult": true }
Pattern 2: Adding Metadata
"template": {
"data": "${input.data}",
"_processedBy": "t-transform",
"_processedAt": "${now()}",
"_sourceTokenId": "${input._meta.id}"
}
Pattern 3: Flattening Nested Data
// Input: { "order": { "id": "123", "items": [...] }, "customer": { "name": "John" } }
"template": {
"orderId": "${input.data.order.id}",
"customerName": "${input.data.customer.name}",
"itemCount": "${input.data.order.items.length}"
}
Summary
- kind: “map” – identifies the transition type
- emit.from: “@response” – emits the transformed template result
- when evaluates @response – conditions check transformed data
- Template interpolation –
${input.data.field}and${input._meta.id} - Add computed fields – categorize, enrich, restructure in the template
Map transitions are the data transformation workhorses – use them whenever you need to reshape token data before routing or processing.