Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Deprecate Gemini engine in favor of experimental Agy
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
  • Loading branch information
pelikhan and Copilot committed Oct 8, 2026
commit b21198bd6050150515e443aeb9cfdca58892424c
5 changes: 5 additions & 0 deletions .changeset/deprecate-gemini-engine.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions docs/adr/34693-add-antigravity-engine-deprecate-gemini.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Native API-key authentication passed on a clean Actions runner in
including real fresh-challenge inference, missing/invalid keys, an unknown
model and controlled endpoint routing. That evidence does not prove AWF or MCP.

Release of Agy and Gemini soft deprecation together requires bounded production
Stable promotion of Agy requires bounded production
conformance through the actual installer, Gemini AWF endpoint, native MCP,
CLI-mounted MCP and staged safe outputs. The manual
`engine-conformance-agy.md` workflow prepares that gate and remains dispatch-only.
Expand All @@ -99,8 +99,10 @@ Both checkers require the exact staged noop receipt. The Gemini-key-only gate
disables the unrelated Copilot threat-detection job directly in each entry point;
its native/shared checks and execution budgets remain mandatory.
Production conformance
has not passed; no Gemini deprecation notice or release changeset is enabled by
this implementation checkpoint.
has not passed. Gemini soft deprecation is now enabled by explicit maintainer
direction, independently of Agy's stable-promotion gate. The informational notice
and release changeset do not claim production conformance or feature equivalence;
Agy remains experimental and Gemini remains supported.

## Consequences

Expand Down
5 changes: 3 additions & 2 deletions docs/src/content/docs/engines/agy.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,9 @@ authentication/model cases. `engine-conformance-agy.md` separately exercises the
production installer, AWF, native MCP, CLI-mounted MCP tools and staged safe
outputs. It remains dispatch-only; Credentials Check calls the feature-branch
`agy-conformance-reusable.lock.yml`, compiled from the same shared probes and
prompt. Release and Gemini deprecation are gated on that production path, not
on mocked tests or native authentication alone.
prompt. Stable promotion is gated on that production path, not on mocked tests
or native authentication alone. Gemini is deprecated in favor of experimental
Agy, but remains supported for workflows outside Agy's capabilities.

Both checkers require the exact staged noop receipt, not an empty output file.
The Agy gate explicitly disables the separate Copilot threat-detection job;
Expand Down
9 changes: 8 additions & 1 deletion docs/src/content/docs/engines/gemini.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
---
title: Using Gemini CLI with GitHub Agentic Workflows
description: Select and authenticate Google Gemini CLI as the AI engine for GitHub Agentic Workflows, understand its capabilities and limitations, and start from an example.
description: Maintain workflows using the deprecated Google Gemini CLI engine and evaluate migration to the experimental Agy engine.
---

