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
38 changes: 38 additions & 0 deletions crates/goose/src/config/declarative_providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
39 changes: 39 additions & 0 deletions crates/goose/src/providers/catalog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -1093,6 +1115,22 @@ mod tests {
.collect::<Vec<_>>(),
["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]
Expand All @@ -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"));
Expand Down
23 changes: 23 additions & 0 deletions crates/goose/src/providers/declarative/atomic_chat.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "atomic_chat",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add Atomic Chat to the setup catalog

Adding the declarative JSON registers atomic_chat for the backend/CLI, but the desktop provider picker is populated from SETUP_METADATA in crates/goose/src/providers/catalog.rs, and there is no provider_id: "atomic_chat" entry there. After the catalog loads, ui/goose2/src/features/providers/hooks/useProviderInventory.ts filters model providers to catalog IDs, so this new provider will not appear in the desktop Configure Providers flow that the docs advertise and its inventory entry can be filtered out; add a CuratedSetupMetadata entry for atomic_chat with the ATOMIC_CHAT_HOST field.

Useful? React with 👍 / 👎.

"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
}
50 changes: 50 additions & 0 deletions documentation/docs/getting-started/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`<br /><br />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. |
Expand Down Expand Up @@ -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.
:::
</TabItem>
<TabItem value="atomic-chat" label="Atomic Chat">
[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:

<Tabs groupId="interface">
<TabItem value="ui" label="goose Desktop" default>
1. Click the <PanelLeft className="inline" size={16} /> 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.
</TabItem>
<TabItem value="cli" label="goose CLI">
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
```
</TabItem>
</Tabs>

:::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).
:::
</TabItem>
<TabItem value="docker" label="Docker Model Runner" default>
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)
Expand Down