## Architecture llm-connect is structured as a **GAAF-2026 layered library**. See `ARCHITECTURE-LAYERS.md` for the full layer map and scorecard. ### Layer summary ``` Core (frozen after v1) LLMAdapter ABC adapter.py RunConfig / LLMResponse models.py LLMError hierarchy exceptions.py MockLLMAdapter adapter.py ← test primitive, belongs with Core Functional (evolvable, independently shippable) OpenAIAdapter openai.py GeminiAdapter gemini.py OpenRouterAdapter openrouter.py ClaudeCodeAdapter claude_code.py EmbeddingAdapter ABC embedding_adapter.py OpenAICompatibleEmbeddingAdapter embedding_openai.py EmbeddingCache embedding_cache.py create_adapter() factory.py create_embedding_adapter() embedding_factory.py _token_estimator _token_estimator.py similarity utilities similarity.py Configuration (user-controlled declarative state) resolve_llm() chain toml_config.py ← 7-level TOML priority chain LLMConfig / load_config config.py _http shared utility _http.py ← also used by Functional adapters ``` ### Dependency rule Core ← Functional ← Configuration No upward dependencies. `_http.py` is consumed by Functional only. ### Key design decisions **API key resolution** (`config.resolve_api_key`): three-step chain — explicit argument → environment variable → plaintext key file in project root. Adapters raise `LLMConfigurationError` at construction time if no key is found (except `ClaudeCodeAdapter` which needs no key). **TOML config chain** (`toml_config.resolve_llm`): 7 priority levels allow per-project and per-user LLM preferences. Currently defaults to `markitect` app_name for backward compatibility — consumers pass their own `app_name`. **Factory pattern** (`factory.create_adapter`): lazy imports prevent pulling all provider SDKs at module load. Add a new provider by registering its FQN in `_PROVIDERS`. **ClaudeCodeAdapter subprocess model**: prompt is piped via stdin (not CLI arg) to avoid shell argument length limits on large prompts (>30 KB). **Retry logic**: `OpenAIAdapter` and `OpenRouterAdapter` retry on 429 and 5xx with exponential backoff. `GeminiAdapter` does not (rate-limit handling deferred).