Buzz stores the OpenAI key as OPENAI_COMPAT_API_KEY (buzz-agent's env contract, reused as the one secret field for every runtime).
goose's openai provider reads OPENAI_API_KEY.
Nothing translates between them, so the goose child starts with no credential it recognizes.
Readiness hides it: readiness::goose_requirements checks for OPENAI_COMPAT_API_KEY - the key Buzz itself wrote - so the agent shows as Ready with the key set, and the only symptom is a 401 at turn time.
Evidence
A live goose child spawned by Buzz:
$ ps eww <pid>
GOOSE_PROVIDER=openai GOOSE_MODEL=gpt-5.6-sol
OPENAI_COMPAT_API_KEY=… # present
OPENAI_API_KEY # absent
And outside Buzz, with the same key:
OPENAI_COMPAT_API_KEY=<key> goose run -t "say ok" # 401
OPENAI_API_KEY=<key> goose run -t "say ok" # ok
Affects
Any goose agent configured through Buzz with provider openai.
Users who stored the key via goose configure (system keychain) are unaffected, since goose falls back to the keyring.
The obvious workaround - typing OPENAI_API_KEY into the env-vars editor - is blocked: the config dialogs still demand the canonical name, so Save stays disabled.
Proposed fix
Export the canonical value under OPENAI_API_KEY too when a goose child's effective provider is openai and the agent has no native key of its own.
Write it after the layered user env, and emit nothing when the user set OPENAI_API_KEY themselves, so an explicit value is never clobbered.
Resolve the provider the way the child does - layered env, then the structured field, then the inherited process env, then goose's config.yaml - since a later env layer can override GOOSE_PROVIDER in either direction.
Not covered by that fix
openai-compat stays broken for goose: it has no such provider, and reaches compatible endpoints via openai plus OPENAI_HOST / OPENAI_BASE_PATH. That needs Buzz's single OPENAI_COMPAT_BASE_URL split into an origin and a path, including a decision about URLs that already carry a version suffix.
- Accepting a user-typed
OPENAI_API_KEY needs readiness and the dialogs changed together: requiredCredentialEnvKeys plus its four consumers, and getGlobalAgentCredentialState, which derives apiKeyMissing from the canonical key directly rather than from the required-keys list.
- The same class of bug exists wherever a harness's native env name differs from Buzz's canonical one. A per-runtime alias table is the durable shape.
Buzz stores the OpenAI key as
OPENAI_COMPAT_API_KEY(buzz-agent's env contract, reused as the one secret field for every runtime).goose's openai provider reads
OPENAI_API_KEY.Nothing translates between them, so the goose child starts with no credential it recognizes.
Readiness hides it:
readiness::goose_requirementschecks forOPENAI_COMPAT_API_KEY- the key Buzz itself wrote - so the agent shows as Ready with the key set, and the only symptom is a 401 at turn time.Evidence
A live goose child spawned by Buzz:
And outside Buzz, with the same key:
Affects
Any goose agent configured through Buzz with provider
openai.Users who stored the key via
goose configure(system keychain) are unaffected, since goose falls back to the keyring.The obvious workaround - typing
OPENAI_API_KEYinto the env-vars editor - is blocked: the config dialogs still demand the canonical name, so Save stays disabled.Proposed fix
Export the canonical value under
OPENAI_API_KEYtoo when a goose child's effective provider isopenaiand the agent has no native key of its own.Write it after the layered user env, and emit nothing when the user set
OPENAI_API_KEYthemselves, so an explicit value is never clobbered.Resolve the provider the way the child does - layered env, then the structured field, then the inherited process env, then goose's
config.yaml- since a later env layer can overrideGOOSE_PROVIDERin either direction.Not covered by that fix
openai-compatstays broken for goose: it has no such provider, and reaches compatible endpoints viaopenaiplusOPENAI_HOST/OPENAI_BASE_PATH. That needs Buzz's singleOPENAI_COMPAT_BASE_URLsplit into an origin and a path, including a decision about URLs that already carry a version suffix.OPENAI_API_KEYneeds readiness and the dialogs changed together:requiredCredentialEnvKeysplus its four consumers, andgetGlobalAgentCredentialState, which derivesapiKeyMissingfrom the canonical key directly rather than from the required-keys list.