diff --git a/docs/src/content/docs/reference/engines.md b/docs/src/content/docs/reference/engines.md index d3f8457e376..b78c90f4fa0 100644 --- a/docs/src/content/docs/reference/engines.md +++ b/docs/src/content/docs/reference/engines.md @@ -1,6 +1,6 @@ --- title: AI Engines (aka Coding Agents) -description: Complete guide to AI engines (coding agents) usable with GitHub Agentic Workflows, including Copilot, Claude, Codex, Gemini, OpenCode, and Pi with their specific configuration options. +description: Complete guide to AI engines (coding agents) usable with GitHub Agentic Workflows, including Copilot, Claude, Codex, Gemini, OpenCode, Pi, and Antigravity with their specific configuration options. sidebar: order: 600 --- @@ -19,6 +19,7 @@ Set `engine:` in your workflow frontmatter and configure the corresponding secre | [Google Gemini CLI](https://github.com/google-gemini/gemini-cli) | `gemini` | [`GEMINI_API_KEY`](/gh-aw/reference/auth/#gemini_api_key) (standard) or [`engine.auth` Google WIF](/gh-aw/reference/auth/#google-workload-identity-federation-wif) (keyless) | | [OpenCode](https://opencode.ai) (experimental) | `opencode` | [COPILOT_GITHUB_TOKEN](/gh-aw/reference/auth/#copilot_github_token) | | [Pi](https://www.npmjs.com/package/@earendil-works/pi-coding-agent) (experimental) | `pi` | [COPILOT_GITHUB_TOKEN](/gh-aw/reference/auth/#copilot_github_token) (default); switches to provider-specific secret when `model:` uses `provider/model` format | +| Google Antigravity CLI (experimental) | `antigravity` | [`ANTIGRAVITY_API_KEY`](/gh-aw/reference/auth/#antigravity_api_key) | Copilot CLI is the default — `engine:` can be omitted when using Copilot. See the linked authentication docs for secret setup instructions. @@ -30,18 +31,18 @@ Choose the engine that best matches your needs and existing AI account: Copilot Not all features are available across all engines. The table below summarizes per-engine support for commonly used workflow options: -| Feature | Copilot | Claude | Codex | Gemini | OpenCode | Pi | -|---------|:-------:|:------:|:-----:|:------:|:--------:|:--:| -| `max-turns` (AWF invocation cap; `max-runs` deprecated) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| `max-turns` | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | -| `max-continuations` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `tools.web-fetch` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| `tools.web-search` | via MCP | via MCP | ✅ (opt-in) | via MCP | via MCP | via MCP | -| `engine.agent` (custom agent file) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | -| `engine.api-target` (custom endpoint) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| `engine.bare` (disable context loading) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | -| `engine.harness` (custom harness script) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | -| Tools allowlist | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | +| Feature | Copilot | Claude | Codex | Gemini | OpenCode | Pi | Antigravity | +|---------|:-------:|:------:|:-----:|:------:|:--------:|:--:|:-----------:| +| `max-turns` (AWF invocation cap; `max-runs` deprecated) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `max-turns` | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `max-continuations` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `tools.web-fetch` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `tools.web-search` | via MCP | via MCP | ✅ (opt-in) | via MCP | via MCP | via MCP | via MCP | +| `engine.agent` (custom agent file) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| `engine.api-target` (custom endpoint) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `engine.bare` (disable context loading) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | +| `engine.harness` (custom harness script) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| Tools allowlist | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | `max-turns` (default `500`, legacy alias `max-runs`) and `max-ai-credits` (default `1000`) are top-level frontmatter fields supported by all engines. `engine.max-turns` is a deprecated nested alias that still limits Claude iterations when present; `max-continuations` enables Copilot autopilot mode. Codex `web-search` is opt-in via `tools: web-search:`; other engines use a third-party MCP server — see [Using Web Search](/gh-aw/reference/web-search/). `engine.agent`, `engine.bare`, and `engine.harness` are described below. @@ -72,6 +73,7 @@ By default, workflows install the latest available version of each engine CLI. T | Gemini CLI | `gemini` | `"0.31.0"` | | OpenCode | `opencode` | `"0.1.0"` | | Pi | `pi` | `"0.72.1"` | +| Antigravity CLI | `antigravity` | `"latest"` | ```yaml wrap engine: diff --git a/pkg/workflow/engine_definition_test.go b/pkg/workflow/engine_definition_test.go index 1b92a2fcf1e..70eba5717e6 100644 --- a/pkg/workflow/engine_definition_test.go +++ b/pkg/workflow/engine_definition_test.go @@ -27,6 +27,7 @@ func TestNewEngineCatalog_BuiltIns(t *testing.T) { {"gemini", "Google Gemini CLI", "google"}, {"opencode", "OpenCode", "github"}, {"pi", "Pi", "github"}, + {"antigravity", "Antigravity CLI", "google"}, } for _, tt := range tests { diff --git a/pkg/workflow/engine_doc_sync_test.go b/pkg/workflow/engine_doc_sync_test.go new file mode 100644 index 00000000000..fd2862f26d4 --- /dev/null +++ b/pkg/workflow/engine_doc_sync_test.go @@ -0,0 +1,56 @@ +//go:build !integration + +package workflow + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +// engineDocSyncPath is the path from the pkg/workflow package directory to +// the engines reference document. +const engineDocSyncPath = "../../docs/src/content/docs/reference/engines.md" + +// TestEngineDocSync verifies that every built-in engine definition in +// data/engines/ has its engine ID referenced in the engines reference +// documentation. +// +// This test is the structural safeguard against "doc drift": when a new engine +// is added to data/engines/*.md but the docs are not updated, this test fails +// at PR time rather than being discovered and manually patched after the fact. +// +// To fix a failure: add the engine ID (e.g. `antigravity`) to the Available +// Coding Agents table in docs/src/content/docs/reference/engines.md. +func TestEngineDocSync(t *testing.T) { + // Read the engines reference doc. + docPath := filepath.Join("..", "..", "docs", "src", "content", "docs", "reference", "engines.md") + docContent, err := os.ReadFile(docPath) + if err != nil { + t.Fatalf("failed to read engines reference doc at %s: %v\n\n"+ + "If the docs file was moved, update engineDocSyncPath in engine_doc_sync_test.go.", + engineDocSyncPath, err) + } + docStr := string(docContent) + + // Load all built-in engine definitions using the same loader used at runtime. + definitions := loadBuiltinEngineDefinitions() + + var missing []string + for _, def := range definitions { + // Check that the engine ID appears in the docs as a backtick-quoted value + // (e.g. `antigravity`) — the canonical form used in the Available Coding + // Agents table and throughout the engines reference page. + if !strings.Contains(docStr, "`"+def.ID+"`") { + missing = append(missing, def.ID) + } + } + + if len(missing) > 0 { + t.Errorf("the following engine IDs are registered in data/engines/ but missing from the engines reference doc (%s):\n\n %s\n\n"+ + "Add each missing engine to the Available Coding Agents table in that file.\n"+ + "This check prevents engine-doc drift from recurring.", + engineDocSyncPath, strings.Join(missing, "\n ")) + } +}