diff --git a/packages/agent-runtime/src/pi/bridge/bridge.ts b/packages/agent-runtime/src/pi/bridge/bridge.ts
index cdac5438d..667774fa4 100644
--- a/packages/agent-runtime/src/pi/bridge/bridge.ts
+++ b/packages/agent-runtime/src/pi/bridge/bridge.ts
@@ -50,6 +50,7 @@ import type { ImageContent } from "@earendil-works/pi-ai";
 import { createPiDeltaTranslator } from "../delta-translation.js";
 import {
   buildPiSessionParams,
+  toPiThinkingLevel,
   type PiSessionParams,
 } from "../session-params.js";
 import { PiSdkSession, type PiSdkSessionOptions } from "./sdk-session.js";
@@ -971,6 +972,20 @@ async function handleTurnStart(
     return;
   }
 
+  // Execution options ride every turn command and the runtime never diffs
+  // them (#2160): a model or reasoning level picked after the session was
+  // constructed is applied to the live session here, before dispatch.
+  try {
+    await threadSession.session.applyTurnOptions({
+      model: params.options.model,
+      thinkingLevel: toPiThinkingLevel(params.options.reasoningLevel),
+    });
+  } catch (error) {
+    const message = error instanceof Error ? error.message : String(error);
+    sendError(id, -32000, message);
+    return;
+  }
+
   // A standalone builtin `/compact` mention is bb's manual-compaction request,
   // not model input. Prompting with the literal text would make the model talk
   // about compaction while the context keeps growing.
diff --git a/packages/agent-runtime/src/pi/bridge/sdk-session.ts b/packages/agent-runtime/src/pi/bridge/sdk-session.ts
index df3d8ad07..b1b79ad17 100644
--- a/packages/agent-runtime/src/pi/bridge/sdk-session.ts
+++ b/packages/agent-runtime/src/pi/bridge/sdk-session.ts
@@ -435,6 +435,49 @@ export class PiSdkSession {
     this.monitorSteerConsumption(tracked.promise);
   }
 
+  /**
+   * Reconcile the execution options a turn command carries with the live
+   * session. Options ride every command (the runtime never diffs them), so a
+   * model or thinking level the user changed after construction is applied
+   * here, before the input is dispatched. Unchanged values are a no-op.
+   */
+  async applyTurnOptions(args: {
+    model: string | undefined;
+    thinkingLevel: CreateAgentSessionOptions["thinkingLevel"] | undefined;
+  }): Promise<void> {
+    if (!this.session) {
+      throw new Error("No active Pi SDK session");
+    }
+    if (args.model !== undefined) {
+      const next = resolveConfiguredModel(this.session.modelRuntime, args.model);
+      const current = this.session.model;
+      if (
+        next &&
+        (current === undefined ||
+          current.provider !== next.provider ||
+          current.id !== next.id)
+      ) {
+        this.recordSdkBoundary("bridge→provider", {
+          method: "setModel",
+          params: { provider: next.provider, id: next.id },
+        });
+        await this.session.setModel(next);
+        this.options.model = args.model;
+      }
+    }
+    if (
+      args.thinkingLevel !== undefined &&
+      args.thinkingLevel !== this.session.thinkingLevel
+    ) {
+      this.recordSdkBoundary("bridge→provider", {
+        method: "setThinkingLevel",
+        params: { level: args.thinkingLevel },
+      });
+      this.session.setThinkingLevel(args.thinkingLevel);
+      this.options.thinkingLevel = args.thinkingLevel;
+    }
+  }
+
   async compact(): Promise<void> {
     if (!this.session) {
       throw new Error("No active Pi SDK session");
diff --git a/packages/agent-runtime/src/pi/session-params.ts b/packages/agent-runtime/src/pi/session-params.ts
index d0e07b03e..fa0fef9ca 100644
--- a/packages/agent-runtime/src/pi/session-params.ts
+++ b/packages/agent-runtime/src/pi/session-params.ts
@@ -13,7 +13,7 @@ type PiReasoningLevel = "off" | "low" | "medium" | "high" | "xhigh" | "max";
 // Levels Pi does not support ("ultracode", "ultra") are dropped so the bridge
 // never receives a value it would reject; reconciliation picks the closest
 // supported level before this point, so this is a defensive floor.
-function toPiThinkingLevel(
+export function toPiThinkingLevel(
   reasoningLevel: ReasoningLevel | undefined,
 ): PiReasoningLevel | undefined {
   switch (reasoningLevel) {
