Skip to content

In-process (FFI) transport: options lowered to env vars (auth token, COPILOT_HOME, keytar, telemetry) are not honored in-process #1934

Description

@SteveSandersonMS

Summary

Several CopilotClientOptions are implemented by lowering them to environment variables set on the spawned CLI child process. With the new in-process (FFI) transport (RuntimeConnection.ForInProcess() / Transport::InProcess / forInProcess()), there is no child process the SDK controls the environment of for these values, so these options are not honored in-process. This affects all SDKs adding the in-process transport (.NET already merged; TypeScript and Rust in progress on stevesa/ffi-inproc-rust-ts).

This issue tracks the gap and the fact that the current workaround is to set the corresponding environment variable on the host/parent process yourself before constructing the client.

Why it happens

For stdio/TCP, the SDK spawns a child process and populates startInfo.Environment (or the equivalent), so per-client values are coherent — each client owns its own OS process.

For in-process, the native runtime cdylib is loaded into the shared host process, and host-side native reads consult the ambient host process environment, not a per-client env block. .NET's ValidateEnvironmentOptions therefore rejects Environment/Telemetry for in-process, and the in-process start path passes an effectively empty env to host_start — so the remaining env-lowered options are simply never applied.

Complete list of options lowered to env vars (from dotnet/src/Client.cs)

Option Env var(s) In-process behavior today
Environment (replaces whole env block) Rejected (throws)
Telemetry COPILOT_OTEL_ENABLED, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL, COPILOT_OTEL_FILE_EXPORTER_PATH, COPILOT_OTEL_EXPORTER_TYPE, COPILOT_OTEL_SOURCE_NAME, OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT Rejected (throws)
GitHubToken COPILOT_SDK_AUTH_TOKEN (+ --auth-token-env CLI arg) Silently ignored
BaseDirectory COPILOT_HOME Silently ignored
Mode == Empty COPILOT_DISABLE_KEYTAR=1 Silently ignored
ConnectionToken (TCP only) COPILOT_CONNECTION_TOKEN N/A (no TCP in-process)

Note: UseLoggedInUser, SessionIdleTimeoutSeconds, EnableRemoteSessions, LogLevel are lowered to CLI args (--no-auto-login, --session-idle-timeout, --remote, --log-level), not env vars — but the FFI host_start argv is [entrypoint, --embedded-host] and does not forward these either, so they are a related (separate) in-process gap worth confirming.

Current workaround

Set the environment variable on the host/parent process before creating the client, e.g.:

  • Auth: export COPILOT_SDK_AUTH_TOKEN (or ensure ambient GH_TOKEN/GITHUB_TOKEN are valid) instead of GitHubToken.
  • Home: export COPILOT_HOME instead of BaseDirectory.
  • Keytar: export COPILOT_DISABLE_KEYTAR=1 instead of relying on Mode = Empty.
  • Telemetry: export the COPILOT_OTEL_* / OTEL_* vars instead of Telemetry.

Proper long-term fix

These should all become first-class server-level options, not reliant on being passed as env vars. The runtime code can continue to look for env vars as an override for back-compat.

Acceptance / follow-ups

  • Decide, cross-SDK, whether each env-lowered option should be honored-for-worker, rejected, or documented-as-unsupported in-process (currently inconsistent: Environment/Telemetry throw; GitHubToken/BaseDirectory/keytar silently no-op).
  • Runtime: consume host_start env_json in host-side reads so per-client env is coherent in-process.
  • Confirm CLI-arg-lowered options (UseLoggedInUser, idle timeout, remote, log level) in-process.

Refs: dotnet/src/Client.cs ValidateEnvironmentOptions (~L215), in-process start (~L339-353), child-process env block (~L2079-2105), ApplyTelemetryEnvironment (~L1971), auth arg (~L2029). Related PRs: #1901, #1920, #1929, #1930.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions