Skip to content

docs: add .env.example examples for Ollama and OpenAI-compatible - #110

Merged
ilblackdragon merged 3 commits into
nearai:mainfrom
BroccoliFin:docs/env-local-llm-examples
Feb 17, 2026
Merged

ilblackdragon merged 3 commits into
nearai:mainfrom
BroccoliFin:docs/env-local-llm-examples

Conversation

@BroccoliFin

Copy link
Copy Markdown
Contributor

Added clear, commented examples of environment variables for local LLM models.

  • LLM_BACKEND=ollama
  • LLM_BACKEND=openai_compatible (LM Studio, vLLM, LiteLLM, Anything-LLM and any other OpenAI-compatible server)

Support for both backends was already fully implemented in code (see the previous PR that updated FEATURE_PARITY.md).

This is a pure documentation PR.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @BroccoliFin, 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 project's documentation by providing explicit examples for setting up local Large Language Model (LLM) providers. It specifically addresses configurations for Ollama and OpenAI-compatible servers, making it easier for developers to integrate and test local LLMs by clarifying the necessary environment variables.

Highlights

  • Documentation for Local LLMs: Added clear, commented examples for configuring Ollama and OpenAI-compatible local LLM providers in the .env.example file.
  • Ollama Configuration: Included specific environment variables like OLLAMA_MODEL, LLM_BACKEND=ollama, and OLLAMA_BASE_URL to guide users in setting up Ollama.
  • OpenAI-compatible Configuration: Provided examples for LLM_MODEL, LLM_BACKEND=openai_compatible, LLM_BASE_URL, and an optional LLM_API_KEY for various OpenAI-compatible local servers.
Changelog
  • .env.example
    • Added a new section for 'Local LLM Providers' including Ollama and OpenAI-compatible servers.
    • Included commented examples for configuring Ollama with OLLAMA_MODEL, LLM_BACKEND, and OLLAMA_BASE_URL.
    • Provided commented examples for OpenAI-compatible servers with LLM_MODEL, LLM_BACKEND, LLM_BASE_URL, and an optional LLM_API_KEY.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds helpful examples to .env.example for configuring local LLM providers like Ollama and other OpenAI-compatible servers. The added documentation accurately reflects the current implementation.

I've added one suggestion to improve the consistency of environment variable names for the openai_compatible backend. Using backend-specific prefixes, similar to other providers like OLLAMA_ and OPENAI_, would enhance clarity and reduce potential user confusion.

Comment thread .env.example Outdated
Comment on lines +24 to +27
LLM_MODEL=llama-3.2-3b-instruct-q4_K_M
LLM_BACKEND=openai_compatible
LLM_BASE_URL=http://localhost:1234/v1
LLM_API_KEY=sk-... # optional for local servers

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with other LLM backend configurations (e.g., OLLAMA_MODEL, OPENAI_MODEL), it would be clearer to use backend-specific environment variables for the OpenAI-compatible provider. The current generic names like LLM_MODEL and LLM_BASE_URL could be confusing, as they might imply a global setting when they are specific to this backend.

I suggest using prefixed variables. This would require corresponding updates in src/config.rs:

  1. In LlmConfig::resolve(), to read these new variable names.
  2. In inject_llm_keys_from_secrets(), to update the mapping for LLM_API_KEY.
OPENAI_COMPATIBLE_MODEL=llama-3.2-3b-instruct-q4_K_M
LLM_BACKEND=openai_compatible
OPENAI_COMPATIBLE_BASE_URL=http://localhost:1234/v1
OPENAI_COMPATIBLE_API_KEY=sk-...                        # optional for local servers

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review!

This is a pure documentation PR to document the current implementation (which uses LLM_* variables for the openai_compatible backend).

The prefix change (OPENAI_COMPATIBLE_*) is a great idea for consistency — happy to do it in a follow-up code PR if you want.

@ilblackdragon ilblackdragon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: docs: add .env.example examples for Ollama and OpenAI-compatible

Thanks for adding documentation for local LLM providers -- this is genuinely useful for users wanting to run with Ollama or LM Studio.

