Skip to content

Prototype agent session start in Shopify CLI#7584

Closed
dmerand wants to merge 2 commits into
mainfrom
donald/agent-session-poc
Closed

Prototype agent session start in Shopify CLI#7584
dmerand wants to merge 2 commits into
mainfrom
donald/agent-session-poc

Conversation

@dmerand

@dmerand dmerand commented May 19, 2026

Copy link
Copy Markdown
Contributor

What

Prototype CLI-owned agent session state.

This PR adds:

  • shopify agent session start
  • persisted agent session state in cli-kit
  • analytics attribution from persisted session state when explicit SHOPIFY_CLI_AGENT_* env vars are absent
  • prototype analytics opt-out through metricsMode=off
  • one downstream default-mode proof in app release

Why

ai-toolkit-source currently attributes agent-run Shopify CLI commands by prefixing each command with SHOPIFY_CLI_AGENT_INFO and SHOPIFY_CLI_AGENT_IDS. That works, but it is noisy, token-expensive, and harness-specific.

This prototype tests a different shape: start one agent session in Shopify CLI, persist it there, and let later CLI commands reuse that state for attribution and behavior.

app release is the default-mode proof because it already has an established non-interactive path through --allow-updates. Reusing that seam makes the prototype easier to evaluate: it shows that agent session state can affect later CLI behavior without inventing a new global --no-input contract or taking on a larger command surface like app init.

Behavior

  • shopify agent session start persists:
    • agent identity
    • session id
    • metrics mode
    • defaultNonInteractive
  • analytics synthesize packed SHOPIFY_CLI_AGENT_INFO / SHOPIFY_CLI_AGENT_IDS from persisted session state when explicit env vars are absent
  • metricsMode=off suppresses command analytics for this prototype path
  • when defaultNonInteractive=true and the user passed no explicit release-control flags, app release follows its existing non-interactive --allow-updates path

Boundaries

This PR does not:

  • migrate all deterministic ai-toolkit helpers into CLI
  • add a universal --no-input contract
  • redesign Monorail schema
  • generalize agent-mode behavior across all commands

The goal is to demonstrate the value of CLI-owned agent session state clearly.

Manual testing

Start a session and inspect the stored shape:

shopify agent session start \
  --agent river \
  --agent-version 1.0.0 \
  --provider openai \
  --metrics on \
  --json

Confirm later CLI analytics can pick up packed agent attribution without explicit SHOPIFY_CLI_AGENT_* env vars.

Then start a non-interactive session:

shopify agent session start \
  --agent river \
  --agent-version 1.0.0 \
  --provider openai \
  --metrics off \
  --default-non-interactive

Then verify:

shopify app release --version <version>

uses the prototype agent-mode path without requiring an explicit --allow-updates.

@github-actions github-actions Bot added the no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users. label May 19, 2026
@gonzaloriestra gonzaloriestra force-pushed the donald/agent-session-poc branch from 81ecf37 to 17c8c0a Compare May 20, 2026 13:11
@dmerand dmerand force-pushed the donald/agent-session-poc branch from 5387c2e to 8a8489a Compare June 1, 2026 19:16
@github-actions github-actions Bot added Area: @shopify/cli @shopify/cli package issues and removed no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users. labels Jun 1, 2026
@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Differences in type declarations

We detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

packages/cli-kit/dist/public/node/agent.d.ts
import { LocalStorage } from './local-storage.js';
import { AgentSession, ConfSchema } from '../../private/node/conf-store.js';
export type { AgentSession };
export interface StartAgentSessionOptions {
    sessionId: string;
    agentName: string;
    agentVersion: string;
    agentProvider: string;
    metricsMode?: 'on' | 'off';
    defaultNonInteractive?: boolean;
}
/**
 * Start a new agent session.
 *
 * Persists the agent session state to the CLI kit config store.
 *
 * @param options - Agent session configuration.
 * @param config - Optional config store for testing.
 * @returns The persisted session value.
 */
export declare function startAgentSession(options: StartAgentSessionOptions, config?: LocalStorage<ConfSchema>): AgentSession;
/**
 * Get the current agent session.
 *
 * @param config - Optional config store for testing.
 * @returns Current agent session, or undefined if no session is active.
 */
