OpenHands/agent-canvas

ACP auth banner is a host-only signal — inaccurate on Docker/cloud backends

Open

#1,244 opened on Jun 8, 2026

View on GitHub
 (3 comments) (0 reactions) (0 assignees)TypeScript (26 forks)github user discovery
good first issue

Repository metrics

Stars
 (43 stars)
PR merge metrics
 (PR metrics pending)

Description

Summary

The ACP "already signed in to {provider}" auth banner — shown in onboarding (setup-acp-secrets-step) and now in Settings → Agent → Credentials (added in #1102 via the shared AcpAuthStatusBanner) — only reflects auth correctly on a native local backend. On a Docker (containerized) backend it almost never shows for Claude/Codex even when the conversation is fully authenticated, and on cloud it never runs. The banner is currently a host-only signal, not a true "will the agent authenticate" signal.

Root cause

The banner is driven by useAcpAuthStatusAcpService.getAuthStatus (src/api/acp-service/acp-service.api.ts), which detects login by shelling the provider's interactive CLI through the agent-server bash endpoint:

  • claude-code → claude auth status --json
  • codex → codex login status
  • gemini-cli → test -f "$HOME/.gemini/oauth_creds.json"

These commands run wherever the agent-server runs. That's fine on a native local backend (the user's machine has claude/codex + their login), but:

  • The agent-server container ships only the ACP wrappers (claude-agent-acp, codex-acp) — not the interactive claude/codex CLIs — so the probe commands hit "command not found" and classify as unknown → banner renders nothing.
  • The agent actually authenticates via the materialized secret (Claude CLAUDE_CODE_OAUTH_TOKEN env, Codex CODEX_AUTH_JSONauth.json, Gemini Vertex SA) seeded at conversation start through the ACP wrappers — which the probe never inspects.
  • On cloud, the probe is gated off entirely (isSupported = backend.kind === "local"), so status is always unknown.

Net: unknown ≠ "logged out" — it means "couldn't tell" — and in a container/cloud it's the default, so the banner is silent even when credentials are correctly configured.

Evidence (verified locally)

Provider Native backend (probes the host) Docker backend (probes inside the container)
claude-code {"loggedIn": true, "authMethod":"claude.ai"}authenticated (banner shows) claude: not found → not JSON → unknown (no banner)
codex Logged in using ChatGPTauthenticated (banner shows) codex: not foundunknown (no banner)
gemini-cli checks ~/.gemini/oauth_creds.json on host gemini present but creds file absent in fresh container → unauthenticated (no banner)

Container CLI inventory: claude-agent-acp, codex-acp, gemini are present; claude and codex are not.

Proposed improvements (pick one / combine)

  1. Make detection container/cloud-aware. Instead of (only) shelling claude/codex, detect auth from what the agent actually uses: the materialized credential files (e.g. Codex auth.json under the relocated CODEX_HOME, the Gemini Vertex SA JSON) and/or the relevant env-var/secret being set. This makes the signal meaningful in a container.
  2. Distinguish "credentials configured" from "signed in (host login)." When a provider secret exists for the active backend, show a "credentials configured" state even if no host login is detected. (The fields already render an alreadySet per-field marker — a section-level summary banner could build on that.)
  3. At minimum, scope it honestly. Treat the host-login banner as a native-backend nicety and don't imply anything on Docker/cloud (current behavior), but document that and lean on the per-field alreadySet markers there.

Acceptance criteria

  • On a Docker/cloud backend with a provider credential configured, the Credentials section conveys an accurate auth/credentials state (not a misleading silence).
  • No false "signed in" on a backend where we can't actually tell.
  • Onboarding and Settings → Agent stay consistent (they share AcpAuthStatusBanner).

References

  • Banner component: src/components/features/settings/acp-auth-status-banner.tsx
  • Probe: src/api/acp-service/acp-service.api.ts, src/hooks/query/use-acp-auth-status.ts
  • Surfaces: src/components/features/onboarding/steps/setup-acp-secrets-step.tsx, src/components/features/settings/acp-credentials-section.tsx
  • Introduced alongside #1102 (containerized + cloud ACP) and the cloud ACP epic #988

Contributor guide