ModelWorks logoModelWorks
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.

JSON
{
  "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:

JSON
{
  "prompts": { "system_prompt": "You are a helpful assistant." },
  "messages": [
    { "role": "system", "content": "Stale system prompt" },
    { "role": "user",   "content": "Hello!" }
  ]
}

transformed_result becomes:

JSON
[
  { "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.

JSON
{
  "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

  • filter only supports == / !=. If you need priority > 5, do it in a map/JMESPath stage or upstream.
  • slice works in array index space, so { "start": 0, "end": 10 } returns at most 10 items.
  • The map stage projects each element using JMESPath multi-select — equivalent to pick but 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.

JSON
{
  "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:

JSON
{
  "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:

JSON
{ "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.

On this page

On this page