From 9d2a899ac4a4e8f1b5fbf11ff094ca4a9eb35b24 Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Tue, 1 Sep 2026 00:31:55 +0000 Subject: [PATCH 1/7] feat(telemetry): give AGENTCORE_TELEMETRY_DISABLED env var top precedence --- src/globalConfig/config.test.tsx | 41 ++++++++++++++++++++++++++++++++ src/globalConfig/config.tsx | 11 ++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/globalConfig/config.test.tsx diff --git a/src/globalConfig/config.test.tsx b/src/globalConfig/config.test.tsx new file mode 100644 index 000000000..cadf55c1e --- /dev/null +++ b/src/globalConfig/config.test.tsx @@ -0,0 +1,41 @@ +import { test, describe, afterEach, expect } from "bun:test"; +import { DEFAULT_GLOBAL_CONFIG, applyOverrides } from "./config"; + +describe("applyOverrides", () => { + afterEach(() => { + delete process.env.AGENTCORE_TELEMETRY_DISABLED; + }); + + test("applies overrides on top of defaults", () => { + const result = applyOverrides(DEFAULT_GLOBAL_CONFIG, { + telemetry: { enabled: false, audit: true }, + }); + expect(result.telemetry.enabled).toBe(false); + expect(result.telemetry.audit).toBe(true); + expect(result.telemetry.endpoint).toBe(DEFAULT_GLOBAL_CONFIG.telemetry.endpoint); + }); + + test.each(["true", "TRUE", "1", " 1 "])( + "AGENTCORE_TELEMETRY_DISABLED=%p disables telemetry over enabled config", + (value) => { + process.env.AGENTCORE_TELEMETRY_DISABLED = value; + const result = applyOverrides(DEFAULT_GLOBAL_CONFIG, { telemetry: { enabled: true } }); + expect(result.telemetry.enabled).toBe(false); + }, + ); + + test("AGENTCORE_TELEMETRY_DISABLED does not affect audit", () => { + process.env.AGENTCORE_TELEMETRY_DISABLED = "1"; + const result = applyOverrides(DEFAULT_GLOBAL_CONFIG, { telemetry: { audit: true } }); + expect(result.telemetry.audit).toBe(true); + }); + + test.each(["false", "0", "", "no"])( + "AGENTCORE_TELEMETRY_DISABLED=%p leaves telemetry enabled", + (value) => { + process.env.AGENTCORE_TELEMETRY_DISABLED = value; + const result = applyOverrides(DEFAULT_GLOBAL_CONFIG, { telemetry: { enabled: true } }); + expect(result.telemetry.enabled).toBe(true); + }, + ); +}); diff --git a/src/globalConfig/config.tsx b/src/globalConfig/config.tsx index 290462754..994c7adb8 100644 --- a/src/globalConfig/config.tsx +++ b/src/globalConfig/config.tsx @@ -12,8 +12,15 @@ export const DEFAULT_GLOBAL_CONFIG: GlobalConfig = { installationId: crypto.randomUUID(), }; +/** Returns true when AGENTCORE_TELEMETRY_DISABLED is set to "true" or "1". */ +function telemetryDisabledByEnv(): boolean { + const value = process.env.AGENTCORE_TELEMETRY_DISABLED?.toLowerCase().trim(); + return value === "true" || value === "1"; +} + /** * Applies the given overrides from a partial config on top of the provided defaults and returns the merged result. + * The AGENTCORE_TELEMETRY_DISABLED env var takes precedence over both overrides and defaults for telemetry.enabled. */ export function applyOverrides( defaults: GlobalConfig, @@ -21,7 +28,9 @@ export function applyOverrides( ): GlobalConfig { return { telemetry: { - enabled: overrides.telemetry?.enabled ?? defaults.telemetry.enabled, + enabled: telemetryDisabledByEnv() + ? false + : (overrides.telemetry?.enabled ?? defaults.telemetry.enabled), audit: overrides.telemetry?.audit ?? defaults.telemetry.audit, endpoint: overrides.telemetry?.endpoint ?? defaults.telemetry.endpoint, }, From f22681e5a14494fc079d89379108a61e3ebb509f Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Tue, 1 Sep 2026 00:31:55 +0000 Subject: [PATCH 2/7] ci: disable telemetry in build and unit-test workflows --- .github/workflows/build.yml | 3 +++ .github/workflows/unit-test.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 502ebe3b9..9194929f1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,6 +7,9 @@ on: required: true type: string +env: + AGENTCORE_TELEMETRY_DISABLED: "1" + jobs: build: name: Build (${{ matrix.name }}) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index f768f80e6..40e81b6df 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -10,6 +10,9 @@ on: CODECOV_TOKEN: required: false +env: + AGENTCORE_TELEMETRY_DISABLED: "1" + jobs: test: name: Test (${{ matrix.name }}) From 3d4d7cfb1163f64124ff902fa728e24a404eafa5 Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Tue, 1 Sep 2026 00:43:32 +0000 Subject: [PATCH 3/7] test: cover AGENTCORE_TELEMETRY_DISABLED in config handler e2e tests --- src/globalConfig/config.test.tsx | 41 ----------------------------- src/handlers/config/config.test.tsx | 28 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 41 deletions(-) delete mode 100644 src/globalConfig/config.test.tsx diff --git a/src/globalConfig/config.test.tsx b/src/globalConfig/config.test.tsx deleted file mode 100644 index cadf55c1e..000000000 --- a/src/globalConfig/config.test.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { test, describe, afterEach, expect } from "bun:test"; -import { DEFAULT_GLOBAL_CONFIG, applyOverrides } from "./config"; - -describe("applyOverrides", () => { - afterEach(() => { - delete process.env.AGENTCORE_TELEMETRY_DISABLED; - }); - - test("applies overrides on top of defaults", () => { - const result = applyOverrides(DEFAULT_GLOBAL_CONFIG, { - telemetry: { enabled: false, audit: true }, - }); - expect(result.telemetry.enabled).toBe(false); - expect(result.telemetry.audit).toBe(true); - expect(result.telemetry.endpoint).toBe(DEFAULT_GLOBAL_CONFIG.telemetry.endpoint); - }); - - test.each(["true", "TRUE", "1", " 1 "])( - "AGENTCORE_TELEMETRY_DISABLED=%p disables telemetry over enabled config", - (value) => { - process.env.AGENTCORE_TELEMETRY_DISABLED = value; - const result = applyOverrides(DEFAULT_GLOBAL_CONFIG, { telemetry: { enabled: true } }); - expect(result.telemetry.enabled).toBe(false); - }, - ); - - test("AGENTCORE_TELEMETRY_DISABLED does not affect audit", () => { - process.env.AGENTCORE_TELEMETRY_DISABLED = "1"; - const result = applyOverrides(DEFAULT_GLOBAL_CONFIG, { telemetry: { audit: true } }); - expect(result.telemetry.audit).toBe(true); - }); - - test.each(["false", "0", "", "no"])( - "AGENTCORE_TELEMETRY_DISABLED=%p leaves telemetry enabled", - (value) => { - process.env.AGENTCORE_TELEMETRY_DISABLED = value; - const result = applyOverrides(DEFAULT_GLOBAL_CONFIG, { telemetry: { enabled: true } }); - expect(result.telemetry.enabled).toBe(true); - }, - ); -}); diff --git a/src/handlers/config/config.test.tsx b/src/handlers/config/config.test.tsx index 6a81b50e0..263a4e53c 100644 --- a/src/handlers/config/config.test.tsx +++ b/src/handlers/config/config.test.tsx @@ -183,4 +183,32 @@ describe("config", () => { const readOutput = await run(["telemetry.enabled"]); expect(JSON.parse(readOutput)).toBe(false); }); + + describe("AGENTCORE_TELEMETRY_DISABLED env var", () => { + afterEach(() => { + delete process.env.AGENTCORE_TELEMETRY_DISABLED; + }); + + test.each(["true", "TRUE", "1", " 1 "])( + "=%p reports telemetry.enabled as false, overriding the enabled config", + async (value) => { + process.env.AGENTCORE_TELEMETRY_DISABLED = value; + expect(JSON.parse(await run(["telemetry.enabled"]))).toBe(false); + }, + ); + + test.each(["false", "0", "", "no"])( + "=%p leaves telemetry.enabled as configured", + async (value) => { + process.env.AGENTCORE_TELEMETRY_DISABLED = value; + expect(JSON.parse(await run(["telemetry.enabled"]))).toBe(true); + }, + ); + + test("does not affect telemetry.audit", async () => { + await writeFile(configPath, JSON.stringify({ telemetry: { enabled: true, audit: true } })); + process.env.AGENTCORE_TELEMETRY_DISABLED = "1"; + expect(JSON.parse(await run(["telemetry.audit"]))).toBe(true); + }); + }); }); From 5ee73acf2a24731e39a60c2e5c8a3fdf628b0d89 Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Tue, 1 Sep 2026 01:08:17 +0000 Subject: [PATCH 4/7] fix(test): isolate config tests from ambient AGENTCORE_TELEMETRY_DISABLED --- src/handlers/config/config.test.tsx | 39 +++++++++++++++++------------ 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/handlers/config/config.test.tsx b/src/handlers/config/config.test.tsx index 263a4e53c..3a8a2e0bc 100644 --- a/src/handlers/config/config.test.tsx +++ b/src/handlers/config/config.test.tsx @@ -11,6 +11,7 @@ import { FsReadWriteJson } from "../../io"; describe("config", () => { let tempDir: string; let configPath: string; + let savedTelemetryDisabled: string | undefined; const validConfigOverrides = { telemetry: { enabled: true, endpoint: "https://example.com" }, @@ -18,12 +19,21 @@ describe("config", () => { }; beforeEach(async () => { + // Isolate tests from an ambient AGENTCORE_TELEMETRY_DISABLED (set in CI) so + // config resolution reflects the config file; individual tests set it as needed. + savedTelemetryDisabled = process.env.AGENTCORE_TELEMETRY_DISABLED; + delete process.env.AGENTCORE_TELEMETRY_DISABLED; tempDir = await mkdtemp(join(tmpdir(), "agentcore-config-test-")); configPath = join(tempDir, "config.json"); await writeFile(configPath, JSON.stringify(validConfigOverrides)); }); afterEach(async () => { + if (savedTelemetryDisabled === undefined) { + delete process.env.AGENTCORE_TELEMETRY_DISABLED; + } else { + process.env.AGENTCORE_TELEMETRY_DISABLED = savedTelemetryDisabled; + } await rm(tempDir, { recursive: true, force: true }); }); @@ -185,23 +195,20 @@ describe("config", () => { }); describe("AGENTCORE_TELEMETRY_DISABLED env var", () => { - afterEach(() => { - delete process.env.AGENTCORE_TELEMETRY_DISABLED; - }); - - test.each(["true", "TRUE", "1", " 1 "])( - "=%p reports telemetry.enabled as false, overriding the enabled config", - async (value) => { - process.env.AGENTCORE_TELEMETRY_DISABLED = value; - expect(JSON.parse(await run(["telemetry.enabled"]))).toBe(false); - }, - ); - - test.each(["false", "0", "", "no"])( - "=%p leaves telemetry.enabled as configured", - async (value) => { + test.each([ + ["true", false], + ["TRUE", false], + ["1", false], + [" 1 ", false], + ["false", true], + ["0", true], + ["", true], + ["no", true], + ])( + "=%p resolves telemetry.enabled to %p, overriding the enabled config", + async (value, expected) => { process.env.AGENTCORE_TELEMETRY_DISABLED = value; - expect(JSON.parse(await run(["telemetry.enabled"]))).toBe(true); + expect(JSON.parse(await run(["telemetry.enabled"]))).toBe(expected); }, ); From 3d6e1d3f44a6928ba26c7e6b7b59a95bafb7866d Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Tue, 1 Sep 2026 01:34:14 +0000 Subject: [PATCH 5/7] test: drop redundant comment in config tests --- src/handlers/config/config.test.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/handlers/config/config.test.tsx b/src/handlers/config/config.test.tsx index 3a8a2e0bc..331e412e4 100644 --- a/src/handlers/config/config.test.tsx +++ b/src/handlers/config/config.test.tsx @@ -19,8 +19,6 @@ describe("config", () => { }; beforeEach(async () => { - // Isolate tests from an ambient AGENTCORE_TELEMETRY_DISABLED (set in CI) so - // config resolution reflects the config file; individual tests set it as needed. savedTelemetryDisabled = process.env.AGENTCORE_TELEMETRY_DISABLED; delete process.env.AGENTCORE_TELEMETRY_DISABLED; tempDir = await mkdtemp(join(tmpdir(), "agentcore-config-test-")); From 25db590b78bd0d35409b646fc8e01cd0564f8b10 Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Tue, 1 Sep 2026 14:02:24 +0000 Subject: [PATCH 6/7] fix(telemetry): honor AGENTCORE_TELEMETRY_DISABLED at emit time, not in persisted config --- src/globalConfig/config.tsx | 11 +------- src/handlers/config/config.test.tsx | 27 ++++-------------- src/telemetry/client.test.tsx | 44 +++++++++++++++++++++++++++++ src/telemetry/client.tsx | 8 +++++- 4 files changed, 57 insertions(+), 33 deletions(-) diff --git a/src/globalConfig/config.tsx b/src/globalConfig/config.tsx index 994c7adb8..290462754 100644 --- a/src/globalConfig/config.tsx +++ b/src/globalConfig/config.tsx @@ -12,15 +12,8 @@ export const DEFAULT_GLOBAL_CONFIG: GlobalConfig = { installationId: crypto.randomUUID(), }; -/** Returns true when AGENTCORE_TELEMETRY_DISABLED is set to "true" or "1". */ -function telemetryDisabledByEnv(): boolean { - const value = process.env.AGENTCORE_TELEMETRY_DISABLED?.toLowerCase().trim(); - return value === "true" || value === "1"; -} - /** * Applies the given overrides from a partial config on top of the provided defaults and returns the merged result. - * The AGENTCORE_TELEMETRY_DISABLED env var takes precedence over both overrides and defaults for telemetry.enabled. */ export function applyOverrides( defaults: GlobalConfig, @@ -28,9 +21,7 @@ export function applyOverrides( ): GlobalConfig { return { telemetry: { - enabled: telemetryDisabledByEnv() - ? false - : (overrides.telemetry?.enabled ?? defaults.telemetry.enabled), + enabled: overrides.telemetry?.enabled ?? defaults.telemetry.enabled, audit: overrides.telemetry?.audit ?? defaults.telemetry.audit, endpoint: overrides.telemetry?.endpoint ?? defaults.telemetry.endpoint, }, diff --git a/src/handlers/config/config.test.tsx b/src/handlers/config/config.test.tsx index 331e412e4..5c20c080e 100644 --- a/src/handlers/config/config.test.tsx +++ b/src/handlers/config/config.test.tsx @@ -192,28 +192,11 @@ describe("config", () => { expect(JSON.parse(readOutput)).toBe(false); }); - describe("AGENTCORE_TELEMETRY_DISABLED env var", () => { - test.each([ - ["true", false], - ["TRUE", false], - ["1", false], - [" 1 ", false], - ["false", true], - ["0", true], - ["", true], - ["no", true], - ])( - "=%p resolves telemetry.enabled to %p, overriding the enabled config", - async (value, expected) => { - process.env.AGENTCORE_TELEMETRY_DISABLED = value; - expect(JSON.parse(await run(["telemetry.enabled"]))).toBe(expected); - }, - ); + test("does not persist telemetry.enabled when AGENTCORE_TELEMETRY_DISABLED is set", async () => { + process.env.AGENTCORE_TELEMETRY_DISABLED = "1"; + await run(["telemetry.audit", "true"]); + delete process.env.AGENTCORE_TELEMETRY_DISABLED; - test("does not affect telemetry.audit", async () => { - await writeFile(configPath, JSON.stringify({ telemetry: { enabled: true, audit: true } })); - process.env.AGENTCORE_TELEMETRY_DISABLED = "1"; - expect(JSON.parse(await run(["telemetry.audit"]))).toBe(true); - }); + expect(JSON.parse(await run(["telemetry.enabled"]))).toBe(true); }); }); diff --git a/src/telemetry/client.test.tsx b/src/telemetry/client.test.tsx index bad75db7b..a2fca90bf 100644 --- a/src/telemetry/client.test.tsx +++ b/src/telemetry/client.test.tsx @@ -287,10 +287,13 @@ describe("DefaultTelemetryClient", () => { describe("OtelHistogramSink", () => { let testCollector: ReturnType; let receivedBodies: any[]; + let savedTelemetryDisabled: string | undefined; const logger = createSilentLogger(); beforeEach(async () => { + savedTelemetryDisabled = process.env.AGENTCORE_TELEMETRY_DISABLED; + delete process.env.AGENTCORE_TELEMETRY_DISABLED; receivedBodies = []; testCollector = Bun.serve({ port: 0, @@ -303,6 +306,11 @@ describe("OtelHistogramSink", () => { }); afterEach(async () => { + if (savedTelemetryDisabled === undefined) { + delete process.env.AGENTCORE_TELEMETRY_DISABLED; + } else { + process.env.AGENTCORE_TELEMETRY_DISABLED = savedTelemetryDisabled; + } testCollector.stop(true); }); @@ -388,4 +396,40 @@ describe("OtelHistogramSink", () => { } }, ); + + test("AGENTCORE_TELEMETRY_DISABLED suppresses network export while audit still writes", async () => { + const auditFilePath = join(tmpdir(), `env-disabled-audit-${crypto.randomUUID()}.jsonl`); + const globalConfigAccessor = new TestGlobalConfigAccessor({ + initialConfigData: { + ...DEFAULT_GLOBAL_CONFIG, + telemetry: { + enabled: true, + audit: true, + endpoint: `http://localhost:${testCollector.port}`, + }, + }, + }); + + process.env.AGENTCORE_TELEMETRY_DISABLED = "1"; + try { + const client = new DefaultTelemetryClient({ + logger, + sessionId: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", + globalConfigAccessor, + auditFilePath, + }); + const event = client.createMetricEvent("cli.command_run", { + exit_reason: "success", + command_path: "/agentcore", + }); + await event.emit(100); + await client.shutdown(); + } finally { + delete process.env.AGENTCORE_TELEMETRY_DISABLED; + } + + expect(receivedBodies).toHaveLength(0); + expect(await readFile(auditFilePath, "utf8")).toContain("cli.command_run"); + await rm(auditFilePath, { force: true }); + }); }); diff --git a/src/telemetry/client.tsx b/src/telemetry/client.tsx index b1d7e0381..ce7b78ed2 100644 --- a/src/telemetry/client.tsx +++ b/src/telemetry/client.tsx @@ -87,7 +87,7 @@ export class DefaultTelemetryClient implements TelemetryClient { }), ); - if (globalConfig.telemetry.enabled) + if (globalConfig.telemetry.enabled && !telemetryDisabledByEnv()) metricSinks.push( new OtelHistogramSink({ logger: this.logger.child({ module: "otelCollectorSink" }), @@ -114,6 +114,12 @@ export class DefaultTelemetryClient implements TelemetryClient { }); } +/** Returns true when AGENTCORE_TELEMETRY_DISABLED is set to "true" or "1". */ +function telemetryDisabledByEnv(): boolean { + const value = process.env.AGENTCORE_TELEMETRY_DISABLED?.toLowerCase().trim(); + return value === "true" || value === "1"; +} + /** wraps an async function such that it only executes once **/ function once(fn: () => Promise): () => Promise { let cachedPromise: Promise | undefined; From d9e85633a396e05cb03f87a0e052741839cd968d Mon Sep 17 00:00:00 2001 From: Hweinstock Date: Tue, 1 Sep 2026 14:05:32 +0000 Subject: [PATCH 7/7] test: revert unrelated config handler test changes --- src/handlers/config/config.test.tsx | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/handlers/config/config.test.tsx b/src/handlers/config/config.test.tsx index 5c20c080e..6a81b50e0 100644 --- a/src/handlers/config/config.test.tsx +++ b/src/handlers/config/config.test.tsx @@ -11,7 +11,6 @@ import { FsReadWriteJson } from "../../io"; describe("config", () => { let tempDir: string; let configPath: string; - let savedTelemetryDisabled: string | undefined; const validConfigOverrides = { telemetry: { enabled: true, endpoint: "https://example.com" }, @@ -19,19 +18,12 @@ describe("config", () => { }; beforeEach(async () => { - savedTelemetryDisabled = process.env.AGENTCORE_TELEMETRY_DISABLED; - delete process.env.AGENTCORE_TELEMETRY_DISABLED; tempDir = await mkdtemp(join(tmpdir(), "agentcore-config-test-")); configPath = join(tempDir, "config.json"); await writeFile(configPath, JSON.stringify(validConfigOverrides)); }); afterEach(async () => { - if (savedTelemetryDisabled === undefined) { - delete process.env.AGENTCORE_TELEMETRY_DISABLED; - } else { - process.env.AGENTCORE_TELEMETRY_DISABLED = savedTelemetryDisabled; - } await rm(tempDir, { recursive: true, force: true }); }); @@ -191,12 +183,4 @@ describe("config", () => { const readOutput = await run(["telemetry.enabled"]); expect(JSON.parse(readOutput)).toBe(false); }); - - test("does not persist telemetry.enabled when AGENTCORE_TELEMETRY_DISABLED is set", async () => { - process.env.AGENTCORE_TELEMETRY_DISABLED = "1"; - await run(["telemetry.audit", "true"]); - delete process.env.AGENTCORE_TELEMETRY_DISABLED; - - expect(JSON.parse(await run(["telemetry.enabled"]))).toBe(true); - }); });