Forcing string cast in service?

I’m banging my head against an issue where a string is sent as a number in a service send sequence step.

This is puzzling because the output I see in the template editor differs from what is produced as data payloads in the script trace, e.g. a string is converted to a number for a template structure like

{% set id = '1' %}
sequence:
    - service: domain.service
      target:
        entity_id: id
      data:
        command: command
        params:
          list:
            - some_id: "{{ id }}"

When running the script I end up with the following in the trace

params:
  service_data:
    params:
      list:
        some_id: 1

Where I expect, which also is what the template editor produces.

params:
  service_data:
    params:
      list:
        some_id: '1'

When hardcoding the id, e.g.

sequence:
    - service: domain.service
      target:
        entity_id: id
      data:
        command: command
        params:
          list:
            - some_id: "1"

the trace output has the string for some_id as expected. Any ideas what I might be running into here?

Full context

I want to automate a robot vacuum to cycle through rooms to clean in first based on the clean counts in the last 48 hours.

I’ve gone with a design where I keep a counter for each room. Each counter gets incremented for every clean start that targets that room. An automation resets all counters every 48 hours. Selection of rooms works by keeping the room list and sorting it by the clean count.

When running the automation below I can see the notification with a list of expected rooms just fine, the problem is that sequece[1].data.params.regions[0].region_id winds up to be 1 (a number) instead of '1' (a string) according to the trace.

Any

alias: Clean least recently cleaned
sequence:
  - device_id: [redacted]
    domain: mobile_app
    type: notify
    message: "Rooms: {{ regions[:3] | map(attribute='name') | join(', ') }} "
    title: Cleaning
  - service: vacuum.send_command
    target:
      entity_id: vacuum.robot
    data:
      command: start
      params:
        pmap_id: [redacted]
        regions:
          - params: null # omitted 
            region_id: "{{ regions[0].region }}"
            type: rid
        user_pmapv_id: [redacted]
mode: single
variables:
  regions: |
    {% set regions = [
        { 'id': 'a', 'name': 'A', 'region': '1',  'count': states('counter.a_clean_count') | int },
        { 'id': 'b', 'name': 'B', 'region': '2',  'count': states('counter.b_clean_count') | int },
        { 'id': 'c', 'name': 'C', 'region': '3',  'count': states('counter.c_clean_count') | int }
 ] | sort(attribute='count') %} {{ regions }}

Template editor results are interpreted. This has confused a lot of people.