Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,21 +100,18 @@ cp .env.example .env

Edit `.env`:
```ini
ENVIRONMENT=development
LOG_LEVEL=INFO

# LLM Providers (at least one key or use offline mode)
LLM_PROVIDER=gemini
LLM_MODEL=gemini-2.0-flash
GEMINI_API_KEY=your_gemini_api_key_here
OPENAI_API_KEY=your_openai_api_key_here

# Persistence
DATABASE_URL=postgresql+asyncpg://agentkit:agentkit_password@localhost:5432/agentkit
REDIS_URL=redis://localhost:6379/0

# Security
API_KEYS=dev_key_1,dev_key_2
JWT_SECRET=super_secret_jwt_key_at_least_32_bytes_long
# Security (comma-separated authorized keys)
API_KEYS=ak_test_key_12345,ak_admin_key_67890
```

### 4. Running with Docker Compose (Recommended)
Expand Down
15 changes: 11 additions & 4 deletions examples/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,24 @@ def build_fake_llm() -> LLMClient:


def build_llm(offline: bool, provider: str) -> LLMClient:
"""Resolve the LLM client, degrading to the scripted fake when no key is present."""
"""Resolve the LLM client, requiring valid API keys unless running in offline/fake mode."""
if offline or provider == "fake":
return build_fake_llm()

settings = get_settings()
key_present = settings.GEMINI_API_KEY if provider == "gemini" else settings.OPENAI_API_KEY
if not key_present:
logger.warning("No API key for provider '%s'; falling back to FakeLLMClient.", provider)
return build_fake_llm()
key_name = "GEMINI_API_KEY" if provider == "gemini" else "OPENAI_API_KEY"
raise ValueError(
f"API key for provider '{provider}' is missing ({key_name} is not set). "
f"To run offline without real API credentials, pass --offline or --provider fake."
)

return create_llm_client(provider)
return create_llm_client(
provider=provider,
api_key=key_present,
model=settings.LLM_MODEL,
)


async def run_demo(
Expand Down
24 changes: 24 additions & 0 deletions tests/integration/test_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,27 @@ async def test_demo_script_runner() -> None:
output = await demo_module.run_demo(offline=True)
assert output is not None
assert "3472" in output or "3,472" in output or "total" in output.lower()


def test_build_llm_strict_live_mode(monkeypatch: pytest.MonkeyPatch) -> None:
"""Verify build_llm requires API keys when live provider is requested without --offline."""
from agentkit.config import get_settings
from examples.demo import build_llm

monkeypatch.setenv("GEMINI_API_KEY", "")
monkeypatch.setenv("OPENAI_API_KEY", "")
get_settings.cache_clear()

# In live mode without key, it must raise ValueError
with pytest.raises(ValueError, match="API key for provider 'gemini' is missing"):
build_llm(offline=False, provider="gemini")

with pytest.raises(ValueError, match="API key for provider 'openai' is missing"):
build_llm(offline=False, provider="openai")

# In offline or fake mode, it returns FakeLLMClient
fake_client_offline = build_llm(offline=True, provider="gemini")
assert isinstance(fake_client_offline, FakeLLMClient)

fake_client_fake_prov = build_llm(offline=False, provider="fake")
assert isinstance(fake_client_fake_prov, FakeLLMClient)
Loading