{"record":{"id":"058b19c01024df1a","repo":"FoundationAgents/MetaGPT","slug":"spo-llm-not-initialized-call-initialize-first","errorCode":null,"errorMessage":"SPO_LLM not initialized. Call initialize() first.","messagePattern":"SPO_LLM not initialized\\. Call initialize\\(\\) first\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"metagpt/ext/spo/utils/llm_client.py","lineNumber":76,"sourceCode":"        }\n\n        llm = llm_mapping.get(request_type)\n        if not llm:\n            raise ValueError(f\"Invalid request type. Valid types: {', '.join([t.value for t in RequestType])}\")\n\n        response = await llm.acompletion(messages)\n        return response.choices[0].message.content\n\n    @classmethod\n    def initialize(cls, optimize_kwargs: dict, evaluate_kwargs: dict, execute_kwargs: dict) -> None:\n        \"\"\"Initialize the global instance\"\"\"\n        cls._instance = cls(optimize_kwargs, evaluate_kwargs, execute_kwargs)\n\n    @classmethod\n    def get_instance(cls) -> \"SPO_LLM\":\n        \"\"\"Get the global instance\"\"\"\n        if cls._instance is None:\n            raise RuntimeError(\"SPO_LLM not initialized. Call initialize() first.\")\n        return cls._instance\n\n\ndef extract_content(xml_string: str, tag: str) -> Optional[str]:\n    pattern = rf\"<{tag}>(.*?)</{tag}>\"\n    match = re.search(pattern, xml_string, re.DOTALL)\n    return match.group(1).strip() if match else None\n\n\nasync def main():\n    # test LLM\n    SPO_LLM.initialize(\n        optimize_kwargs={\"model\": \"gpt-4o\", \"temperature\": 0.7},\n        evaluate_kwargs={\"model\": \"gpt-4o-mini\", \"temperature\": 0.3},\n        execute_kwargs={\"model\": \"gpt-4o-mini\", \"temperature\": 0.3},\n    )\n\n    llm = SPO_LLM.get_instance()","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/ext/spo/utils/llm_client.py#L58-L94","documentation":"SPO_LLM is a singleton with a lazily set class-level _instance; get_instance() raises RuntimeError if initialize(optimize_kwargs, evaluate_kwargs, execute_kwargs) has not been called yet in the process. It guards against using the SPO pipeline before its three LLM roles are configured.","triggerScenarios":"Calling SPO_LLM.get_instance() (directly, or indirectly via the SPO evaluator/optimizer components) before any SPO_LLM.initialize(...) call; running in a fresh subprocess or after resetting the class where initialize was skipped.","commonSituations":"Starting a new Python session / notebook kernel and jumping straight to prompt optimization; scripts that import the pipeline components but only conditionally call initialize; tests that instantiate SPO objects without the global setup.","solutions":["Call SPO_LLM.initialize(optimize_kwargs, evaluate_kwargs, execute_kwargs) once at startup, before any component that uses get_instance().","If it may already be initialized (notebooks, repeated runs), guard with a check on SPO_LLM._instance before calling initialize.","In tests, put initialize in a fixture/setup so every test session has the singleton configured."],"exampleFix":"// before\nllm = SPO_LLM.get_instance()  # RuntimeError: not initialized\n\n// after\nSPO_LLM.initialize(\n    optimize_kwargs={\"model\": \"gpt-4o\"},\n    evaluate_kwargs={\"model\": \"gpt-4o-mini\"},\n    execute_kwargs={\"model\": \"gpt-4o-mini\"},\n)\nllm = SPO_LLM.get_instance()","handlingStrategy":"validation","validationCode":"from metagpt.ext.spo.utils.llm_client import SPO_LLM\n\ndef ensure_spo_llm(**kwargs_sets) -> SPO_LLM:\n    if SPO_LLM._instance is None:\n        SPO_LLM.initialize(**kwargs_sets)\n    return SPO_LLM.get_instance()","typeGuard":null,"tryCatchPattern":"try:\n    llm = SPO_LLM.get_instance()\nexcept RuntimeError as e:\n    if \"not initialized\" in str(e):\n        SPO_LLM.initialize(opt_kwargs, eva_kwargs, exe_kwargs)\n        llm = SPO_LLM.get_instance()\n    else:\n        raise","preventionTips":["Centralize SPO_LLM.initialize in application bootstrap (main/session start), never mid-pipeline.","In tests, initialize via a session fixture."],"tags":["initialization","singleton","spo","lifecycle"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}