fix(pi): use api-proxy Docker service hostname for LLM gateway routing to enable /reflect access#30045
Conversation
…pilot Agent-Logs-Url: https://github.com/github/gh-aw/sessions/5f990e7a-a34d-4cdf-bf2d-7b57564c37cb Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
… /reflect access The Pi engine was constructing models.json with `baseUrl: "http://host.docker.internal:PORT"`, which bypasses the api-proxy Docker container entirely. As a result, the api-proxy was never an active participant in the Docker network from Pi's perspective, making its management endpoint (api-proxy:10000/reflect) unreachable from the agent container. Fix buildPiModelsJSON to use constants.AWFAPIProxyContainerIP (172.30.0.30) via net.JoinHostPort, matching the pattern used by the Codex engine (codex_mcp.go). This routes Pi's LLM traffic through the api-proxy sidecar on the AWF Docker network, which initialises the proxy and makes /reflect respond. Also update resolveGatewayUrl in pi_provider.cjs (used for diagnostic logging) to use the same api-proxy container IP for accuracy. Add TestBuildPiModelsJSON_UsesAPIProxyContainerIP to assert the fix. Agent-Logs-Url: https://github.com/github/gh-aw/sessions/f07dcb97-a7b7-41f0-aeee-3837a13bb6d3 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…ngine test Agent-Logs-Url: https://github.com/github/gh-aw/sessions/f07dcb97-a7b7-41f0-aeee-3837a13bb6d3 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot merge main and recompile |
There was a problem hiding this comment.
Pull request overview
Updates Pi engine gateway routing so LLM traffic goes through the AWF api-proxy sidecar (via its fixed container IP) instead of bypassing it via host.docker.internal, enabling /reflect access from the agent container.
Changes:
- Switch Pi’s generated
models.jsonbaseUrltohttp://<AWF api-proxy container IP>:<gatewayPort>. - Add a unit test asserting Pi models JSON uses the api-proxy container IP and not
host.docker.internal. - Update Pi JS provider logging to resolve gateway URLs using the same container IP; recompile workflow lockfiles to embed updated
models.jsonpayloads.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/pi_engine.go | Build Pi models.json with constants.AWFAPIProxyContainerIP via net.JoinHostPort for gateway routing through api-proxy. |
| pkg/workflow/pi_engine_test.go | Add test coverage ensuring generated baseUrl uses api-proxy container IP (and not host.docker.internal). |
| actions/setup/js/pi_provider.cjs | Align diagnostic gateway URL resolution with api-proxy container IP (for accurate logging). |
| .github/workflows/workflow-skill-extractor.lock.yml | Recompiled lock output; updates embedded models.json payload and tool allowlist entries. |
| .github/workflows/ubuntu-image-analyzer.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/spec-librarian.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/spec-extractor.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/smoke-pi.lock.yml | Recompiled lock output; updates embedded models.json baseUrl to api-proxy container IP. |
| .github/workflows/layout-spec-maintainer.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/discussion-task-miner.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/dev.lock.yml | Recompiled lock output; updates embedded models.json baseUrl to api-proxy container IP. |
| .github/workflows/delight.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/daily-testify-uber-super-expert.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/daily-safe-output-integrator.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/daily-mcp-concurrency-analysis.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/daily-file-diet.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/daily-compiler-quality.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/copilot-cli-deep-research.lock.yml | Recompiled lock output (tool allowlist entry changes). |
| .github/workflows/ab-testing-advisor.lock.yml | Recompiled lock output (tool allowlist entry changes). |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 19/19 changed files
- Comments generated: 3
| // Fixed IP of the AWF api-proxy sidecar container within the AWF Docker network. | ||
| // Matches constants.AWFAPIProxyContainerIP on the Go side. | ||
| const AWF_API_PROXY_CONTAINER_IP = "172.30.0.30"; |
| # shellcheck disable=SC1003 | ||
| sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ | ||
| -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool '\''shell(cat *)'\'' --allow-tool '\''shell(cat > /tmp/gh-aw/agent/*.py)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find .github/workflows -name '\''\'\'''\''*.md'\''\'\'''\'')'\'' --allow-tool '\''shell(grep -r '\''\'\'''\''*'\''\'\'''\'' .github/workflows)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(ls *)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(python3 *)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc *)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log | ||
| -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool '\''shell(cat *)'\'' --allow-tool '\''shell(cat > /tmp/gh-aw/agent/*.py)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find .github/workflows -name)'\'' --allow-tool '\''shell(grep -r)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(ls *)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(python3 *)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc *)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log |
| # shellcheck disable=SC1003 | ||
| sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ | ||
| -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool serena --allow-tool '\''shell(cat pkg/**/*.go)'\'' --allow-tool '\''shell(cat pkg/*/*.go)'\'' --allow-tool '\''shell(cat pkg/*/README.md)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find pkg -maxdepth 1 -type d)'\'' --allow-tool '\''shell(find pkg -name '\''\'\'''\''*.go'\''\'\'''\'' ! -name '\''\'\'''\''*_test.go'\''\'\'''\'' -type f)'\'' --allow-tool '\''shell(find pkg -name '\''\'\'''\''README.md'\''\'\'''\'' -type f)'\'' --allow-tool '\''shell(find pkg -type f -name '\''\'\'''\''*.go'\''\'\'''\'' ! -name '\''\'\'''\''*_test.go'\''\'\'''\'')'\'' --allow-tool '\''shell(find pkg/ -maxdepth 1 -ls)'\'' --allow-tool '\''shell(find pkg/* -maxdepth 0 -type d)'\'' --allow-tool '\''shell(find pkg/workflow/ -maxdepth 1 -ls)'\'' --allow-tool '\''shell(git log --oneline --since='\''\'\'''\''30 days ago'\''\'\'''\'' -- pkg/*)'\'' --allow-tool '\''shell(git log --oneline --since='\''\'\'''\''7 days ago'\''\'\'''\'' -- pkg/*/README.md)'\'' --allow-tool '\''shell(git log -1 --format=%H -- pkg/*)'\'' --allow-tool '\''shell(grep -r '\''\'\'''\''func '\''\'\'''\'' pkg --include='\''\'\'''\''*.go'\''\'\'''\'')'\'' --allow-tool '\''shell(grep -rn '\''\'\'''\''const [A-Z]'\''\'\'''\'' pkg --include='\''\'\'''\''*.go'\''\'\'''\'')'\'' --allow-tool '\''shell(grep -rn '\''\'\'''\''func [A-Z]'\''\'\'''\'' pkg --include='\''\'\'''\''*.go'\''\'\'''\'')'\'' --allow-tool '\''shell(grep -rn '\''\'\'''\''import '\''\'\'''\'' pkg --include='\''\'\'''\''*.go'\''\'\'''\'')'\'' --allow-tool '\''shell(grep -rn '\''\'\'''\''package '\''\'\'''\'' pkg --include='\''\'\'''\''*.go'\''\'\'''\'')'\'' --allow-tool '\''shell(grep -rn '\''\'\'''\''type [A-Z]'\''\'\'''\'' pkg --include='\''\'\'''\''*.go'\''\'\'''\'')'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head -n * pkg/**/*.go)'\'' --allow-tool '\''shell(head -n * pkg/*/*.go)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(serena:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc -l pkg/**/*.go)'\'' --allow-tool '\''shell(wc -l pkg/*/*.go)'\'' --allow-tool '\''shell(wc -l pkg/*/README.md)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log | ||
| -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool serena --allow-tool '\''shell(cat pkg/**/*.go)'\'' --allow-tool '\''shell(cat pkg/*/*.go)'\'' --allow-tool '\''shell(cat pkg/*/README.md)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find pkg -maxdepth 1 -type d)'\'' --allow-tool '\''shell(find pkg -name)'\'' --allow-tool '\''shell(find pkg -type f -name)'\'' --allow-tool '\''shell(find pkg/ -maxdepth 1 -ls)'\'' --allow-tool '\''shell(find pkg/* -maxdepth 0 -type d)'\'' --allow-tool '\''shell(find pkg/workflow/ -maxdepth 1 -ls)'\'' --allow-tool '\''shell(git log --oneline --since=)'\'' --allow-tool '\''shell(git log -1 --format=%H -- pkg/*)'\'' --allow-tool '\''shell(grep -r)'\'' --allow-tool '\''shell(grep -rn)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head -n * pkg/**/*.go)'\'' --allow-tool '\''shell(head -n * pkg/*/*.go)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(serena:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc -l pkg/**/*.go)'\'' --allow-tool '\''shell(wc -l pkg/*/*.go)'\'' --allow-tool '\''shell(wc -l pkg/*/README.md)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log |
|
@copilot merge main and recompile |
…lags-dev-smoke-copilot # Conflicts: # .github/workflows/dev.lock.yml # .github/workflows/smoke-pi.lock.yml # actions/setup/js/pi_provider.cjs # pkg/workflow/pi_engine.go # pkg/workflow/pi_engine_test.go Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in e05ccc1. Merged origin/main and recompiled — 210/210 workflows updated. Lock files now use Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
The branch is already up to date with main — the merge was done in |
|
✅ Dev completed successfully! |
|
@lpcox Why would the reflect endpoint not be enabled? |
|
The The issue was that Pi routed LLM traffic through This PR correctly fixes it by routing through the |
Summary
The Pi engine's
buildPiModelsJSONwas constructing the LLM gatewaybaseUrlashttp://host.docker.internal:PORT. This routes Pi's inference traffic to the host machine's port, bypassing theapi-proxyDocker container's network interface entirely.As a result, the api-proxy was never an active participant in the AWF Docker network when Pi ran. Its management endpoint (
api-proxy:10000/reflect) was therefore unreachable from the agent container — explaining whydev(Pi engine) could not access/reflectwhilesmoke-copilot(Copilot engine, which routes through the api-proxy transparently via Squid) could.Root cause
http://host.docker.internal:10002(host-side, bypasses api-proxy)api-proxy:10000/reflectreachable?Fix
Change
buildPiModelsJSONto use theapi-proxyDocker service hostname (http://api-proxy:PORT). This routes Pi's LLM traffic through the api-proxy sidecar on the AWF Docker network, which initializes the proxy and makes/reflectrespond. Using the service hostname is cleaner than a hardcoded IP and is consistent with how other containers reference each other within the AWF Docker network.Also update the diagnostic logging helper
resolveGatewayUrlinpi_provider.cjsto use the sameapi-proxyhostname for accuracy.Changes
pkg/workflow/pi_engine.go:buildPiModelsJSON—host.docker.internal:PORT→http://api-proxy:PORTpkg/workflow/pi_engine_test.go: Add firewall execution step tests (TestPiEngine_GetExecutionSteps_FirewallCopilotProvider,TestPiEngine_GetExecutionSteps_FirewallAnthropicProvider,TestPiEngine_GetExecutionSteps_FirewallCodexProvider) assertingapi-proxy:is used andhost.docker.internalis absentactions/setup/js/pi_provider.cjs:resolveGatewayUrllogging —host.docker.internal:PORT→http://api-proxy:PORT*.lock.yml: Recompiled — models.json base64 payload updated with newbaseUrlVerification