Skip to content

Gateway re-scans plugin metadata during model normalization #78461

Description

@ginishuh

Summary

Gateway-owned plugin metadata snapshots are not always reused during model alias / manifest model-id normalization. In a workspace-scoped gateway runtime, resolveDefaultModelForAgent() can fall back to loadPluginMetadataSnapshot() during every embedded agent attempt, causing repeated plugin index / manifest discovery in the Node gateway process.

Observed impact

On a live gateway running OpenClaw 2026.5.4 (70d92b5), embedded agent prep repeatedly logged:

prep stages ... totalMs=15513
system-prompt:openclaw-reference-paths:8788ms

An inspector CPU profile showed the time was not actually reference-path lookup; the marker included the preceding model resolution path:

runEmbeddedAttempt
resolveDefaultModelForAgent
resolveConfiguredModelRef
buildModelAliasIndex
parseModelRefWithCompatAlias
parseModelRef
normalizeProviderModelId
loadManifestModelIdNormalizationPolicies
resolveMetadataSnapshotForPolicies
loadPluginMetadataSnapshot
loadPluginRegistrySnapshotWithMetadata
loadInstalledPluginIndex
discoverOpenClawPlugins

This made every agent turn pay a large fixed cost before the stream was ready, and contributed to gateway event-loop pressure.

Root cause

The gateway sets the current plugin metadata snapshot without the gateway workspace:

setCurrentPluginMetadataSnapshot(pluginLookUpTable, { config: gatewayPluginConfigAtStart });

But manifest model-id normalization resolves the active registry workspace:

const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDirFromState();
const current = getCurrentPluginMetadataSnapshot({ config, env, workspaceDir });

That can make the current snapshot lookup miss even though the gateway already has a valid metadata snapshot for the running plugin set. When it misses, the normalization path reloads plugin metadata instead of reusing the gateway-owned snapshot.

Suggested fix

Two small changes fixed the live repro locally:

  1. Include defaultWorkspaceDir when handing off the current metadata snapshot at gateway startup and reload:
setCurrentPluginMetadataSnapshot(pluginLookUpTable, {
  config: gatewayPluginConfigAtStart,
  workspaceDir: defaultWorkspaceDir,
});
  1. In manifest model-id normalization, when the caller did not explicitly request a workspace, allow reuse of a workspace-scoped current snapshot:
const workspaceScopedCurrent = getCurrentPluginMetadataSnapshot({
  config: params.config,
  env,
  allowWorkspaceScopedSnapshot: true,
});

Validation from local patch

After applying the above locally:

  • The per-turn prep stages totalMs=15513-16467 warnings stopped appearing.
  • A shira embedded agent smoke completed successfully with OK.
  • Targeted tests passed:
node scripts/test-projects.mjs \
  src/plugins/current-plugin-metadata-snapshot.test.ts \
  src/plugins/manifest-model-id-normalization.test.ts \
  src/agents/pi-embedded-runner/run/attempt-stage-timing.test.ts

Test Files 3 passed
Tests 18 passed

Also passed:

pnpm tsgo:core
pnpm build

Version notes

I also inspected the published [email protected] tarball. The dist bundle still appears to call:

setCurrentPluginMetadataSnapshot(pluginLookUpTable, { config: gatewayPluginConfigAtStart });
setCurrentPluginMetadataSnapshot(nextPluginLookUpTable, { config: params.nextConfig });

So this does not appear fixed in 2026.5.5.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions