```python:inference/core/workflows/core_steps/composition/workflow_caller/v1.py
from typing import List, Optional, Tuple

WORKFLOW_CALLER_BLOCK_TYPE = "roboflow_core/workflow_caller@v1"


def _extract_workflow_caller_ids_from_spec(
    spec: dict,
) -> List[Tuple[str, Optional[str]]]:
    """Extract static (workflow_id, workflow_version_id) tuples from a raw
    workflow specification.  Only includes entries where ``workflow_id`` is a
    literal string (not a selector).  ``workflow_version_id`` is included when
    it is a literal string, otherwise ``None``."""
    steps = spec.get("steps", [])
    result: List[Tuple[str, Optional[str]]] = []
    # Localize the frequently-used constant to reduce global lookup overhead.
    block_type = WORKFLOW_CALLER_BLOCK_TYPE
    for step in steps:
        step_type = step.get("type", "")
        if step_type != block_type:
            continue
        workflow_id = step.get("workflow_id", "")
        # Preserve original semantics: require a str and skip if it starts with "$".
        # Use a first-character check which is slightly faster than startswith.
        if not isinstance(workflow_id, str) or (workflow_id and workflow_id[0] == "$"):
            continue
        version_id = step.get("workflow_version_id")
        # If version_id is a string that starts with "$", treat it as None.
        if isinstance(version_id, str) and version_id and version_id[0] == "$":
            version_id = None
        result.append((workflow_id, version_id))
    return result
```