However, there is a correctness issue that would cause breakage for users who copy-paste from this file, and a usability issue with the structure.

1. Wrong environment variable names for openai_compatible backend (blocking)

The PR currently uses OPENAI_COMPATIBLE_MODEL, OPENAI_COMPATIBLE_BASE_URL, and OPENAI_COMPATIBLE_API_KEY, but the actual code in src/config.rs (lines 523-529) reads LLM_MODEL, LLM_BASE_URL, and LLM_API_KEY:

let base_url = optional_env("LLM_BASE_URL")?
    ...
let api_key = optional_env("LLM_API_KEY")?.map(SecretString::from);
let model = optional_env("LLM_MODEL")?

If a user sets OPENAI_COMPATIBLE_BASE_URL, the code will not find it and will return an error: "Set LLM_BASE_URL when LLM_BACKEND=openai_compatible".

It looks like Gemini suggested renaming these for consistency, and you adopted the names in the .env.example, but without a corresponding code change, the documentation is now incorrect. Since this is a docs-only PR, the variable names should match what the code actually reads today. Please revert to LLM_MODEL, LLM_BASE_URL, and LLM_API_KEY.

(Renaming the env vars in code for consistency is a good idea, but that belongs in a separate code PR.)

2. Both backends are uncommented simultaneously (minor)

Both the Ollama and OpenAI-compatible sections set LLM_BACKEND= as uncommented lines. Since .env files are read top-to-bottom with last-value-wins semantics, this means:

  • OLLAMA_MODEL, OLLAMA_BASE_URL are set but LLM_BACKEND=ollama is silently overridden by LLM_BACKEND=openai_compatible below.
  • A user copying the whole file would get openai_compatible as the backend, but would also have the Ollama vars set (which are ignored).

I'd suggest commenting out the lines in both sections (except possibly the header comments), so users explicitly uncomment the one they want. For example:

# === Ollama ===
# OLLAMA_MODEL=llama3.2
# LLM_BACKEND=ollama
# OLLAMA_BASE_URL=http://localhost:11434   # default

# === OpenAI-compatible (LM Studio, vLLM, Anything-LLM) ===
# LLM_MODEL=llama-3.2-3b-instruct-q4_K_M
# LLM_BACKEND=openai_compatible
# LLM_BASE_URL=http://localhost:1234/v1
# LLM_API_KEY=sk-...                        # optional for local servers

