JSON Transform
Examples
End-to-end JSON Transform pipelines
Examples
Worked examples that combine multiple JSON Transform operations into useful real-world pipelines.
1. Inject a System Prompt
Filter out any existing system messages and prepend a fresh one based on prompts.system_prompt.
{
"name": "prepare_messages",
"description": "Inject or override the system prompt in messages array",
"function": "circuit.core.transform.json",
"input": {
"source": "${{ messages }}",
"operations": [
{ "type": "filter", "options": { "expression": "role != `system`" } },
{
"type": "unshift",
"options": {
"items": [
{ "role": "system", "content": "${{ prompts.system_prompt }}" }
]
}
}
]
},
"outputs": [
{
"name": "prepared_messages",
"description": "Messages array with system prompt injected",
"value": "${{ prepare_messages.output.transformed_result }}"
}
]
}Given memory:
{
"prompts": { "system_prompt": "You are a helpful assistant." },
"messages": [
{ "role": "system", "content": "Stale system prompt" },
{ "role": "user", "content": "Hello!" }
]
}transformed_result becomes:
[
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": "Hello!" }
]2. Top-N Filter → Sort → Slice → Pick
A typical "top 10 active items, projected to a small payload" pipeline.
{
"name": "process_items",
"description": "Active items, top 10 by priority, projected fields only",
"function": "circuit.core.transform.json",
"input": {
"source": "${{ raw_items }}",
"operations": [
{ "type": "filter", "options": { "expression": "status == `active`" } },
{ "type": "sort", "options": { "key": "priority", "order": "desc" } },
{ "type": "slice", "options": { "start": 0, "end": 10 } },
{ "type": "map", "options": { "expression": "{ id: id, name: name, priority: priority }" } }
]
},
"outputs": [
{
"name": "top_items",
"description": "Top 10 active items projected to id/name/priority",
"value": "${{ process_items.output.transformed_result }}"
}
]
}Tips
filteronly supports==/!=. If you needpriority > 5, do it in amap/JMESPath stage or upstream.sliceworks in array index space, so{ "start": 0, "end": 10 }returns at most 10 items.- The
mapstage projects each element using JMESPath multi-select — equivalent topickbut element-level.
3. Merge Defaults + Project Fields
Normalise a config object by merging request-level overrides on top of environment defaults, then keeping only the fields the caller cares about.
{
"name": "normalize_config",
"description": "Merge per-request overrides on top of defaults",
"function": "circuit.core.transform.json",
"input": {
"source": "${{ secrets.default_config }}",
"operations": [
{ "type": "merge", "options": { "objects": ["${{ input.overrides }}"] } },
{ "type": "pick", "options": { "keys": ["model", "temperature", "max_tokens"] } }
]
},
"outputs": [
{
"name": "config",
"description": "Final, normalized model config",
"value": "${{ normalize_config.output.transformed_result }}"
}
]
}Given:
{
"env": {
"default_config": {
"model": "gpt-4o-mini",
"temperature": 0.2,
"max_tokens": 1024,
"top_p": 1,
"internal_flag": true
}
},
"input": {
"overrides": { "temperature": 0.7, "max_tokens": 256 }
}
}transformed_result becomes:
{ "model": "gpt-4o-mini", "temperature": 0.7, "max_tokens": 256 }merge is a deep merge: nested objects on the right are recursively merged into the left, scalar values overwrite, and arrays are replaced wholesale.