-
-
Notifications
You must be signed in to change notification settings - Fork 80.7k
perf: per-request auth (5.5s) and tool bundling (8.9s) dominate gateway TTFT #80131
Copy link
Copy link
Open
Labels
P2Normal backlog priority with limited blast radius.Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.ClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.ClawSweeper needs live local, crabbox, or manual validation to confirm this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.ClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.ClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.Auth, provider routing, model choice, or SecretRef resolution may break.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.This issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.Good issue quality with a plausible reproduction path needing some confirmation.
Description
Metadata
Metadata
Assignees
Labels
P2Normal backlog priority with limited blast radius.Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.ClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.ClawSweeper needs live local, crabbox, or manual validation to confirm this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.ClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.ClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.Auth, provider routing, model choice, or SecretRef resolution may break.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.This issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.Good issue quality with a plausible reproduction path needing some confirmation.
Type
Fields
Priority
None yet
Summary
Profiling the embedded-run pipeline on a Mac mini M4 (24GB RAM, openclaw 2026.5.7, primary
google/gemini-3.1-pro-previewvia Vertex SA) shows that ~14 of every ~43 seconds of time-to-first-token is spent on work that doesn't change between requests:authattempt-dispatchcore-plugin-toolsbundle-toolssystem-promptstream-setupNetwork RTT to all relevant endpoints is 9-32ms — none of the 42s comes from raw network.
This issue covers the two stages where the work is most clearly redundant:
authandbundle-tools/core-plugin-tools.Problem 1:
authre-resolves Vertex SA token every request (5.5s)Evidence:
/tmp/google-sa-token.cacheis rarely refreshed, suggesting the underlying token IS being cached somewhereauthstage still takes 5.5s on every request, including back-to-back requestsThe most likely cause is the google-auth-library-nodejs cache being instance-scoped —
cachedCredentiallives on theGoogleAuthinstance. If openclaw constructs a newGoogleAuth(...)per request, the underlying token cache is discarded each time. See issue #390: "getClient ignores credentials when cached".Compounding this is issue #49:
getRequestMetadata()historically re-signed JWTs on every call. UsegetAccessToken()instead.Proposal 1: Singleton GoogleAuth, eager-warmed at boot
Pre-warm at gateway boot so first request doesn't pay the JWT-sign cost.
Expected impact: 5.5s → ~5ms for cache hits (≥99% of requests after warmup).
Problem 2: Tool bundling re-runs static work every request (8.9s)
core-plugin-tools(3.9s) +bundle-tools(5.0s) = 8.9s spent re-loading and re-serializing tool definitions that don't change between requests.Likely contributors (in order of probability):
new Function(), 17x slower at creation than v3. With ~50 tools and nested schemas, rebuild seconds.require.cacheinvalidation for hot-reload — if the loader explicitlydelete require.cache[...]to support plugin reload, every request re-parses every plugin file.This is the same pattern other LLM gateways have moved away from:
WeakMapfor Zod-conversion memoization (per their docs)cache_tools_list=True+invalidate_tools_cache()— "set to True only if you are confident that the tool definitions do not change frequently"Proposal 2: Module-scope tool memoization with explicit invalidation hook
Stable JSON output also unlocks Anthropic prompt caching (cache_control on the last tool entry → 90% input-token cost reduction on the tool prefix) and Vertex context caching. See Anthropic Prompt Caching docs — "verify that the keys in your
tool_usecontent blocks have stable ordering as some languages randomize key order during JSON conversion, breaking caches".Expected impact: 8.9s → <50ms after first build.
Combined potential
If both proposals land, gateway TTFT drops from ~43s to ~28s on this workload — without functional changes. Plus a separate ~1s win from connection keep-alive (
undiciglobal dispatcher withallowH2) which I'm not raising here since it's a more invasive transport change.Tradeoffs
invalidateTools()SIGHUP hook — moves invalidation off the request path while preserving the feature for users who want it.eagerRefreshThresholdMilliskeeps tokens fresh; revoked SAs can keep working for ~55min, which is the SDK's default behavior anyway.Environment
google/gemini-3.1-pro-preview(Vertex SA via service-account file)Happy to test patches if anyone takes this on, or to open a PR myself if there's interest in the approach.
Sources