fix: allow agent modules to import without OPENAI_API_KEY set (fixes #412)

Agent modules that use AsyncOpenAI() at module level fail at import time
when OPENAI_API_KEY is not set (e.g. when using Ollama). This causes the
/agent listing command to crash with an unhelpful error rather than a
clear message about the missing key.

Use os.getenv("OPENAI_API_KEY", "sk-placeholder") so modules can always
be imported; the key is only validated when an actual API call is made.
Also fix memory.py which was missing the AsyncOpenAI import and using an
undefined model_name variable.

Co-Authored-By: Octopus <liyuan851277048@icloud.com>
This commit is contained in:
octo-patch 2026-04-26 09:21:20 +08:00
parent 603af3f16d
commit ae715ca15a
13 changed files with 18 additions and 16 deletions

View File

@ -41,7 +41,7 @@ app_logic_mapper = Agent(
tools=tools,
model=OpenAIChatCompletionsModel(
model=model_name,
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
),
)
@ -61,7 +61,7 @@ android_sast = Agent(
],
model=OpenAIChatCompletionsModel(
model=model_name,
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
),
)

View File

@ -44,7 +44,7 @@ blueteam_agent = Agent(
Expert in cybersecurity protection and incident response.""",
model=OpenAIChatCompletionsModel(
model=os.getenv('CAI_MODEL', "alias1"),
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
),
tools=tools,
)

View File

@ -63,7 +63,7 @@ dfir_agent = Agent(
Expert in investigation and analysis of digital evidence.""",
model=OpenAIChatCompletionsModel(
model=os.getenv('CAI_MODEL', "alias1"),
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
),
tools=tools,

View File

@ -82,11 +82,13 @@ Environment Variables enabling the episodic memory store
"""
import os
from openai import AsyncOpenAI
from cai.sdk.agents import Agent, OpenAIChatCompletionsModel
from cai.tools.misc.rag import add_to_memory_semantic, add_to_memory_episodic
# Get model from environment or use default
model = os.getenv('CAI_MODEL', "alias1")
model_name = model
def get_previous_steps(query: str) -> str:
@ -198,7 +200,7 @@ semantic_builder = Agent(
tools=[add_to_memory_semantic],
model=OpenAIChatCompletionsModel(
model=model_name,
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
)
)
@ -213,7 +215,7 @@ episodic_builder = Agent(
tools=[add_to_memory_episodic],
model=OpenAIChatCompletionsModel(
model=model_name,
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
)
)
@ -227,6 +229,6 @@ query_agent = Agent(
temperature=0,
model=OpenAIChatCompletionsModel(
model=model_name,
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
)
)

View File

@ -44,6 +44,6 @@ memory_analysis_agent = Agent(
tools=functions,
model=OpenAIChatCompletionsModel(
model=os.getenv('CAI_MODEL', "alias1"),
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
)
)

View File

@ -77,7 +77,7 @@ network_security_analyzer_agent = Agent(
Expert in monitoring, capturing, and analyzing network communications for security threats.""",
model=OpenAIChatCompletionsModel(
model=os.getenv('CAI_MODEL', "alias1"),
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
),
tools=tools,
handoffs=[ # Handoff to DFIR agent for further analysis

View File

@ -69,7 +69,7 @@ replay_attack_agent = Agent(
Expert in packet manipulation, traffic replay, and protocol exploitation.""",
model=OpenAIChatCompletionsModel(
model=os.getenv('CAI_MODEL', "alias1"),
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
),
tools=tools,
)

View File

@ -32,6 +32,6 @@ reporting_agent = Agent(
tools=functions,
model=OpenAIChatCompletionsModel(
model=os.getenv('CAI_MODEL', "alias1"),
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
)
)

View File

@ -45,6 +45,6 @@ reverse_engineering_agent = Agent(
tools=functions,
model=OpenAIChatCompletionsModel(
model=os.getenv('CAI_MODEL', "alias1"),
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
)
)

View File

@ -44,6 +44,6 @@ subghz_sdr_agent = Agent(
tools=functions,
model=OpenAIChatCompletionsModel(
model=os.getenv('CAI_MODEL', "alias1"),
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
)
)

View File

@ -37,7 +37,7 @@ use_case_agent = Agent(
tools=tools,
model=OpenAIChatCompletionsModel(
model=model_name,
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
),
)

View File

@ -52,7 +52,7 @@ web_pentester_agent = Agent(
output_guardrails=output_guardrails,
model=OpenAIChatCompletionsModel(
model=model_name,
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
),
)

View File

@ -43,6 +43,6 @@ wifi_security_agent = Agent(
tools=functions,
model=OpenAIChatCompletionsModel(
model=os.getenv('CAI_MODEL', "alias1"),
openai_client=AsyncOpenAI(),
openai_client=AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY", "sk-placeholder")),
)
)