Skip to content

Claude-only deployments still log into GitHub Copilot and poll it for tokens #489

Description

@pjdoland

Summary

A deployment using Claude mode still logs into GitHub Copilot at startup, stores and refreshes a Copilot token, and runs a background thread that polls api.github.com for the life of the server. Nothing in Claude mode will ever use that token. Reported by a user running Claude only:

WARNING - Storing the GitHub Copilot token under the default NBI_GH_ACCESS_TOKEN_PASSWORD. Set a per-user password in multi-tenant deployments.
INFO - Using existing GitHub access token
INFO - Refreshing GitHub token

Cause

The Copilot login is gated on using_github_copilot_service (notebook_intelligence/config.py:143-145):

def using_github_copilot_service(self) -> bool:
    return self.chat_model.get("provider") == 'github-copilot' or \
        self.inline_completion_model.get("provider") == 'github-copilot'

That reads the configured provider fields and nothing else. It does not ask whether an agent mode is active, and in Claude mode neither field necessarily describes what serves a request:

  • Chat is served by the Claude participant, not chat_model (ai_service_manager.py:199-204).
  • Inline completion is served by Claude unless claude_settings.inline_completion_model is inherit (ai_service_manager.py:202-233). When it is none or a Claude model id, the general inline model is discarded outright.

Both fields default to github-copilot (config.py:219, config.py:226), so a user who enables Claude mode without touching the General tab, which is the ordinary path, satisfies the gate on defaults alone.

The ordering makes it unconditional: update_models_from_config calls login_with_existing_credentials at ai_service_manager.py:169-171, before the is_claude_code_mode branch at :202 decides the Copilot inline model is not wanted.

Impact

More than log noise:

  • wait_for_tokens starts get_token_thread_func (github_copilot.py:630-645), a loop that lives for the server's lifetime and refreshes the token via GET {GH_REST_API_BASE_URL}/copilot_internal/v2/token (github_copilot.py:446) every TOKEN_FETCH_INTERVAL.
  • An egress-restricted or air-gapped deployment running Claude only makes recurring calls to GitHub that its policy forbids and its operators did not ask for. PRIVACY.md lists api.github.com under Copilot, which reads as conditional on using Copilot.
  • The multi-tenant warning about NBI_GH_ACCESS_TOKEN_PASSWORD fires in deployments that never use Copilot, so an admin is told to set a password for a service they do not run.
  • A stored Copilot token is read and kept refreshed rather than left alone.

Suggested fix

Decide the gate from what will actually serve a request, not from the configured provider fields alone. In Claude mode that means Copilot is needed only when claude_settings.inline_completion_model == 'inherit' and the general inline model is Copilot; in ACP mode the same question applies to whatever that mode leaves to the native path.

The check lives on NBIConfig, which knows claude_settings and acp_settings already, so it can answer this without new plumbing. Worth confirming against the inline-completion inherit path rather than special-casing "an agent mode is on", which would break the user who deliberately runs Claude chat with Copilot autocomplete.

Also in the report, separately

The same log carries a CanUseToolShadowedWarning from claude_agent_sdk about can_use_tool not being invoked for the twelve mcp__nbi__ tools. That one is not a bug: NBI allowlists its own Jupyter UI tools on purpose (claude.py:2976-2978) so Claude does not ask permission for each cell edit, and the permission handler has no branch for those tools that the allowlist makes unreachable. It is new warning output from an unpinned claude-agent-sdk (pyproject.toml:67), and it will confuse anyone reading these logs. Worth suppressing that specific warning, or narrowing the entries, so it does not read as a permission bypass.

Environment

NBI main at 6333cd6. Reported against a Claude-only deployment on Windows.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions