{"record":{"id":"56a1cc8f1fafdf35","repo":"TencentCloud/TencentDB-Agent-Memory","slug":"llm-provider-proxy-llm-baseurl-context-proxy-56a1cc","errorCode":null,"errorMessage":"llm.provider=proxy 需要 llm.baseUrl 指向 context_proxy 根 URL (如 http://127.0.0.1:8096)","messagePattern":"llm\\.provider=proxy 需要 llm\\.baseUrl 指向 context_proxy 根 URL \\(如 http://127\\.0\\.0\\.1:8096\\)","errorType":"validation","errorClass":"LlmResolveError","httpStatus":null,"severity":"error","filePath":"MemoryCore/src/gateway/llm-resolver.ts","lineNumber":55,"sourceCode":" * @param memorySystemUser 已解析的 memory 系统用户配置（可选，仅 provider=proxy 且\n *                         useMemorySystemUserKey=true 时使用）\n *\n * @throws {LlmResolveError} provider=proxy 但缺失必要配置时\n */\nexport function resolveEffectiveLlmConfig(\n  llm: StandaloneLLMConfig,\n  instanceId: string | undefined,\n  memorySystemUser: MemorySystemUserConfig | undefined,\n): StandaloneLLMConfig {\n  const provider = llm.provider ?? \"openai\";\n  if (provider !== \"proxy\") {\n    // 默认路径：原样返回，行为完全等价改造前\n    return llm;\n  }\n\n  // provider=proxy 的校验\n  if (!llm.baseUrl) {\n    throw new LlmResolveError(\n      \"llm.provider=proxy 需要 llm.baseUrl 指向 context_proxy 根 URL (如 http://127.0.0.1:8096)\",\n    );\n  }\n  if (!instanceId || !instanceId.trim()) {\n    throw new LlmResolveError(\n      \"llm.provider=proxy 需要 instanceId，但 core 当前 instanceId 为空 —— \" +\n      \"service 模式下确保请求带 x-tdai-service-id，standalone 模式下确保 yaml 有 instanceId\",\n    );\n  }\n\n  const useSystemUserKey = llm.proxy?.useMemorySystemUserKey ?? true;\n  let effectiveApiKey = llm.apiKey;\n  if (useSystemUserKey) {\n    if (!memorySystemUser) {\n      throw new LlmResolveError(\n        \"llm.provider=proxy 且 llm.proxy.useMemorySystemUserKey=true 需要 \" +\n        \"metadata.systemUser.memory 完整配置（userId + userKey），当前缺失\",\n      );","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/3efcd317b84146d6a08518ac0f7ee7c8a8d200ec/MemoryCore/src/gateway/llm-resolver.ts#L37-L73","documentation":"When llm.provider is set to \"proxy\", resolveEffectiveLlmConfig requires llm.baseUrl to point at the context_proxy root URL, because all LLM calls are rewritten to <baseUrl>/proxy/<iid>/v1. If baseUrl is missing/empty, the gateway cannot build the proxy endpoint and throws LlmResolveError.","triggerScenarios":"Configuring llm: { provider: proxy } in the gateway yaml (or runtime LLM config) without llm.baseUrl, or with baseUrl: \"\" after a migration from direct provider mode.","commonSituations":"Switching provider from \"openai\"/direct to \"proxy\" but deleting the old baseUrl; copying a config snippet that omitted baseUrl; forgetting that provider=proxy ignores provider-specific hosts and requires the context_proxy service address (e.g. http://127.0.0.1:8096).","solutions":["Set llm.baseUrl to the context_proxy root, e.g. baseUrl: http://127.0.0.1:8096 (no trailing path like /v1 — the resolver appends /proxy/<iid>/v1).","Ensure the context_proxy service is deployed and its address is reachable from MemoryCore.","If you don't intend to use the proxy, set llm.provider back to the direct provider (e.g. openai) with its own baseUrl/apiKey."],"exampleFix":"// before\nllm:\n  provider: proxy\n  apiKey: sk-...\n// after\nllm:\n  provider: proxy\n  baseUrl: http://127.0.0.1:8096\n  apiKey: sk-...","handlingStrategy":"validation","validationCode":"if (llmConfig.provider === 'proxy' && (!llmConfig.baseUrl || !llmConfig.baseUrl.trim())) {\n  throw new Error('llm.provider=proxy requires llm.baseUrl, e.g. http://127.0.0.1:8096');\n}","typeGuard":"function hasProxyBaseUrl(llm: { provider: string; baseUrl?: string }): llm is typeof llm & { baseUrl: string } {\n  return llm.provider !== 'proxy' || (typeof llm.baseUrl === 'string' && llm.baseUrl.length > 0);\n}","tryCatchPattern":"try {\n  gateway.start();\n} catch (err) {\n  if (err instanceof LlmResolveError && err.message.includes('llm.baseUrl')) {\n    console.error('Set llm.baseUrl to the context_proxy root URL');\n  }\n  throw err;\n}","preventionTips":["Keep a config template with baseUrl present whenever provider: proxy","Remember baseUrl is the proxy ROOT (no /v1 suffix); the resolver appends /proxy/<iid>/v1","Validate the full llm block before deploying config overlays","Smoke-test gateway startup in staging after provider changes"],"tags":["configuration","llm-proxy","startup"],"backgroundTag":"missing-config-field","analyzedSha":"3efcd317b84146d6a08518ac0f7ee7c8a8d200ec","analyzedAt":"2026-09-01T05:44:22.276Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}