[Google Gemini CLI](https://geminicli.com/) is a coding agent from Google. GitHub Agentic Workflows runs Gemini CLI in GitHub Actions, adding GitHub event triggers, sandbox controls, and safe outputs for constrained, reviewable automation.

> [!WARNING]
> The `gemini` engine is deprecated in favor of the experimental [`agy` engine](/gh-aw/engines/agy/).
> Existing Gemini workflows remain supported, with no automatic migration or removal date.
> For API-key workflows, review [Agy's migration guidance](/gh-aw/engines/agy/#evaluating-a-gemini-api-key-workflow)
> before changing engines. Keep `engine: gemini` for Google WIF or features Agy does not support,
> including native bash restrictions.

## Selecting Gemini CLI as the AI engine

To select Gemini CLI as the AI engine, with inference hosted and billed through a Google subscription, add this to the workflow frontmatter:
Expand Down
8 changes: 5 additions & 3 deletions docs/src/content/docs/reference/engines.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ Set `engine:` in workflow frontmatter and configure the corresponding authentica
| [GitHub Copilot CLI](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/use-copilot-cli) (default) | `copilot` | [`copilot-requests: write`](/gh-aw/reference/auth/#copilot-requests-write-permission) or [`COPILOT_GITHUB_TOKEN`](/gh-aw/reference/auth/#copilot_github_token) | [Using GitHub Copilot with GitHub Agentic Workflows](/gh-aw/engines/copilot/) |
| [Claude Code](https://www.anthropic.com/index/claude) | `claude` | [`ANTHROPIC_API_KEY`](/gh-aw/reference/auth/#anthropic_api_key) or [Anthropic WIF](/gh-aw/reference/auth/#anthropic-workload-identity-federation-wif) | [Using Claude Code with GitHub Agentic Workflows](/gh-aw/engines/claude/) |
| [OpenAI Codex](https://openai.com/blog/openai-codex) | `codex` | `CODEX_API_KEY` or [`OPENAI_API_KEY`](/gh-aw/reference/auth/#openai_api_key) | [Using OpenAI Codex with GitHub Agentic Workflows](/gh-aw/engines/codex/) |
| [Google Gemini CLI](https://github.com/google-gemini/gemini-cli) | `gemini` | [`GEMINI_API_KEY`](/gh-aw/reference/auth/#gemini_api_key) or [Google WIF](/gh-aw/reference/auth/#google-workload-identity-federation-wif) | [Using Google Gemini with GitHub Agentic Workflows](/gh-aw/engines/gemini/) |
| [Google Gemini CLI](https://github.com/google-gemini/gemini-cli) (deprecated in favor of `agy`) | `gemini` | [`GEMINI_API_KEY`](/gh-aw/reference/auth/#gemini_api_key) or [Google WIF](/gh-aw/reference/auth/#google-workload-identity-federation-wif) | [Using Google Gemini with GitHub Agentic Workflows](/gh-aw/engines/gemini/) |
| [Google Antigravity CLI](https://github.com/google-antigravity/antigravity-cli) (experimental) | `agy` | [`GEMINI_API_KEY`](/gh-aw/reference/auth/#gemini_api_key) only; no ADC/WIF | [Using experimental Agy](/gh-aw/engines/agy/) |
| [Pi](https://www.npmjs.com/package/@earendil-works/pi-coding-agent) | `pi` | Copilot authentication by default; Anthropic or OpenAI/Codex key for a provider-prefixed `model:` | [Using Pi with GitHub Agentic Workflows](/gh-aw/engines/pi/) |

Copilot CLI is the default, so `engine:` can be omitted when using Copilot. Copilot SDK mode is an execution mode of the Copilot engine, not a separate engine; enable it with `engine: copilot` and `copilot-sdk: true`. See [Copilot SDK support](#copilot-sdk-support).

Gemini remains selectable and emits an informational deprecation notice after effective engine resolution, including imports and CLI overrides. The notice does not count as a warning or affect strict-mode success. Evaluate experimental Agy for compatible API-key workflows; retain Gemini for Google WIF or unsupported capabilities. See [migration guidance](/gh-aw/engines/agy/#evaluating-a-gemini-api-key-workflow).

Copilot also supports experimental per-run model and reasoning-effort selection through `engine.model-routing`. See [Model Routing](/gh-aw/reference/model-routing/) for configuration, requirements, known limitations, and troubleshooting.

## Configuration conformance workflows
Expand Down Expand Up @@ -81,8 +83,8 @@ same probes and prompt from `shared/agy-conformance.md`; trigger-bearing
workflows cannot be imported as shared Markdown. Both Agy selectors
have isolated, ref-specific concurrency. The production gate has a ten-minute
job timeout, five-credit budget, and staged safe outputs. Native authentication
has passed; production conformance and Gemini soft deprecation remain pending.
The new engine and deprecation must not be released independently of that gate.
has passed; production conformance remains pending. Gemini is soft-deprecated,
but this does not promote Agy to stable or establish feature equivalence.

## Unsupported engine samples

Expand Down
4 changes: 2 additions & 2 deletions pkg/constants/engine_constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ var EngineOptions = []EngineOption{
},
{
Value: string(GeminiEngine),
Label: "Gemini",
Description: "Google Gemini CLI coding agent",
Label: "Gemini (Deprecated)",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the expected option label to Gemini (Deprecated) and covered it with the existing constants test. Fixed in e0912e8.

Description: "Deprecated Google Gemini CLI; use the experimental agy engine where supported",
SecretName: GeminiAPIKey,
KeyURL: "https://aistudio.google.com/app/apikey",
WhenNeeded: "Gemini engine workflows",
Expand Down
3 changes: 3 additions & 0 deletions pkg/workflow/compiler_orchestrator_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ func (c *Compiler) setupEngineAndImports(result *parser.FrontmatterResult, clean
if err := c.runPostEngineValidations(result.Frontmatter, engineSetting, engineConfig, networkPermissions, sandboxConfig, agenticEngine, importsResult); err != nil {
return nil, err
}
if agenticEngine.GetID() == string(constants.GeminiEngine) {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("The gemini engine is deprecated in favor of the experimental agy engine. Use engine: agy where supported; retain engine: gemini for Google WIF or features Agy does not support. See https://github.github.com/gh-aw/engines/agy/"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched the notice to FormatInfoMessageStderr so its styling follows stderr TTY/color detection. Fixed in e0912e8.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] This notice is printed unconditionally on every compile that resolves gemini, with no c.batchMode/c.quiet gating like the nearby experimental-engine notice at line 664 or the plugins/drive-memory warnings in compiler_validators.go. In a batch compile over many Gemini workflows this will repeat the same multi-sentence message per file.

💡 Suggested fix

Follow the existing pattern used for other informational/warning messages in this file, e.g.:

if agenticEngine.GetID() == string(constants.GeminiEngine) {
    if c.batchMode {
        c.featureUsage["gemini deprecation"]++
    } else {
        fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("The gemini engine is deprecated..."))
    }
}

This keeps per-file notices during single-file compiles but avoids noisy repeated output during gh aw compile over an entire repo.

@copilot please address this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Batch compilation now aggregates Gemini deprecation notices into the existing feature-usage summary, while quiet single-file compilation suppresses the notice. Added regression coverage. Fixed in e0912e8.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] This uses console.FormatInfoMessage (the stdout-styling helper, degraded via isTTY/stdoutEnviron) to format a string written to os.Stderr, whereas the neighboring experimental-engine notice at line 664 correctly uses console.FormatInfoMessageStderr (checks isStderrTTY/stderrEnviron). If stdout is redirected but stderr is a TTY (or vice versa), this message could render without expected ANSI styling or apply unwanted styling in a piped stderr context.

💡 Suggested fix
fmt.Fprintln(os.Stderr, console.FormatInfoMessageStderr("The gemini engine is deprecated in favor of the experimental agy engine. ..."))

Minor, but keeps the two adjacent deprecation/experimental notices in this file consistent.

@copilot please address this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to the stderr-specific info formatter, preserving stderr TTY/color behavior independently of stdout. Fixed in e0912e8.

}
return &engineSetupResult{
engineSetting: engineSetting,
model: model,
Expand Down
71 changes: 71 additions & 0 deletions pkg/workflow/compiler_orchestrator_engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package workflow
import (
"os"
"path/filepath"
"strings"
"testing"

"github.com/github/gh-aw/pkg/parser"
Expand All @@ -14,6 +15,76 @@ import (
"github.com/stretchr/testify/require"
)

func TestSetupEngineAndImports_GeminiDeprecation(t *testing.T) {
tests := []struct {
name string
engine string
imported bool
override string
wantEngine string
wantNotices int
wantWarnings int
}{
{name: "string form", engine: "engine: gemini\n", wantEngine: "gemini", wantNotices: 1},
{name: "object form with pin", engine: "engine:\n id: gemini\n version: \"0.39.1\"\n", wantEngine: "gemini", wantNotices: 1},
{name: "imported engine", imported: true, wantEngine: "gemini", wantNotices: 1},
{name: "override to Gemini", engine: "engine: copilot\n", override: "gemini", wantEngine: "gemini", wantNotices: 1, wantWarnings: 1},
{name: "override away from Gemini", engine: "engine: gemini\n", override: "copilot", wantEngine: "copilot", wantWarnings: 1},
{name: "default engine", wantEngine: "copilot"},
{name: "experimental replacement", engine: "engine: agy\n", wantEngine: "agy"},
{
name: "Google WIF",
engine: `engine:
id: gemini
auth:
type: github-oidc
provider: gcp
workload-identity-provider: projects/123/locations/global/workloadIdentityPools/test/providers/test
service-account: test@example.iam.gserviceaccount.com
project: test-project
`,
wantEngine: "gemini", wantNotices: 1,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tmpDir := testutil.TempDir(t, "gemini-deprecation")
engine := tt.engine
if tt.imported {
require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "shared.md"), []byte("---\nengine: gemini\n---\n"), 0644))
engine = "imports:\n - shared.md\n"
}
content := "---\non: push\n" + engine + "---\n\n# Test Workflow\n"
frontmatter, err := parser.ExtractFrontmatterFromContent(content)
require.NoError(t, err)
compiler := NewCompiler(WithEngineOverride(tt.override))
compiler.SetStrictMode(true)
output := testutil.CaptureStderr(t, func() {
result, err := compiler.setupEngineAndImports(frontmatter, filepath.Join(tmpDir, "test.md"), []byte(content), tmpDir)
require.NoError(t, err)
require.NotNil(t, result)
assert.Equal(t, tt.wantEngine, result.agenticEngine.GetID())
assert.Equal(t, tt.wantEngine, result.engineConfig.ID)
if tt.name == "object form with pin" {
assert.Equal(t, "0.39.1", result.engineConfig.Version)
}
if tt.name == "Google WIF" {
require.NotNil(t, result.engineConfig.Auth)
assert.Equal(t, "github-oidc", result.engineConfig.Auth.Type)
assert.Equal(t, "gcp", result.engineConfig.Auth.Provider)
}
})
assert.Equal(t, tt.wantNotices, strings.Count(output, "The gemini engine is deprecated"))
assert.Equal(t, tt.wantWarnings, compiler.GetWarningCount())
if tt.wantNotices > 0 {
assert.Contains(t, output, "Use engine: agy where supported")
assert.Contains(t, output, "retain engine: gemini for Google WIF")
}
})
}
}

func TestFrontmatterDeclaresImports(t *testing.T) {
tests := []struct {
name string
Expand Down
2 changes: 1 addition & 1 deletion pkg/workflow/data/engines/gemini.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
engine:
id: gemini
display-name: Google Gemini CLI
description: Google Gemini CLI with headless mode and LLM gateway support
description: Deprecated Google Gemini CLI; use the experimental agy engine where supported
runtime-id: gemini
provider:
name: google
Expand Down
13 changes: 13 additions & 0 deletions pkg/workflow/engine_catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ func TestEngineCatalog_All(t *testing.T) {
}
}

func TestEngineCatalog_GeminiDeprecated(t *testing.T) {
catalog := NewEngineCatalog(NewEngineRegistry())
for _, def := range catalog.All() {
if def.ID == "gemini" {
assert.Contains(t, def.Description, "Deprecated")
assert.Contains(t, def.Description, "agy")
assert.Equal(t, NewGeminiEngine().GetDescription(), def.Description)
return
}
}
t.Fatal("deprecated Gemini engine must remain selectable")
}

// engineSchemaOneOfVariants parses the main workflow schema and returns the
// type identifiers of each variant in engine_config.oneOf for structural assertions.
func engineSchemaOneOfVariants(t *testing.T) []map[string]any {
Expand Down
2 changes: 1 addition & 1 deletion pkg/workflow/gemini_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func NewGeminiEngine() *GeminiEngine {
BaseEngine: BaseEngine{
id: "gemini",
displayName: "Google Gemini CLI",
description: "Google Gemini CLI with headless mode and LLM gateway support",
description: "Deprecated Google Gemini CLI; use the experimental agy engine where supported",
experimental: false,
ghSkillAgentName: "gemini-cli",
capabilities: EngineCapabilities{
Expand Down
Loading