feat: direct api key and cheap model#116
Conversation
Allow using IronClaw with any OpenAI-compatible API provider (e.g. Anthropic Claude) via API key, without requiring NEAR AI session auth. Changes: - Skip session authentication in chat_completions mode (API key auth) - Skip first-run onboard check when NEARAI_API_KEY is configured - Add `cheap_model` config field (NEARAI_CHEAP_MODEL env var) for a secondary lightweight model used for heartbeat, routing, evaluation - Add `create_cheap_llm_provider()` factory in llm module - Add `cheap_llm` to AgentDeps with fallback to main model - Route heartbeat through cheap model to reduce costs - Fix wizard compilation for new config field Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Check API key presence (not api_mode) for auth skip (ilblackdragon) - Add Settings::load() call in check_onboard_needed (ilblackdragon) - Warn and ignore cheap_model for non-NearAi backends (ilblackdragon) - Add unit tests for create_cheap_llm_provider (ilblackdragon) - Minor formatting cleanup in cheap provider match arm Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello @ilblackdragon, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request enhances the system's flexibility and cost-efficiency by introducing the capability to use a dedicated, less resource-intensive LLM for background and auxiliary functions. It also improves the user experience by making the authentication process more intelligent, recognizing direct API key usage and adjusting onboarding requirements accordingly. These changes aim to optimize operational costs and simplify initial setup for certain configurations. Highlights
Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
The pull request adds support for direct API key authentication and a secondary 'cheap' LLM provider for lightweight tasks. The implementation is generally sound and integrates well with the existing configuration and agent loop. I have identified a few areas for improvement regarding authentication logic robustness and code duplication.
| match cheap_config.api_mode { | ||
| NearAiApiMode::Responses => Ok(Some(Arc::new(NearAiProvider::new(cheap_config, session)))), | ||
| NearAiApiMode::ChatCompletions => { | ||
| Ok(Some(Arc::new(NearAiChatProvider::new(cheap_config)?))) | ||
| } | ||
| } |
| // Session-based auth is only needed for NEAR AI backend without an API key. | ||
| // ChatCompletions mode with an API key skips session auth entirely. | ||
| if config.llm.backend == ironclaw::config::LlmBackend::NearAi | ||
| && config.llm.nearai.api_key.is_none() | ||
| { | ||
| session.ensure_authenticated().await?; | ||
| } |
There was a problem hiding this comment.
The condition for skipping session-based authentication should ideally check the api_mode rather than just the presence of an API key. While api_key.is_some() usually implies ChatCompletions mode, a user could explicitly configure Responses mode while having an API key set. In Responses mode, the NearAiProvider always requires a session token, so ensure_authenticated() must be called.
There was a problem hiding this comment.
Pull request overview
This PR adds support for direct API key authentication with NEAR AI and introduces a cheap model configuration for cost-sensitive operations. It builds upon PR #20 by implementing the infrastructure for using a secondary, lightweight LLM for tasks like heartbeat monitoring, with future support planned for routing and evaluation.
Changes:
- Added
NEARAI_CHEAP_MODELenvironment variable to configure a secondary lightweight model for cost-sensitive tasks - Modified session authentication logic to skip OAuth when using ChatCompletions mode with an API key
- Enhanced first-run detection to skip onboarding when an API key is already configured
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/config.rs | Added cheap_model optional field to NearAiConfig structure and loaded from environment variable |
| src/llm/mod.rs | Implemented create_cheap_llm_provider() factory function with comprehensive unit tests |
| src/main.rs | Integrated cheap LLM provider initialization, updated session auth logic to skip when API key present, modified onboarding check |
| src/agent/agent_loop.rs | Added cheap_llm field to AgentDeps, implemented cheap_llm() accessor with fallback, routed heartbeat to use cheap model |
| src/setup/wizard.rs | Added cheap_model: None to fix NearAiConfig struct initialization |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Initialize cheap LLM provider for lightweight tasks (heartbeat, evaluation) | ||
| let cheap_llm = create_cheap_llm_provider(&config.llm, session.clone())?; | ||
| if let Some(ref cheap) = cheap_llm { | ||
| tracing::info!("Cheap LLM provider initialized: {}", cheap.model_name()); | ||
| } |
There was a problem hiding this comment.
Consider adding a warning when the cheap model is the same as the main model, similar to the fallback model check above (lines 522-526). This would help users avoid misconfiguration where they set NEARAI_CHEAP_MODEL to the same value as NEARAI_MODEL, defeating the purpose of having a cheaper model for lightweight tasks.
|
|
||
| assert!(result.is_ok()); | ||
| assert!(result.unwrap().is_none()); | ||
| } |
There was a problem hiding this comment.
Consider adding a test case for creating a cheap LLM provider with ChatCompletions API mode. The existing tests only cover the Responses mode, but the code supports both modes (lines 213-218). This would improve test coverage for this feature.
| } | |
| } | |
| #[test] | |
| fn test_create_cheap_llm_provider_with_chat_completions_mode() { | |
| let mut config = test_llm_config(); | |
| config.nearai.cheap_model = Some("cheap-test-model".to_string()); | |
| config.nearai.api_mode = NearAiApiMode::ChatCompletions; | |
| let session = Arc::new(SessionManager::new(SessionConfig::default())); | |
| let result = create_cheap_llm_provider(&config, session); | |
| assert!(result.is_ok()); | |
| let provider = result.unwrap(); | |
| assert!(provider.is_some()); | |
| assert_eq!(provider.unwrap().model_name(), "cheap-test-model"); | |
| } |
* feat: Support direct API key auth and cheap model routing Allow using IronClaw with any OpenAI-compatible API provider (e.g. Anthropic Claude) via API key, without requiring NEAR AI session auth. Changes: - Skip session authentication in chat_completions mode (API key auth) - Skip first-run onboard check when NEARAI_API_KEY is configured - Add `cheap_model` config field (NEARAI_CHEAP_MODEL env var) for a secondary lightweight model used for heartbeat, routing, evaluation - Add `create_cheap_llm_provider()` factory in llm module - Add `cheap_llm` to AgentDeps with fallback to main model - Route heartbeat through cheap model to reduce costs - Fix wizard compilation for new config field Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR nearai#20 review feedback - Check API key presence (not api_mode) for auth skip (ilblackdragon) - Add Settings::load() call in check_onboard_needed (ilblackdragon) - Warn and ignore cheap_model for non-NearAi backends (ilblackdragon) - Add unit tests for create_cheap_llm_provider (ilblackdragon) - Minor formatting cleanup in cheap provider match arm Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Samuel Barbosa <sambarbosaa@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: Support direct API key auth and cheap model routing Allow using IronClaw with any OpenAI-compatible API provider (e.g. Anthropic Claude) via API key, without requiring NEAR AI session auth. Changes: - Skip session authentication in chat_completions mode (API key auth) - Skip first-run onboard check when NEARAI_API_KEY is configured - Add `cheap_model` config field (NEARAI_CHEAP_MODEL env var) for a secondary lightweight model used for heartbeat, routing, evaluation - Add `create_cheap_llm_provider()` factory in llm module - Add `cheap_llm` to AgentDeps with fallback to main model - Route heartbeat through cheap model to reduce costs - Fix wizard compilation for new config field Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR nearai#20 review feedback - Check API key presence (not api_mode) for auth skip (ilblackdragon) - Add Settings::load() call in check_onboard_needed (ilblackdragon) - Warn and ignore cheap_model for non-NearAi backends (ilblackdragon) - Add unit tests for create_cheap_llm_provider (ilblackdragon) - Minor formatting cleanup in cheap provider match arm Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Samuel Barbosa <sambarbosaa@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fixes from #20
Co-authored with @desamtralized