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
27 changes: 27 additions & 0 deletions crates/goose/src/config/declarative_providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -855,4 +855,31 @@ mod tests {
let result = expand_env_vars("${TEST_EXPAND_OVERRIDE}/path", &env_vars).unwrap();
assert_eq!(result, "https://from-env.com/path");
}

#[test]
fn test_routstr_json_deserializes() {
let json = include_str!("../providers/declarative/routstr.json");
let config: DeclarativeProviderConfig =
serde_json::from_str(json).expect("routstr.json should parse");
assert_eq!(config.name, "routstr");
assert_eq!(config.display_name, "Routstr");
assert!(matches!(config.engine, ProviderEngine::OpenAI));
assert_eq!(config.api_key_env, "ROUTSTR_API_KEY");
assert_eq!(config.base_url, "${ROUTSTR_HOST}/v1");
assert_eq!(config.dynamic_models, Some(true));
assert_eq!(config.supports_streaming, Some(true));
assert!(config.skip_canonical_filtering);
assert_eq!(config.models.len(), 6);

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, "ROUTSTR_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("https://api.routstr.com".to_string())
);
}
}
35 changes: 35 additions & 0 deletions crates/goose/src/providers/declarative/routstr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "routstr",
"engine": "openai",
"display_name": "Routstr",
"description": "OpenAI-compatible aggregator that fronts dozens of upstream providers (OpenAI, Anthropic, Google, DeepSeek, Llama, …) behind a single API. Authenticate with an sk-... bearer issued by a Routstr instance — payment (e.g. Cashu top-up) is handled outside goose.",
"api_key_env": "ROUTSTR_API_KEY",
"base_url": "${ROUTSTR_HOST}/v1",

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 Disable Responses routing for Routstr

When Routstr's dynamic /v1/models list includes OpenAI o*/gpt-5* IDs, this base URL derives the default OpenAI v1/chat/completions path, and OpenAiProvider::should_use_responses_api routes those model names to /v1/responses instead. Routstr is being documented here as a chat-completions OpenAI-compatible router, so users who pick one of those dynamically fetched models will send requests to an endpoint the Routstr integration does not configure or document. Add a provider-level way to force chat completions for Routstr before enabling dynamic models for OpenAI-family IDs.

Useful? React with 👍 / 👎.