export declare function getCurrentAgentSession(config?: LocalStorage<ConfSchema>): AgentSession | undefined;
/**
 * Clear the current agent session.
 *
 * Removes the persisted agent session state from the CLI kit config store.
 *
 * @param config - Optional config store for testing.
 */
export declare function clearAgentSession(config?: LocalStorage<ConfSchema>): void;
/**
 * Pack SHOPIFY_CLI_AGENT_INFO environment variable value from agent session.
 *
 * The format is a tagged string with agent metadata:
 * n:<name>|v:<version>|p:<provider>.
 *
 * Precedence: explicit process.env.SHOPIFY_CLI_AGENT_INFO takes priority over
 * persisted session state.
 *
 * @param session - Optional session to pack from. If not provided, uses current session.
 * @param config - Optional config store for testing.
 * @returns Tagged string for SHOPIFY_CLI_AGENT_INFO, or undefined if no data available.
 */
export declare function packAgentInfo(session?: AgentSession, config?: LocalStorage<ConfSchema>): string | undefined;
/**
 * Pack SHOPIFY_CLI_AGENT_IDS environment variable value from agent session.
 *
 * The format is a tagged string with session identifier:
 * s:<sessionId>.
 *
 * Precedence: explicit process.env.SHOPIFY_CLI_AGENT_IDS takes priority over
 * persisted session state.
 *
 * @param session - Optional session to pack from. If not provided, uses current session.
 * @param config - Optional config store for testing.
 * @returns Tagged string for SHOPIFY_CLI_AGENT_IDS, or undefined if no data available.
 */
export declare function packAgentIds(session?: AgentSession, config?: LocalStorage<ConfSchema>): string | undefined;

Existing type declarations

packages/cli-kit/dist/private/node/conf-store.d.ts
@@ -18,11 +18,22 @@ interface Cache {
     [mostRecentOccurrenceKey: MostRecentOccurrenceKey]: CacheValue<boolean>;
     [rateLimitKey: RateLimitKey]: CacheValue<number[]>;
 }
+export interface AgentSession {
+    sessionId: string;
+    startedAt: string;
+    agentName: string;
+    agentVersion: string;
+    agentProvider: string;
+    metricsMode: 'on' | 'off';
+    defaultNonInteractive: boolean;
+}
 export interface ConfSchema {
     sessionStore: string;
     currentSessionId?: string;
     devSessionStore?: string;
     currentDevSessionId?: string;
+    currentAgentSession?: AgentSession;
+    devAgentSession?: AgentSession;
     cache?: Cache;
     autoUpgradeEnabled?: boolean;
 }
@@ -128,7 +139,8 @@ interface RunWithRateLimitOptions {
 export declare function runWithRateLimit(options: RunWithRateLimitOptions, config?: LocalStorage<ConfSchema>): Promise<boolean>;
 /**
  * Get auto-upgrade preference.
- * Defaults to true if the preference has never been explicitly set.
+ *
+ * Auto-upgrade is enabled by default when the preference has never been set.
  *
  * @returns Whether auto-upgrade is enabled.
  */
@@ -145,4 +157,20 @@ export declare function getConfigStoreForPartnerStatus(): LocalStorage<Record<st
 }>>;
 export declare function getCachedPartnerAccountStatus(partnersToken: string): true | null;
 export declare function setCachedPartnerAccountStatus(partnersToken: string): void;
+/**
+ * Get current agent session.
+ *
+ * @returns Current agent session.
+ */
+export declare function getAgentSession(config?: LocalStorage<ConfSchema>): AgentSession | undefined;
+/**
+ * Set current agent session.
+ *
+ * @param session - Agent session.
+ */
+export declare function setAgentSession(session: AgentSession, config?: LocalStorage<ConfSchema>): void;
+/**
+ * Remove current agent session.
+ */
+export declare function removeAgentSession(config?: LocalStorage<ConfSchema>): void;
 export {};
\ No newline at end of file

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

This PR seems inactive. If it's still relevant, please add a comment saying so. Otherwise, take no action.
→ If there's no activity within a week, then a bot will automatically close this.
Thanks for helping to improve Shopify's dev tooling and experience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: @shopify/cli @shopify/cli package issues no-pr-activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant