Expose built-in workflow agents outside internal experiments

External builds were inheriting internal feature-gate defaults, so Explore,
Plan, and verification disappeared from the active agent registry. Keep the
internal ant experiment behavior gated, but make public builds default to the
full workflow agent set while preserving the SDK opt-out path.

Constraint: Internal ant builds still rely on GrowthBook rollout gates.
Rejected: Force-enable all users unconditionally | would bypass internal experiment controls.
Confidence: high
Scope-risk: narrow
Directive: Do not move public built-in agents behind internal-only feature flags without verifying desktop /api/agents and real Agent subagent orchestration.
Tested: bun test src/tools/AgentTool/builtInAgents.test.ts
Tested: git diff --check
Not-tested: Full quality gate in this commit step; earlier quality:pr is blocked by cli-core approval policy.
This commit is contained in:
程序员阿江(Relakkes) 2026-05-06 11:56:59 +08:00
parent 4e9c6dbda1
commit 13b765b5e9
2 changed files with 66 additions and 6 deletions

View File

@ -0,0 +1,50 @@
import { afterEach, describe, expect, test } from 'bun:test'
import {
setIsInteractive,
} from '../../bootstrap/state.js'
import {
areExplorePlanAgentsEnabled,
getBuiltInAgents,
} from './builtInAgents.js'
const originalDisableBuiltIns =
process.env.CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS
const originalEntrypoint = process.env.CLAUDE_CODE_ENTRYPOINT
afterEach(() => {
if (originalDisableBuiltIns === undefined) {
delete process.env.CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS
} else {
process.env.CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS =
originalDisableBuiltIns
}
if (originalEntrypoint === undefined) {
delete process.env.CLAUDE_CODE_ENTRYPOINT
} else {
process.env.CLAUDE_CODE_ENTRYPOINT = originalEntrypoint
}
setIsInteractive(false)
})
describe('built-in agents', () => {
test('enables public built-in agents in external builds', () => {
setIsInteractive(true)
expect(areExplorePlanAgentsEnabled()).toBe(true)
const agentTypes = getBuiltInAgents().map(agent => agent.agentType)
expect(agentTypes).toContain('Explore')
expect(agentTypes).toContain('Plan')
expect(agentTypes).toContain('verification')
})
test('preserves SDK opt-out in noninteractive sessions', () => {
setIsInteractive(false)
process.env.CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS = 'true'
expect(getBuiltInAgents()).toEqual([])
})
})

View File

@ -11,14 +11,27 @@ import { VERIFICATION_AGENT } from './built-in/verificationAgent.js'
import type { AgentDefinition } from './loadAgentsDir.js'
export function areExplorePlanAgentsEnabled(): boolean {
if (process.env.USER_TYPE !== 'ant') {
return true
}
if (feature('BUILTIN_EXPLORE_PLAN_AGENTS')) {
// 3P default: true — Bedrock/Vertex keep agents enabled (matches pre-experiment
// external behavior). A/B test treatment sets false to measure impact of removal.
return getFeatureValue_CACHED_MAY_BE_STALE('tengu_amber_stoat', true)
}
return false
}
function isVerificationAgentEnabled(): boolean {
if (process.env.USER_TYPE !== 'ant') {
return true
}
if (feature('VERIFICATION_AGENT')) {
return getFeatureValue_CACHED_MAY_BE_STALE('tengu_hive_evidence', false)
}
return false
}
export function getBuiltInAgents(): AgentDefinition[] {
// Allow disabling all built-in agents via env var (useful for SDK users who want a blank slate)
// Only applies in noninteractive mode (SDK/API usage)
@ -61,10 +74,7 @@ export function getBuiltInAgents(): AgentDefinition[] {
agents.push(CLAUDE_CODE_GUIDE_AGENT)
}
if (
feature('VERIFICATION_AGENT') &&
getFeatureValue_CACHED_MAY_BE_STALE('tengu_hive_evidence', false)
) {
if (isVerificationAgentEnabled()) {
agents.push(VERIFICATION_AGENT)
}