Repository: browserbase/stagehand
File: packages/core/lib/v3/handlers/v3AgentHandler.ts (TypeScript)

Code before:
  private systemInstructions?: string;
  private mcpTools?: ToolSet;
  private mode: AgentToolMode;

  constructor(
    v3: V3,
    logger: (message: LogLine) => void,
    llmClient: LLMClient,
    executionModel?: string,
    systemInstructions?: string,
    mcpTools?: ToolSet,
    mode?: AgentToolMode,
  ) {
    this.v3 = v3;
    this.logger = logger;
    this.llmClient = llmClient;
    this.executionModel = executionModel;
    this.systemInstructions = systemInstructions;
    this.mcpTools = mcpTools;
    this.mode = mode ?? "dom";

    if (this.mode === "dom") {
      this.logger({
        category: "agent",
        message:
          "Using DOM mode (legacy). Consider using mode: 'hybrid' for improved performance.\n  → https://docs.stagehand.dev/v3/basics/agent\n",
        level: 0,
      });
    }
  }

  private async prepareAgent(
    instructionOrOptions: string | AgentExecuteOptionsBase,
  ): Promise<AgentContext> {
    try {
      const options =
        typeof instructionOrOptions === "string"
          ? { instruction: instructionOrOptions }
          : instructionOrOptions;

      const maxSteps = options.maxSteps || 20;

      // Get the initial page URL first (needed for the system prompt)
      const initialPageUrl = (await this.v3.context.awaitActivePage()).url();

      // Build the system prompt with mode-aware tool guidance
      const systemPrompt = buildAgentSystemPrompt({
        url: initialPageUrl,
        executionInstruction: options.instruction,
        mode: this.mode,
        systemInstructions: this.systemInstructions,

Review comment (performance):
we should say 
```suggestion
          "Using default DOM mode in agent (legacy). Consider using mode: 'hybrid' for improved performance.\n  → https://docs.stagehand.dev/v3/basics/agent\n",
```

Code after:
  private systemInstructions?: string;
  private mcpTools?: ToolSet;
  private mode: AgentToolMode;

  constructor(
    v3: V3,
    logger: (message: LogLine) => void,
    llmClient: LLMClient,
    executionModel?: string,
    systemInstructions?: string,
    mcpTools?: ToolSet,
    mode?: AgentToolMode,
  ) {
    this.v3 = v3;
    this.logger = logger;
    this.llmClient = llmClient;
    this.executionModel = executionModel;
    this.systemInstructions = systemInstructions;
    this.mcpTools = mcpTools;
    this.mode = mode ?? "dom";
  }

  private async prepareAgent(
    instructionOrOptions: string | AgentExecuteOptionsBase,
  ): Promise<AgentContext> {
    try {
      const options =
        typeof instructionOrOptions === "string"
          ? { instruction: instructionOrOptions }
          : instructionOrOptions;

      const maxSteps = options.maxSteps || 20;

      // Get the initial page URL first (needed for the system prompt)
      const initialPageUrl = (await this.v3.context.awaitActivePage()).url();

      // Build the system prompt with mode-aware tool guidance
      const systemPrompt = buildAgentSystemPrompt({
        url: initialPageUrl,
        executionInstruction: options.instruction,
        mode: this.mode,
        systemInstructions: this.systemInstructions,
        isBrowserbase: this.v3.isBrowserbase,
        excludeTools: options.excludeTools,
      });

      const tools = this.createTools(options.excludeTools);
      const allTools: ToolSet = { ...tools, ...this.mcpTools };

      // Use provided messages for continuation, or start fresh with the instruction
      const messages: ModelMessage[] = options.messages?.length