This follows the convention already used in the file (e.g., # NEARAI_SESSION_PATH=...).

Summary

Issue 1 is blocking -- the env var names must match the code or users will get runtime errors. Issue 2 is a usability improvement.

@tribendu

Copy link
Copy Markdown

Batch 2 PR Review: nearai/ironclaw PRs 111, 110, 109, 103, 95, 74

Reviewer: AI Sub-Agent
Date: February 17, 2026
Review Method: Manual diff analysis with focus on code quality, bugs, security, performance, test coverage, and Rust best practices


PR #111: Fix backwards compatibility for nearai.session_token

Summary

This PR adds backwards compatibility for the nearai session management by implementing a fallback mechanism. When nearai.session_token is not found, the system now attempts to fall back to the legacy nearai.session setting. The change is minimal and focused on the session token retrieval logic in SessionManager::renew_session(). The implementation uses a graceful fallback pattern with proper error handling and logging.

Pros

  • Graceful degradation: Implements backwards compatibility without breaking existing functionality
  • Clear error handling: Preserves original error handling for both primary and fallback paths
  • Informative logging: Adds a warning message when falling back to legacy session storage
  • Minimal change scope: Only affects session token retrieval logic, reducing risk of regression
  • Proper pattern: Uses idiomatic Rust if let Some(...) for optional value handling

Concerns

  • Technical debt: This adds maintenance burden by keeping two parallel session storage schemas
  • No migration path: There's no clear deprecation timeline or migration strategy for the legacy schema
  • Silent fallback: The warning log may be missed in production, leading to continued use of deprecated schema
  • Error propagation: The error messages remain generic - they could be more specific about whether the primary or fallback path failed

Suggestions

  • Add a migration function to convert legacy sessions to the new format periodically
  • Consider adding telemetry/metrics to track usage of the legacy fallback path
  • Document the expected lifecycle and deprecation timeline for nearai.session
  • Add a configuration option to disable the fallback after migration is complete
  • Consider making the fallback opt-in rather than silent to encourage migration

PR #110: Add env docs for local LLM providers

Summary

This PR updates the .env.example file to document environment variables for local LLM providers including Ollama, LM Studio, vLLM, and other OpenAI-compatible endpoints. The changes are purely documentation-focused, providing clear examples of environment variable configurations for users who want to use local models instead of the default NEAR AI backend.

Pros

  • User-friendly: Makes it easy for new users to configure local LLM providers
  • Comprehensive: Covers multiple backend options (Ollama, OpenAI-compatible)
  • Clear defaults: Shows default values for URLs and ports
  • Well-organized: Groups related configurations logically
  • No code changes: Documentation-only PR, zero risk of breaking functionality

Concerns

  • No validation: Environment variables are documented but there's no validation that the backend value matches the selected provider
  • Incomplete examples: Example model names are specific but may not match what users have installed
  • Missing authentication notes: Doesn't document that LLM_API_KEY is optional for local servers

Suggestions

  • Add comments explaining when LLM_API_KEY is optional vs required
  • Include a link to documentation for each provider
  • Add a note about model availability requiring local installation
  • Consider adding environment variable validation logic in a future PR
  • Document how to switch between providers at runtime
  • Add example commands to test connections (e.g., curl http://localhost:11434/api/tags)

PR #109: Normalize memory search query and update marked.js

Summary

This PR addresses two security and stability issues in the web interface. First, it adds input normalization for memory search queries to prevent excessive query lengths and invalid input types. Second, it updates the marked.js dependency to a specific version with integrity hashing for supply chain security. The changes are defensive in nature, preventing potential DoS attacks and ensuring the integrity of third-party JavaScript dependencies.

Pros

  • Input validation: Adds MEMORY_SEARCH_QUERY_MAX_LENGTH constant (100 chars) to prevent excessively long queries
  • Type safety: Normalizes queries to string type, preventing crashes from non-string input
  • Supply chain security: Uses SRI (Subresource Integrity) hashing for marked.js CDN dependency
  • Consistent application: Applies normalization throughout search functions (searchMemory, snippetAround, highlightQuery)
  • Clear error handling: Early return when normalized query is empty

Concerns

  • Arbitrary limit: 100-character limit may be too restrictive for complex semantic search queries
  • Silent truncation: Queries longer than the limit are silently truncated without user feedback
  • CDN dependency: Still relies on external CDN for marked.js despite SRI - could use bundled version
  • No rate limiting: Query length limit doesn't prevent rapid-fire spam queries
  • Client-side only: Validation happens on client side only - server should also validate

Suggestions

  • Increase the limit or make it configurable (e.g., 200-500 characters)
  • Add user feedback when query is truncated (toast message or inline warning)
  • Implement rate limiting on the /api/memory/search endpoint
  • Add server-side query validation to defend against bypassed client checks
  • Consider bundling marked.js with the application to eliminate CDN dependency
  • Add unit tests for the normalization function covering edge cases (null, undefined, empty string, very long string)

PR #103: Per-request model override for OpenAI-compatible API

Summary

This is a significant feature PR that adds per-request model override capability across the entire LLM provider ecosystem. Previously, all requests used the active model, but now clients can specify a different model per request. The changes span multiple modules: request structs now include optional model fields, providers check for request-level models before falling back to defaults, OpenAI-compatible endpoint validates model names, and comprehensive integration tests verify functionality. The PR includes migration documentation and removes the previous strict model validation that returned 404 for non-active models.

Pros

  • Well-architected: Uses Option with builder pattern (with_model()) for clean API
  • Comprehensive testing: Updated integration tests to mock model tracking and verify model override works
  • Full stack coverage: Changes propagate from API entry points through worker layer to actual providers
  • Good error handling: Validates model name length (MAX_MODEL_NAME_BYTES: 256) before processing
  • Backwards compatible: Existing behavior preserved when model field is not provided
  • Code quality: Consistent pattern across CompletionRequest and ToolCompletionRequest
  • Documentation: Updates FEATURE_PARITY.md to reflect new capability

Concerns

  • No model validation: The endpoint now accepts ANY model name without checking if it exists or is configured
  • Validation bypasses providers: Validation happens at HTTP layer, but providers don't validate model availability
  • Security implications: Users can request models they shouldn't have access to; cost tracking may break
  • Incomplete fallback: If provider doesn't support the requested model, behavior is undefined
  • Missing permissions: No RBAC or policy checking for model override capability
  • Potential for confusion: Active model concept remains but can be overridden per request

Suggestions

  • Add a method to validate if a model exists/can be used before making the request
  • Implement optional model allowlist/denylist configuration per user or API key
  • Add telemetry to track model usage patterns across different requests
  • Document the precedence: request model > active model > provider default
  • Consider adding a force_model flag that fails fast if model is unavailable
  • Add tests for error cases (non-existent model, invalid characters, empty string)
  • Update cost tracking to handle per-request model pricing differences
  • Consider adding model availability check to LlmProvider trait's set_model() method

PR #95: Add Venice AI provider and embeddings

Summary

This PR adds comprehensive support for Venice AI as both an LLM provider and an embeddings provider. It introduces a new VeniceProvider module with full API integration including Venice-specific features like web search, web scraping, and dynamic model pricing fetched from the /models endpoint. The PR also adds VeniceEmbeddings for semantic search, updates configuration handling, and integrates Venice into the setup wizard. The implementation includes extensive unit tests, proper error handling, caching of model catalogs with TTL, and follows the existing provider patterns.

Pros

  • Fully featured: Implements complete Venice API including proprietary parameters (web search, scraping, system prompt)
  • Dynamic pricing: Fetches model catalog with pricing from Venice API, updates cost tracking automatically
  • Good caching: Uses 1-hour TTL for model catalog to reduce API calls
  • Comprehensive testing: Extensive unit tests for message conversion, serialization, cost calculation
  • Type safety:Uses properly typed structures and enums for Venice-specific functionality
  • Consistent patterns: Follows existing provider patterns (NearAiProvider, etc.)
  • Error handling: Proper HTTP error mapping (401→AuthFailed, 429→RateLimited)
  • Config validation: Validates Venice-specific config values (web_search must be "off"/"on"/"auto")

Concerns

  • Large file: venice.rs is 880 lines - consider splitting into smaller modules
  • Lock choice: Uses std::sync::RwLock with comment about async safety - risk if async code is added later
  • Secret handling: API key exposed as String in multiple places despite being wrapped in SecretString in Config
  • No retry logic: Network requests don't have exponential backoff for transient failures
  • Hardcoded timeout: 120-second timeout may be too long or too short for different use cases
  • Cache misses on errors: If catalog fetch fails, stale cache is kept indefinitely
  • Embeddings dimension hardcoding: Magic numbers for dimensions (1536, 3072) scattered in code

Suggestions

  • Split venice.rs into multiple modules: provider.rs, models.rs, api.rs
  • Consider using tokio::sync::RwLock for future-proofing with async code
  • Add retry logic with exponential backoff for API requests
  • Make timeout configurable via VeniceConfig
  • Add metrics for cache hit/miss ratio
  • Document the security model: when are secrets exposed?
  • Extract dimension mapping to a constant or helper function
  • Add integration test that calls actual Venice API with test credentials
  • Consider adding health check endpoint for provider connectivity
  • Add support for streaming responses (if Venice API supports it)

PR #74: Security fix: Enhanced HTTP response size validation

Summary

This PR strengthens the HTTP tool's defense against OOM attacks by implementing two-stage response size validation. First, it checks the Content-Length header before downloading any content to immediately reject oversized responses. Second, it streams the response body with a hard size cap during download, protecting against malicious or misconfigured servers that may send incorrect or missing Content-Length headers. The implementation uses streaming with futures::StreamExt and enforces a consistent 5 MB limit across both stages.

Pros

  • Defense in depth: Two-stage validation (header check + streaming cap) protects against multiple attack vectors
  • Early rejection: Aborts request before downloading potentially malicious content
  • Streaming approach: Memory-efficient, doesn't load entire response before checking size
  • Informative logging: Warns with URL and size details when rejecting responses
  • Consistent constant: Uses same 5 MB limit as WASM HTTP wrapper
  • Well-documented: Clear comments explain the security rationale and 5 MB justification
  • Test coverage: Includes test verifying the constant value is reasonable

Concerns

  • Header spoofing: Relies on server sending accurate Content-Length - malicious servers can send small value then send large body
  • No byte limit on individual chunks: Only checks cumulative size; individual chunks could still be large
  • Error message exposure: Returns detailed size information in errors which might leak information
  • No rate limiting: An attacker could still send many small requests to exhaust resources
  • Hardcoded limit: 5 MB may be too small for some legitimate use cases (e.g., downloading large JSON datasets)

Suggestions

  • Add per-chunk size limit (e.g., 1 MB max per chunk) in addition to cumulative limit
  • Consider making MAX_RESPONSE_SIZE configurable per tool or per request
  • Add telemetry/metrics for rejected responses to detect DDoS patterns
  • Implement request rate limiting in addition to size limiting
  • Add option to override limit for authorized users/admins
  • Consider adding a timeout for the streaming operation
  • Add test cases for Content-Length header spoofing attempt
  • Document how users can work around the limit if needed (e.g., using multiple smaller requests with pagination)

Overall Recommendations

High Priority

  1. PR feat: support per-request model override in /v1/chat/completions #103: Address the security implications of unrestricted model override before merging - add allowlist/denylist functionality
  2. PR fix: check Content-Length before downloading HTTP response body #74: Consider making the size limit configurable for flexibility while maintaining security

Medium Priority

  1. PR feat: add Venice AI as first-class LLM backend #95: Refactor the large venice.rs file and add retry logic for network resilience
  2. PR web: add integrity check for marked CDN and cap highlight regex input #109: Add server-side validation to complement client-side checks
  3. PR llm: fallback to legacy nearai.session key when loading DB session #111: Add migration strategy for legacy session tokens

Low Priority

  1. PR docs: add .env.example examples for Ollama and OpenAI-compatible #110: Add validation documentation and testing commands
  2. PR feat: add Venice AI as first-class LLM backend #95: Extract magic numbers and add integration tests
  3. PR web: add integrity check for marked CDN and cap highlight regex input #109: Consider removing CDN dependency for marked.js

General Observations

  • All PRs follow Rust best practices and maintain code quality
  • Test coverage is generally good, though some integration tests could be expanded
  • Error handling is consistent across the codebase
  • Documentation (comments and inline docs) is clear and helpful
  • Most PRs are backwards compatible, which is good for production deployments

@BroccoliFin

Copy link
Copy Markdown
Contributor Author

Illia, thanks for the review! I've updated the .env.example with the requested changes (all examples are now fully commented out for safety). Let me know if anything else needs tweaking.

@ilblackdragon
ilblackdragon merged commit 436dda0 into nearai:main Feb 17, 2026
2 checks passed
@github-actions github-actions Bot mentioned this pull request Feb 17, 2026
jaswinder6991 pushed a commit to jaswinder6991/ironclaw that referenced this pull request Feb 26, 2026
…rai#110)

* docs: add .env.example examples for Ollama and OpenAI-compatible

* docs: update .env.example with commented examples

---------

Co-authored-by: BroccoliFin <mikhailsadovoy@MacBook-Air-MacMike.local>
bkutasi pushed a commit to bkutasi/ironclaw that referenced this pull request Mar 28, 2026
…rai#110)

* docs: add .env.example examples for Ollama and OpenAI-compatible

* docs: update .env.example with commented examples

---------

Co-authored-by: BroccoliFin <mikhailsadovoy@MacBook-Air-MacMike.local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants