From e187fcddf719c30f6a455b8bc659bd85b164acbf Mon Sep 17 00:00:00 2001 From: yanalialiuk Date: Thu, 14 May 2026 22:29:56 +0300 Subject: [PATCH] feat: add Atomic Chat as declarative OpenAI-compatible provider (#9210) Co-authored-by: Yana Lyalyuk Co-authored-by: Cursor --- .../goose/src/config/declarative_providers.rs | 38 ++++++++++++++ crates/goose/src/providers/catalog.rs | 39 +++++++++++++++ .../providers/declarative/atomic_chat.json | 23 +++++++++ .../docs/getting-started/providers.md | 50 +++++++++++++++++++ 4 files changed, 150 insertions(+) create mode 100644 crates/goose/src/providers/declarative/atomic_chat.json diff --git a/crates/goose/src/config/declarative_providers.rs b/crates/goose/src/config/declarative_providers.rs index d6d4d8c16d..32f765cfd9 100644 --- a/crates/goose/src/config/declarative_providers.rs +++ b/crates/goose/src/config/declarative_providers.rs @@ -879,6 +879,44 @@ mod tests { assert_eq!(result, "https://from-env.com/path"); } + #[test] + fn test_atomic_chat_json_deserializes() { + let json = include_str!("../providers/declarative/atomic_chat.json"); + let config: DeclarativeProviderConfig = + serde_json::from_str(json).expect("atomic_chat.json should parse"); + assert_eq!(config.name, "atomic_chat"); + assert_eq!(config.display_name, "Atomic Chat"); + assert_eq!( + config.description.as_deref(), + Some("Local models through Atomic Chat\u{2019}s OpenAI-compatible server") + ); + assert!(matches!(config.engine, ProviderEngine::OpenAI)); + assert_eq!(config.api_key_env, ""); + assert!(!config.requires_auth); + assert!(config.skip_canonical_filtering); + assert_eq!(config.dynamic_models, Some(true)); + assert_eq!(config.supports_streaming, Some(true)); + assert_eq!(config.base_url, "${ATOMIC_CHAT_HOST}/v1/chat/completions"); + assert!(config.models.is_empty()); + assert!(config.model_doc_link.is_none()); + assert!(config.setup_steps.is_empty()); + + let env_vars = config.env_vars.as_ref().expect("env_vars should be set"); + assert_eq!(env_vars.len(), 1); + assert_eq!(env_vars[0].name, "ATOMIC_CHAT_HOST"); + assert!(!env_vars[0].required); + assert!(!env_vars[0].secret); + assert_eq!(env_vars[0].primary, Some(true)); + assert_eq!( + env_vars[0].default, + Some("http://localhost:1337".to_string()) + ); + assert_eq!( + env_vars[0].description.as_deref(), + Some("Base URL of the Atomic Chat server (default: http://localhost:1337)") + ); + } + #[test] fn test_routstr_json_deserializes() { let json = include_str!("../providers/declarative/routstr.json"); diff --git a/crates/goose/src/providers/catalog.rs b/crates/goose/src/providers/catalog.rs index 33ea12d902..1cfdd662bb 100644 --- a/crates/goose/src/providers/catalog.rs +++ b/crates/goose/src/providers/catalog.rs @@ -703,6 +703,28 @@ const SETUP_METADATA: &[CuratedSetupMetadata] = &[ default_value: None, }], }, + CuratedSetupMetadata { + provider_id: "atomic_chat", + category: ProviderSetupCategory::Model, + setup_method: ProviderSetupMethod::ConfigFields, + group: ProviderSetupGroup::Additional, + display_name: None, + description: None, + docs_url: Some("https://github.com/AtomicBot-ai/Atomic-Chat?tab=readme-ov-file#readme"), + aliases: &[], + native_connect_query: None, + binary_name: None, + setup_capabilities: setup_capabilities(false, false, false), + show_only_when_installed: false, + synthetic: false, + secret_field_default: None, + field_overrides: &[CuratedFieldMetadata { + key: "ATOMIC_CHAT_HOST", + label: "Host URL", + placeholder: Some("http://localhost:1337"), + default_value: Some("http://localhost:1337"), + }], + }, CuratedSetupMetadata { provider_id: "nvidia", category: ProviderSetupCategory::Model, @@ -1093,6 +1115,22 @@ mod tests { .collect::>(), ["DATABRICKS_HOST", "DATABRICKS_TOKEN"] ); + + let atomic_chat = entries + .iter() + .find(|entry| entry.provider_id == "atomic_chat") + .expect("setup catalog should include atomic_chat declarative provider"); + assert_eq!(atomic_chat.setup_method, ProviderSetupMethod::ConfigFields); + let host_field = atomic_chat + .fields + .iter() + .find(|field| field.key == "ATOMIC_CHAT_HOST") + .expect("atomic_chat should expose ATOMIC_CHAT_HOST"); + assert_eq!(host_field.label, "Host URL"); + assert_eq!( + host_field.default_value.as_deref(), + Some("http://localhost:1337") + ); } #[tokio::test] @@ -1105,6 +1143,7 @@ mod tests { assert!(provider_ids.contains("claude-acp")); assert!(provider_ids.contains("codex-acp")); + assert!(provider_ids.contains("atomic_chat")); assert!(!provider_ids.contains("claude_code")); assert!(!provider_ids.contains("codex")); assert!(!provider_ids.contains("gemini_cli")); diff --git a/crates/goose/src/providers/declarative/atomic_chat.json b/crates/goose/src/providers/declarative/atomic_chat.json new file mode 100644 index 0000000000..ca537e7e4e --- /dev/null +++ b/crates/goose/src/providers/declarative/atomic_chat.json @@ -0,0 +1,23 @@ +{ + "name": "atomic_chat", + "engine": "openai", + "display_name": "Atomic Chat", + "description": "Local models through Atomic Chat\u2019s OpenAI-compatible server", + "api_key_env": "", + "base_url": "${ATOMIC_CHAT_HOST}/v1/chat/completions", + "env_vars": [ + { + "name": "ATOMIC_CHAT_HOST", + "required": false, + "secret": false, + "primary": true, + "default": "http://localhost:1337", + "description": "Base URL of the Atomic Chat server (default: http://localhost:1337)" + } + ], + "dynamic_models": true, + "models": [], + "supports_streaming": true, + "requires_auth": false, + "skip_canonical_filtering": true +} diff --git a/documentation/docs/getting-started/providers.md b/documentation/docs/getting-started/providers.md index f873caeb1f..983046cff6 100644 --- a/documentation/docs/getting-started/providers.md +++ b/documentation/docs/getting-started/providers.md @@ -25,6 +25,7 @@ goose is compatible with a wide range of LLM providers, allowing you to choose a | [Amazon Bedrock](https://aws.amazon.com/bedrock/) | Offers a variety of foundation models, including Claude, Jurassic-2, and others. **AWS environment variables must be set in advance, not configured through `goose configure`** | Credential auth: `AWS_PROFILE`, or `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`

Bearer token auth: `AWS_BEARER_TOKEN_BEDROCK` and `AWS_REGION`, `AWS_DEFAULT_REGION`, or `AWS_PROFILE` | | [Amazon SageMaker TGI](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints.html) | Run Text Generation Inference models through Amazon SageMaker endpoints. **AWS credentials must be configured in advance.** | `SAGEMAKER_ENDPOINT_NAME`, `AWS_REGION` (optional), `AWS_PROFILE` (optional) | | [Anthropic](https://www.anthropic.com/) | Offers Claude, an advanced AI model for natural language tasks. | `ANTHROPIC_API_KEY`, `ANTHROPIC_HOST` (optional) | +| [Atomic Chat](https://github.com/AtomicBot-ai/Atomic-Chat) | Run local models with Atomic Chat's OpenAI-compatible server. **Because this provider runs locally, you must first [download a model](#local-llms).** | None required. Connects to local server at `localhost:1337` by default. | | [Avian](https://avian.io/) | Cost-effective inference API with DeepSeek, Kimi, GLM, and MiniMax models. OpenAI-compatible with streaming and function calling support. | `AVIAN_API_KEY`, `AVIAN_HOST` (optional) | | [Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-services/openai/) | Access Azure-hosted OpenAI models, including GPT-4 and GPT-3.5. Supports both API key and Azure credential chain authentication. | `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_DEPLOYMENT_NAME`, `AZURE_OPENAI_API_KEY` (optional) | | [ChatGPT Codex](https://chatgpt.com/codex) | Access GPT-5 Codex models optimized for code generation and understanding. **Requires a ChatGPT Plus/Pro subscription.** | No manual key. Uses browser-based OAuth authentication for both CLI and Desktop. | @@ -1210,6 +1211,55 @@ Here are some local providers we support: Make sure the model name you enter in goose matches the model identifier shown in LM Studio's server panel. ::: + + [Atomic Chat](https://github.com/AtomicBot-ai/Atomic-Chat) lets you run open-source models locally with an OpenAI-compatible API server. + + 1. Download and install Atomic Chat from [atomic.chat](https://atomic.chat/) or [GitHub Releases](https://github.com/AtomicBot-ai/Atomic-Chat/releases). + 2. Open Atomic Chat and download a model that supports tool calling (e.g., Qwen, Llama, or Mistral variants). + 3. Start the local server in Atomic Chat. The server runs on `http://localhost:1337` by default + + 4. Configure goose to use Atomic Chat: + + + + 1. Click the button in the top-left to open the sidebar. + 2. Click the `Settings` button on the sidebar. + 3. Click the `Models` tab. + 4. Click `Configure providers`. + 5. Choose `Atomic Chat` from the provider list and click `Configure`. + 6. Click `Submit` (no API key is needed). + 7. Select the model you have loaded in Atomic Chat. + + + 1. Run: + ```sh + goose configure + ``` + 2. Select `Configure Providers` from the menu. + 3. Choose `Atomic Chat` as the provider. + 4. Enter the model name that matches the model loaded in Atomic Chat. + + ``` + ┌ goose-configure + │ + ◇ What would you like to configure? + │ Configure Providers + │ + ◇ Which model provider should we use? + │ Atomic Chat + │ + ◇ Enter a model from that provider: + │ qwen2.5-7b-instruct + │ + └ Configuration saved successfully + ``` + + + + :::tip Model Name + Make sure the model name you enter in goose matches the model identifier shown for your server in Atomic Chat. If the API listens on a different origin than `http://localhost:1337`, set `ATOMIC_CHAT_HOST` in goose to match (scheme, host, and port only). + ::: + 1. [Get Docker](https://docs.docker.com/get-started/get-docker/) 2. [Enable Docker Model Runner](https://docs.docker.com/ai/model-runner/#enable-dmr-in-docker-desktop)