"env_vars": [
{
"name": "ROUTSTR_HOST",
"required": false,
"secret": false,
"primary": true,
"default": "https://api.routstr.com",
"description": "Base URL of the Routstr proxy (default: https://api.routstr.com)"
}
],
"dynamic_models": true,
"models": [
{ "name": "claude-opus-4.7", "context_limit": 1000000 },

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 Preserve Routstr model namespaces

When dynamic model fetching is unavailable or a user accepts the provider's default model, register_with_name uses these static models entries directly as the model IDs sent to the API. The Routstr docs added in this same commit show namespaced IDs such as anthropic/claude-opus-4.7 and deepseek/deepseek-v4-pro, but the static defaults drop those namespaces, so goose can send claude-opus-4.7 to Routstr and fail to route the model as documented. Keep the provider prefixes in the shipped model IDs so the fallback/default path matches Routstr's IDs.

Useful? React with 👍 / 👎.

{ "name": "gemini-3.1-pro-preview", "context_limit": 1048576 },
{ "name": "gemini-3-flash-preview", "context_limit": 1048576 },
{ "name": "deepseek-v4-pro", "context_limit": 1048576 },
{ "name": "glm-5.1", "context_limit": 202752 },
{ "name": "minimax-m2.7", "context_limit": 196608 }
],
"supports_streaming": true,
"skip_canonical_filtering": true,
"model_doc_link": "https://routstr.com/docs",
"setup_steps": [
"Pick a Routstr instance (e.g. https://api.routstr.com) and obtain an sk-... API key from its payment flow.",
"Paste the key above as ROUTSTR_API_KEY.",
"Optionally override ROUTSTR_HOST to point at a different Routstr proxy."
]
}
38 changes: 38 additions & 0 deletions documentation/docs/getting-started/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ goose is compatible with a wide range of LLM providers, allowing you to choose a
| [OpenRouter](https://openrouter.ai/) | API gateway for unified access to various models with features like rate-limiting management. | `OPENROUTER_API_KEY` |
| [OVHcloud AI](https://www.ovhcloud.com/en/public-cloud/ai-endpoints/) | Provides access to open-source models including Qwen, Llama, Mistral, and DeepSeek through AI Endpoints service. | `OVHCLOUD_API_KEY` |
| [Ramalama](https://ramalama.ai/) | Local model using native [OCI](https://opencontainers.org/) container runtimes, [CNCF](https://www.cncf.io/) tools, and supporting models as OCI artifacts. Ramalama API is a compatible alternative to Ollama and can be used with the goose Ollama provider. Supports Qwen, Llama, DeepSeek, and other open-source models. **Because this provider runs locally, you must first [download and run a model](#local-llms).** | `OLLAMA_HOST` |
| [Routstr](https://routstr.com/) | OpenAI-compatible aggregator that fronts dozens of upstream providers (Anthropic, OpenAI, Google, DeepSeek, Llama, …) behind a single API. Authenticate with an `sk-...` bearer issued by your Routstr instance — payment is handled outside goose. | `ROUTSTR_API_KEY`, `ROUTSTR_HOST` (optional, default `https://api.routstr.com`) |
| [Snowflake](https://docs.snowflake.com/user-guide/snowflake-cortex/aisql#choosing-a-model) | Access the latest models using Snowflake Cortex services, including Claude models. **Requires a Snowflake account and programmatic access token (PAT)**. | `SNOWFLAKE_HOST`, `SNOWFLAKE_TOKEN` |
| [VMware Tanzu Platform](https://techdocs.broadcom.com/us/en/vmware-tanzu/platform/ai-services/10-3/ai/index.html) | Enterprise-managed LLM access through AI Services on VMware Tanzu Platform. Models are fetched dynamically from the endpoint. | `TANZU_AI_API_KEY`, `TANZU_AI_ENDPOINT` |
| [Tetrate Agent Router Service](https://router.tetrate.ai) | Unified API gateway for AI models including Claude, Gemini, GPT, open-weight models, and others. Supports PKCE authentication flow for secure API key generation. | `TETRATE_API_KEY`, `TETRATE_HOST` (optional) |
Expand Down Expand Up @@ -733,6 +734,43 @@ To set up Novita AI with goose, follow these steps:
</TabItem>
</Tabs>

### Routstr
[Routstr](https://routstr.com/) is an OpenAI-compatible aggregator that fronts dozens of upstream providers behind a single API. Payment is handled by the Routstr instance itself, so all goose needs is the `sk-...` bearer that instance issues you. To use Routstr with goose, pick an instance (the default is `https://api.routstr.com`) and obtain an API key from its payment flow.

Routstr aggregates models from many upstream providers, including:
- **claude-opus-4.7** — Anthropic's Claude opus 4.7
- **deepseek-v4-pro** — DeepSeek V4 Pro
- **gemini-3.1-pro-preview** — gemini-3.1 Pro Preview

`/v1/models` is queried at configure time, so the full catalogue your Routstr instance exposes is available in the model picker. For the static defaults shipped with goose, see [routstr.json](https://github.com/aaif-goose/goose/blob/main/crates/goose/src/providers/declarative/routstr.json).

To set up Routstr with goose, follow these steps:

<Tabs groupId="interface">
<TabItem value="ui" label="goose Desktop" default>
**To update your LLM provider and API key:**

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 `Routstr` as provider from the list.
6. Click `Configure`, enter your `ROUTSTR_API_KEY` (and optionally override `ROUTSTR_HOST` to point at a different Routstr instance), and click `Submit`.
7. Select the Routstr model of your choice.

</TabItem>
<TabItem value="cli" label="goose CLI">
1. Run:
```sh
goose configure
```
2. Select `Configure Providers` from the menu.
3. Follow the prompts to choose `Routstr` as the provider.
4. Enter your API key when prompted (and optionally override `ROUTSTR_HOST`).
5. Select the Routstr model of your choice.
</TabItem>
</Tabs>

### Google Gemini
Google Gemini provides a free tier. To start using the Gemini API with goose, you need an API Key from [Google AI studio](https://aistudio.google.com/app/apikey).

Expand Down
Loading