Describe the bug
A postman://<collection>?env=<environment> target fetches its environment and correctly uses it for the authorized base URL, but non-URL values disappear before the collection reaches the sandbox. The staged collection retains placeholders such as {{tenantId}} and {{fixtureToken}}; their values are absent from the root task and target metadata too. The environment ID is retained, but its contents are not.
The CLI documentation describes environment support for base-URL and token variables, and the API-spec skill expects environment values to help construct valid requests. Losing those values prevents the agent from constructing the selected environment's requests without the user supplying the same data again.
To Reproduce This setup-only reproduction mocks the Postman HTTP transport with dummy values. It exercises the real environment parser, target setup, staging and root-task builder, including an enabled/disabled control and environment precedence over a collection default:
LITELLM_MODE=PRODUCTION LITELLM_LOCAL_MODEL_COST_MAP=True STRIX_TELEMETRY=0 uv run --frozen python - <<'PY'
import argparse
import json
import tempfile
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import patch
from strix.core.inputs import build_root_task
from strix.interface import scan_setup
from strix.interface.utils import stage_api_specs
from strix.utils import api_spec
collection = {
"info": {"_postman_id": "fixture", "name": "Offline fixture"},
"variable": [{"key": "baseUrl", "value": "https://default.example.test"}],
"item": [{"request": {
"method": "GET", "url": "{{baseUrl}}/tenants/{{tenantId}}",
"header": [{"key": "Authorization", "value": "Bearer {{fixtureToken}}"}],
}}],
}
environment = {"values": [
{"key": "baseUrl", "value": "https://selected.example.test"},
{"key": "tenantId", "value": "tenant-42"},
{"key": "fixtureToken", "value": "dummy-fixture-value", "enabled": True},
{"key": "disabledValue", "value": "disabled-fixture", "enabled": False},
]}
def fake_get(url, **kwargs):
payload = ({"environment": environment} if "/environments/" in url
else {"collection": collection})
return SimpleNamespace(status_code=200, json=lambda: payload)
settings = SimpleNamespace(integrations=SimpleNamespace(postman_api_key="dummy-key"))
with tempfile.TemporaryDirectory() as temporary:
with (patch("tempfile.gettempdir", return_value=temporary),
patch.object(api_spec.requests, "get", side_effect=fake_get),
patch.object(scan_setup, "load_settings", return_value=settings)):
variables = api_spec.fetch_postman_environment("fixture-env", "dummy-key")
assert "disabledValue" not in variables
args = argparse.Namespace(target=["postman://fixture-coll?env=fixture-env"], target_list=None)
scan_setup.build_targets_info(args)
sources = stage_api_specs(args.targets_info, "postman-repro")
staged = Path(sources[0]["source_path"])
contents = "\n".join(p.read_text() for p in staged.rglob("*") if p.is_file())
prompt = build_root_task({"targets": args.targets_info})
outputs = contents + json.dumps(args.targets_info) + prompt
print("base_urls:", args.targets_info[0]["details"]["base_urls"])
print("disabled variable filtered:", "disabledValue" not in variables)
print("tenant value reaches sandbox/task:", "tenant-42" in outputs)
print("token value reaches sandbox/task:", "dummy-fixture-value" in outputs)
print("tenant placeholder remains:", "{{tenantId}}" in contents)
PYActual output:
base_urls: ['https://selected.example.test']
disabled variable filtered: True
tenant value reaches sandbox/task: False
token value reaches sandbox/task: False
tenant placeholder remains: TrueExpected behavior The selected enabled environment values needed by the collection should remain usable by the agent, with environment values taking precedence over collection defaults. Disabled variables should remain excluded. The Postman API key should stay on the host.
Additional context / proposed decision
_resolve_api_spec()writes the unchanged collection;extra_variablesis passed only tospec_base_urls()and then discarded.- Environment filtering and base-URL precedence work in this reproduction. The gap is after extraction. A source search found no other consumer/channel for the fetched environment; the root-task renderer receives only the file path and base URLs.
- Please confirm the intended delivery contract: an effective collection variable map, a separate staged environment file, or explicit substitution. This needs to define how required values reach the agent without adding unused environment values or the Postman API key to its context.
- Any implementation should retain enabled-only filtering and precedence, and coordinate with #1158's existing file-protection work. This report proposes no change to that PR's scope or findings.
- I checked the open/closed inventory and #866's discussion; I did not find an existing issue or active PR for environment values being dropped after scope extraction.
System Information:
- OS: macOS 27.0.1, arm64
- Strix commit:
6b7ae2ebe4d47037a927aade23265ff4e4f27e84(currentmain) - Python: 3.12.14; frozen
uv.lockdependencies; isolated temporary HOME - LLM: none. No Docker sandbox, target scan, or live Postman request was used.
The existing tests/test_api_spec.py and tests/test_api_spec_targets.py suites pass (39 tests). These reproductions exercise setup/staging directly; they do not measure end-to-end model behavior.
Activity
0No activity yet.