perf(agents): reduce repeated turn setup latency (#105220)

* perf(agents): reuse prepared auth route models

* chore: leave release notes to release automation
This commit is contained in:
Peter Steinberger
2026-07-12 10:21:31 +01:00
committed by GitHub
parent 9bdb2a5ac0
commit b4a0fc5c57
2 changed files with 42 additions and 7 deletions
@@ -1922,6 +1922,7 @@ describe("runEmbeddedAgent overflow compaction trigger routing", () => {
}
expect(mockedGetApiKeyForModel).toHaveBeenCalledTimes(1);
expect(mockedResolveModelAsync).toHaveBeenCalledTimes(1);
expect(mockedBuildAgentRuntimePlan).toHaveBeenCalledTimes(1);
expect(authStorage.setRuntimeApiKey).toHaveBeenCalledTimes(1);
const pluginParams = expectMockCallFields(pluginRunAttempt, {
@@ -2840,11 +2841,6 @@ describe("runEmbeddedAgent overflow compaction trigger routing", () => {
baseUrl: "https://api.openai.com/v1",
authStorage,
});
queueOpenAIResolvedModel({
api: "openai-responses",
baseUrl: "https://api.openai.com/v1",
authStorage,
});
queueOpenAIResolvedModel({
api: "openai-chatgpt-responses",
baseUrl: "https://chatgpt.com/backend-api/codex",
@@ -2906,6 +2902,7 @@ describe("runEmbeddedAgent overflow compaction trigger routing", () => {
}
expect(mockedGetApiKeyForModel).toHaveBeenCalledOnce();
expect(mockedResolveModelAsync).toHaveBeenCalledTimes(3);
expect(pluginRunAttempt).toHaveBeenCalledTimes(2);
const firstAttempt = mockCallArg(pluginRunAttempt) as EmbeddedRunAttemptParams;
const secondAttempt = mockCallArg(pluginRunAttempt, 1) as EmbeddedRunAttemptParams;
+40 -2
View File
@@ -1495,6 +1495,7 @@ async function runEmbeddedAgentInternal(
agentHarness = selectHarnessForModel(effectiveModel);
pluginHarnessOwnsTransport = agentHarness.id !== "openclaw";
const authStages = log.isEnabled("trace") ? createEmbeddedRunStageTracker() : undefined;
const usesOpenAIAuthRouting = provider === OPENAI_PROVIDER_ID;
const openClawNativeCodexResponsesNeedsAuthBootstrap =
!pluginHarnessOwnsTransport &&
@@ -1532,6 +1533,7 @@ async function runEmbeddedAgentInternal(
params.authProfileIdSource === "user" ? params.authProfileId : undefined,
});
}
authStages?.mark("scope");
const attemptAuthProfileStore = usesOpenAIAuthRouting
? ensureAuthProfileStore(agentDir, {
externalCliProviderIds: [OPENAI_PROVIDER_ID],
@@ -1550,6 +1552,7 @@ async function runEmbeddedAgentInternal(
ensureAuthProfileStoreWithoutExternalProfiles(agentDir, {
allowKeychainPrompt: false,
}));
authStages?.mark("store");
const requestedProfileId = params.authProfileId?.trim() || undefined;
const lockedProfileId =
params.authProfileIdSource === "user" ? requestedProfileId : undefined;
@@ -1586,12 +1589,19 @@ async function runEmbeddedAgentInternal(
}),
});
const materializeAuthPlan = async (plan: AgentRuntimeAuthPlan) => {
const materializedRouteModels = new WeakMap<
AgentRuntimeAuthPlan,
Promise<typeof runtimeModel>
>();
const materializeAuthPlanUncached = async (plan: AgentRuntimeAuthPlan) => {
// Native harness sessions own their model tuple. Route preparation may
// attest auth/transport, but must not rediscover or replace that model.
if (nativeModelOwned) {
return runtimeModel;
}
const requiresCredentialScopedResolve = Boolean(
plan.modelRoute && (plan.forwardedAuthProfileId || params.authProfileId),
);
return (
(await materializePreparedRuntimeModel({
plan,
@@ -1599,7 +1609,9 @@ async function runEmbeddedAgentInternal(
modelId,
config: params.config,
model: runtimeModel,
forceResolve: Boolean(plan.modelRoute),
// Unscoped direct auth cannot change credential-scoped metadata.
// Reuse an already matching tuple; route mismatches still resolve.
forceResolve: requiresCredentialScopedResolve,
resolveModel: ({ config, authProfileId, authProfileMode }) =>
resolveModelAsync(provider, modelId, agentDir, config, {
authStorage,
@@ -1614,10 +1626,25 @@ async function runEmbeddedAgentInternal(
})) ?? runtimeModel
);
};
const materializeAuthPlan = (plan: AgentRuntimeAuthPlan) => {
if (!plan.modelRoute) {
return materializeAuthPlanUncached(plan);
}
const cached = materializedRouteModels.get(plan);
if (cached) {
return cached;
}
// Prepared plans are immutable within one run. Carry their exact model
// tuple into auth initialization instead of repeating provider discovery.
const materialized = materializeAuthPlanUncached(plan);
materializedRouteModels.set(plan, materialized);
return materialized;
};
let resolvedAuthPreparation = createAuthPreparation();
let preparedAuthAttempts = resolvedAuthPreparation.attempts;
let activePreparedAuthPlan = resolvedAuthPreparation.plan;
applyResolvedRuntimeModel(await materializeAuthPlan(activePreparedAuthPlan));
authStages?.mark("prepare-plan");
const finalizedHarness = selectHarnessForPreparedAttempts(
effectiveModel,
@@ -1640,6 +1667,7 @@ async function runEmbeddedAgentInternal(
);
}
}
authStages?.mark("harness");
// A selected plugin harness owns context pressure with its native transcript,
// even if it cannot expose manual compaction. Generic recovery is OpenClaw-only.
const genericCompactionRecoveryAllowed = !pluginHarnessOwnsTransport;
@@ -1851,6 +1879,7 @@ async function runEmbeddedAgentInternal(
},
log,
});
authStages?.mark("controller");
const advancePluginHarnessAuthAttempt = async (): Promise<boolean> => {
if (!pluginHarnessOwnsTransport || lockedProfileId) {
return false;
@@ -1951,6 +1980,15 @@ async function runEmbeddedAgentInternal(
lastProfileId = forwardedPluginHarnessProfileId;
}
}
authStages?.mark("initialize");
if (authStages) {
log.trace(
formatEmbeddedRunStageSummary(
`[trace:embedded-run] auth stages: runId=${params.runId} sessionId=${params.sessionId} phase=auth`,
authStages.snapshot(),
),
);
}
startupStages.mark("auth");
notifyExecutionPhase("auth", { provider, model: modelId });
const resolveRunAttemptAuthProfileStore = (): AuthProfileStore => {